Files
@ 9bb0eb587d5b
Branch filter:
Location: light9/web/ascoltami/main.ts - annotation
9bb0eb587d5b
3.4 KiB
video/MP2T
640x480 camera res
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 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)!;
}
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);
});
};
|