fix: skip CoreBridge actions for echo SET_STATE commands

The server echoes every state report as a SET_STATE with only next_track
(playing_state=null, current_track=null). These echoes were triggering
align_corebridge_queue_cursor which uses the accumulated renderer state
current_track (from a different context, e.g. iOS). When the track
wasn't found in the local queue, it replaced the entire queue with a
single track, destroying the user's loaded queue.

Now echo SET_STATE commands are detected early and only update the
internal renderer state (for next_track tracking). CoreBridge actions
(align cursor, load track, play/pause) and state reports are skipped
entirely for these echoes.
This commit is contained in:
vicrodh committed 2026-02-22 16:58:45 -06:00
1 parent f6506cd4ea
commit 633c755d3b
1 file changed
+22
+22
View File
@@ -313,16 +313,38 @@ where
return Ok(());
};
// Detect echo SET_STATE commands: the server echoes every state report
// as a SET_STATE with only next_track (playing_state=None, current_track=None).
// These echoes must NOT trigger CoreBridge actions (align cursor, load track,
// resume/pause) or state reports, otherwise they destroy the local queue
// and cause feedback loops.
let is_echo = matches!(
&renderer_command,
RendererCommand::SetState {
playing_state,
current_track,
..
} if playing_state.is_none() && current_track.is_none()
);
let (snapshot, queue_version) = {
let mut state = self.state.lock().await;
apply_renderer_command(&mut state.renderer, &renderer_command, now_ms());
(state.renderer.clone(), state.queue.version)
};
// Always update renderer state (for tracking next_track etc.)
self.sink
.on_event(QconnectAppEvent::RendererUpdated(snapshot.clone()))
.await;
if is_echo {
log::debug!(
"[QConnect] Skipping echo SET_STATE (no playing_state or current_track)"
);
return Ok(());
}
self.sink
.on_event(QconnectAppEvent::RendererCommandApplied {
command: renderer_command.clone(),