From 574f78939d51d88d9a6fc91d131c10a430ccc05a Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 5 Aug 2022 21:37:27 +0200 Subject: [PATCH] add PCM.drain() for playback, this allows making sure that all written frames are played, without using an external delay. in principle, it's also usable for capture, but there isn't really a practical reason to do so, as simply discarding excess captured frames has no real cost. --- alsaaudio.c | 25 +++++++++++++++++++++++++ doc/libalsaaudio.rst | 10 ++++++++++ 2 files changed, 35 insertions(+) diff --git a/alsaaudio.c b/alsaaudio.c index dd990ae..8508730 100644 --- a/alsaaudio.c +++ b/alsaaudio.c @@ -1512,6 +1512,30 @@ static PyObject *alsapcm_drop(alsapcm_t *self) return PyLong_FromLong(res); } +static PyObject *alsapcm_drain(alsapcm_t *self) +{ + int res; + + if (!self->handle) { + PyErr_SetString(ALSAAudioError, "PCM device is closed"); + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + res = snd_pcm_drain(self->handle); + Py_END_ALLOW_THREADS + + if (res < 0) + { + PyErr_Format(ALSAAudioError, "%s [%s]", snd_strerror(res), + self->cardname); + + return NULL; + } + + return PyLong_FromLong(res); +} + static PyObject * alsapcm_polldescriptors(alsapcm_t *self, PyObject *args) { @@ -1589,6 +1613,7 @@ static PyMethodDef alsapcm_methods[] = { {"write", (PyCFunction)alsapcm_write, METH_VARARGS}, {"pause", (PyCFunction)alsapcm_pause, METH_VARARGS}, {"drop", (PyCFunction)alsapcm_drop, METH_VARARGS}, + {"drain", (PyCFunction)alsapcm_drain, METH_VARARGS}, {"close", (PyCFunction)alsapcm_close, METH_VARARGS}, {"polldescriptors", (PyCFunction)alsapcm_polldescriptors, METH_VARARGS}, {NULL, NULL} diff --git a/doc/libalsaaudio.rst b/doc/libalsaaudio.rst index fa54796..2ed5f7a 100644 --- a/doc/libalsaaudio.rst +++ b/doc/libalsaaudio.rst @@ -344,6 +344,16 @@ PCM objects have the following methods: *New in 0.9* +.. method:: PCM.drain() + + For :const:`PCM_PLAYBACK` PCM objects, play residual buffered frames + and then stop the stream. In :const:`PCM_NORMAL` mode, + this function blocks until all pending playback is drained. + + For :const:`PCM_CAPTURE` PCM objects, this function is not very useful. + + *New in 0.10* + .. method:: PCM.close() Closes the PCM device.