diff options
author | Max Kellermann <max@musicpd.org> | 2019-06-28 08:55:23 +0200 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2019-06-28 08:55:25 +0200 |
commit | 543776d9c94763a6870511ed569df2fd7eda1577 (patch) | |
tree | 885fdf053a7049ed292bc78f3771b8f18798ca08 /src | |
parent | 8bf3f9b87437e2969b50a8d1bcb380678a5ad58c (diff) |
output/alsa: check PCM state before calling snd_pcm_drain()
Apparently, if snd_pcm_drain() returns EAGAIN, it does not actually
want to be called again; the next call will snd_pcm_drain() will also
return EAGAIN, forever, even though the PCM state has meanwhile
switched to SND_PCM_STATE_SETUP. This causes a busy loop; to fix
this, we should always check snd_pcm_state() to see if draining is
really required.
Diffstat (limited to 'src')
-rw-r--r-- | src/output/plugins/AlsaOutputPlugin.cxx | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx index 8f32cf8d7..eefb7f467 100644 --- a/src/output/plugins/AlsaOutputPlugin.cxx +++ b/src/output/plugins/AlsaOutputPlugin.cxx @@ -774,6 +774,24 @@ AlsaOutput::DrainInternal() don't need to drain it */ return true; + switch (snd_pcm_state(pcm)) { + case SND_PCM_STATE_PREPARED: + case SND_PCM_STATE_RUNNING: + /* these states require a call to snd_pcm_drain() */ + break; + + case SND_PCM_STATE_DRAINING: + /* already draining, but not yet finished; this is + probably a spurious epoll event, and we should wait + for the next one */ + return false; + + default: + /* all other states cannot be drained, and we're + done */ + return true; + } + /* .. and finally drain the ALSA hardware buffer */ int result; |