mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-10-29 05:40:25 -04:00 
			
		
		
		
	Direct plugins update:
- moved more common code to pcm_direct.c - added missing initialization of some variables in hw_params
This commit is contained in:
		
							parent
							
								
									c0e493eb5a
								
							
						
					
					
						commit
						95418afc67
					
				
					 5 changed files with 244 additions and 585 deletions
				
			
		|  | @ -374,6 +374,199 @@ int snd_pcm_direct_client_discard(snd_pcm_direct_t *dmix) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  plugin helpers | ||||
|  */ | ||||
| 
 | ||||
| int snd_pcm_direct_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* value is cached for us in pcm->mode (SND_PCM_NONBLOCK flag) */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_direct_async(snd_pcm_t *pcm, int sig, pid_t pid) | ||||
| { | ||||
| 	snd_pcm_direct_t *dmix = pcm->private_data; | ||||
| 	return snd_timer_async(dmix->timer, sig, pid); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) | ||||
| { | ||||
| 	snd_pcm_direct_t *dmix = pcm->private_data; | ||||
| 	unsigned short events; | ||||
| 	static snd_timer_read_t rbuf[5];	/* can be overwriten by multiple plugins, we don't need the value */ | ||||
| 
 | ||||
| 	assert(pfds && nfds == 1 && revents); | ||||
| 	events = pfds[0].revents; | ||||
| 	if (events & POLLIN) { | ||||
| 		events |= POLLOUT; | ||||
| 		events &= ~POLLIN; | ||||
| 		/* empty the timer read queue */ | ||||
| 		while (snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)) == sizeof(rbuf)) ; | ||||
| 	} | ||||
| 	*revents = events; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_direct_info(snd_pcm_t *pcm, snd_pcm_info_t * info) | ||||
| { | ||||
| 	// snd_pcm_direct_t *dmix = pcm->private_data;
 | ||||
| 
 | ||||
| 	memset(info, 0, sizeof(*info)); | ||||
| 	info->stream = pcm->stream; | ||||
| 	info->card = -1; | ||||
| 	/* FIXME: fill this with something more useful: we know the hardware name */ | ||||
| 	if (pcm->name) { | ||||
| 		strncpy(info->id, pcm->name, sizeof(info->id)); | ||||
| 		strncpy(info->name, pcm->name, sizeof(info->name)); | ||||
| 		strncpy(info->subname, pcm->name, sizeof(info->subname)); | ||||
| 	} | ||||
| 	info->subdevices_count = 1; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static inline snd_mask_t *hw_param_mask(snd_pcm_hw_params_t *params, | ||||
| 					snd_pcm_hw_param_t var) | ||||
| { | ||||
| 	return ¶ms->masks[var - SND_PCM_HW_PARAM_FIRST_MASK]; | ||||
| } | ||||
| 
 | ||||
| static inline snd_interval_t *hw_param_interval(snd_pcm_hw_params_t *params, | ||||
| 						snd_pcm_hw_param_t var) | ||||
| { | ||||
| 	return ¶ms->intervals[var - SND_PCM_HW_PARAM_FIRST_INTERVAL]; | ||||
| } | ||||
| 
 | ||||
| static int hw_param_interval_refine_one(snd_pcm_hw_params_t *params, | ||||
| 					snd_pcm_hw_param_t var, | ||||
| 					snd_pcm_hw_params_t *src) | ||||
| { | ||||
| 	snd_interval_t *i; | ||||
| 
 | ||||
| 	if (!(params->rmask & (1<<var)))	/* nothing to do? */ | ||||
| 		return 0; | ||||
| 	i = hw_param_interval(params, var); | ||||
| 	if (snd_interval_empty(i)) { | ||||
| 		SNDERR("dshare interval %i empty?", (int)var); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 	if (snd_interval_refine(i, hw_param_interval(src, var))) | ||||
| 		params->cmask |= 1<<var; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #undef REFINE_DEBUG | ||||
| 
 | ||||
| int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_direct_t *dshare = pcm->private_data; | ||||
| 	snd_pcm_hw_params_t *hw_params = &dshare->shmptr->hw_params; | ||||
| 	static snd_mask_t access = { .bits = {  | ||||
| 					(1<<SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) | | ||||
| 					(1<<SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED) | | ||||
| 					(1<<SNDRV_PCM_ACCESS_RW_INTERLEAVED) | | ||||
| 					(1<<SNDRV_PCM_ACCESS_RW_NONINTERLEAVED), | ||||
| 					0, 0, 0 } }; | ||||
| 	int err; | ||||
| 
 | ||||
| #ifdef REFINE_DEBUG | ||||
| 	snd_output_t *log; | ||||
| 	snd_output_stdio_attach(&log, stderr, 0); | ||||
| 	snd_output_puts(log, "DMIX REFINE (begin):\n"); | ||||
| 	snd_pcm_hw_params_dump(params, log); | ||||
| #endif | ||||
| 	if (params->rmask & (1<<SND_PCM_HW_PARAM_ACCESS)) { | ||||
| 		if (snd_mask_empty(hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS))) { | ||||
| 			SNDERR("dshare access mask empty?"); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 		if (snd_mask_refine(hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS), &access)) | ||||
| 			params->cmask |= 1<<SND_PCM_HW_PARAM_ACCESS; | ||||
| 	} | ||||
| 	if (params->rmask & (1<<SND_PCM_HW_PARAM_FORMAT)) { | ||||
| 		if (snd_mask_empty(hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT))) { | ||||
| 			SNDERR("dshare format mask empty?"); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 		if (snd_mask_refine_set(hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT), | ||||
| 				        snd_mask_value(hw_param_mask(hw_params, SND_PCM_HW_PARAM_FORMAT)))) | ||||
| 			params->cmask |= 1<<SND_PCM_HW_PARAM_FORMAT; | ||||
| 	} | ||||
| 	//snd_mask_none(hw_param_mask(params, SND_PCM_HW_PARAM_SUBFORMAT));
 | ||||
| 	if (params->rmask & (1<<SND_PCM_HW_PARAM_CHANNELS)) { | ||||
| 		if (snd_interval_empty(hw_param_interval(params, SND_PCM_HW_PARAM_CHANNELS))) { | ||||
| 			SNDERR("dshare channels mask empty?"); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 		err = snd_interval_refine_set(hw_param_interval(params, SND_PCM_HW_PARAM_CHANNELS), dshare->channels); | ||||
| 		if (err < 0) | ||||
| 			return err; | ||||
| 	} | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_RATE, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_SIZE, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_TIME, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIODS, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| #ifdef REFINE_DEBUG | ||||
| 	snd_output_puts(log, "DMIX REFINE (end):\n"); | ||||
| 	snd_pcm_hw_params_dump(params, log); | ||||
| 	snd_output_close(log); | ||||
| #endif | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_direct_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) | ||||
| { | ||||
| 	snd_pcm_direct_t *dmix = pcm->private_data; | ||||
| 
 | ||||
| 	params->info = dmix->shmptr->s.info; | ||||
| 	params->rate_num = dmix->shmptr->s.rate; | ||||
| 	params->rate_den = 1; | ||||
| 	params->fifo_size = 0; | ||||
| 	params->msbits = dmix->shmptr->s.msbits; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_direct_hw_free(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* values are cached in the pcm structure */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_direct_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t * params ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* values are cached in the pcm structure */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_direct_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info) | ||||
| { | ||||
|         return snd_pcm_channel_info_shm(pcm, info, -1); | ||||
| } | ||||
| 
 | ||||
| int snd_pcm_direct_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
|          | ||||
| int snd_pcm_direct_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * this function initializes hardware and starts playback operation with | ||||
|  * no stop threshold (it operates all time without xrun checking) | ||||
|  | @ -578,6 +771,8 @@ int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, str | |||
| 	dmix->shmptr->s.rate = spcm->rate; | ||||
| 	dmix->shmptr->s.format = spcm->format; | ||||
| 	dmix->shmptr->s.boundary = spcm->boundary; | ||||
| 	dmix->shmptr->s.info = spcm->info; | ||||
| 	dmix->shmptr->s.msbits = spcm->msbits; | ||||
| 
 | ||||
| 	spcm->donot_close = 1; | ||||
| 	return 0; | ||||
|  |  | |||
|  | @ -64,6 +64,8 @@ typedef struct { | |||
| 		unsigned int sample_bits; | ||||
| 		unsigned int rate; | ||||
| 		snd_pcm_format_t format; | ||||
| 		unsigned int info; | ||||
| 		unsigned int msbits; | ||||
| 	} s; | ||||
| 	union { | ||||
| 		struct { | ||||
|  | @ -128,6 +130,17 @@ int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, str | |||
| int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix); | ||||
| int snd_pcm_direct_check_interleave(snd_pcm_direct_t *dmix, snd_pcm_t *pcm); | ||||
| int snd_pcm_direct_parse_bindings(snd_pcm_direct_t *dmix, snd_config_t *cfg); | ||||
| int snd_pcm_direct_nonblock(snd_pcm_t *pcm, int nonblock); | ||||
| int snd_pcm_direct_async(snd_pcm_t *pcm, int sig, pid_t pid); | ||||
| int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents); | ||||
| int snd_pcm_direct_info(snd_pcm_t *pcm, snd_pcm_info_t * info); | ||||
| int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); | ||||
| int snd_pcm_direct_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params); | ||||
| int snd_pcm_direct_hw_free(snd_pcm_t *pcm); | ||||
| int snd_pcm_direct_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params); | ||||
| int snd_pcm_direct_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info); | ||||
| int snd_pcm_direct_mmap(snd_pcm_t *pcm); | ||||
| int snd_pcm_direct_munmap(snd_pcm_t *pcm); | ||||
| 
 | ||||
