[fix](trx-server): pause audio playback stream when idle

Start the output stream paused and only play when TX packets
arrive. Pause again when the packet queue drains to prevent
continuous ALSA buffer underruns (EPIPE errno -32) on Linux.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
This commit is contained in:
2026-02-08 13:07:28 +01:00
parent 22482a34c3
commit ee7f0360fb
+21 -2
View File
@@ -224,12 +224,19 @@ fn run_playback(
None, None,
)?; )?;
stream.play()?; // Start paused — only play when TX packets arrive
info!("Audio playback: started"); info!("Audio playback: ready ({}Hz, {} ch)", sample_rate, channels);
let mut pcm_buf = vec![0f32; frame_samples]; let mut pcm_buf = vec![0f32; frame_samples];
let mut playing = false;
while let Some(packet) = rx.blocking_recv() { while let Some(packet) = rx.blocking_recv() {
if !playing {
stream.play()?;
playing = true;
info!("Audio playback: started");
}
match decoder.decode_float(&packet, &mut pcm_buf, false) { match decoder.decode_float(&packet, &mut pcm_buf, false) {
Ok(decoded) => { Ok(decoded) => {
let mut ring = ring_writer.lock().unwrap(); let mut ring = ring_writer.lock().unwrap();
@@ -239,6 +246,18 @@ fn run_playback(
warn!("Opus decode error: {}", e); warn!("Opus decode error: {}", e);
} }
} }
// Pause when no more packets are queued to avoid ALSA underruns
if rx.is_empty() {
// Drain remaining samples before pausing
std::thread::sleep(std::time::Duration::from_millis(frame_duration_ms as u64 * 2));
if rx.is_empty() {
let _ = stream.pause();
playing = false;
ring_writer.lock().unwrap().clear();
info!("Audio playback: paused (idle)");
}
}
} }
Ok(()) Ok(())