From 4188f159a67d9bed5d14f7b17f24abf03c7a1601 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Sat, 18 Apr 2026 21:43:59 +0200 Subject: [PATCH] skipped_idx --- modules/active_modifier.py | 16 ++++++++-------- modules/web.py | 6 ++---- modules/web/index.html | 2 +- modules/web/web.js | 23 +++++++++++++++-------- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/modules/active_modifier.py b/modules/active_modifier.py index fe0ae19..424b010 100644 --- a/modules/active_modifier.py +++ b/modules/active_modifier.py @@ -23,6 +23,7 @@ class Module(ActiveModifier): self.file_lock = Lock() self.crossfade = DEFAULT_CROSSFADE self.skip_next = 0 + self.skip_indexes = set() def on_new_playlist(self, playlist: list[Track], global_args: dict[str, str]): self.playlist = playlist self.originals = [] @@ -62,12 +63,6 @@ class Module(ActiveModifier): if (index - 1) >= 0: last_track_fade_out = self.playlist[index - 1].fade_out else: last_track_fade_out = 0.0 - if len(songs) != 0: next_track_fade_in = self.crossfade - else: - if index + 1 < len(self.playlist) and next_track: next_track_fade_in = next_track.fade_in - elif not next_track: next_track_fade_in = 0.0 - else: next_track_fade_in = self.crossfade - if not self.originals or self.originals[-1] != track: self.originals.append(track) with self.file_lock: @@ -163,13 +158,18 @@ class Module(ActiveModifier): i += 1 with open(TOPLAY, "w") as f: f.write(first_line.strip() + "\n") return {"status": "ok", "data": [first_line.strip()]} - elif data.get("action") == "skip_next": return {"status": "removed"} elif data.get("action") == "skipc": if (count := data.get("set", -1)) > -1: self.skip_next = count - if (count2 := data.get("add", -1)) > -1: self.skip_next += count2 + if (count2 := data.get("add", None)): self.skip_next += count2 if (count3 := data.get("remove", 1)) < 0: self.skip_next += count3 self.skip_next = max(self.skip_next, 0) return {"status": "ok", "data": self.skip_next} + elif data.get("action") == "skipi": + idx = data.get("target") + if not idx or not isinstance(idx, int): return {"status": "data", "data": list(self.skip_indexes)} + self.skip_indexes.add(idx) + return {"status": "ok", "data": list(self.skip_indexes)} + activemod = Module() diff --git a/modules/web.py b/modules/web.py index 76eaf4d..802f41b 100644 --- a/modules/web.py +++ b/modules/web.py @@ -71,14 +71,12 @@ async def ws_handler(websocket: ServerConnection, shared_data: dict, imc_q: mult result = await get_imc("activemod", {"action": "clear_toplay"}) if result is None: await websocket.send(json.dumps({"error": "timeout", "code": 504})) else: - await websocket.send(json.dumps({"data": result, "event": "toplay"})) # Yes, this is not an accident await asyncio.get_event_loop().run_in_executor(None, ws_q.put, {"data": result, "event": "toplay"}) - elif action == "skipc": + elif action == "skipc" or action == "skipi": result = await get_imc("activemod", msg) if result is None: await websocket.send(json.dumps({"error": "timeout", "code": 504})) else: - await websocket.send(json.dumps({"data": result, "event": action})) - await asyncio.get_event_loop().run_in_executor(None, ws_q.put, {"data": result, "event": action}) # broadcast + await asyncio.get_event_loop().run_in_executor(None, ws_q.put, {"data": result, "event": action}) elif action == "jingle": result = await get_imc("jingle", msg.get("top", False)) if result is None: await websocket.send(json.dumps({"error": "timeout", "code": 504})) diff --git a/modules/web/index.html b/modules/web/index.html index 533e8ae..794c93e 100644 --- a/modules/web/index.html +++ b/modules/web/index.html @@ -66,7 +66,7 @@ .listbox div.item:hover{background:rgba(255,255,255,0.04); cursor:pointer} .listbox div.item.selected{background:rgba(62, 165, 255, 0.305)} - #section-playlist { flex: 3 1; } + #section-playlist { flex: 2 1; } #section-queue { flex: 1; display: flex; flex-direction: column; } #section-queue .collapsible-content { flex-grow: 1; } #section-queue.collapsed .collapsible-content { display: none; } diff --git a/modules/web/web.js b/modules/web/web.js index a993699..541b17b 100644 --- a/modules/web/web.js +++ b/modules/web/web.js @@ -10,6 +10,8 @@ let selectedSubFile = null; let basePath = ""; let subbasePath = ""; let skipCount = 0; +let indexDigits = 1; +let skipped_idx = []; function toggleSection(id) { document.getElementById(id).classList.toggle('collapsed'); @@ -24,7 +26,7 @@ function initLayout() { if(window.location.protocol === "file:") document.getElementById("whep-url-input").value = "https://webrtc.terminal.tnet/radio/whep" } -function connectWs(){ +function connectWs() { const statusText = document.getElementById("server-status"); statusText.textContent = "connecting..."; @@ -37,6 +39,7 @@ function connectWs(){ reconnectDelay = 1500; ws.send(JSON.stringify({action:"get_toplay"})); ws.send(JSON.stringify({action:"skipc"})); + ws.send(JSON.stringify({action:"skipi"})); }); ws.addEventListener("close", () => { @@ -71,6 +74,7 @@ function handleMessage(msg){ applyTrackState(msg.data); ws.send(JSON.stringify({action:"get_toplay"})); ws.send(JSON.stringify({action:"skipc"})); + ws.send(JSON.stringify({action:"skipi"})); } else if(msg.event === "progress") applyProgressState(msg.data); else if(msg.event === "toplay") { Queue = msg.data.data || []; @@ -81,15 +85,18 @@ function handleMessage(msg){ document.getElementById("skpn-count").textContent = skipCount; renderPlaylist(); renderQueue(); + } else if(msg.event === "skipi") { + skipped_idx = msg.data?.data ?? skipped_idx; + renderPlaylist(); } } -function applyTrackState(payload){ +function applyTrackState(payload) { const track = payload.track || {}; const next = payload.next_track || {}; currentTrackPath = track.path; currentTrackIndex = payload.index; - document.getElementById("now-track").textContent = (track.official ? "(official) " : "(unofficial) ") + track.path.replace(basePath, "").slice(1);; + document.getElementById("now-track").textContent = `${String(currentTrackIndex).padStart(indexDigits,'0')}: ` + (track.official ? "(official) " : "(unofficial) ") + track.path.replace(basePath, "").slice(1);; document.getElementById("next-track").textContent = (next.official ? "(official) " : "(unofficial) ") + next.path.replace(basePath, "").slice(1); renderPlaylist(); } @@ -106,7 +113,7 @@ function applyProgressState(payload) { currentTrackIndex = payload.index; if(track.path){ currentTrackPath = track.path; - document.getElementById("now-track").textContent = (track.official ? "(official) " : "(unofficial) ") + track.path.replace(basePath, "").slice(1); + document.getElementById("now-track").textContent = `${String(currentTrackIndex).padStart(indexDigits,'0')}: ` + (track.official ? "(official) " : "(unofficial) ") + track.path.replace(basePath, "").slice(1); } if(next_track.path) document.getElementById("next-track").textContent = `${next_track.official ? "(official)" : "(unofficial)"} ${next_track.path.replace(basePath, "").slice(1)}`; } @@ -144,7 +151,7 @@ function renderPlaylist() { const ul = document.getElementById("playlist-ul"); ul.innerHTML = ""; let currentIndex = null; - const digits = playlist.length.toString().length + indexDigits = playlist.length.toString().length playlist.forEach((t, i) => { const li = document.createElement("li"); const path = t.path || ""; @@ -155,11 +162,11 @@ function renderPlaylist() { li.addEventListener("click", () => { selectPlaylistItem(i, li); }); if (path === currentTrackPath && i === currentTrackIndex) { li.classList.add("current"); currentIndex = i; } else if (i === currentTrackIndex) { li.classList.add("pointer"); currentIndex = i - 1; } - if(currentIndex !== null && Queue.length === 0 && i > currentIndex && i <= currentIndex + skipCount) - li.style.textDecoration = "line-through"; - li.textContent = ` ${String(i).padStart(digits,'0')}: `; + if(currentIndex !== null && Queue.length === 0 && i > currentIndex && i <= currentIndex + skipCount) li.style.textDecoration = "line-through"; + li.textContent = ` ${String(i).padStart(indexDigits,'0')}: `; li.textContent = (i === currentTrackIndex ? "▶ " : " ") + li.textContent + displayPath; ul.appendChild(li); + if(skipped_idx.includes(i)) li.style.textDecoration = "line-through"; }); if(currentIndex !== null){ const el = ul.children[currentIndex];