| int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid); | ||||
| struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm); | ||||
|  |  | |||
|  | @ -376,180 +376,6 @@ static int snd_pcm_dmix_sync_ptr(snd_pcm_t *pcm) | |||
|  *  plugin implementation | ||||
|  */ | ||||
| 
 | ||||
| static int snd_pcm_dmix_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* value is cached for us in pcm->mode (SND_PCM_NONBLOCK flag) */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_async(snd_pcm_t *pcm, int sig, pid_t pid) | ||||
| { | ||||
| 	snd_pcm_direct_t *dmix = pcm->private_data; | ||||
| 	return snd_timer_async(dmix->timer, sig, pid); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) | ||||
| { | ||||
| 	snd_pcm_direct_t *dmix = pcm->private_data; | ||||
| 	unsigned short events; | ||||
| 	static snd_timer_read_t rbuf[5];	/* can be overwriten by multiple plugins, we don't need the value */ | ||||
| 
 | ||||
| 	assert(pfds && nfds == 1 && revents); | ||||
| 	events = pfds[0].revents; | ||||
| 	if (events & POLLIN) { | ||||
| 		events |= POLLOUT; | ||||
| 		events &= ~POLLIN; | ||||
| 		/* empty the timer read queue */ | ||||
| 		while (snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)) == sizeof(rbuf)) ; | ||||
| 	} | ||||
| 	*revents = events; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_info(snd_pcm_t *pcm, snd_pcm_info_t * info) | ||||
| { | ||||
| 	// snd_pcm_direct_t *dmix = pcm->private_data;
 | ||||
| 
 | ||||
| 	memset(info, 0, sizeof(*info)); | ||||
| 	info->stream = pcm->stream; | ||||
| 	info->card = -1; | ||||
| 	/* FIXME: fill this with something more useful: we know the hardware name */ | ||||
| 	if (pcm->name) { | ||||
| 		strncpy(info->id, pcm->name, sizeof(info->id)); | ||||
| 		strncpy(info->name, pcm->name, sizeof(info->name)); | ||||
| 		strncpy(info->subname, pcm->name, sizeof(info->subname)); | ||||
| 	} | ||||
| 	info->subdevices_count = 1; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static inline snd_mask_t *hw_param_mask(snd_pcm_hw_params_t *params, | ||||
| 					snd_pcm_hw_param_t var) | ||||
| { | ||||
| 	return ¶ms->masks[var - SND_PCM_HW_PARAM_FIRST_MASK]; | ||||
| } | ||||
| 
 | ||||
| static inline snd_interval_t *hw_param_interval(snd_pcm_hw_params_t *params, | ||||
| 						snd_pcm_hw_param_t var) | ||||
| { | ||||
| 	return ¶ms->intervals[var - SND_PCM_HW_PARAM_FIRST_INTERVAL]; | ||||
| } | ||||
| 
 | ||||
| static int hw_param_interval_refine_one(snd_pcm_hw_params_t *params, | ||||
| 					snd_pcm_hw_param_t var, | ||||
| 					snd_pcm_hw_params_t *src) | ||||
| { | ||||
| 	snd_interval_t *i; | ||||
| 
 | ||||
| 	if (!(params->rmask & (1<<var)))	/* nothing to do? */ | ||||
| 		return 0; | ||||
| 	i = hw_param_interval(params, var); | ||||
| 	if (snd_interval_empty(i)) { | ||||
| 		SNDERR("dmix interval %i empty?", (int)var); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 	if (snd_interval_refine(i, hw_param_interval(src, var))) | ||||
| 		params->cmask |= 1<<var; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #undef REFINE_DEBUG | ||||
| 
 | ||||
| static int snd_pcm_dmix_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_direct_t *dmix = pcm->private_data; | ||||
| 	snd_pcm_hw_params_t *hw_params = &dmix->shmptr->hw_params; | ||||
| 	static snd_mask_t access = { .bits = {  | ||||
| 					(1<<SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) | | ||||
| 					(1<<SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED) | | ||||
| 					(1<<SNDRV_PCM_ACCESS_RW_INTERLEAVED) | | ||||
| 					(1<<SNDRV_PCM_ACCESS_RW_NONINTERLEAVED), | ||||
| 					0, 0, 0 } }; | ||||
| 	int err; | ||||
| 
 | ||||
| #ifdef REFINE_DEBUG | ||||
| 	snd_output_t *log; | ||||
| 	snd_output_stdio_attach(&log, stderr, 0); | ||||
| 	snd_output_puts(log, "DMIX REFINE (begin):\n"); | ||||
| 	snd_pcm_hw_params_dump(params, log); | ||||
| #endif | ||||
| 	if (params->rmask & (1<<SND_PCM_HW_PARAM_ACCESS)) { | ||||
| 		if (snd_mask_empty(hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS))) { | ||||
| 			SNDERR("dmix access mask empty?"); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 		if (snd_mask_refine(hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS), &access)) | ||||
| 			params->cmask |= 1<<SND_PCM_HW_PARAM_ACCESS; | ||||
| 	} | ||||
| 	if (params->rmask & (1<<SND_PCM_HW_PARAM_FORMAT)) { | ||||
| 		if (snd_mask_empty(hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT))) { | ||||
| 			SNDERR("dmix format mask empty?"); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 		if (snd_mask_refine_set(hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT), | ||||
| 				        snd_mask_value(hw_param_mask(hw_params, SND_PCM_HW_PARAM_FORMAT)))) | ||||
| 			params->cmask |= 1<<SND_PCM_HW_PARAM_FORMAT; | ||||
| 	} | ||||
| 	//snd_mask_none(hw_param_mask(params, SND_PCM_HW_PARAM_SUBFORMAT));
 | ||||
| 	if (params->rmask & (1<<SND_PCM_HW_PARAM_CHANNELS)) { | ||||
| 		if (snd_interval_empty(hw_param_interval(params, SND_PCM_HW_PARAM_CHANNELS))) { | ||||
| 			SNDERR("dmix channels mask empty?"); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 		err = snd_interval_refine_set(hw_param_interval(params, SND_PCM_HW_PARAM_CHANNELS), dmix->channels); | ||||
| 		if (err < 0) | ||||
| 			return err; | ||||
| 	} | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_RATE, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_SIZE, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_TIME, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIODS, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| #ifdef REFINE_DEBUG | ||||
| 	snd_output_puts(log, "DMIX REFINE (end):\n"); | ||||
| 	snd_pcm_hw_params_dump(params, log); | ||||
| 	snd_output_close(log); | ||||
| #endif | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_hw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t * params ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* values are cached in the pcm structure */ | ||||
| 	 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_hw_free(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* values are cached in the pcm structure */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t * params ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* values are cached in the pcm structure */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info) | ||||
| { | ||||
|         return snd_pcm_channel_info_shm(pcm, info, -1); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status) | ||||
| { | ||||
| 	snd_pcm_direct_t *dmix = pcm->private_data; | ||||
|  | @ -752,16 +578,6 @@ static snd_pcm_sframes_t snd_pcm_dmix_readn(snd_pcm_t *pcm ATTRIBUTE_UNUSED, voi | |||
| 	return -ENODEV; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dmix_close(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_direct_t *dmix = pcm->private_data; | ||||
|  | @ -835,18 +651,18 @@ static void snd_pcm_dmix_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_dmix_ops = { | ||||
| 	.close = snd_pcm_dmix_close, | ||||
| 	.info = snd_pcm_dmix_info, | ||||
| 	.hw_refine = snd_pcm_dmix_hw_refine, | ||||
| 	.hw_params = snd_pcm_dmix_hw_params, | ||||
| 	.hw_free = snd_pcm_dmix_hw_free, | ||||
| 	.sw_params = snd_pcm_dmix_sw_params, | ||||
| 	.channel_info = snd_pcm_dmix_channel_info, | ||||
| 	.info = snd_pcm_direct_info, | ||||
| 	.hw_refine = snd_pcm_direct_hw_refine, | ||||
| 	.hw_params = snd_pcm_direct_hw_params, | ||||
| 	.hw_free = snd_pcm_direct_hw_free, | ||||
| 	.sw_params = snd_pcm_direct_sw_params, | ||||
| 	.channel_info = snd_pcm_direct_channel_info, | ||||
| 	.dump = snd_pcm_dmix_dump, | ||||
| 	.nonblock = snd_pcm_dmix_nonblock, | ||||
| 	.async = snd_pcm_dmix_async, | ||||
| 	.poll_revents = snd_pcm_dmix_poll_revents, | ||||
| 	.mmap = snd_pcm_dmix_mmap, | ||||
| 	.munmap = snd_pcm_dmix_munmap, | ||||
| 	.nonblock = snd_pcm_direct_nonblock, | ||||
| 	.async = snd_pcm_direct_async, | ||||
| 	.poll_revents = snd_pcm_direct_poll_revents, | ||||
| 	.mmap = snd_pcm_direct_mmap, | ||||
| 	.munmap = snd_pcm_direct_munmap, | ||||
| }; | ||||
| 
 | ||||
| static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = { | ||||
|  | @ -999,6 +815,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, | |||
| 		spcm->channels = dmix->shmptr->s.channels; | ||||
| 		spcm->format = dmix->shmptr->s.format; | ||||
| 		spcm->boundary = dmix->shmptr->s.boundary; | ||||
| 		spcm->info = dmix->shmptr->s.info; | ||||
| 		ret = snd_pcm_mmap(spcm); | ||||
| 		if (ret < 0) { | ||||
| 			SNDERR("unable to mmap channels"); | ||||
|  |  | |||
|  | @ -163,180 +163,6 @@ static int snd_pcm_dshare_sync_ptr(snd_pcm_t *pcm) | |||
|  *  plugin implementation | ||||
|  */ | ||||
| 
 | ||||
| static int snd_pcm_dshare_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* value is cached for us in pcm->mode (SND_PCM_NONBLOCK flag) */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dshare_async(snd_pcm_t *pcm, int sig, pid_t pid) | ||||
| { | ||||
| 	snd_pcm_direct_t *dshare = pcm->private_data; | ||||
| 	return snd_timer_async(dshare->timer, sig, pid); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dshare_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) | ||||
| { | ||||
| 	snd_pcm_direct_t *dshare = pcm->private_data; | ||||
| 	unsigned short events; | ||||
| 	static snd_timer_read_t rbuf[5];	/* can be overwriten by multiple plugins, we don't need the value */ | ||||
| 
 | ||||
| 	assert(pfds && nfds == 1 && revents); | ||||
| 	events = pfds[0].revents; | ||||
| 	if (events & POLLIN) { | ||||
| 		events |= POLLOUT; | ||||
| 		events &= ~POLLIN; | ||||
| 		/* empty the timer read queue */ | ||||
| 		while (snd_timer_read(dshare->timer, &rbuf, sizeof(rbuf)) == sizeof(rbuf)) ; | ||||
| 	} | ||||
| 	*revents = events; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dshare_info(snd_pcm_t *pcm, snd_pcm_info_t * info) | ||||
| { | ||||
| 	// snd_pcm_direct_t *dshare = pcm->private_data;
 | ||||
| 
 | ||||
| 	memset(info, 0, sizeof(*info)); | ||||
| 	info->stream = pcm->stream; | ||||
| 	info->card = -1; | ||||
| 	/* FIXME: fill this with something more useful: we know the hardware name */ | ||||
| 	if (pcm->name) { | ||||
| 		strncpy(info->id, pcm->name, sizeof(info->id)); | ||||
| 		strncpy(info->name, pcm->name, sizeof(info->name)); | ||||
| 		strncpy(info->subname, pcm->name, sizeof(info->subname)); | ||||
| 	} | ||||
| 	info->subdevices_count = 1; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static inline snd_mask_t *hw_param_mask(snd_pcm_hw_params_t *params, | ||||
| 					snd_pcm_hw_param_t var) | ||||
| { | ||||
| 	return ¶ms->masks[var - SND_PCM_HW_PARAM_FIRST_MASK]; | ||||
| } | ||||
| 
 | ||||
| static inline snd_interval_t *hw_param_interval(snd_pcm_hw_params_t *params, | ||||
| 						snd_pcm_hw_param_t var) | ||||
| { | ||||
| 	return ¶ms->intervals[var - SND_PCM_HW_PARAM_FIRST_INTERVAL]; | ||||
| } | ||||
| 
 | ||||
| static int hw_param_interval_refine_one(snd_pcm_hw_params_t *params, | ||||
| 					snd_pcm_hw_param_t var, | ||||
| 					snd_pcm_hw_params_t *src) | ||||
| { | ||||
| 	snd_interval_t *i; | ||||
| 
 | ||||
| 	if (!(params->rmask & (1<<var)))	/* nothing to do? */ | ||||
| 		return 0; | ||||
| 	i = hw_param_interval(params, var); | ||||
| 	if (snd_interval_empty(i)) { | ||||
| 		SNDERR("dshare interval %i empty?", (int)var); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 	if (snd_interval_refine(i, hw_param_interval(src, var))) | ||||
| 		params->cmask |= 1<<var; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #undef REFINE_DEBUG | ||||
| 
 | ||||
| static int snd_pcm_dshare_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_direct_t *dshare = pcm->private_data; | ||||
| 	snd_pcm_hw_params_t *hw_params = &dshare->shmptr->hw_params; | ||||
| 	static snd_mask_t access = { .bits = {  | ||||
| 					(1<<SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) | | ||||
| 					(1<<SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED) | | ||||
| 					(1<<SNDRV_PCM_ACCESS_RW_INTERLEAVED) | | ||||
| 					(1<<SNDRV_PCM_ACCESS_RW_NONINTERLEAVED), | ||||
| 					0, 0, 0 } }; | ||||
| 	int err; | ||||
| 
 | ||||
| #ifdef REFINE_DEBUG | ||||
| 	snd_output_t *log; | ||||
| 	snd_output_stdio_attach(&log, stderr, 0); | ||||
| 	snd_output_puts(log, "DMIX REFINE (begin):\n"); | ||||
| 	snd_pcm_hw_params_dump(params, log); | ||||
| #endif | ||||
| 	if (params->rmask & (1<<SND_PCM_HW_PARAM_ACCESS)) { | ||||
| 		if (snd_mask_empty(hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS))) { | ||||
| 			SNDERR("dshare access mask empty?"); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 		if (snd_mask_refine(hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS), &access)) | ||||
| 			params->cmask |= 1<<SND_PCM_HW_PARAM_ACCESS; | ||||
| 	} | ||||
| 	if (params->rmask & (1<<SND_PCM_HW_PARAM_FORMAT)) { | ||||
| 		if (snd_mask_empty(hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT))) { | ||||
| 			SNDERR("dshare format mask empty?"); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 		if (snd_mask_refine_set(hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT), | ||||
| 				        snd_mask_value(hw_param_mask(hw_params, SND_PCM_HW_PARAM_FORMAT)))) | ||||
| 			params->cmask |= 1<<SND_PCM_HW_PARAM_FORMAT; | ||||
| 	} | ||||
| 	//snd_mask_none(hw_param_mask(params, SND_PCM_HW_PARAM_SUBFORMAT));
 | ||||
| 	if (params->rmask & (1<<SND_PCM_HW_PARAM_CHANNELS)) { | ||||
| 		if (snd_interval_empty(hw_param_interval(params, SND_PCM_HW_PARAM_CHANNELS))) { | ||||
| 			SNDERR("dshare channels mask empty?"); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 		err = snd_interval_refine_set(hw_param_interval(params, SND_PCM_HW_PARAM_CHANNELS), dshare->channels); | ||||
| 		if (err < 0) | ||||
| 			return err; | ||||
| 	} | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_RATE, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_SIZE, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_TIME, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIODS, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| #ifdef REFINE_DEBUG | ||||
| 	snd_output_puts(log, "DMIX REFINE (end):\n"); | ||||
| 	snd_pcm_hw_params_dump(params, log); | ||||
| 	snd_output_close(log); | ||||
| #endif | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dshare_hw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t * params ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* values are cached in the pcm structure */ | ||||
| 	 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dshare_hw_free(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* values are cached in the pcm structure */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dshare_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t * params ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* values are cached in the pcm structure */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dshare_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info) | ||||
| { | ||||
|         return snd_pcm_channel_info_shm(pcm, info, -1); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status) | ||||
| { | ||||
| 	snd_pcm_direct_t *dshare = pcm->private_data; | ||||
|  | @ -541,16 +367,6 @@ static snd_pcm_sframes_t snd_pcm_dshare_readn(snd_pcm_t *pcm ATTRIBUTE_UNUSED, v | |||
| 	return -ENODEV; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dshare_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dshare_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dshare_close(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_direct_t *dshare = pcm->private_data; | ||||
|  | @ -625,18 +441,18 @@ static void snd_pcm_dshare_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_dshare_ops = { | ||||
| 	.close = snd_pcm_dshare_close, | ||||
| 	.info = snd_pcm_dshare_info, | ||||
| 	.hw_refine = snd_pcm_dshare_hw_refine, | ||||
| 	.hw_params = snd_pcm_dshare_hw_params, | ||||
| 	.hw_free = snd_pcm_dshare_hw_free, | ||||
| 	.sw_params = snd_pcm_dshare_sw_params, | ||||
| 	.channel_info = snd_pcm_dshare_channel_info, | ||||
| 	.info = snd_pcm_direct_info, | ||||
| 	.hw_refine = snd_pcm_direct_hw_refine, | ||||
| 	.hw_params = snd_pcm_direct_hw_params, | ||||
| 	.hw_free = snd_pcm_direct_hw_free, | ||||
| 	.sw_params = snd_pcm_direct_sw_params, | ||||
| 	.channel_info = snd_pcm_direct_channel_info, | ||||
| 	.dump = snd_pcm_dshare_dump, | ||||
| 	.nonblock = snd_pcm_dshare_nonblock, | ||||
| 	.async = snd_pcm_dshare_async, | ||||
| 	.poll_revents = snd_pcm_dshare_poll_revents, | ||||
| 	.mmap = snd_pcm_dshare_mmap, | ||||
| 	.munmap = snd_pcm_dshare_munmap, | ||||
| 	.nonblock = snd_pcm_direct_nonblock, | ||||
| 	.async = snd_pcm_direct_async, | ||||
| 	.poll_revents = snd_pcm_direct_poll_revents, | ||||
| 	.mmap = snd_pcm_direct_mmap, | ||||
| 	.munmap = snd_pcm_direct_munmap, | ||||
| }; | ||||
| 
 | ||||
| static snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = { | ||||
|  | @ -794,6 +610,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, | |||
| 		spcm->channels = dshare->shmptr->s.channels; | ||||
| 		spcm->format = dshare->shmptr->s.format; | ||||
| 		spcm->boundary = dshare->shmptr->s.boundary; | ||||
| 		spcm->info = dshare->shmptr->s.info; | ||||
| 		ret = snd_pcm_mmap(spcm); | ||||
| 		if (ret < 0) { | ||||
| 			SNDERR("unable to mmap channels"); | ||||
|  |  | |||
|  | @ -146,180 +146,6 @@ static snd_pcm_sframes_t snd_pcm_dsnoop_sync_ptr(snd_pcm_t *pcm) | |||
|  *  plugin implementation | ||||
|  */ | ||||
| 
 | ||||
| static int snd_pcm_dsnoop_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* value is cached for us in pcm->mode (SND_PCM_NONBLOCK flag) */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dsnoop_async(snd_pcm_t *pcm, int sig, pid_t pid) | ||||
| { | ||||
| 	snd_pcm_direct_t *dsnoop = pcm->private_data; | ||||
| 	return snd_timer_async(dsnoop->timer, sig, pid); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dsnoop_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) | ||||
| { | ||||
| 	snd_pcm_direct_t *dsnoop = pcm->private_data; | ||||
| 	unsigned short events; | ||||
| 	static snd_timer_read_t rbuf[5];	/* can be overwriten by multiple plugins, we don't need the value */ | ||||
| 
 | ||||
| 	assert(pfds && nfds == 1 && revents); | ||||
| 	events = pfds[0].revents; | ||||
| 	if (events & POLLIN) { | ||||
| 		events |= POLLOUT; | ||||
| 		events &= ~POLLIN; | ||||
| 		/* empty the timer read queue */ | ||||
| 		while (snd_timer_read(dsnoop->timer, &rbuf, sizeof(rbuf)) == sizeof(rbuf)) ; | ||||
| 	} | ||||
| 	*revents = events; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dsnoop_info(snd_pcm_t *pcm, snd_pcm_info_t * info) | ||||
| { | ||||
| 	// snd_pcm_direct_t *dsnoop = pcm->private_data;
 | ||||
| 
 | ||||
| 	memset(info, 0, sizeof(*info)); | ||||
| 	info->stream = pcm->stream; | ||||
| 	info->card = -1; | ||||
| 	/* FIXME: fill this with something more useful: we know the hardware name */ | ||||
| 	if (pcm->name) { | ||||
| 		strncpy(info->id, pcm->name, sizeof(info->id)); | ||||
| 		strncpy(info->name, pcm->name, sizeof(info->name)); | ||||
| 		strncpy(info->subname, pcm->name, sizeof(info->subname)); | ||||
| 	} | ||||
| 	info->subdevices_count = 1; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static inline snd_mask_t *hw_param_mask(snd_pcm_hw_params_t *params, | ||||
| 					snd_pcm_hw_param_t var) | ||||
| { | ||||
| 	return ¶ms->masks[var - SND_PCM_HW_PARAM_FIRST_MASK]; | ||||
| } | ||||
| 
 | ||||
| static inline snd_interval_t *hw_param_interval(snd_pcm_hw_params_t *params, | ||||
| 						snd_pcm_hw_param_t var) | ||||
| { | ||||
| 	return ¶ms->intervals[var - SND_PCM_HW_PARAM_FIRST_INTERVAL]; | ||||
| } | ||||
| 
 | ||||
| static int hw_param_interval_refine_one(snd_pcm_hw_params_t *params, | ||||
| 					snd_pcm_hw_param_t var, | ||||
| 					snd_pcm_hw_params_t *src) | ||||
| { | ||||
| 	snd_interval_t *i; | ||||
| 
 | ||||
| 	if (!(params->rmask & (1<<var)))	/* nothing to do? */ | ||||
| 		return 0; | ||||
| 	i = hw_param_interval(params, var); | ||||
| 	if (snd_interval_empty(i)) { | ||||
| 		SNDERR("dsnoop interval %i empty?", (int)var); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 	if (snd_interval_refine(i, hw_param_interval(src, var))) | ||||
| 		params->cmask |= 1<<var; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #undef REFINE_DEBUG | ||||
| 
 | ||||
| static int snd_pcm_dsnoop_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | ||||
| { | ||||
| 	snd_pcm_direct_t *dsnoop = pcm->private_data; | ||||
| 	snd_pcm_hw_params_t *hw_params = &dsnoop->shmptr->hw_params; | ||||
| 	static snd_mask_t access = { .bits = {  | ||||
| 					(1<<SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) | | ||||
| 					(1<<SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED) | | ||||
| 					(1<<SNDRV_PCM_ACCESS_RW_INTERLEAVED) | | ||||
| 					(1<<SNDRV_PCM_ACCESS_RW_NONINTERLEAVED), | ||||
| 					0, 0, 0 } }; | ||||
| 	int err; | ||||
| 
 | ||||
| #ifdef REFINE_DEBUG | ||||
| 	snd_output_t *log; | ||||
| 	snd_output_stdio_attach(&log, stderr, 0); | ||||
| 	snd_output_puts(log, "DMIX REFINE (begin):\n"); | ||||
| 	snd_pcm_hw_params_dump(params, log); | ||||
| #endif | ||||
| 	if (params->rmask & (1<<SND_PCM_HW_PARAM_ACCESS)) { | ||||
| 		if (snd_mask_empty(hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS))) { | ||||
| 			SNDERR("dsnoop access mask empty?"); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 		if (snd_mask_refine(hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS), &access)) | ||||
| 			params->cmask |= 1<<SND_PCM_HW_PARAM_ACCESS; | ||||
| 	} | ||||
| 	if (params->rmask & (1<<SND_PCM_HW_PARAM_FORMAT)) { | ||||
| 		if (snd_mask_empty(hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT))) { | ||||
| 			SNDERR("dsnoop format mask empty?"); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 		if (snd_mask_refine_set(hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT), | ||||
| 				        snd_mask_value(hw_param_mask(hw_params, SND_PCM_HW_PARAM_FORMAT)))) | ||||
| 			params->cmask |= 1<<SND_PCM_HW_PARAM_FORMAT; | ||||
| 	} | ||||
| 	//snd_mask_none(hw_param_mask(params, SND_PCM_HW_PARAM_SUBFORMAT));
 | ||||
| 	if (params->rmask & (1<<SND_PCM_HW_PARAM_CHANNELS)) { | ||||
| 		if (snd_interval_empty(hw_param_interval(params, SND_PCM_HW_PARAM_CHANNELS))) { | ||||
| 			SNDERR("dsnoop channels mask empty?"); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 		err = snd_interval_refine_set(hw_param_interval(params, SND_PCM_HW_PARAM_CHANNELS), dsnoop->channels); | ||||
| 		if (err < 0) | ||||
| 			return err; | ||||
| 	} | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_RATE, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_SIZE, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_TIME, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIODS, hw_params); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| #ifdef REFINE_DEBUG | ||||
| 	snd_output_puts(log, "DMIX REFINE (end):\n"); | ||||
| 	snd_pcm_hw_params_dump(params, log); | ||||
| 	snd_output_close(log); | ||||
| #endif | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dsnoop_hw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t * params ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* values are cached in the pcm structure */ | ||||
| 	 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dsnoop_hw_free(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* values are cached in the pcm structure */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dsnoop_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t * params ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	/* values are cached in the pcm structure */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dsnoop_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info) | ||||
| { | ||||
|         return snd_pcm_channel_info_shm(pcm, info, -1); | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dsnoop_status(snd_pcm_t *pcm, snd_pcm_status_t * status) | ||||
| { | ||||
| 	snd_pcm_direct_t *dsnoop = pcm->private_data; | ||||
|  | @ -514,16 +340,6 @@ static snd_pcm_sframes_t snd_pcm_dsnoop_writen(snd_pcm_t *pcm ATTRIBUTE_UNUSED, | |||
| 	return -ENODEV; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dsnoop_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dsnoop_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snd_pcm_dsnoop_close(snd_pcm_t *pcm) | ||||
| { | ||||
| 	snd_pcm_direct_t *dsnoop = pcm->private_data; | ||||
|  | @ -593,18 +409,18 @@ static void snd_pcm_dsnoop_dump(snd_pcm_t *pcm, snd_output_t *out) | |||
| 
 | ||||
| static snd_pcm_ops_t snd_pcm_dsnoop_ops = { | ||||
| 	.close = snd_pcm_dsnoop_close, | ||||
| 	.info = snd_pcm_dsnoop_info, | ||||
| 	.hw_refine = snd_pcm_dsnoop_hw_refine, | ||||
| 	.hw_params = snd_pcm_dsnoop_hw_params, | ||||
| 	.hw_free = snd_pcm_dsnoop_hw_free, | ||||
| 	.sw_params = snd_pcm_dsnoop_sw_params, | ||||
| 	.channel_info = snd_pcm_dsnoop_channel_info, | ||||
| 	.info = snd_pcm_direct_info, | ||||
| 	.hw_refine = snd_pcm_direct_hw_refine, | ||||
| 	.hw_params = snd_pcm_direct_hw_params, | ||||
| 	.hw_free = snd_pcm_direct_hw_free, | ||||
| 	.sw_params = snd_pcm_direct_sw_params, | ||||
| 	.channel_info = snd_pcm_direct_channel_info, | ||||
| 	.dump = snd_pcm_dsnoop_dump, | ||||
| 	.nonblock = snd_pcm_dsnoop_nonblock, | ||||
| 	.async = snd_pcm_dsnoop_async, | ||||
| 	.poll_revents = snd_pcm_dsnoop_poll_revents, | ||||
| 	.mmap = snd_pcm_dsnoop_mmap, | ||||
| 	.munmap = snd_pcm_dsnoop_munmap, | ||||
| 	.nonblock = snd_pcm_direct_nonblock, | ||||
| 	.async = snd_pcm_direct_async, | ||||
| 	.poll_revents = snd_pcm_direct_poll_revents, | ||||
| 	.mmap = snd_pcm_direct_mmap, | ||||
| 	.munmap = snd_pcm_direct_munmap, | ||||
| }; | ||||
| 
 | ||||
| static snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = { | ||||
|  | @ -754,6 +570,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, | |||
| 		spcm->channels = dsnoop->shmptr->s.channels; | ||||
| 		spcm->format = dsnoop->shmptr->s.format; | ||||
| 		spcm->boundary = dsnoop->shmptr->s.boundary; | ||||
| 		spcm->info = dsnoop->shmptr->s.info; | ||||
| 		ret = snd_pcm_mmap(spcm); | ||||
| 		if (ret < 0) { | ||||
| 			SNDERR("unable to mmap channels"); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jaroslav Kysela
						Jaroslav Kysela