output/alsa: work around dmix non-blocking snd_pcm_drain() bug
See code comment. Bug was reported against MPD, but it's really an alsa-lib bug. https://bugs.musicpd.org/view.php?id=4662
This commit is contained in:
parent
b4e4bdcda9
commit
f85d4d28d1
|
@ -20,6 +20,7 @@
|
|||
#include "config.h"
|
||||
#include "AlsaOutputPlugin.hxx"
|
||||
#include "lib/alsa/NonBlock.hxx"
|
||||
#include "lib/alsa/Version.hxx"
|
||||
#include "../OutputAPI.hxx"
|
||||
#include "../Wrapper.hxx"
|
||||
#include "mixer/MixerList.hxx"
|
||||
|
@ -107,6 +108,17 @@ class AlsaOutput final
|
|||
*/
|
||||
snd_pcm_uframes_t period_frames;
|
||||
|
||||
/**
|
||||
* Is this a buggy alsa-lib version, which needs a workaround
|
||||
* for the snd_pcm_drain() bug always returning -EAGAIN? See
|
||||
* alsa-lib commits fdc898d41135 and e4377b16454f for details.
|
||||
* This bug was fixed in alsa-lib version 1.1.4.
|
||||
*
|
||||
* The workaround is to re-enable blocking mode for the
|
||||
* snd_pcm_drain() call.
|
||||
*/
|
||||
bool work_around_drain_bug;
|
||||
|
||||
/**
|
||||
* After Open(), has this output been activated by a Play()
|
||||
* command?
|
||||
|
@ -988,6 +1000,19 @@ AlsaOutput::SetupOrDop(AudioFormat &audio_format, PcmExport::Params ¶ms)
|
|||
#endif
|
||||
}
|
||||
|
||||
static constexpr bool
|
||||
MaybeDmix(snd_pcm_type_t type)
|
||||
{
|
||||
return type == SND_PCM_TYPE_DMIX || type == SND_PCM_TYPE_PLUG;
|
||||
}
|
||||
|
||||
gcc_pure
|
||||
static bool
|
||||
MaybeDmix(snd_pcm_t *pcm)
|
||||
{
|
||||
return MaybeDmix(snd_pcm_type(pcm));
|
||||
}
|
||||
|
||||
inline void
|
||||
AlsaOutput::Open(AudioFormat &audio_format)
|
||||
{
|
||||
|
@ -1012,6 +1037,9 @@ AlsaOutput::Open(AudioFormat &audio_format)
|
|||
GetDevice()));
|
||||
}
|
||||
|
||||
work_around_drain_bug = MaybeDmix(pcm) &&
|
||||
GetRuntimeAlsaVersion() < MakeAlsaVersion(1, 1, 4);
|
||||
|
||||
snd_pcm_nonblock(pcm, 1);
|
||||
|
||||
#ifdef ENABLE_DSD
|
||||
|
@ -1117,6 +1145,14 @@ AlsaOutput::DrainInternal()
|
|||
}
|
||||
|
||||
/* .. and finally drain the ALSA hardware buffer */
|
||||
|
||||
if (work_around_drain_bug) {
|
||||
snd_pcm_nonblock(pcm, 0);
|
||||
bool result = snd_pcm_drain(pcm) != -EAGAIN;
|
||||
snd_pcm_nonblock(pcm, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
return snd_pcm_drain(pcm) != -EAGAIN;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue