music box fixes
This commit is contained in:
@@ -536,7 +536,7 @@
|
|||||||
"mixers": 255,
|
"mixers": 255,
|
||||||
"sync": 0,
|
"sync": 0,
|
||||||
"flags": 0,
|
"flags": 0,
|
||||||
"volume": 0.64026409387588501,
|
"volume": 0.20938195288181305,
|
||||||
"balance": 0.5,
|
"balance": 0.5,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"muted": false,
|
"muted": false,
|
||||||
@@ -2577,7 +2577,7 @@
|
|||||||
"id": "scene",
|
"id": "scene",
|
||||||
"versioned_id": "scene",
|
"versioned_id": "scene",
|
||||||
"settings": {
|
"settings": {
|
||||||
"id_counter": 7,
|
"id_counter": 9,
|
||||||
"custom_size": false,
|
"custom_size": false,
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
@@ -2638,7 +2638,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Music Box HUD",
|
"name": "Music Box HUD",
|
||||||
"source_uuid": "1b9f5436-864d-4f24-9f92-f45702a23953",
|
"source_uuid": "1b9f5436-864d-4f24-9f92-f45702a23953",
|
||||||
"visible": false,
|
"visible": true,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"rot": 0.0,
|
"rot": 0.0,
|
||||||
"scale_ref": {
|
"scale_ref": {
|
||||||
@@ -3716,7 +3716,7 @@
|
|||||||
"saved_projectors": [],
|
"saved_projectors": [],
|
||||||
"preview_locked": false,
|
"preview_locked": false,
|
||||||
"scaling_enabled": false,
|
"scaling_enabled": false,
|
||||||
"scaling_level": -5,
|
"scaling_level": -12,
|
||||||
"scaling_off_x": 0.0,
|
"scaling_off_x": 0.0,
|
||||||
"scaling_off_y": 0.0,
|
"scaling_off_y": 0.0,
|
||||||
"modules": {
|
"modules": {
|
||||||
|
|||||||
@@ -503,10 +503,10 @@ body {
|
|||||||
|
|
||||||
function renderMusicState(s) {
|
function renderMusicState(s) {
|
||||||
if (!npLine) ensureNowPlayingLine();
|
if (!npLine) ensureNowPlayingLine();
|
||||||
if (lastTrackIndex !== null && s.index !== lastTrackIndex) {
|
if (lastTrackFile !== null && s.file && s.file !== lastTrackFile) {
|
||||||
logBeforeNp(`[audio] next: ${s.title || '?'}`);
|
logBeforeNp(`[audio] next: ${s.title || '?'}`);
|
||||||
}
|
}
|
||||||
lastTrackIndex = s.index;
|
if (s.file) lastTrackFile = s.file;
|
||||||
npLine.querySelector('.np-title').textContent = s.title || '—';
|
npLine.querySelector('.np-title').textContent = s.title || '—';
|
||||||
npLine.querySelector('.np-time').textContent =
|
npLine.querySelector('.np-time').textContent =
|
||||||
`[${fmtClock(s.currentTime)} / ${fmtClock(s.duration)}]`;
|
`[${fmtClock(s.currentTime)} / ${fmtClock(s.duration)}]`;
|
||||||
@@ -533,7 +533,8 @@ body {
|
|||||||
if (pendingState) renderMusicState(pendingState);
|
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() {
|
async function connectMusic() {
|
||||||
if (!window.__OBSWS) {
|
if (!window.__OBSWS) {
|
||||||
logBeforeNp('[audio] vendor/obs-config.js missing — run scripts/setup.sh', 'term-dim');
|
logBeforeNp('[audio] vendor/obs-config.js missing — run scripts/setup.sh', 'term-dim');
|
||||||
|
|||||||
@@ -92,8 +92,8 @@ body {
|
|||||||
.terminal {
|
.terminal {
|
||||||
width: 60vw;
|
width: 60vw;
|
||||||
max-width: 1380px;
|
max-width: 1380px;
|
||||||
height: 58vh;
|
height: 62vh;
|
||||||
max-height: 740px;
|
max-height: 820px;
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -514,10 +514,10 @@ body {
|
|||||||
|
|
||||||
function renderMusicState(s) {
|
function renderMusicState(s) {
|
||||||
if (!npLine) ensureNowPlayingLine();
|
if (!npLine) ensureNowPlayingLine();
|
||||||
if (lastTrackIndex !== null && s.index !== lastTrackIndex) {
|
if (lastTrackFile !== null && s.file && s.file !== lastTrackFile) {
|
||||||
logBeforeNp(`[audio] next: ${s.title || '?'}`);
|
logBeforeNp(`[audio] next: ${s.title || '?'}`);
|
||||||
}
|
}
|
||||||
lastTrackIndex = s.index;
|
if (s.file) lastTrackFile = s.file;
|
||||||
npLine.querySelector('.np-title').textContent = s.title || '—';
|
npLine.querySelector('.np-title').textContent = s.title || '—';
|
||||||
npLine.querySelector('.np-time').textContent =
|
npLine.querySelector('.np-time').textContent =
|
||||||
`[${fmtClock(s.currentTime)} / ${fmtClock(s.duration)}]`;
|
`[${fmtClock(s.currentTime)} / ${fmtClock(s.duration)}]`;
|
||||||
@@ -537,9 +537,9 @@ body {
|
|||||||
|
|
||||||
append('> ', `[audio] indexed ${allTracks.length} tracks`, 'term-out');
|
append('> ', `[audio] indexed ${allTracks.length} tracks`, 'term-out');
|
||||||
await sleep(180);
|
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);
|
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);
|
await sleep(180);
|
||||||
append('> ', '[audio] standby for transmission ✓', 'term-out');
|
append('> ', '[audio] standby for transmission ✓', 'term-out');
|
||||||
bootFinished = true;
|
bootFinished = true;
|
||||||
@@ -547,7 +547,8 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Connect to OBS WebSocket and listen for daemon broadcasts.
|
// 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() {
|
async function connectMusic() {
|
||||||
if (!window.__OBSWS) {
|
if (!window.__OBSWS) {
|
||||||
logBeforeNp('[audio] vendor/obs-config.js missing — run scripts/setup.sh', 'term-dim');
|
logBeforeNp('[audio] vendor/obs-config.js missing — run scripts/setup.sh', 'term-dim');
|
||||||
|
|||||||
@@ -465,12 +465,17 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── State application ──
|
// ── 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) {
|
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}`);
|
logBeforePins(`[audio] now: ${s.title}`);
|
||||||
}
|
}
|
||||||
lastTrackIndex = s.index;
|
if (s.file) lastTrackFile = s.file;
|
||||||
|
|
||||||
npTitle.textContent = s.title || '—';
|
npTitle.textContent = s.title || '—';
|
||||||
npTime.textContent = `[${fmtClock(s.currentTime)} / ${fmtClock(s.duration)}]`;
|
npTime.textContent = `[${fmtClock(s.currentTime)} / ${fmtClock(s.duration)}]`;
|
||||||
|
|||||||
@@ -662,10 +662,10 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderState(s) {
|
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}`);
|
logBeforePins(`[audio] now: ${s.title}`);
|
||||||
}
|
}
|
||||||
lastTrackIndex = s.index;
|
if (s.file) lastTrackFile = s.file;
|
||||||
|
|
||||||
// Terminal pinned block
|
// Terminal pinned block
|
||||||
npTitle.textContent = s.title || '—';
|
npTitle.textContent = s.title || '—';
|
||||||
@@ -829,7 +829,10 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── State application ──
|
// ── 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) {
|
function applyState(s) {
|
||||||
pendingState = s;
|
pendingState = s;
|
||||||
if (!bootStarted) {
|
if (!bootStarted) {
|
||||||
|
|||||||
@@ -249,12 +249,13 @@ body {
|
|||||||
pruneTerminal();
|
pruneTerminal();
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastTrackIndex = null;
|
// Dedupe by file URI, not s.index — see music-box/index.html for context.
|
||||||
|
let lastTrackFile = null;
|
||||||
function applyState(s) {
|
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}`);
|
logBeforePins(`[audio] now: ${s.title}`);
|
||||||
}
|
}
|
||||||
lastTrackIndex = s.index;
|
if (s.file) lastTrackFile = s.file;
|
||||||
|
|
||||||
npTitle.textContent = s.title || '—';
|
npTitle.textContent = s.title || '—';
|
||||||
npTime.textContent = `[${fmtClock(s.currentTime)} / ${fmtClock(s.duration)}]`;
|
npTime.textContent = `[${fmtClock(s.currentTime)} / ${fmtClock(s.duration)}]`;
|
||||||
|
|||||||
4
user.ini
4
user.ini
@@ -25,8 +25,8 @@ cx=720
|
|||||||
cy=580
|
cy=580
|
||||||
|
|
||||||
[BasicWindow]
|
[BasicWindow]
|
||||||
geometry=AdnQywADAAAAAAAAAAAAAAAACf8AAAVDAAAGPwAAABkAAAn+AAAEFgAAAAECAAAACgAAAAAAAAAAAAAACf8AAAVD
|
geometry=AdnQywADAAAAAAoAAAAAAAAAEX8AAAQDAAAKAAAAAAAAAA2/AAAD/QAAAAACAAAAB4AAAAoAAAAAAAAAEX8AAAQD
|
||||||
DockState=AAAA/wAAAAD9AAAAAQAAAAMAAAoAAAABA/wBAAAABvsAAAAUAHMAYwBlAG4AZQBzAEQAbwBjAGsBAAAAAAAAAdgAAACYAP////sAAAAWAHMAbwB1AHIAYwBlAHMARABvAGMAawEAAAHcAAAB1QAAAJgA////+wAAABIAbQBpAHgAZQByAEQAbwBjAGsBAAADtQAAAroAAAECAP////sAAAAeAHQAcgBhAG4AcwBpAHQAaQBvAG4AcwBEAG8AYwBrAQAABnMAAAHSAAAArQD////7AAAAGABjAG8AbgB0AHIAbwBsAHMARABvAGMAawEAAAhJAAABtwAAAKIA////+wAAABIAcwB0AGEAdABzAEQAbwBjAGsCAAAExAAAAXAAAAK8AAAAyAAACgAAAAQBAAAABAAAAAQAAAAIAAAACPwAAAAA
|
DockState=AAAA/wAAAAD9AAAAAQAAAAMAAAeAAAABA/wBAAAABvsAAAAUAHMAYwBlAG4AZQBzAEQAbwBjAGsBAAAAAAAAAWEAAACYAP////sAAAAWAHMAbwB1AHIAYwBlAHMARABvAGMAawEAAAFlAAABXwAAAJgA////+wAAABIAbQBpAHgAZQByAEQAbwBjAGsBAAACyAAAAgoAAAECAP////sAAAAeAHQAcgBhAG4AcwBpAHQAaQBvAG4AcwBEAG8AYwBrAQAABNYAAAFdAAAArQD////7AAAAGABjAG8AbgB0AHIAbwBsAHMARABvAGMAawEAAAY3AAABSQAAAKIA////+wAAABIAcwB0AGEAdABzAEQAbwBjAGsCAAAExAAAAXAAAAK8AAAAyAAAB4AAAALBAAAABAAAAAQAAAAIAAAACPwAAAAA
|
||||||
PreviewEnabled=true
|
PreviewEnabled=true
|
||||||
AlwaysOnTop=false
|
AlwaysOnTop=false
|
||||||
SceneDuplicationMode=true
|
SceneDuplicationMode=true
|
||||||
|
|||||||
Reference in New Issue
Block a user