pcm: fix read_areas and write_areas

The stream state was wrongly updated and handled.

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Jaroslav Kysela 2010-01-31 09:40:08 +01:00
parent 63acb87329
commit 2e48439ad9

View file

@ -6528,46 +6528,51 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_
{ {
snd_pcm_uframes_t xfer = 0; snd_pcm_uframes_t xfer = 0;
snd_pcm_sframes_t err = 0; snd_pcm_sframes_t err = 0;
snd_pcm_state_t state = snd_pcm_state(pcm); snd_pcm_state_t state;
if (size == 0) if (size == 0)
return 0; return 0;
switch (state) {
case SND_PCM_STATE_PREPARED:
err = snd_pcm_start(pcm);
if (err < 0)
goto _end;
break;
case SND_PCM_STATE_DRAINING:
case SND_PCM_STATE_RUNNING:
break;
case SND_PCM_STATE_XRUN:
return -EPIPE;
case SND_PCM_STATE_SUSPENDED:
return -ESTRPIPE;
case SND_PCM_STATE_DISCONNECTED:
return -ENODEV;
default:
return -EBADFD;
}
while (size > 0) { while (size > 0) {
snd_pcm_uframes_t frames; snd_pcm_uframes_t frames;
snd_pcm_sframes_t avail; snd_pcm_sframes_t avail;
_again: _again:
if (state == SND_PCM_STATE_RUNNING) { state = snd_pcm_state(pcm);
switch (state) {
case SND_PCM_STATE_PREPARED:
err = snd_pcm_start(pcm);
if (err < 0)
goto _end;
break;
case SND_PCM_STATE_RUNNING:
err = snd_pcm_hwsync(pcm); err = snd_pcm_hwsync(pcm);
if (err < 0) if (err < 0)
goto _end; goto _end;
break;
case SND_PCM_STATE_DRAINING:
case SND_PCM_STATE_PAUSED:
break;
case SND_PCM_STATE_XRUN:
err = -EPIPE;
goto _end;
case SND_PCM_STATE_SUSPENDED:
err = -ESTRPIPE;
goto _end;
case SND_PCM_STATE_DISCONNECTED:
err = -ENODEV;
goto _end;
default:
err = -EBADFD;
goto _end;
} }
avail = snd_pcm_avail_update(pcm); avail = snd_pcm_avail_update(pcm);
if (avail < 0) { if (avail < 0) {
err = avail; err = avail;
goto _end; goto _end;
} }
if ((snd_pcm_uframes_t)avail < pcm->avail_min && if (avail == 0) {
size > (snd_pcm_uframes_t)avail) { if (state == SND_PCM_STATE_DRAINING)
goto _end;
if (pcm->mode & SND_PCM_NONBLOCK) { if (pcm->mode & SND_PCM_NONBLOCK) {
err = -EAGAIN; err = -EAGAIN;
goto _end; goto _end;
@ -6602,33 +6607,37 @@ snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area
{ {
snd_pcm_uframes_t xfer = 0; snd_pcm_uframes_t xfer = 0;
snd_pcm_sframes_t err = 0; snd_pcm_sframes_t err = 0;
snd_pcm_state_t state = snd_pcm_state(pcm); snd_pcm_state_t state;
if (size == 0) if (size == 0)
return 0; return 0;
switch (state) {
case SND_PCM_STATE_PREPARED:
case SND_PCM_STATE_RUNNING:
break;
case SND_PCM_STATE_XRUN:
return -EPIPE;
case SND_PCM_STATE_SUSPENDED:
return -ESTRPIPE;
case SND_PCM_STATE_DISCONNECTED:
return -ENODEV;
default:
return -EBADFD;
}
while (size > 0) { while (size > 0) {
snd_pcm_uframes_t frames; snd_pcm_uframes_t frames;
snd_pcm_sframes_t avail; snd_pcm_sframes_t avail;
_again: _again:
if (state == SND_PCM_STATE_RUNNING) { state = snd_pcm_state(pcm);
switch (state) {
case SND_PCM_STATE_PREPARED:
case SND_PCM_STATE_PAUSED:
break;
case SND_PCM_STATE_RUNNING:
err = snd_pcm_hwsync(pcm); err = snd_pcm_hwsync(pcm);
if (err < 0) if (err < 0)
goto _end; goto _end;
break;
case SND_PCM_STATE_XRUN:
err = -EPIPE;
goto _end;
case SND_PCM_STATE_SUSPENDED:
err = -ESTRPIPE;
goto _end;
case SND_PCM_STATE_DISCONNECTED:
err = -ENODEV;
goto _end;
default:
err = -EBADFD;
goto _end;
} }
avail = snd_pcm_avail_update(pcm); avail = snd_pcm_avail_update(pcm);
if (avail < 0) { if (avail < 0) {