const $ = id => document.getElementById(id); const formatDuration = date => `${date.getUTCHours() > 0 ? date.getUTCHours() + ":" : ""}${date.getUTCMinutes()}:${date.getUTCSeconds().toString().padStart(2, "0")}`; const formatStartAt = date => `${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`; let cursong_startat = null; let cursong_duration_msec = 0; async function updateStatus() { const resp = await fetch("/api/status"); if (!resp.ok || 200 != resp.status) { $("radio-song").textContent = $("radio-duration-estimate").textContent = $("radio-duration").textContent = ""; $("radio-listeners").textContent = $("radio-listener-peak").textContent = "0"; $("last-songs").firstChild.remove(); return [-1, null]; } const s = await resp.json(); if (undefined != s.most_listened_song) { $("radio-mls-song").textContent = s.most_listened_song.song; $("radio-mls-listeners").textContent = s.most_listened_song.listeners; $("radio-mls-date").textContent = (new Intl.DateTimeFormat('en-GB', {timeStyle: "long", dateStyle: "long", timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone})) .format(new Date(s.most_listened_song.date)) } if (undefined == s.current_song) return [-1, null]; $("radio-song").textContent = `${s.current_song.artist} - ${s.current_song.title}`; $("radio-duration").textContent = formatDuration(new Date(s.current_song.duration_msec)); $("radio-listeners").textContent = s.listeners.current; $("radio-listener-peak").textContent = s.listeners.peak; if (undefined != s.last_songs) { $("last-songs").firstChild.remove(); $("last-songs").appendChild(document.createElement("tbody")); for (let i = 0; i < s.last_songs.length; ++i) { let row = $("last-songs").insertRow(); row.insertCell().appendChild(document.createTextNode(formatStartAt(new Date(s.last_songs[i].start_at)))); row.insertCell().appendChild(document.createTextNode(s.last_songs[i].listeners == 0 ? "" : s.last_songs[i].listeners)); row.insertCell().appendChild(document.createTextNode(`${s.last_songs[i].artist} - ${s.last_songs[i].title}`)); } } return [s.current_song.duration_msec, new Date(s.current_song.start_at)]; } async function update() { if (null === cursong_startat) return -1; const estimate = (new Date()) - (new Date(cursong_startat)); if (estimate >= cursong_duration_msec) { return 1; } $("radio-duration-estimate").textContent = `${formatDuration(new Date(estimate))} / `; return 0; } $("radio-update").addEventListener("click", async () => [cursong_duration_msec, cursong_startat] = await updateStatus()); let update_interval_id = null; async function interval() { switch (await update()) { case 1: [cursong_duration_msec, cursong_startat] = await updateStatus(); break; case -1: clearInterval(update_interval_id); await new Promise(resolve => setTimeout(resolve, 5000)); [cursong_duration_msec, cursong_startat] = await updateStatus(); update_interval_id = setInterval(interval, 1000); } } updateStatus().then(r => [cursong_duration_msec, cursong_startat] = r); update_interval_id = setInterval(interval, 1000); const audio = document.getElementsByTagName("audio")[0]; audio.hidden = true; const audio_src = audio.childNodes[0].src; const volume = $("radio-volume"); audio.volume = volume.value / 100.0; volume.addEventListener("input", e => audio.volume = e.target.value / 100.0); $("player").style.display = $("player").firstChild.style.display = "flex"; $("radio-play").addEventListener("click", e => { audio.paused ? (audio.src = audio_src) && audio.play() : audio.src = ""; e.target.style.maskImage = e.target.style.webkitMaskImage = audio.paused ? "url(/assets/img/play.svg)" : "url(/assets/img/stop.svg)"; });