mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-10-29 05:40:25 -04:00 
			
		
		
		
	Added snd_pcm_hwptr() and enhanced snd_pcm_mmap_begin() for no xrun mode.
This commit is contained in:
		
							parent
							
								
									a91efc0fe6
								
							
						
					
					
						commit
						fbd99fdec0
					
				
					 17 changed files with 231 additions and 13 deletions
				
			
		
							
								
								
									
										10
									
								
								src/Versions
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/Versions
									
										
									
									
									
								
							|  | @ -6,6 +6,7 @@ ALSA_0.9 { | |||
|   local: | ||||
|     *; | ||||
| }; | ||||
| 
 | ||||
| ALSA_0.9.0rc4 { | ||||
|   global: | ||||
| 
 | ||||
|  | @ -77,4 +78,11 @@ ALSA_0.9.0rc4 { | |||
|     snd_pcm_hw_params_set_tick_time_first; | ||||
|     snd_pcm_hw_params_set_tick_time_last; | ||||
| 
 | ||||
| }ALSA_0.9; | ||||
| } ALSA_0.9; | ||||
| 
 | ||||
| ALSA_0.9.0rc8 { | ||||
|   global: | ||||
| 
 | ||||
|     snd_pcm_hwptr; | ||||
| 
 | ||||
| } ALSA_0.9.0rc4; | ||||
|  |  | |||
|  | @ -868,6 +868,30 @@ int snd_pcm_hwsync(snd_pcm_t *pcm) | |||
| 	return pcm->fast_ops->hwsync(pcm->fast_op_arg); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief Return hardware pointer | ||||
|  * \param pcm PCM handle | ||||
|  * \return 0 on success otherwise a negative error code | ||||
|  * | ||||
|  * The hardware pointer is in range 0 ... (boundary - 1). It contains | ||||
|  * count_of_ring_buffer_crosses * buffer_size + offset in the ring buffer. | ||||
|  * | ||||
|  * Note this function does not return the real hardware pointer. | ||||
|  * The function \link ::snd_pcm_hwsync \endlink have to be called | ||||
|  * before to obtain the real hardware position. | ||||
|  */ | ||||
| #ifndef DOXYGEN | ||||
| int INTERNAL(snd_pcm_hwptr)(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr) | ||||
| #else | ||||
| int snd_pcm_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr) | ||||
| #endif | ||||
| { | ||||
| 	assert(pcm); | ||||
| 	assert(pcm->setup); | ||||
| 	return pcm->fast_ops->hwptr(pcm->fast_op_arg, hwptr); | ||||
| } | ||||
| default_symbol_version(__snd_pcm_hwptr, snd_pcm_hwptr, ALSA_0.9.0rc8); | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief Obtain delay for a running PCM handle | ||||
|  * \param pcm PCM handle | ||||
|  | @ -5792,7 +5816,7 @@ void snd_pcm_info_set_stream(snd_pcm_info_t *obj, snd_pcm_stream_t val) | |||
|  * \brief Application request to access a portion of direct (mmap) area | ||||
|  * \param pcm PCM handle  | ||||
|  * \param areas Returned mmap channel areas | ||||
|  * \param offset Returned mmap area offset in area steps (== frames) | ||||
|  * \param offset mmap area offset in area steps (== frames) (wanted on entry (see note), returned on exit) | ||||
|  * \param frames mmap area portion size in frames (wanted on entry, contiguous available on exit) | ||||
|  * \return 0 on success otherwise a negative error code | ||||
|  * | ||||
|  | @ -5805,6 +5829,9 @@ void snd_pcm_info_set_stream(snd_pcm_info_t *obj, snd_pcm_stream_t val) | |||
|  * | ||||
|  * See the snd_pcm_mmap_commit() function to finish the frame processing in | ||||
|  * the direct areas. | ||||
|  * | ||||
|  * Note: The offset value is always overriden when stop_threshold < boundary. | ||||
|  *       Otherwise, the application must specify it's own offset value. | ||||
|  *  | ||||
|  */ | ||||
| int snd_pcm_mmap_begin(snd_pcm_t *pcm, | ||||
|  | @ -5817,12 +5844,18 @@ int snd_pcm_mmap_begin(snd_pcm_t *pcm, | |||
| 	snd_pcm_uframes_t avail; | ||||
| 	assert(pcm && areas && offset && frames); | ||||
| 	*areas = snd_pcm_mmap_areas(pcm); | ||||
| 	*offset = *pcm->appl.ptr % pcm->buffer_size; | ||||
| 	if (pcm->stop_threshold < pcm->boundary) { | ||||
| 		*offset = *pcm->appl.ptr % pcm->buffer_size; | ||||
| 		avail = snd_pcm_mmap_avail(pcm); | ||||
| 		if (avail > pcm->buffer_size) | ||||
| 			avail = pcm->buffer_size; | ||||
| 	} else { | ||||
| 		if (*offset >= pcm->buffer_size) | ||||
| 			return -EINVAL; | ||||
| 		avail = pcm->buffer_size; | ||||
| 	} | ||||
| 	cont = pcm->buffer_size - *offset; | ||||
| 	f = *frames; | ||||
| 	avail = snd_pcm_mmap_avail(pcm); | ||||
| 	if (avail > pcm->buffer_size) | ||||
| 		avail = pcm->buffer_size; | ||||
| 	if (f > avail) | ||||
| 		f = avail; | ||||
| 	if (f > cont) | ||||
|  |  | |||
|  | @ -954,7 +954,6 @@ static int snd_pcm_dmix_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) | |||
| 	snd_pcm_dmix_t *dmix = pcm->private_data; | ||||
| 	int err; | ||||
| 	 | ||||
| 	assert(pcm && delayp); | ||||
| 	switch(dmix->state) { | ||||
| 	case SNDRV_PCM_STATE_DRAINING: | ||||
| 	case SNDRV_PCM_STATE_RUNNING: | ||||
|  | @ -990,6 +989,25 @@ static int snd_pcm_dmix_hwsync(snd_pcm_t *pcm) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr) | ||||
| { | ||||
| 	snd_pcm_dmix_t *dmix = pcm->private_data; | ||||
| 
 | ||||
| 	switch(dmix->state) { | ||||
| 	case SNDRV_PCM_STATE_DRAINING: | ||||
| 	case SNDRV_PCM_STATE_RUNNING: | ||||
| 	case SNDRV_PCM_STATE_PREPARED: | ||||
| 	case SNDRV_PCM_STATE_PAUSED: | ||||
| 	case SNDRV_PCM_STATE_SUSPENDED: | ||||
| 		*hwptr = *pcm->hw.ptr; | ||||
| 		return 0; | ||||
| 	case SNDRV_PCM_STATE_XRUN: | ||||
| 		return -EPIPE; | ||||
| 	default: | ||||
| 		return -EBADFD; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_prepare(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_dmix_t *dmix = pcm->private_data; | ||||
|  | @ -1206,6 +1224,7 @@ static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = { | |||
| 	status: snd_pcm_dmix_status, | ||||
| 	state: snd_pcm_dmix_state, | ||||
| 	hwsync: snd_pcm_dmix_hwsync, | ||||
| 	hwptr: snd_pcm_dmix_hwptr, | ||||
| 	delay: snd_pcm_dmix_delay, | ||||
| 	prepare: snd_pcm_dmix_prepare, | ||||
| 	reset: snd_pcm_dmix_reset, | ||||
|  |  | |||
|  | @ -168,6 +168,12 @@ static int snd_pcm_file_hwsync(snd_pcm_t *pcm) | |||
| 	return snd_pcm_hwsync(file->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	return INTERNAL(snd_pcm_hwptr)(file->slave, hwptr); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_file_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
|  | @ -366,6 +372,9 @@ static int snd_pcm_file_hw_free(snd_pcm_t *pcm) | |||
| static int snd_pcm_file_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) | ||||
| { | ||||
| 	snd_pcm_file_t *file = pcm->private_data; | ||||
| 	/* we don't support mode without xrun detection */ | ||||
| 	if (params->stop_threshold >= params->boundary) | ||||
| 		return -EINVAL; | ||||
| 	return snd_pcm_sw_params(file->slave, params); | ||||
| } | ||||
| 
 | ||||
|  | @ -413,6 +422,7 @@ static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = { | |||
| 	status: snd_pcm_file_status, | ||||
| 	state: snd_pcm_file_state, | ||||
| 	hwsync: snd_pcm_file_hwsync, | ||||
| 	hwptr: snd_pcm_file_hwptr, | ||||
| 	delay: snd_pcm_file_delay, | ||||
| 	prepare: snd_pcm_file_prepare, | ||||
| 	reset: snd_pcm_file_reset, | ||||
|  |  | |||
|  | @ -122,6 +122,12 @@ static int snd_pcm_hooks_hwsync(snd_pcm_t *pcm) | |||
| 	return snd_pcm_hwsync(h->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
| 	return INTERNAL(snd_pcm_hwptr)(h->slave, hwptr); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hooks_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) | ||||
| { | ||||
| 	snd_pcm_hooks_t *h = pcm->private_data; | ||||
|  | @ -299,6 +305,7 @@ static snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = { | |||
| 	status: snd_pcm_hooks_status, | ||||
| 	state: snd_pcm_hooks_state, | ||||
| 	hwsync: snd_pcm_hooks_hwsync, | ||||
| 	hwptr: snd_pcm_hooks_hwptr, | ||||
| 	delay: snd_pcm_hooks_delay, | ||||
| 	prepare: snd_pcm_hooks_prepare, | ||||
| 	reset: snd_pcm_hooks_reset, | ||||
|  |  | |||
|  | @ -345,6 +345,9 @@ static int snd_pcm_hw_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) | |||
| 		hw->mmap_control->avail_min = params->avail_min; | ||||
| 		return 0; | ||||
| 	} | ||||
| 	/* FIXME */ | ||||
| 	if (hw->mmap_shm && params->stop_threshold >= params->boundary) | ||||
| 		return -EINVAL; | ||||
| 	if (ioctl(fd, SNDRV_PCM_IOCTL_SW_PARAMS, params) < 0) { | ||||
| 		SYSERR("SNDRV_PCM_IOCTL_SW_PARAMS failed"); | ||||
| 		return -errno; | ||||
|  | @ -428,6 +431,23 @@ static int snd_pcm_hw_hwsync(snd_pcm_t *pcm) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hw_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr) | ||||
| { | ||||
| 	switch (snd_pcm_state(pcm)) { | ||||
| 	case SND_PCM_STATE_RUNNING: | ||||
| 	case SND_PCM_STATE_DRAINING: | ||||
| 	case SND_PCM_STATE_PREPARED: | ||||
| 	case SND_PCM_STATE_PAUSED: | ||||
| 	case SND_PCM_STATE_SUSPENDED: | ||||
| 		*hwptr = *pcm->hw.ptr; | ||||
| 		return 0; | ||||
| 	case SND_PCM_STATE_XRUN: | ||||
| 		return -EPIPE; | ||||
| 	default: | ||||
| 		return -EBADFD; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_hw_prepare(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_hw_t *hw = pcm->private_data; | ||||
|  | @ -690,7 +710,7 @@ static int snd_pcm_hw_close(snd_pcm_t *pcm) | |||
| } | ||||
| 
 | ||||
| static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm, | ||||
| 						snd_pcm_uframes_t offset ATTRIBUTE_UNUSED, | ||||
| 						snd_pcm_uframes_t offset, | ||||
| 						snd_pcm_uframes_t size) | ||||
| { | ||||
| 	snd_pcm_hw_t *hw = pcm->private_data; | ||||
|  | @ -698,6 +718,12 @@ static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm, | |||
| 	if (hw->mmap_shm) { | ||||
| 		if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { | ||||
| 		    	snd_pcm_sframes_t result = 0, res; | ||||
| 			snd_pcm_uframes_t last_offset; | ||||
| 
 | ||||
| 			/* FIXME */ | ||||
| 			last_offset = *pcm->appl.ptr - offset; | ||||
| 			if (last_offset != offset) | ||||
| 				return -EINVAL; | ||||
| 
 | ||||
| 			do { | ||||
| 				res = snd_pcm_write_mmap(pcm, size); | ||||
|  | @ -793,6 +819,7 @@ static snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = { | |||
| 	status: snd_pcm_hw_status, | ||||
| 	state: snd_pcm_hw_state, | ||||
| 	hwsync: snd_pcm_hw_hwsync, | ||||
| 	hwptr: snd_pcm_hw_hwptr, | ||||
| 	delay: snd_pcm_hw_delay, | ||||
| 	prepare: snd_pcm_hw_prepare, | ||||
| 	reset: snd_pcm_hw_reset, | ||||
|  |  | |||
|  | @ -185,6 +185,24 @@ static int snd_pcm_jack_hwsync(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_jack_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr) | ||||
| { | ||||
| #ifdef PCM_JACK_DEBUG | ||||
| 	printf("snd_pcm_jack_hwptr\n"); fflush(stdout); | ||||
| #endif | ||||
| 	switch (snd_pcm_state(pcm)) { | ||||
| 	case SND_PCM_STATE_RUNNING: | ||||
| 	case SND_PCM_STATE_DRAINING: | ||||
| 	case SND_PCM_STATE_PREPARED: | ||||
| 	case SND_PCM_STATE_PAUSED: | ||||
| 	case SND_PCM_STATE_SUSPENDED: | ||||
| 		*hwptr = *pcm->hw.ptr; | ||||
| 		return 0; | ||||
| 	default: | ||||
| 		return -EBADFD; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_jack_delay(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sframes_t *delayp) | ||||
| { | ||||
| #ifdef PCM_JACK_DEBUG | ||||
|  | @ -593,6 +611,7 @@ static snd_pcm_fast_ops_t snd_pcm_jack_fast_ops = { | |||
| 	status: snd_pcm_jack_status, | ||||
| 	state: snd_pcm_jack_state, | ||||
| 	hwsync: snd_pcm_jack_hwsync, | ||||
| 	hwptr: snd_pcm_jack_hwptr, | ||||
| 	delay: snd_pcm_jack_delay, | ||||
| 	prepare: snd_pcm_jack_prepare, | ||||
| 	reset: snd_pcm_jack_reset, | ||||
|  |  | |||
|  | @ -147,6 +147,7 @@ typedef struct { | |||
| 	int (*pause)(snd_pcm_t *pcm, int enable); | ||||
| 	snd_pcm_state_t (*state)(snd_pcm_t *pcm); | ||||
| 	int (*hwsync)(snd_pcm_t *pcm); | ||||
| 	int (*hwptr)(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr); | ||||
| 	int (*delay)(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp); | ||||
| 	int (*resume)(snd_pcm_t *pcm); | ||||
| 	snd_pcm_sframes_t (*rewind)(snd_pcm_t *pcm, snd_pcm_uframes_t frames); | ||||
|  | @ -549,6 +550,8 @@ int snd_pcm_hw_param_get_max(const snd_pcm_hw_params_t *params, | |||
| 			     unsigned int *val, int *dir); | ||||
| 
 | ||||
| #ifdef INTERNAL | ||||
| int INTERNAL(snd_pcm_hwptr)(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr); | ||||
| 
 | ||||
| int INTERNAL(snd_pcm_hw_params_get_access)(const snd_pcm_hw_params_t *params, snd_pcm_access_t *access); | ||||
| int snd_pcm_hw_params_test_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access); | ||||
| int snd_pcm_hw_params_set_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access); | ||||
|  |  | |||
|  | @ -325,6 +325,12 @@ static int snd_pcm_meter_hwsync(snd_pcm_t *pcm) | |||
| 	return snd_pcm_hwsync(meter->slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_meter_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr) | ||||
| { | ||||
| 	snd_pcm_meter_t *meter = pcm->private_data; | ||||
| 	return INTERNAL(snd_pcm_hwptr)(meter->slave, hwptr); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_meter_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) | ||||
| { | ||||
| 	snd_pcm_meter_t *meter = pcm->private_data; | ||||
|  |  | |||
|  | @ -89,7 +89,7 @@ static int snd_pcm_multi_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock | |||
| static int snd_pcm_multi_async(snd_pcm_t *pcm, int sig, pid_t pid) | ||||
| { | ||||
| 	snd_pcm_multi_t *multi = pcm->private_data; | ||||
| 	snd_pcm_t *slave_0 = multi->slaves[0].pcm; | ||||
| 	snd_pcm_t *slave_0 = multi->slaves[multi->master_slave].pcm; | ||||
| 	return snd_pcm_async(slave_0, sig, pid); | ||||
| } | ||||
| 
 | ||||
|  | @ -340,28 +340,35 @@ static int snd_pcm_multi_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) | |||
| static int snd_pcm_multi_status(snd_pcm_t *pcm, snd_pcm_status_t *status) | ||||
| { | ||||
| 	snd_pcm_multi_t *multi = pcm->private_data; | ||||
| 	snd_pcm_t *slave = multi->slaves[0].pcm; | ||||
| 	snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm; | ||||
| 	return snd_pcm_status(slave, status); | ||||
| } | ||||
| 
 | ||||
| static snd_pcm_state_t snd_pcm_multi_state(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_multi_t *multi = pcm->private_data; | ||||
| 	snd_pcm_t *slave = multi->slaves[0].pcm; | ||||
| 	snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm; | ||||
| 	return snd_pcm_state(slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_multi_hwsync(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_multi_t *multi = pcm->private_data; | ||||
| 	snd_pcm_t *slave = multi->slaves[0].pcm; | ||||
| 	snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm; | ||||
| 	return snd_pcm_hwsync(slave); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_multi_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr) | ||||
| { | ||||
| 	snd_pcm_multi_t *multi = pcm->private_data; | ||||
| 	snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm; | ||||
| 	return INTERNAL(snd_pcm_hwptr)(slave, hwptr); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_multi_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) | ||||
| { | ||||
| 	snd_pcm_multi_t *multi = pcm->private_data; | ||||
| 	snd_pcm_t *slave = multi->slaves[0].pcm; | ||||
| 	snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm; | ||||
| 	return snd_pcm_delay(slave, delayp); | ||||
| } | ||||
| 
 | ||||
|  | @ -602,6 +609,7 @@ static snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = { | |||
| 	status: snd_pcm_multi_status, | ||||
| 	state: snd_pcm_multi_state, | ||||
| 	hwsync: snd_pcm_multi_hwsync, | ||||
| 	hwptr: snd_pcm_multi_hwptr, | ||||
| 	delay: snd_pcm_multi_delay, | ||||
| 	prepare: snd_pcm_multi_prepare, | ||||
| 	reset: snd_pcm_multi_reset, | ||||
|  |  | |||
|  | @ -105,6 +105,23 @@ static int snd_pcm_null_hwsync(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_null_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr) | ||||
| { | ||||
| 	switch (snd_pcm_state(pcm)) { | ||||
| 	case SND_PCM_STATE_RUNNING: | ||||
| 	case SND_PCM_STATE_DRAINING: | ||||
| 	case SND_PCM_STATE_PREPARED: | ||||
| 	case SND_PCM_STATE_PAUSED: | ||||
| 	case SND_PCM_STATE_SUSPENDED: | ||||
| 		*hwptr = *pcm->hw.ptr; | ||||
| 		return 0; | ||||
| 	case SND_PCM_STATE_XRUN: | ||||
| 		return -EPIPE; | ||||
| 	default: | ||||
| 		return -EBADFD; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_null_delay(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sframes_t *delayp) | ||||
| { | ||||
| 	*delayp = 0; | ||||
|  | @ -312,6 +329,7 @@ static snd_pcm_fast_ops_t snd_pcm_null_fast_ops = { | |||
| 	status: snd_pcm_null_status, | ||||
| 	state: snd_pcm_null_state, | ||||
| 	hwsync: snd_pcm_null_hwsync, | ||||
| 	hwptr: snd_pcm_null_hwptr, | ||||
| 	delay: snd_pcm_null_delay, | ||||
| 	prepare: snd_pcm_null_prepare, | ||||
| 	reset: snd_pcm_null_reset, | ||||
|  |  | |||
|  | @ -199,6 +199,12 @@ int snd_pcm_plugin_hwsync(snd_pcm_t *pcm) | |||
| 	return snd_pcm_hwsync(plugin->slave); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
| 	return INTERNAL(snd_pcm_hwptr)(plugin->slave, hwptr); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) | ||||
| { | ||||
| 	snd_pcm_plugin_t *plugin = pcm->private_data; | ||||
|  | @ -626,6 +632,7 @@ snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = { | |||
| 	status: snd_pcm_plugin_status, | ||||
| 	state: snd_pcm_plugin_state, | ||||
| 	hwsync: snd_pcm_plugin_hwsync, | ||||
| 	hwptr: snd_pcm_plugin_hwptr, | ||||
| 	delay: snd_pcm_plugin_delay, | ||||
| 	prepare: snd_pcm_plugin_prepare, | ||||
| 	reset: snd_pcm_plugin_reset, | ||||
|  |  | |||
|  | @ -737,6 +737,36 @@ static int snd_pcm_share_hwsync(snd_pcm_t *pcm) | |||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| static int _snd_pcm_share_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr) | ||||
| { | ||||
| 	snd_pcm_share_t *share = pcm->private_data; | ||||
| 	snd_pcm_share_slave_t *slave = share->slave; | ||||
| 	switch (share->state) { | ||||
| 	case SND_PCM_STATE_RUNNING: | ||||
| 	case SND_PCM_STATE_DRAINING: | ||||
| 	case SND_PCM_STATE_PREPARED: | ||||
| 	case SND_PCM_STATE_PAUSED: | ||||
| 	case SND_PCM_STATE_SUSPENDED: | ||||
| 		*hwptr = *pcm->hw.ptr; | ||||
| 		return 0; | ||||
| 	case SND_PCM_STATE_XRUN: | ||||
| 		return -EPIPE; | ||||
| 	default: | ||||
| 		return -EBADFD; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_share_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr) | ||||
| { | ||||
| 	snd_pcm_share_t *share = pcm->private_data; | ||||
| 	snd_pcm_share_slave_t *slave = share->slave; | ||||
| 	int err; | ||||
| 	Pthread_mutex_lock(&slave->mutex); | ||||
| 	err = _snd_pcm_share_hwptr(pcm, hwptr); | ||||
| 	Pthread_mutex_unlock(&slave->mutex); | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| static int _snd_pcm_share_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) | ||||
| { | ||||
| 	snd_pcm_share_t *share = pcm->private_data; | ||||
|  | @ -1234,6 +1264,7 @@ static snd_pcm_fast_ops_t snd_pcm_share_fast_ops = { | |||
| 	status: snd_pcm_share_status, | ||||
| 	state: snd_pcm_share_state, | ||||
| 	hwsync: snd_pcm_share_hwsync, | ||||
| 	hwptr: snd_pcm_share_hwptr, | ||||
| 	delay: snd_pcm_share_delay, | ||||
| 	prepare: snd_pcm_share_prepare, | ||||
| 	reset: snd_pcm_share_reset, | ||||
|  |  | |||
|  | @ -451,6 +451,19 @@ static int snd_pcm_shm_hwsync(snd_pcm_t *pcm) | |||
| 	return snd_pcm_shm_action(pcm); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_shm_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *uframes) | ||||
| { | ||||
| 	snd_pcm_shm_t *shm = pcm->private_data; | ||||
| 	volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; | ||||
| 	int err; | ||||
| 	ctrl->cmd = SND_PCM_IOCTL_HWPTR; | ||||
| 	return snd_pcm_shm_action(pcm); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	*uframes = ctrl->u.hwptr.frames; | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_shm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) | ||||
| { | ||||
| 	snd_pcm_shm_t *shm = pcm->private_data; | ||||
|  | @ -619,6 +632,7 @@ static snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = { | |||
| 	status: snd_pcm_shm_status, | ||||
| 	state: snd_pcm_shm_state, | ||||
| 	hwsync: snd_pcm_shm_hwsync, | ||||
| 	hwptr: snd_pcm_shm_hwptr, | ||||
| 	delay: snd_pcm_shm_delay, | ||||
| 	prepare: snd_pcm_shm_prepare, | ||||
| 	reset: snd_pcm_shm_reset, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jaroslav Kysela
						Jaroslav Kysela