mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -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