From 579e4984c25b9717bfdb34a9d3769468cf2dcc26 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Wed, 29 Apr 2026 22:57:12 +0200 Subject: [PATCH] music box fixes --- basic/scenes/Default_Stream_HUD.json | 8 ++++---- goodbye/index.html | 7 ++++--- loading/index.html | 15 ++++++++------- music-box/index.html | 11 ++++++++--- music-box/nc-music-box.html | 9 ++++++--- music-box/widget.html | 7 ++++--- user.ini | 4 ++-- 7 files changed, 36 insertions(+), 25 deletions(-) diff --git a/basic/scenes/Default_Stream_HUD.json b/basic/scenes/Default_Stream_HUD.json index 5d9a710..c134ca9 100644 --- a/basic/scenes/Default_Stream_HUD.json +++ b/basic/scenes/Default_Stream_HUD.json @@ -536,7 +536,7 @@ "mixers": 255, "sync": 0, "flags": 0, - "volume": 0.64026409387588501, + "volume": 0.20938195288181305, "balance": 0.5, "enabled": true, "muted": false, @@ -2577,7 +2577,7 @@ "id": "scene", "versioned_id": "scene", "settings": { - "id_counter": 7, + "id_counter": 9, "custom_size": false, "items": [ { @@ -2638,7 +2638,7 @@ { "name": "Music Box HUD", "source_uuid": "1b9f5436-864d-4f24-9f92-f45702a23953", - "visible": false, + "visible": true, "locked": false, "rot": 0.0, "scale_ref": { @@ -3716,7 +3716,7 @@ "saved_projectors": [], "preview_locked": false, "scaling_enabled": false, - "scaling_level": -5, + "scaling_level": -12, "scaling_off_x": 0.0, "scaling_off_y": 0.0, "modules": { diff --git a/goodbye/index.html b/goodbye/index.html index 9b29fc4..368736d 100644 --- a/goodbye/index.html +++ b/goodbye/index.html @@ -503,10 +503,10 @@ body { function renderMusicState(s) { if (!npLine) ensureNowPlayingLine(); - if (lastTrackIndex !== null && s.index !== lastTrackIndex) { + if (lastTrackFile !== null && s.file && s.file !== lastTrackFile) { logBeforeNp(`[audio] next: ${s.title || '?'}`); } - lastTrackIndex = s.index; + if (s.file) lastTrackFile = s.file; npLine.querySelector('.np-title').textContent = s.title || '—'; npLine.querySelector('.np-time').textContent = `[${fmtClock(s.currentTime)} / ${fmtClock(s.duration)}]`; @@ -533,7 +533,8 @@ body { if (pendingState) renderMusicState(pendingState); } - let lastTrackIndex = null; + // Dedupe by file URI — see music-box/index.html for the rationale. + let lastTrackFile = null; async function connectMusic() { if (!window.__OBSWS) { logBeforeNp('[audio] vendor/obs-config.js missing — run scripts/setup.sh', 'term-dim'); diff --git a/loading/index.html b/loading/index.html index 1432f4c..060cfba 100644 --- a/loading/index.html +++ b/loading/index.html @@ -92,8 +92,8 @@ body { .terminal { width: 60vw; max-width: 1380px; - height: 58vh; - max-height: 740px; + height: 62vh; + max-height: 820px; min-height: 400px; position: relative; overflow: hidden; @@ -514,10 +514,10 @@ body { function renderMusicState(s) { if (!npLine) ensureNowPlayingLine(); - if (lastTrackIndex !== null && s.index !== lastTrackIndex) { + if (lastTrackFile !== null && s.file && s.file !== lastTrackFile) { logBeforeNp(`[audio] next: ${s.title || '?'}`); } - lastTrackIndex = s.index; + if (s.file) lastTrackFile = s.file; npLine.querySelector('.np-title').textContent = s.title || '—'; npLine.querySelector('.np-time').textContent = `[${fmtClock(s.currentTime)} / ${fmtClock(s.duration)}]`; @@ -537,9 +537,9 @@ body { append('> ', `[audio] indexed ${allTracks.length} tracks`, 'term-out'); await sleep(180); - append('> ', '[audio] connecting to daemon on ws://localhost:4455', 'term-out'); + append('> ', `[audio] uplink to daemon @ ophi-118://${rigName.toLowerCase()}.audio.bus`, 'term-out'); await sleep(180); - append('> ', '[audio] subscribing to mpd:state events', 'term-out'); + append('> ', '[audio] chat ops armed :: !skip · !queue · !info', 'term-out'); await sleep(180); append('> ', '[audio] standby for transmission ✓', 'term-out'); bootFinished = true; @@ -547,7 +547,8 @@ body { } // Connect to OBS WebSocket and listen for daemon broadcasts. - let lastTrackIndex = null; + // Dedupe by file URI — see music-box/index.html for the rationale. + let lastTrackFile = null; async function connectMusic() { if (!window.__OBSWS) { logBeforeNp('[audio] vendor/obs-config.js missing — run scripts/setup.sh', 'term-dim'); diff --git a/music-box/index.html b/music-box/index.html index aeefaa0..92e42ae 100644 --- a/music-box/index.html +++ b/music-box/index.html @@ -465,12 +465,17 @@ body { } // ── State application ── - let lastTrackIndex = null; + // Dedupe by file URI, not s.index. MPD's status.song (s.index) is the + // queue position and shifts mid-playback when the queue is reordered + // (consume mode removes the prior track → later indices shift down, + // mpc shuffle reshuffles, etc.) — using it caused duplicate "now: …" + // lines for a single playthrough. + let lastTrackFile = null; function applyState(s) { - if (lastTrackIndex !== null && s.index !== lastTrackIndex && s.title) { + if (lastTrackFile !== null && s.file && s.file !== lastTrackFile && s.title) { logBeforePins(`[audio] now: ${s.title}`); } - lastTrackIndex = s.index; + if (s.file) lastTrackFile = s.file; npTitle.textContent = s.title || '—'; npTime.textContent = `[${fmtClock(s.currentTime)} / ${fmtClock(s.duration)}]`; diff --git a/music-box/nc-music-box.html b/music-box/nc-music-box.html index 142e530..630c77d 100644 --- a/music-box/nc-music-box.html +++ b/music-box/nc-music-box.html @@ -662,10 +662,10 @@ body { } function renderState(s) { - if (lastTrackIndex !== null && s.index !== lastTrackIndex && s.title) { + if (lastTrackFile !== null && s.file && s.file !== lastTrackFile && s.title) { logBeforePins(`[audio] now: ${s.title}`); } - lastTrackIndex = s.index; + if (s.file) lastTrackFile = s.file; // Terminal pinned block npTitle.textContent = s.title || '—'; @@ -829,7 +829,10 @@ body { } // ── State application ── - let lastTrackIndex = null; + // Dedupe by file URI, not s.index — MPD's status.song shifts mid-playback + // when the queue is reordered (consume mode, mpc shuffle, etc.), which + // would otherwise cause duplicate "now: …" lines for one playthrough. + let lastTrackFile = null; function applyState(s) { pendingState = s; if (!bootStarted) { diff --git a/music-box/widget.html b/music-box/widget.html index d56805f..43d0f1d 100644 --- a/music-box/widget.html +++ b/music-box/widget.html @@ -249,12 +249,13 @@ body { pruneTerminal(); } - let lastTrackIndex = null; + // Dedupe by file URI, not s.index — see music-box/index.html for context. + let lastTrackFile = null; function applyState(s) { - if (lastTrackIndex !== null && s.index !== lastTrackIndex && s.title) { + if (lastTrackFile !== null && s.file && s.file !== lastTrackFile && s.title) { logBeforePins(`[audio] now: ${s.title}`); } - lastTrackIndex = s.index; + if (s.file) lastTrackFile = s.file; npTitle.textContent = s.title || '—'; npTime.textContent = `[${fmtClock(s.currentTime)} / ${fmtClock(s.duration)}]`; diff --git a/user.ini b/user.ini index 8ae5861..ab85505 100644 --- a/user.ini +++ b/user.ini @@ -25,8 +25,8 @@ cx=720 cy=580 [BasicWindow] -geometry=AdnQywADAAAAAAAAAAAAAAAACf8AAAVDAAAGPwAAABkAAAn+AAAEFgAAAAECAAAACgAAAAAAAAAAAAAACf8AAAVD -DockState=AAAA/wAAAAD9AAAAAQAAAAMAAAoAAAABA/wBAAAABvsAAAAUAHMAYwBlAG4AZQBzAEQAbwBjAGsBAAAAAAAAAdgAAACYAP////sAAAAWAHMAbwB1AHIAYwBlAHMARABvAGMAawEAAAHcAAAB1QAAAJgA////+wAAABIAbQBpAHgAZQByAEQAbwBjAGsBAAADtQAAAroAAAECAP////sAAAAeAHQAcgBhAG4AcwBpAHQAaQBvAG4AcwBEAG8AYwBrAQAABnMAAAHSAAAArQD////7AAAAGABjAG8AbgB0AHIAbwBsAHMARABvAGMAawEAAAhJAAABtwAAAKIA////+wAAABIAcwB0AGEAdABzAEQAbwBjAGsCAAAExAAAAXAAAAK8AAAAyAAACgAAAAQBAAAABAAAAAQAAAAIAAAACPwAAAAA +geometry=AdnQywADAAAAAAoAAAAAAAAAEX8AAAQDAAAKAAAAAAAAAA2/AAAD/QAAAAACAAAAB4AAAAoAAAAAAAAAEX8AAAQD +DockState=AAAA/wAAAAD9AAAAAQAAAAMAAAeAAAABA/wBAAAABvsAAAAUAHMAYwBlAG4AZQBzAEQAbwBjAGsBAAAAAAAAAWEAAACYAP////sAAAAWAHMAbwB1AHIAYwBlAHMARABvAGMAawEAAAFlAAABXwAAAJgA////+wAAABIAbQBpAHgAZQByAEQAbwBjAGsBAAACyAAAAgoAAAECAP////sAAAAeAHQAcgBhAG4AcwBpAHQAaQBvAG4AcwBEAG8AYwBrAQAABNYAAAFdAAAArQD////7AAAAGABjAG8AbgB0AHIAbwBsAHMARABvAGMAawEAAAY3AAABSQAAAKIA////+wAAABIAcwB0AGEAdABzAEQAbwBjAGsCAAAExAAAAXAAAAK8AAAAyAAAB4AAAALBAAAABAAAAAQAAAAIAAAACPwAAAAA PreviewEnabled=true AlwaysOnTop=false SceneDuplicationMode=true