mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	pcm: dmix: Do not discard slave reported delay in status result
Like the change done for dshare plugin, we can calculate the delay more precisely from the slave PCM. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
		
							parent
							
								
									ea74ebbe4d
								
							
						
					
					
						commit
						38a2d2eda8
					
				
					 1 changed files with 28 additions and 17 deletions
				
			
		| 
						 | 
					@ -391,23 +391,14 @@ static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *  synchronize hardware pointer (hw_ptr) with ours
 | 
					 *  synchronize hardware pointer (hw_ptr) with ours
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
 | 
					static int snd_pcm_dmix_sync_ptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_ptr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	snd_pcm_direct_t *dmix = pcm->private_data;
 | 
						snd_pcm_direct_t *dmix = pcm->private_data;
 | 
				
			||||||
	snd_pcm_uframes_t slave_hw_ptr, old_slave_hw_ptr, avail;
 | 
						snd_pcm_uframes_t old_slave_hw_ptr, avail;
 | 
				
			||||||
	snd_pcm_sframes_t diff;
 | 
						snd_pcm_sframes_t diff;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	switch (snd_pcm_state(dmix->spcm)) {
 | 
					 | 
				
			||||||
	case SND_PCM_STATE_DISCONNECTED:
 | 
					 | 
				
			||||||
		dmix->state = SND_PCM_STATE_DISCONNECTED;
 | 
					 | 
				
			||||||
		return -ENODEV;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (dmix->slowptr)
 | 
					 | 
				
			||||||
		snd_pcm_hwsync(dmix->spcm);
 | 
					 | 
				
			||||||
	old_slave_hw_ptr = dmix->slave_hw_ptr;
 | 
						old_slave_hw_ptr = dmix->slave_hw_ptr;
 | 
				
			||||||
	slave_hw_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
 | 
						dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
 | 
				
			||||||
	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;
 | 
				
			||||||
| 
						 | 
					@ -440,6 +431,24 @@ static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						snd_pcm_direct_t *dmix = pcm->private_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (snd_pcm_state(dmix->spcm)) {
 | 
				
			||||||
 | 
						case SND_PCM_STATE_DISCONNECTED:
 | 
				
			||||||
 | 
							dmix->state = SND_PCM_STATE_DISCONNECTED;
 | 
				
			||||||
 | 
							return -ENODEV;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dmix->slowptr)
 | 
				
			||||||
 | 
							snd_pcm_hwsync(dmix->spcm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return snd_pcm_dmix_sync_ptr0(pcm, *dmix->spcm->hw.ptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *  plugin implementation
 | 
					 *  plugin implementation
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -467,22 +476,24 @@ static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	snd_pcm_direct_t *dmix = pcm->private_data;
 | 
						snd_pcm_direct_t *dmix = pcm->private_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(status, 0, sizeof(*status));
 | 
				
			||||||
 | 
						snd_pcm_status(dmix->spcm, status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (dmix->state) {
 | 
						switch (dmix->state) {
 | 
				
			||||||
	case SNDRV_PCM_STATE_DRAINING:
 | 
						case SNDRV_PCM_STATE_DRAINING:
 | 
				
			||||||
	case SNDRV_PCM_STATE_RUNNING:
 | 
						case SNDRV_PCM_STATE_RUNNING:
 | 
				
			||||||
		snd_pcm_dmix_sync_ptr(pcm);
 | 
							snd_pcm_dmix_sync_ptr0(pcm, status->hw_ptr);
 | 
				
			||||||
 | 
							status->delay += snd_pcm_mmap_playback_delay(pcm)
 | 
				
			||||||
 | 
									+ status->avail - dmix->spcm->buffer_size;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	memset(status, 0, sizeof(*status));
 | 
					
 | 
				
			||||||
	snd_pcm_status(dmix->spcm, status);
 | 
					 | 
				
			||||||
	status->state = snd_pcm_dmix_state(pcm);
 | 
					 | 
				
			||||||
	status->trigger_tstamp = dmix->trigger_tstamp;
 | 
						status->trigger_tstamp = dmix->trigger_tstamp;
 | 
				
			||||||
	status->avail = snd_pcm_mmap_playback_avail(pcm);
 | 
						status->avail = snd_pcm_mmap_playback_avail(pcm);
 | 
				
			||||||
	status->avail_max = status->avail > dmix->avail_max ? status->avail : dmix->avail_max;
 | 
						status->avail_max = status->avail > dmix->avail_max ? status->avail : dmix->avail_max;
 | 
				
			||||||
	dmix->avail_max = 0;
 | 
						dmix->avail_max = 0;
 | 
				
			||||||
	status->delay = snd_pcm_mmap_playback_delay(pcm);
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue