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.
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.
Don't reactivate the PCM device immediately after Cancel() is
finished; if Cancel() gets called this may mean that new data may take
a while to produce, or no data at all will be produced because the
current song is being stopped.
Once new data is available, Play() will automatically reactivate the
PCM.
This fixes underruns when switching songs manually (closes#264).
After UnlockActivate() returns, we not only need to check for errors,
but also for more room in the ring buffer. If we don't check the ring
buffer, it may be drained already, and the cond.wait() call will never
finish.
Closes#151
Allows defining a list of supported audio formats, and allows
switching on and off DoP with certain formats.
This is a first rough draft. The setting syntax and its semantics may
still be redesigned.
This loop was introduced in commit
24c1f46353, but -EPIPE is not a possible
error condition for snd_pcm_hw_params(). This code does not appear to
make sense. Problems with a wrong period_time should be caught before
that by snd_pcm_hw_params_set_period_time_near().
This commit removes the last "goto" in MPD! Yay!