From e08598e7e2526b65fd8790a49794c1d4d00945d0 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 26 Apr 2018 10:31:22 +0200 Subject: [PATCH] output/alsa: don't submit silence if PCM is not yet running See code comment. Closes #260 --- src/output/plugins/AlsaOutputPlugin.cxx | 31 ++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx index b7c9f256d..dfd843da9 100644 --- a/src/output/plugins/AlsaOutputPlugin.cxx +++ b/src/output/plugins/AlsaOutputPlugin.cxx @@ -922,10 +922,39 @@ try { CopyRingToPeriodBuffer(); - if (period_buffer.IsEmpty()) + if (period_buffer.IsEmpty()) { + if (snd_pcm_state(pcm) == SND_PCM_STATE_PREPARED) { + /* at SND_PCM_STATE_PREPARED (not yet switched + to SND_PCM_STATE_RUNNING), we have no + pressure to fill the ALSA buffer, because + no xrun can possibly occur; and if no data + is available right now, we can easily wait + until some is available; so we just stop + monitoring the ALSA file descriptor, and + let it be reactivated by Play()/Activate() + whenever more data arrives */ + + { + const std::lock_guard lock(mutex); + active = false; + } + + /* avoid race condition: see if data has + arrived meanwhile before disabling the + event (but after clearing the "active" + flag) */ + if (!CopyRingToPeriodBuffer()) { + MultiSocketMonitor::Reset(); + defer_invalidate_sockets.Cancel(); + } + + return; + } + /* insert some silence if the buffer has not enough data yet, to avoid ALSA xrun */ period_buffer.FillWithSilence(silence, out_frame_size); + } auto frames_written = WriteFromPeriodBuffer(); if (frames_written < 0) {