Files
@ a8281a147cb6
Branch filter:
Location: light9/web/ascoltami/main.ts - annotation
a8281a147cb6
3.4 KiB
video/MP2T
checkpoint show data
4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 cc69faa87c27 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 cc69faa87c27 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 4556eebe5d73 | 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<number> = [];
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);
});
};
|