reshuffle XRUN recovery somewhat

perform it prior to invoking read()/write() if necessary, not right
after a failure event. this makes things more uniform and predictable.

we don't use snd_pcm_recover() any more, as we used it only for the
EPIPE case anyway, which boils down to snd_pcm_prepare() exactly.
handling ESTRPIPE as well might be desirable, but that's a separate
consideration.
This commit is contained in:
Oswald Buddenhagen
2022-08-05 20:37:13 +02:00
parent da7d04e2fd
commit c2a6b6e583
+14 -25
View File
@@ -1311,6 +1311,7 @@ alsapcm_setperiodsize(alsapcm_t *self, PyObject *args)
static PyObject * static PyObject *
alsapcm_read(alsapcm_t *self, PyObject *args) alsapcm_read(alsapcm_t *self, PyObject *args)
{ {
snd_pcm_state_t state;
int res; int res;
int size = self->framesize * self->periodsize; int size = self->framesize * self->periodsize;
int sizeout = 0; int sizeout = 0;
@@ -1344,14 +1345,13 @@ alsapcm_read(alsapcm_t *self, PyObject *args)
buffer = PyBytes_AS_STRING(buffer_obj); buffer = PyBytes_AS_STRING(buffer_obj);
#endif #endif
Py_BEGIN_ALLOW_THREADS state = snd_pcm_state(self->handle);
res = snd_pcm_readi(self->handle, buffer, self->periodsize); if ((state != SND_PCM_STATE_XRUN && state != SND_PCM_STATE_SETUP) ||
if (res == -EPIPE) (res = snd_pcm_prepare(self->handle)) >= 0) {
{ Py_BEGIN_ALLOW_THREADS
/* EPIPE means overrun */ res = snd_pcm_readi(self->handle, buffer, self->periodsize);
snd_pcm_prepare(self->handle); Py_END_ALLOW_THREADS
} }
Py_END_ALLOW_THREADS
if (res != -EPIPE) if (res != -EPIPE)
{ {
@@ -1404,6 +1404,7 @@ alsapcm_read(alsapcm_t *self, PyObject *args)
static PyObject *alsapcm_write(alsapcm_t *self, PyObject *args) static PyObject *alsapcm_write(alsapcm_t *self, PyObject *args)
{ {
snd_pcm_state_t state;
int res; int res;
int datalen; int datalen;
char *data; char *data;
@@ -1435,16 +1436,13 @@ static PyObject *alsapcm_write(alsapcm_t *self, PyObject *args)
return NULL; return NULL;
} }
Py_BEGIN_ALLOW_THREADS state = snd_pcm_state(self->handle);
res = snd_pcm_writei(self->handle, data, datalen/self->framesize); if ((state != SND_PCM_STATE_XRUN && state != SND_PCM_STATE_SETUP) ||
if (res == -EPIPE) (res = snd_pcm_prepare(self->handle)) >= 0) {
{ Py_BEGIN_ALLOW_THREADS
/* EPIPE means underrun */ res = snd_pcm_writei(self->handle, data, datalen/self->framesize);
res = snd_pcm_recover(self->handle, res, 1); Py_END_ALLOW_THREADS
if (res >= 0)
res = snd_pcm_writei(self->handle, data, datalen/self->framesize);
} }
Py_END_ALLOW_THREADS
if (res == -EAGAIN) { if (res == -EAGAIN) {
rc = PyLong_FromLong(0); rc = PyLong_FromLong(0);
@@ -1507,15 +1505,6 @@ static PyObject *alsapcm_drop(alsapcm_t *self)
return NULL; return NULL;
} }
res = snd_pcm_prepare(self->handle);
if (res < 0)
{
PyErr_Format(ALSAAudioError, "%s [%s]", snd_strerror(res),
self->cardname);
return NULL;
}
return PyLong_FromLong(res); return PyLong_FromLong(res);
} }