function byId(id: string): HTMLElement { return document.getElementById(id)!; } // obsolete: watch the graph instead export interface TimingUpdate { // GET /ascoltami/time response duration: number; next: string; // e.g. 'play' playing: boolean; song: string; started: number; // unix sec t: number; // seconds into song state: { current: { name: string }; pending: { name: string } }; } (window as any).finishOldStyleSetup = async (times: { intro: number; post: number }, timingUpdate: (data: TimingUpdate) => void) => { let currentHighlightedSong = ""; // let lastPlaying = false; const events = new EventSource("/service/ascoltami/time/stream"); events.addEventListener("message", (m)=>{ const update = JSON.parse(m.data) as TimingUpdate updateCurrent(update) markUpdateTiming(); }) async function updateCurrent(data:TimingUpdate) { byId("currentSong").innerText = data.song; if (data.song != currentHighlightedSong) { showCurrentSong(data.song); } byId("currentTime").innerText = data.t.toFixed(1); byId("leftTime").innerText = (data.duration - data.t).toFixed(1); byId("leftAutoStopTime").innerText = Math.max(0, data.duration - times.post - data.t).toFixed(1); byId("states").innerText = JSON.stringify(data.state); // document.querySelector("#timeSlider").slider({ value: data.t, max: data.duration }); timingUpdate(data); } let recentUpdates: Array = []; function markUpdateTiming() { recentUpdates.push(+new Date()); recentUpdates = recentUpdates.slice(Math.max(recentUpdates.length - 5, 0)); } function refreshUpdateFreqs() { if (recentUpdates.length > 1) { if (+new Date() - recentUpdates[recentUpdates.length - 1] > 1000) { byId("updateActual").innerText = "(stalled)"; return; } var avgMs = (recentUpdates[recentUpdates.length - 1] - recentUpdates[0]) / (recentUpdates.length - 1); byId("updateActual").innerText = "" + Math.round(1000 / avgMs); } } setInterval(refreshUpdateFreqs, 2000); function showCurrentSong(uri: string) { document.querySelectorAll(".songs div").forEach((row: Element, i: number) => { if (row.querySelector("button")!.dataset.uri == uri) { row.classList.add("currentSong"); } else { row.classList.remove("currentSong"); } }); currentHighlightedSong = uri; } const data = await (await fetch("api/songs")).json(); data.songs.forEach((song: { uri: string; label: string }) => { const button = document.createElement("button"); // link is just for dragging, not clicking const link = document.createElement("a"); const n = document.createElement("span"); n.classList.add("num"); n.innerText = song.label.slice(0, 2); link.appendChild(n); const sn = document.createElement("span"); sn.classList.add("song-name"); sn.innerText = song.label.slice(2).trim(); link.appendChild(sn); link.setAttribute("href", song.uri); link.addEventListener("click", (ev) => { ev.stopPropagation(); button.click(); }); button.appendChild(link); button.dataset.uri = song.uri; button.addEventListener("click", async (ev) => { await fetch("api/song", { method: "POST", body: song.uri }); showCurrentSong(song.uri); }); const dv = document.createElement("div"); dv.appendChild(button); document.querySelector(".songs")!.appendChild(dv); }); };