improve write() underrun handling, take 2

we *really* should not paper over underruns, as they require attention.
however, the previous attempt (c2a6b6e) caused an exception to be thrown
(see #130), which was a bit excessive, and was consequently reverted
(438e52e).

so instead we make the handling consistent with what we do in read():
return the verbatim -EPIPE in this case. this can be simply ignored, and
the next write will resume the stream, so this is mostly backwards-
compatible (the failing write will be discarded and would need
repeating, but that will just cause a skip after the interruption,
which does not seem particularly relevant).

as a drive-by, again stop using snd_pcm_recover(), as it still just
obfuscates the snd_pcm_prepare() call it does in the end.
This commit is contained in:
Oswald Buddenhagen
2024-02-02 13:33:00 +01:00
committed by Lars Immisch
parent 691c1d9b23
commit 8fb33ddd49
3 changed files with 39 additions and 25 deletions

View File

@@ -338,14 +338,23 @@ PCM objects have the following methods:
period. If less than 'period size' frames are provided, the actual
playout will not happen until more data is written.
If the device is not in :const:`PCM_NONBLOCK` mode, this call will block if
the kernel buffer is full, and until enough sound has been played
to allow the sound data to be buffered. The call always returns the
size of the data provided.
If the data was successfully written, the call returns the size of the
data *in frames*.
If the device is not in :const:`PCM_NONBLOCK` mode, this call will block
if the kernel buffer is full, and until enough sound has been played
to allow the sound data to be buffered.
In :const:`PCM_NONBLOCK` mode, the call will return immediately, with a
return value of zero, if the buffer is full. In this case, the data
should be written at a later time.
should be written again at a later time.
In case of a buffer underrun, this function will return the negative
size :const:`-EPIPE`, and no data is written.
At this point, the playback was already corrupted. If you want to play
the data nonetheless, call write again with the same data.
To avoid the problem in the future, try using a larger period size
and/or more periods, at the cost of higher latency.
Note that this call completing means only that the samples were buffered
in the kernel, and playout will continue afterwards. Make sure that the