mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-11-02 09:01:48 -05:00
Fix dshare plugin codes
Modify dshare plugin codes to follow the recent change of dmix: proper XRUN and poll handling, async data transfer.
This commit is contained in:
parent
1661759351
commit
ddd9c29a0d
1 changed files with 128 additions and 60 deletions
|
|
@ -49,6 +49,9 @@
|
||||||
const char *_snd_module_pcm_dshare = "";
|
const char *_snd_module_pcm_dshare = "";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* start is pending - this state happens when rate plugin does a delayed commit */
|
||||||
|
#define STATE_RUN_PENDING 1024
|
||||||
|
|
||||||
static void do_silence(snd_pcm_t *pcm)
|
static void do_silence(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_direct_t *dshare = pcm->private_data;
|
snd_pcm_direct_t *dshare = pcm->private_data;
|
||||||
|
|
@ -94,30 +97,51 @@ static void share_areas(snd_pcm_direct_t *dshare,
|
||||||
/*
|
/*
|
||||||
* synchronize shm ring buffer with hardware
|
* synchronize shm ring buffer with hardware
|
||||||
*/
|
*/
|
||||||
static void snd_pcm_dshare_sync_area(snd_pcm_t *pcm, snd_pcm_uframes_t size)
|
static void snd_pcm_dshare_sync_area(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_direct_t *dshare = pcm->private_data;
|
snd_pcm_direct_t *dshare = pcm->private_data;
|
||||||
snd_pcm_uframes_t appl_ptr, slave_appl_ptr, transfer;
|
snd_pcm_uframes_t appl_ptr, slave_appl_ptr, slave_bsize;
|
||||||
|
snd_pcm_uframes_t size, slave_hw_ptr;
|
||||||
const snd_pcm_channel_area_t *src_areas, *dst_areas;
|
const snd_pcm_channel_area_t *src_areas, *dst_areas;
|
||||||
|
|
||||||
/* get the start of update area */
|
/* calculate the size to transfer */
|
||||||
appl_ptr = dshare->appl_ptr - size;
|
size = dshare->appl_ptr - dshare->last_appl_ptr;
|
||||||
if (appl_ptr > pcm->boundary)
|
if (! size)
|
||||||
appl_ptr += pcm->boundary;
|
return;
|
||||||
appl_ptr %= pcm->buffer_size;
|
slave_bsize = dshare->shmptr->s.buffer_size;
|
||||||
|
slave_hw_ptr = dshare->slave_hw_ptr;
|
||||||
|
/* don't write on the last active period - this area may be cleared
|
||||||
|
* by the driver during write operation...
|
||||||
|
*/
|
||||||
|
slave_hw_ptr -= slave_hw_ptr % dshare->shmptr->s.period_size;
|
||||||
|
slave_hw_ptr += slave_bsize;
|
||||||
|
if (dshare->slave_hw_ptr > dshare->slave_appl_ptr)
|
||||||
|
slave_hw_ptr -= dshare->shmptr->s.boundary;
|
||||||
|
if (dshare->slave_appl_ptr + size >= slave_hw_ptr)
|
||||||
|
size = slave_hw_ptr - dshare->slave_appl_ptr;
|
||||||
|
if (! size)
|
||||||
|
return;
|
||||||
/* add sample areas here */
|
/* add sample areas here */
|
||||||
src_areas = snd_pcm_mmap_areas(pcm);
|
src_areas = snd_pcm_mmap_areas(pcm);
|
||||||
dst_areas = snd_pcm_mmap_areas(dshare->spcm);
|
dst_areas = snd_pcm_mmap_areas(dshare->spcm);
|
||||||
slave_appl_ptr = dshare->slave_appl_ptr % dshare->shmptr->s.buffer_size;
|
appl_ptr = dshare->last_appl_ptr % pcm->buffer_size;
|
||||||
|
dshare->last_appl_ptr += size;
|
||||||
|
dshare->last_appl_ptr %= pcm->boundary;
|
||||||
|
slave_appl_ptr = dshare->slave_appl_ptr % slave_bsize;
|
||||||
dshare->slave_appl_ptr += size;
|
dshare->slave_appl_ptr += size;
|
||||||
dshare->slave_appl_ptr %= dshare->shmptr->s.boundary;
|
dshare->slave_appl_ptr %= dshare->shmptr->s.boundary;
|
||||||
while (size > 0) {
|
for (;;) {
|
||||||
transfer = appl_ptr + size > pcm->buffer_size ? pcm->buffer_size - appl_ptr : size;
|
snd_pcm_uframes_t transfer = size;
|
||||||
transfer = slave_appl_ptr + transfer > dshare->shmptr->s.buffer_size ? dshare->shmptr->s.buffer_size - slave_appl_ptr : transfer;
|
if (appl_ptr + transfer > pcm->buffer_size)
|
||||||
size -= transfer;
|
transfer = pcm->buffer_size - appl_ptr;
|
||||||
|
if (slave_appl_ptr + transfer > slave_bsize)
|
||||||
|
transfer = slave_bsize - slave_appl_ptr;
|
||||||
share_areas(dshare, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer);
|
share_areas(dshare, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer);
|
||||||
|
size -= transfer;
|
||||||
|
if (! size)
|
||||||
|
break;
|
||||||
slave_appl_ptr += transfer;
|
slave_appl_ptr += transfer;
|
||||||
slave_appl_ptr %= dshare->shmptr->s.buffer_size;
|
slave_appl_ptr %= slave_bsize;
|
||||||
appl_ptr += transfer;
|
appl_ptr += transfer;
|
||||||
appl_ptr %= pcm->buffer_size;
|
appl_ptr %= pcm->buffer_size;
|
||||||
}
|
}
|
||||||
|
|
@ -146,6 +170,10 @@ static int snd_pcm_dshare_sync_ptr(snd_pcm_t *pcm)
|
||||||
diff = slave_hw_ptr - old_slave_hw_ptr;
|
diff = slave_hw_ptr - old_slave_hw_ptr;
|
||||||
if (diff == 0) /* fast path */
|
if (diff == 0) /* fast path */
|
||||||
return 0;
|
return 0;
|
||||||
|
if (dshare->state != SND_PCM_STATE_RUNNING &&
|
||||||
|
dshare->state != SND_PCM_STATE_DRAINING)
|
||||||
|
/* not really started yet - don't update hw_ptr */
|
||||||
|
return 0;
|
||||||
if (diff < 0) {
|
if (diff < 0) {
|
||||||
slave_hw_ptr += dshare->shmptr->s.boundary;
|
slave_hw_ptr += dshare->shmptr->s.boundary;
|
||||||
diff = slave_hw_ptr - old_slave_hw_ptr;
|
diff = slave_hw_ptr - old_slave_hw_ptr;
|
||||||
|
|
@ -155,17 +183,23 @@ static int snd_pcm_dshare_sync_ptr(snd_pcm_t *pcm)
|
||||||
// printf("sync ptr diff = %li\n", diff);
|
// printf("sync ptr diff = %li\n", diff);
|
||||||
if (pcm->stop_threshold >= pcm->boundary) /* don't care */
|
if (pcm->stop_threshold >= pcm->boundary) /* don't care */
|
||||||
return 0;
|
return 0;
|
||||||
if ((avail = snd_pcm_mmap_playback_avail(pcm)) >= pcm->stop_threshold) {
|
avail = snd_pcm_mmap_playback_avail(pcm);
|
||||||
|
if (avail > dshare->avail_max)
|
||||||
|
dshare->avail_max = avail;
|
||||||
|
if (avail >= pcm->stop_threshold) {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
snd_timer_stop(dshare->timer);
|
||||||
gettimeofday(&tv, 0);
|
gettimeofday(&tv, 0);
|
||||||
dshare->trigger_tstamp.tv_sec = tv.tv_sec;
|
dshare->trigger_tstamp.tv_sec = tv.tv_sec;
|
||||||
dshare->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
|
dshare->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
|
||||||
dshare->state = SND_PCM_STATE_XRUN;
|
if (dshare->state == SND_PCM_STATE_RUNNING) {
|
||||||
dshare->avail_max = avail;
|
dshare->state = SND_PCM_STATE_XRUN;
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
|
}
|
||||||
|
dshare->state = SND_PCM_STATE_SETUP;
|
||||||
|
/* clear queue to remove pending poll events */
|
||||||
|
snd_pcm_direct_clear_timer_queue(dshare);
|
||||||
}
|
}
|
||||||
if (avail > dshare->avail_max)
|
|
||||||
dshare->avail_max = avail;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,7 +210,6 @@ static int snd_pcm_dshare_sync_ptr(snd_pcm_t *pcm)
|
||||||
static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
|
static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
|
||||||
{
|
{
|
||||||
snd_pcm_direct_t *dshare = pcm->private_data;
|
snd_pcm_direct_t *dshare = pcm->private_data;
|
||||||
snd_pcm_state_t state;
|
|
||||||
|
|
||||||
switch (dshare->state) {
|
switch (dshare->state) {
|
||||||
case SNDRV_PCM_STATE_DRAINING:
|
case SNDRV_PCM_STATE_DRAINING:
|
||||||
|
|
@ -187,8 +220,7 @@ static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memset(status, 0, sizeof(*status));
|
memset(status, 0, sizeof(*status));
|
||||||
state = snd_pcm_state(dshare->spcm);
|
status->state = snd_pcm_state(dshare->spcm);
|
||||||
status->state = state == SND_PCM_STATE_RUNNING ? dshare->state : state;
|
|
||||||
status->trigger_tstamp = dshare->trigger_tstamp;
|
status->trigger_tstamp = dshare->trigger_tstamp;
|
||||||
status->tstamp = snd_pcm_hw_fast_tstamp(dshare->spcm);
|
status->tstamp = snd_pcm_hw_fast_tstamp(dshare->spcm);
|
||||||
status->avail = snd_pcm_mmap_playback_avail(pcm);
|
status->avail = snd_pcm_mmap_playback_avail(pcm);
|
||||||
|
|
@ -204,11 +236,12 @@ static snd_pcm_state_t snd_pcm_dshare_state(snd_pcm_t *pcm)
|
||||||
case SND_PCM_STATE_SUSPENDED:
|
case SND_PCM_STATE_SUSPENDED:
|
||||||
return SND_PCM_STATE_SUSPENDED;
|
return SND_PCM_STATE_SUSPENDED;
|
||||||
case SND_PCM_STATE_DISCONNECTED:
|
case SND_PCM_STATE_DISCONNECTED:
|
||||||
dshare->state = SNDRV_PCM_STATE_DISCONNECTED;
|
return SND_PCM_STATE_DISCONNECTED;
|
||||||
return -ENOTTY;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (dshare->state == STATE_RUN_PENDING)
|
||||||
|
return SNDRV_PCM_STATE_RUNNING;
|
||||||
return dshare->state;
|
return dshare->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,8 +256,10 @@ static int snd_pcm_dshare_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||||
err = snd_pcm_dshare_sync_ptr(pcm);
|
err = snd_pcm_dshare_sync_ptr(pcm);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
/* fallthru */
|
||||||
case SNDRV_PCM_STATE_PREPARED:
|
case SNDRV_PCM_STATE_PREPARED:
|
||||||
case SNDRV_PCM_STATE_SUSPENDED:
|
case SNDRV_PCM_STATE_SUSPENDED:
|
||||||
|
case STATE_RUN_PENDING:
|
||||||
*delayp = snd_pcm_mmap_playback_hw_avail(pcm);
|
*delayp = snd_pcm_mmap_playback_hw_avail(pcm);
|
||||||
return 0;
|
return 0;
|
||||||
case SNDRV_PCM_STATE_XRUN:
|
case SNDRV_PCM_STATE_XRUN:
|
||||||
|
|
@ -263,7 +298,7 @@ static int snd_pcm_dshare_prepare(snd_pcm_t *pcm)
|
||||||
snd_pcm_direct_check_interleave(dshare, pcm);
|
snd_pcm_direct_check_interleave(dshare, pcm);
|
||||||
// assert(pcm->boundary == dshare->shmptr->s.boundary); /* for sure */
|
// assert(pcm->boundary == dshare->shmptr->s.boundary); /* for sure */
|
||||||
dshare->state = SND_PCM_STATE_PREPARED;
|
dshare->state = SND_PCM_STATE_PREPARED;
|
||||||
dshare->appl_ptr = 0;
|
dshare->appl_ptr = dshare->last_appl_ptr = 0;
|
||||||
dshare->hw_ptr = 0;
|
dshare->hw_ptr = 0;
|
||||||
return snd_pcm_direct_set_timer_params(dshare);
|
return snd_pcm_direct_set_timer_params(dshare);
|
||||||
}
|
}
|
||||||
|
|
@ -272,11 +307,24 @@ static int snd_pcm_dshare_reset(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_direct_t *dshare = pcm->private_data;
|
snd_pcm_direct_t *dshare = pcm->private_data;
|
||||||
dshare->hw_ptr %= pcm->period_size;
|
dshare->hw_ptr %= pcm->period_size;
|
||||||
dshare->appl_ptr = dshare->hw_ptr;
|
dshare->appl_ptr = dshare->last_appl_ptr = dshare->hw_ptr;
|
||||||
dshare->slave_appl_ptr = dshare->slave_hw_ptr = *dshare->spcm->hw.ptr;
|
dshare->slave_appl_ptr = dshare->slave_hw_ptr = *dshare->spcm->hw.ptr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_dshare_start_timer(snd_pcm_direct_t *dshare)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
snd_pcm_hwsync(dshare->spcm);
|
||||||
|
dshare->slave_appl_ptr = dshare->slave_hw_ptr = *dshare->spcm->hw.ptr;
|
||||||
|
err = snd_timer_start(dshare->timer);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
dshare->state = SND_PCM_STATE_RUNNING;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_dshare_start(snd_pcm_t *pcm)
|
static int snd_pcm_dshare_start(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_direct_t *dshare = pcm->private_data;
|
snd_pcm_direct_t *dshare = pcm->private_data;
|
||||||
|
|
@ -286,18 +334,16 @@ static int snd_pcm_dshare_start(snd_pcm_t *pcm)
|
||||||
|
|
||||||
if (dshare->state != SND_PCM_STATE_PREPARED)
|
if (dshare->state != SND_PCM_STATE_PREPARED)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
snd_pcm_hwsync(dshare->spcm);
|
|
||||||
dshare->slave_appl_ptr = dshare->slave_hw_ptr = *dshare->spcm->hw.ptr;
|
|
||||||
err = snd_timer_start(dshare->timer);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
dshare->state = SND_PCM_STATE_RUNNING;
|
|
||||||
avail = snd_pcm_mmap_playback_hw_avail(pcm);
|
avail = snd_pcm_mmap_playback_hw_avail(pcm);
|
||||||
if (avail < 0)
|
if (avail == 0)
|
||||||
|
dshare->state = STATE_RUN_PENDING;
|
||||||
|
else if (avail < 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (avail > (snd_pcm_sframes_t)pcm->buffer_size)
|
else {
|
||||||
avail = pcm->buffer_size;
|
if ((err = snd_pcm_dshare_start_timer(dshare)) < 0)
|
||||||
snd_pcm_dshare_sync_area(pcm, avail);
|
return err;
|
||||||
|
snd_pcm_dshare_sync_area(pcm);
|
||||||
|
}
|
||||||
gettimeofday(&tv, 0);
|
gettimeofday(&tv, 0);
|
||||||
dshare->trigger_tstamp.tv_sec = tv.tv_sec;
|
dshare->trigger_tstamp.tv_sec = tv.tv_sec;
|
||||||
dshare->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
|
dshare->trigger_tstamp.tv_nsec = tv.tv_usec * 1000L;
|
||||||
|
|
@ -309,7 +355,7 @@ static int snd_pcm_dshare_drop(snd_pcm_t *pcm)
|
||||||
snd_pcm_direct_t *dshare = pcm->private_data;
|
snd_pcm_direct_t *dshare = pcm->private_data;
|
||||||
if (dshare->state == SND_PCM_STATE_OPEN)
|
if (dshare->state == SND_PCM_STATE_OPEN)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
snd_timer_stop(dshare->timer);
|
snd_pcm_direct_timer_stop(dshare);
|
||||||
do_silence(pcm);
|
do_silence(pcm);
|
||||||
dshare->state = SND_PCM_STATE_SETUP;
|
dshare->state = SND_PCM_STATE_SETUP;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -323,22 +369,34 @@ static int snd_pcm_dshare_drain(snd_pcm_t *pcm)
|
||||||
|
|
||||||
if (dshare->state == SND_PCM_STATE_OPEN)
|
if (dshare->state == SND_PCM_STATE_OPEN)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
|
if (pcm->mode & SND_PCM_NONBLOCK)
|
||||||
|
return -EAGAIN;
|
||||||
|
if (dshare->state == SND_PCM_STATE_PREPARED) {
|
||||||
|
if (snd_pcm_mmap_playback_hw_avail(pcm) > 0)
|
||||||
|
snd_pcm_dshare_start(pcm);
|
||||||
|
else {
|
||||||
|
snd_pcm_dshare_drop(pcm);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
stop_threshold = pcm->stop_threshold;
|
stop_threshold = pcm->stop_threshold;
|
||||||
if (pcm->stop_threshold > pcm->buffer_size)
|
if (pcm->stop_threshold > pcm->buffer_size)
|
||||||
pcm->stop_threshold = pcm->buffer_size;
|
pcm->stop_threshold = pcm->buffer_size;
|
||||||
if (dshare->state == SND_PCM_STATE_PREPARED &&
|
dshare->state = SND_PCM_STATE_DRAINING;
|
||||||
snd_pcm_mmap_playback_hw_avail(pcm) > 0)
|
do {
|
||||||
snd_pcm_dshare_start(pcm);
|
|
||||||
while (dshare->state == SND_PCM_STATE_RUNNING) {
|
|
||||||
err = snd_pcm_dshare_sync_ptr(pcm);
|
err = snd_pcm_dshare_sync_ptr(pcm);
|
||||||
if (err < 0)
|
if (err < 0) {
|
||||||
|
snd_pcm_dshare_drop(pcm);
|
||||||
break;
|
break;
|
||||||
if (pcm->mode & SND_PCM_NONBLOCK)
|
}
|
||||||
return -EAGAIN;
|
if (dshare->state == SND_PCM_STATE_DRAINING) {
|
||||||
snd_pcm_wait(pcm, -1);
|
snd_pcm_dshare_sync_area(pcm);
|
||||||
}
|
snd_pcm_wait_nocheck(pcm, -1);
|
||||||
|
snd_pcm_direct_clear_timer_queue(dshare); /* force poll to wait */
|
||||||
|
}
|
||||||
|
} while (dshare->state == SND_PCM_STATE_DRAINING);
|
||||||
pcm->stop_threshold = stop_threshold;
|
pcm->stop_threshold = stop_threshold;
|
||||||
return snd_pcm_dshare_drop(pcm);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_dshare_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTRIBUTE_UNUSED)
|
static int snd_pcm_dshare_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTRIBUTE_UNUSED)
|
||||||
|
|
@ -346,18 +404,22 @@ static int snd_pcm_dshare_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTR
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
static snd_pcm_sframes_t snd_pcm_dshare_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
|
static snd_pcm_sframes_t snd_pcm_dshare_rewind(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_uframes_t frames ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
/* FIXME: substract samples from the mix ring buffer, too? */
|
/* FIXME: substract samples from the mix ring buffer, too? */
|
||||||
snd_pcm_mmap_appl_backward(pcm, frames);
|
snd_pcm_mmap_appl_backward(pcm, frames);
|
||||||
return frames;
|
return frames;
|
||||||
|
#else
|
||||||
|
return -EIO;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static snd_pcm_sframes_t snd_pcm_dshare_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
|
static snd_pcm_sframes_t snd_pcm_dshare_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
|
||||||
{
|
{
|
||||||
snd_pcm_sframes_t avail;
|
snd_pcm_sframes_t avail;
|
||||||
|
|
||||||
avail = snd_pcm_mmap_avail(pcm);
|
avail = snd_pcm_mmap_playback_avail(pcm);
|
||||||
if (avail < 0)
|
if (avail < 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (frames > (snd_pcm_uframes_t)avail)
|
if (frames > (snd_pcm_uframes_t)avail)
|
||||||
|
|
@ -425,28 +487,34 @@ static snd_pcm_sframes_t snd_pcm_dshare_mmap_commit(snd_pcm_t *pcm,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (! size)
|
||||||
|
return 0;
|
||||||
snd_pcm_mmap_appl_forward(pcm, size);
|
snd_pcm_mmap_appl_forward(pcm, size);
|
||||||
if (dshare->state == SND_PCM_STATE_RUNNING) {
|
if (dshare->state == STATE_RUN_PENDING) {
|
||||||
err = snd_pcm_dshare_sync_ptr(pcm);
|
if ((err = snd_pcm_dshare_start_timer(dshare)) < 0)
|
||||||
if (err < 0)
|
|
||||||
return err;
|
return err;
|
||||||
|
} else if (dshare->state == SND_PCM_STATE_RUNNING ||
|
||||||
|
dshare->state == SND_PCM_STATE_DRAINING)
|
||||||
|
snd_pcm_dshare_sync_ptr(pcm);
|
||||||
|
if (dshare->state == SND_PCM_STATE_RUNNING ||
|
||||||
|
dshare->state == SND_PCM_STATE_DRAINING) {
|
||||||
/* ok, we commit the changes after the validation of area */
|
/* ok, we commit the changes after the validation of area */
|
||||||
/* it's intended, although the result might be crappy */
|
/* it's intended, although the result might be crappy */
|
||||||
snd_pcm_dshare_sync_area(pcm, size);
|
snd_pcm_dshare_sync_area(pcm);
|
||||||
|
/* clear timer queue to avoid a bogus return from poll */
|
||||||
|
if (snd_pcm_mmap_playback_avail(pcm) < pcm->avail_min)
|
||||||
|
snd_pcm_direct_clear_timer_queue(dshare);
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static snd_pcm_sframes_t snd_pcm_dshare_avail_update(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
|
static snd_pcm_sframes_t snd_pcm_dshare_avail_update(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_direct_t *dshare = pcm->private_data;
|
snd_pcm_direct_t *dshare = pcm->private_data;
|
||||||
int err;
|
|
||||||
|
|
||||||
if (dshare->state == SND_PCM_STATE_RUNNING) {
|
if (dshare->state == SND_PCM_STATE_RUNNING ||
|
||||||
err = snd_pcm_dshare_sync_ptr(pcm);
|
dshare->state == SND_PCM_STATE_DRAINING)
|
||||||
if (err < 0)
|
snd_pcm_dshare_sync_ptr(pcm);
|
||||||
return err;
|
|
||||||
}
|
|
||||||
return snd_pcm_mmap_playback_avail(pcm);
|
return snd_pcm_mmap_playback_avail(pcm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue