From 1f320d9771bac2780e5a09d6a3bc063b35cf58de Mon Sep 17 00:00:00 2001 From: salmonik Date: Tue, 5 May 2026 21:37:44 +0200 Subject: fix(audio): resolve deadlock preventing auto-advance to next track The audio callback deadlocked when trying to lock audio_data twice, preventing track_ended from being set and breaking auto-advance. Also removed erroneous track_ended.store(true) calls from error paths that were causing incorrect queue advancement when playback failed. --- src/daemon.rs | 47 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) (limited to 'src/daemon.rs') diff --git a/src/daemon.rs b/src/daemon.rs index 8ac3a89..9fa5cea 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -150,18 +150,57 @@ pub fn start_daemon() -> Result<(), Box> { // Accept connections until shutdown listener.set_nonblocking(true)?; + // Helper: poll until a specific track actually starts playing or timeout + fn wait_for_start(audio: &AudioEngine, target: &PathBuf, timeout_ms: u64) -> bool { + use std::time::{Duration, Instant}; + let start = Instant::now(); + while start.elapsed() < Duration::from_millis(timeout_ms) { + // If playing and the current track matches, assume started + if audio.is_playing() { + if let Some(cur) = audio.current_track() { + if &cur == target { + return true; + } + } + } + std::thread::sleep(Duration::from_millis(10)); + } + false + } loop { // Check for shutdown signal if shutdown_flag.load(Ordering::SeqCst) { break; } - // Check if track ended and play next + // Check if track ended and play next (robust with startup feedback) if audio_engine.poll_track_ended() { if let Ok(mut q) = queue.lock() { - if let Some(next_track) = q.next() { - audio_engine.play(next_track); - } else { + // Save the current position in case we need to revert + let original_position = q.position; + // Try a handful of next candidates until one starts + let mut started = false; + // We'll attempt up to 4 candidates ahead + let max_trials = 4usize; + for _ in 0..max_trials { + if let Some(next_track) = q.next() { + audio_engine.play(next_track.clone()); + // Wait a short time to see if playback actually starts + if wait_for_start(&audio_engine, &next_track, 500) { + started = true; + break; + } else { + // Try next candidate - q.next() already advanced position + continue; + } + } else { + break; + } + } + if !started { + // Revert position since we couldn't start any track + q.position = original_position; + // No candidate started; stop playback safely audio_engine.stop(); } } -- cgit v1.2.3