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 "config.h"
|
||||||
#include "AlsaOutputPlugin.hxx"
|
#include "AlsaOutputPlugin.hxx"
|
||||||
#include "lib/alsa/NonBlock.hxx"
|
#include "lib/alsa/NonBlock.hxx"
|
||||||
|
#include "lib/alsa/Version.hxx"
|
||||||
#include "../OutputAPI.hxx"
|
#include "../OutputAPI.hxx"
|
||||||
#include "../Wrapper.hxx"
|
#include "../Wrapper.hxx"
|
||||||
#include "mixer/MixerList.hxx"
|
#include "mixer/MixerList.hxx"
|
||||||
|
@ -107,6 +108,17 @@ class AlsaOutput final
|
||||||
*/
|
*/
|
||||||
snd_pcm_uframes_t period_frames;
|
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()
|
* After Open(), has this output been activated by a Play()
|
||||||
* command?
|
* command?
|
||||||
|
@ -988,6 +1000,19 @@ AlsaOutput::SetupOrDop(AudioFormat &audio_format, PcmExport::Params ¶ms)
|
||||||
#endif
|
#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
|
inline void
|
||||||
AlsaOutput::Open(AudioFormat &audio_format)
|
AlsaOutput::Open(AudioFormat &audio_format)
|
||||||
{
|
{
|
||||||
|
@ -1012,6 +1037,9 @@ AlsaOutput::Open(AudioFormat &audio_format)
|
||||||
GetDevice()));
|
GetDevice()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
work_around_drain_bug = MaybeDmix(pcm) &&
|
||||||
|
GetRuntimeAlsaVersion() < MakeAlsaVersion(1, 1, 4);
|
||||||
|
|
||||||
snd_pcm_nonblock(pcm, 1);
|
snd_pcm_nonblock(pcm, 1);
|
||||||
|
|
||||||
#ifdef ENABLE_DSD
|
#ifdef ENABLE_DSD
|
||||||
|
@ -1117,6 +1145,14 @@ AlsaOutput::DrainInternal()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .. and finally drain the ALSA hardware buffer */
|
/* .. 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;
|
return snd_pcm_drain(pcm) != -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue