This function is sparsely documented and a look at the bluez-alsa
source code shows that implementations make undocumented assumptions
on the `struct pollfd` array parameter which can lead to strange
effects.
Since we switched from autotools to Meson in commit
94592c1406, we don't need to include
`config.h` early to properly enable large file support. Meson passes
the required macros on the compiler command line instead of defining
them in `config.h`.
This means we can include `config.h` at any time, whenever we want to
check its macros, and there are no ordering constraints.
Works around a problem where MPD goes into a busy loop because
snd_pcm_drain() always returns `-EAGAIN` without making any progress
(fixes#425).
This problem was triggered by snd_pcm_drain() after snd_pcm_cancel()
and snd_pcm_prepare(), but without submitting any data with
snd_pcm_writei().
I believe this is a kernel bug: in non-blocking mode, the kernel's
snd_pcm_drain() function returns early. In this mode, it only checks
whether snd_pcm_drain_done() has been called already, but
snd_pcm_drain_done() is never called if no data was submitted.
In blocking mode, the following `for` loop detects this condition, so
snd_pcm_drain_done() is not necessary, but without this extra check,
we get `-EAGAIN` forever.
This fixes a problem which caused a failure with snd_pcm_writei()
because snd_pcm_drain() had already been called in the previous
iteration. This commit makes sure that snd_pcm_drain() is only called
after the final snd_pcm_writei() call.
This fixes discarded samples at the end of playback.
MPD's default is 100ms, which is too long for the real-time I/O
thread. The OutputThread has 100us, but the real-time I/O thread
might have tighter deadlines.
This change has currently no effect (I believe), because nobody uses
timers on the RTIO thread.
If our `ring_buffer` is smaller than the ALSA-PCM buffer (if the
latter has more than the 4 periods we allocate), it can happen that
the start threshold is crossed and ALSA switches to
`SND_PCM_STATE_RUNNING`, but the `ring_buffer` is empty. In this
case, MPDD will generate silence, even though the ALSA-PCM buffer has
enough data. This causes stuttering (#420).
This commit amends an older workaround for a similar problem (commit
e08598e7e2) by adding a snd_pcm_avail()
check, and only generate silence if there is less than one period of
data in the ALSA-PCM buffer.
Fixes#420
The method Cancel() assumes that the `period_buffer` must be empty
when `active==false`, but that is not the case when Play() fails.
Of course the assertion in Cancel() is not 100% correct, but I decided
to rather fix this in LockCaughtError() because the `period_buffer`
should only be accessed from within the RTIO thread, and this is the
only code path where `active` can be set to `false` with a non-empty
`period_buffer`.
Fixes#423
This check was added 9 years ago in commit
4dc25d3908 to work around a dmix bug
which I assume has been fixed long ago.
Removing this fixes another corner case: if draining is requested
before the start threshold is reached, the PCM is still in
SND_PCM_STATE_PREPARED but not yet SND_PCM_STATE_RUNNING, which means
the submitted data will never be played. This corner case is
realistic when playing songs shorter than the ALSA buffer (if the
buffer is very large).
This fixes a corner case which has probably never occurred and
probably never will: if Cancel() is called, and then Play() followed
by Drain(), the plugin should really play that data. However
currently, this never happens, because snd_pcm_prepare() is never
called.
When `metadata_sent` is `false`, the plugin assumes there is metadata
which must be sent, even if no metadata page was passed to the plugin.
Initializing it to `true` avoids dereferencing this `nullptr`.
Fixes#412
If the output is already open, the `current_chunk` pointer may be
bogus and out of sync with `SharedPipeConsumer::chunk`, leading to an
assertion failure in `SharedPipeConsumer::Consume()`.
Fixes#411
Meson always enables large file support on the compiler command line,
thus config.h doesn't need to be included anymore. We'll remove the
whole `check.h` header soon.
Closes#409
`AVCodecParameters` contains values from the codec detected by
avformat_find_stream_info(), but after avcodec_open2(), a different
codec might be selected with a different `AVSampleFormat`. This leads
to misinterpretation of data returned from FFmpeg, leading to random
noise or silence.
This was observed with FFmpeg 4.0.2 and a TS container file containing
MP2. A mp3-float codec was detected returning `AV_SAMPLE_FMT_FLTP`,
but finally the `mpegaudiodec_fixed.c` was used, returning
`AV_SAMPLE_FMT_S16`.
By using the audio format from `AVCodecContext`, we ensure that MPD
and FFmpeg always agree on the actual audio format in the buffer.
This removes the FFmpeg bug workaround from commit e1b032cbad which I
assume is obsolete after 7 years.
Fixes#380
ensure that valid mixer values are set also when the ALSA driver
does not report a valid dB range ('set_raw' fallback)
correct a bug in which volume is assumed to lie in [0..100]
instead of [0..1]