fix: prevent ALSA device lock on streaming failure, add Drop for PlaybackEngine

Add Drop impl to PlaybackEngine so the ALSA Direct writer thread is
properly stopped when the engine is dropped (e.g. streaming timeout).
Previously, a failed streaming attempt would orphan the writer thread,
keeping the ALSA device locked and blocking all subsequent playback.

Also force HTTP/1.1 for audio downloads and add detailed error chain
logging to diagnose persistent "error decoding response body" failures
for specific tracks.
This commit is contained in:
vicrodh committed 2026-03-11 20:15:11 -06:00
1 parent be2e2956f8
commit d02090f30d
2 files changed
+46 -15

No files matched your search

@@ -199,8 +199,15 @@ impl PlaybackEngine {
}
}
/// Stop
pub fn stop(self) {
/// Stop playback and release resources.
/// For ALSA Direct, signals the writer thread and waits for it to exit.
/// The Drop impl handles the same cleanup if stop() is not called explicitly.
pub fn stop(mut self) {
self.stop_inner();
}
/// Internal stop logic shared by stop() and Drop
fn stop_inner(&mut self) {
match self {
Self::Rodio { sink } => {
sink.stop();
@@ -212,11 +219,14 @@ impl PlaybackEngine {
playback_thread,
..
} => {
if should_stop.load(Ordering::SeqCst) {
return; // Already stopped
}
log::info!("[ALSA Direct Engine] Stop requested");
should_stop.store(true, Ordering::SeqCst);
is_playing.store(false, Ordering::SeqCst);
if let Some(handle) = playback_thread {
if let Some(handle) = playback_thread.take() {
let _ = handle.join();
}
@@ -424,3 +434,9 @@ fn alsa_writer_thread(
is_playing.store(false, Ordering::SeqCst);
log::info!("[ALSA Direct Engine] Writer thread finished");
}
impl Drop for PlaybackEngine {
fn drop(&mut self) {
self.stop_inner();
}
}