mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
pcm: improve handling for snd_pcm_wait()
The snd_pcm_wait() function is called also internally from the various plugins to wait for the drain with -1 and from i/o routines in pcm.c. Define two special negative timeout values to distinguish the drain and i/o wait and calculate the maximal timeout according the wait place. Fixes: https://github.com/alsa-project/alsa-lib/issues/228 Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
1de6f99c7d
commit
e2d9e41174
9 changed files with 55 additions and 10 deletions
|
|
@ -498,6 +498,13 @@ typedef union _snd_pcm_sync_id {
|
|||
unsigned int id32[4];
|
||||
} snd_pcm_sync_id_t;
|
||||
|
||||
/** Infinite wait for snd_pcm_wait() */
|
||||
#define SND_PCM_WAIT_INFINITE (-1)
|
||||
/** Wait for next i/o in snd_pcm_wait() */
|
||||
#define SND_PCM_WAIT_IO (-10001)
|
||||
/** Wait for drain in snd_pcm_wait() */
|
||||
#define SND_PCM_WAIT_DRAIN (-10002)
|
||||
|
||||
/** #SND_PCM_TYPE_METER scope handle */
|
||||
typedef struct _snd_pcm_scope snd_pcm_scope_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -2834,7 +2834,8 @@ int snd_pcm_open_named_slave(snd_pcm_t **pcmp, const char *name,
|
|||
* \brief Wait for a PCM to become ready
|
||||
* \param pcm PCM handle
|
||||
* \param timeout maximum time in milliseconds to wait,
|
||||
* a negative value means infinity
|
||||
* a -1 value means infinity (SND_PCM_WAIT_INFINITE),
|
||||
* see also SND_PCM_WAIT_IO and SND_PCM_WAIT_DRAIN
|
||||
* \return a positive value on success otherwise a negative error code
|
||||
* (-EPIPE for the xrun and -ESTRPIPE for the suspended status,
|
||||
* others for general errors)
|
||||
|
|
@ -2869,6 +2870,37 @@ int __snd_pcm_wait_in_lock(snd_pcm_t *pcm, int timeout)
|
|||
return snd_pcm_wait_nocheck(pcm, timeout);
|
||||
}
|
||||
|
||||
static int __snd_pcm_wait_io_timeout(snd_pcm_t *pcm)
|
||||
{
|
||||
int timeout;
|
||||
|
||||
/* period size is the time boundary */
|
||||
timeout = (pcm->period_size * 1000ULL) / pcm->rate;
|
||||
/* should not happen */
|
||||
if (timeout < 0)
|
||||
timeout = 0;
|
||||
/* add extra time of 200 milliseconds */
|
||||
timeout += 200;
|
||||
return timeout;
|
||||
}
|
||||
|
||||
static int __snd_pcm_wait_drain_timeout(snd_pcm_t *pcm)
|
||||
{
|
||||
int timeout;
|
||||
|
||||
/* for capture, there's no reason to wait, just one iteration */
|
||||
if (snd_pcm_stream(pcm) == SND_PCM_STREAM_CAPTURE)
|
||||
return 0;
|
||||
/* result is in milliseconds */
|
||||
timeout = (snd_pcm_mmap_playback_delay(pcm) * 1000LL) / pcm->rate;
|
||||
/* should not happen */
|
||||
if (timeout < 0)
|
||||
timeout = 0;
|
||||
/* add extra time of 200 milliseconds */
|
||||
timeout += 200;
|
||||
return timeout;
|
||||
}
|
||||
|
||||
/*
|
||||
* like snd_pcm_wait() but doesn't check mmap_avail before calling poll()
|
||||
*
|
||||
|
|
@ -2895,6 +2927,12 @@ int snd_pcm_wait_nocheck(snd_pcm_t *pcm, int timeout)
|
|||
SNDMSG("invalid poll descriptors %d\n", err);
|
||||
return -EIO;
|
||||
}
|
||||
if (timeout == SND_PCM_WAIT_IO)
|
||||
timeout = __snd_pcm_wait_io_timeout(pcm);
|
||||
else if (timeout == SND_PCM_WAIT_DRAIN)
|
||||
timeout = __snd_pcm_wait_drain_timeout(pcm);
|
||||
else if (timeout < -1)
|
||||
SNDMSG("invalid snd_pcm_wait timeout argument %d\n", timeout);
|
||||
do {
|
||||
__snd_pcm_unlock(pcm->fast_op_arg);
|
||||
err_poll = poll(pfd, npfds, timeout);
|
||||
|
|
@ -7525,7 +7563,7 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_
|
|||
goto _end;
|
||||
}
|
||||
|
||||
err = __snd_pcm_wait_in_lock(pcm, -1);
|
||||
err = __snd_pcm_wait_in_lock(pcm, SND_PCM_WAIT_IO);
|
||||
if (err < 0)
|
||||
break;
|
||||
goto _again;
|
||||
|
|
@ -7594,7 +7632,7 @@ snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area
|
|||
goto _end;
|
||||
}
|
||||
|
||||
err = snd_pcm_wait_nocheck(pcm, -1);
|
||||
err = snd_pcm_wait_nocheck(pcm, SND_PCM_WAIT_IO);
|
||||
if (err < 0)
|
||||
break;
|
||||
goto _again;
|
||||
|
|
|
|||
|
|
@ -623,7 +623,7 @@ static int __snd_pcm_dmix_drain(snd_pcm_t *pcm)
|
|||
if (dmix->state == SND_PCM_STATE_DRAINING) {
|
||||
snd_pcm_dmix_sync_area(pcm);
|
||||
if ((pcm->mode & SND_PCM_NONBLOCK) == 0) {
|
||||
snd_pcm_wait_nocheck(pcm, -1);
|
||||
snd_pcm_wait_nocheck(pcm, SND_PCM_WAIT_DRAIN);
|
||||
snd_pcm_direct_clear_timer_queue(dmix); /* force poll to wait */
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -400,7 +400,7 @@ static int __snd_pcm_dshare_drain(snd_pcm_t *pcm)
|
|||
}
|
||||
if (dshare->state == SND_PCM_STATE_DRAINING) {
|
||||
snd_pcm_dshare_sync_area(pcm);
|
||||
snd_pcm_wait_nocheck(pcm, -1);
|
||||
snd_pcm_wait_nocheck(pcm, SND_PCM_WAIT_DRAIN);
|
||||
snd_pcm_direct_clear_timer_queue(dshare); /* force poll to wait */
|
||||
|
||||
switch (snd_pcm_state(dshare->spcm)) {
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ static int __snd_pcm_dsnoop_drain(snd_pcm_t *pcm)
|
|||
break;
|
||||
if (pcm->mode & SND_PCM_NONBLOCK)
|
||||
return -EAGAIN;
|
||||
__snd_pcm_wait_in_lock(pcm, -1);
|
||||
__snd_pcm_wait_in_lock(pcm, SND_PCM_WAIT_DRAIN);
|
||||
}
|
||||
pcm->stop_threshold = stop_threshold;
|
||||
return snd_pcm_dsnoop_drop(pcm);
|
||||
|
|
|
|||
|
|
@ -522,7 +522,7 @@ static int ioplug_drain_via_poll(snd_pcm_t *pcm)
|
|||
/* in non-blocking mode, let application to poll() by itself */
|
||||
if (io->data->nonblock)
|
||||
return -EAGAIN;
|
||||
if (snd_pcm_wait_nocheck(pcm, -1) < 0)
|
||||
if (snd_pcm_wait_nocheck(pcm, SND_PCM_WAIT_DRAIN) < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1146,7 +1146,7 @@ static int snd_pcm_rate_drain(snd_pcm_t *pcm)
|
|||
snd_pcm_uframes_t psize, spsize;
|
||||
int err;
|
||||
|
||||
err = __snd_pcm_wait_in_lock(rate->gen.slave, -1);
|
||||
err = __snd_pcm_wait_in_lock(rate->gen.slave, SND_PCM_WAIT_DRAIN);
|
||||
if (err < 0)
|
||||
break;
|
||||
if (size > pcm->period_size) {
|
||||
|
|
|
|||
|
|
@ -1194,7 +1194,7 @@ static int snd_pcm_share_drain(snd_pcm_t *pcm)
|
|||
_snd_pcm_share_update(pcm);
|
||||
Pthread_mutex_unlock(&slave->mutex);
|
||||
if (!(pcm->mode & SND_PCM_NONBLOCK))
|
||||
snd_pcm_wait(pcm, -1);
|
||||
snd_pcm_wait(pcm, SND_PCM_WAIT_DRAIN);
|
||||
return 0;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
|
|||
|
|
@ -495,7 +495,7 @@ static int snd_pcm_shm_drain(snd_pcm_t *pcm)
|
|||
if (err < 0)
|
||||
return err;
|
||||
if (!(pcm->mode & SND_PCM_NONBLOCK))
|
||||
snd_pcm_wait(pcm, -1);
|
||||
snd_pcm_wait(pcm, SND_PCM_WAIT_DRAIN);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue