mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-10-29 05:40:25 -04:00 
			
		
		
		
	Added possibility to disable also channel and format conversions + softvol.
Unified disable option using mode bits in snd_pcm_open().
This commit is contained in:
		
							parent
							
								
									6814d23d29
								
							
						
					
					
						commit
						ab8331c882
					
				
					 3 changed files with 55 additions and 38 deletions
				
			
		|  | @ -292,9 +292,17 @@ typedef unsigned long snd_pcm_uframes_t; | ||||||
| typedef long snd_pcm_sframes_t; | typedef long snd_pcm_sframes_t; | ||||||
| 
 | 
 | ||||||
| /** Non blocking mode (flag for open mode) \hideinitializer */ | /** Non blocking mode (flag for open mode) \hideinitializer */ | ||||||
| #define SND_PCM_NONBLOCK		0x0001 | #define SND_PCM_NONBLOCK		0x00000001 | ||||||
| /** Async notification (flag for open mode) \hideinitializer */ | /** Async notification (flag for open mode) \hideinitializer */ | ||||||
| #define SND_PCM_ASYNC			0x0002 | #define SND_PCM_ASYNC			0x00000002 | ||||||
|  | /** Disable automatic (but not forced!) rate resamplinig */ | ||||||
|  | #define SND_PCM_NO_AUTO_RESAMPLE	0x00010000 | ||||||
|  | /** Disable automatic (but not forced!) channel conversion */ | ||||||
|  | #define SND_PCM_NO_AUTO_CHANNELS	0x00020000 | ||||||
|  | /** Disable automatic (but not forced!) format conversion */ | ||||||
|  | #define SND_PCM_NO_AUTO_FORMAT		0x00040000 | ||||||
|  | /** Disable soft volume control */ | ||||||
|  | #define SND_PCM_NO_SOFTVOL		0x00080000 | ||||||
| 
 | 
 | ||||||
| /** PCM handle */ | /** PCM handle */ | ||||||
| typedef struct _snd_pcm snd_pcm_t; | typedef struct _snd_pcm snd_pcm_t; | ||||||
|  |  | ||||||
|  | @ -707,7 +707,9 @@ static int snd_pcm_plug_hw_refine_schange(snd_pcm_t *pcm, snd_pcm_hw_params_t *p | ||||||
| 	snd_interval_t t, buffer_size; | 	snd_interval_t t, buffer_size; | ||||||
| 	const snd_interval_t *srate, *crate; | 	const snd_interval_t *srate, *crate; | ||||||
| 
 | 
 | ||||||
| 	if (plug->srate == -2) | 	if (plug->srate == -2 || | ||||||
|  | 	    (pcm->mode & pcm->mode & SND_PCM_NO_AUTO_RESAMPLE) || | ||||||
|  | 	    (params->flags & SND_PCM_HW_PARAMS_NORESAMPLE)) | ||||||
| 		links |= SND_PCM_HW_PARBIT_RATE; | 		links |= SND_PCM_HW_PARBIT_RATE; | ||||||
| 	else { | 	else { | ||||||
| 		err = snd_pcm_hw_param_refine_multiple(slave, sparams, SND_PCM_HW_PARAM_RATE, params); | 		err = snd_pcm_hw_param_refine_multiple(slave, sparams, SND_PCM_HW_PARAM_RATE, params); | ||||||
|  | @ -715,14 +717,14 @@ static int snd_pcm_plug_hw_refine_schange(snd_pcm_t *pcm, snd_pcm_hw_params_t *p | ||||||
| 			return err; | 			return err; | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	if (plug->schannels == -2) | 	if (plug->schannels == -2 || (pcm->mode & SND_PCM_NO_AUTO_CHANNELS)) | ||||||
| 		links |= SND_PCM_HW_PARBIT_CHANNELS; | 		links |= SND_PCM_HW_PARBIT_CHANNELS; | ||||||
| 	else { | 	else { | ||||||
| 		err = snd_pcm_hw_param_refine_near(slave, sparams, SND_PCM_HW_PARAM_CHANNELS, params); | 		err = snd_pcm_hw_param_refine_near(slave, sparams, SND_PCM_HW_PARAM_CHANNELS, params); | ||||||
| 		if (err < 0) | 		if (err < 0) | ||||||
| 			return err; | 			return err; | ||||||
| 	} | 	} | ||||||
| 	if (plug->sformat == -2) | 	if (plug->sformat == -2 || (pcm->mode & SND_PCM_NO_AUTO_FORMAT)) | ||||||
| 		links |= SND_PCM_HW_PARBIT_FORMAT; | 		links |= SND_PCM_HW_PARBIT_FORMAT; | ||||||
| 	else { | 	else { | ||||||
| 		format_mask = snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_FORMAT); | 		format_mask = snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_FORMAT); | ||||||
|  | @ -791,8 +793,6 @@ static int snd_pcm_plug_hw_refine_schange(snd_pcm_t *pcm, snd_pcm_hw_params_t *p | ||||||
| 	err = _snd_pcm_hw_params_refine(sparams, links, params); | 	err = _snd_pcm_hw_params_refine(sparams, links, params); | ||||||
| 	if (err < 0) | 	if (err < 0) | ||||||
| 		return err; | 		return err; | ||||||
| 	if (params->flags & SND_PCM_HW_PARAMS_NORESAMPLE) |  | ||||||
| 		snd_interval_copy((snd_interval_t *)snd_pcm_hw_param_get_interval(params, SND_PCM_HW_PARAM_RATE), snd_pcm_hw_param_get_interval(sparams, SND_PCM_HW_PARAM_RATE)); |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 	 | 	 | ||||||
|  | @ -811,10 +811,10 @@ static int snd_pcm_plug_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, | ||||||
| 	const snd_interval_t *sbuffer_size; | 	const snd_interval_t *sbuffer_size; | ||||||
| 	const snd_interval_t *srate, *crate; | 	const snd_interval_t *srate, *crate; | ||||||
| 
 | 
 | ||||||
| 	if (plug->schannels == -2) | 	if (plug->schannels == -2 || (pcm->mode & SND_PCM_NO_AUTO_CHANNELS)) | ||||||
| 		links |= SND_PCM_HW_PARBIT_CHANNELS; | 		links |= SND_PCM_HW_PARBIT_CHANNELS; | ||||||
| 
 | 
 | ||||||
| 	if (plug->sformat == -2) | 	if (plug->sformat == -2 || (pcm->mode & SND_PCM_NO_AUTO_FORMAT)) | ||||||
| 		links |= SND_PCM_HW_PARBIT_FORMAT; | 		links |= SND_PCM_HW_PARBIT_FORMAT; | ||||||
| 	else { | 	else { | ||||||
| 		format_mask = snd_pcm_hw_param_get_mask(params, | 		format_mask = snd_pcm_hw_param_get_mask(params, | ||||||
|  | @ -857,7 +857,9 @@ static int snd_pcm_plug_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, | ||||||
| 			return err; | 			return err; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (plug->srate == -2) | 	if (plug->srate == -2 || | ||||||
|  | 	    (pcm->mode & SND_PCM_NO_AUTO_RESAMPLE) || | ||||||
|  | 	    (params->flags & SND_PCM_HW_PARAMS_NORESAMPLE)) | ||||||
| 		links |= SND_PCM_HW_PARBIT_RATE; | 		links |= SND_PCM_HW_PARBIT_RATE; | ||||||
| 	else { | 	else { | ||||||
| 		unsigned int rate_min, srate_min; | 		unsigned int rate_min, srate_min; | ||||||
|  | @ -895,8 +897,6 @@ static int snd_pcm_plug_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, | ||||||
| 	err = _snd_pcm_hw_params_refine(params, links, sparams); | 	err = _snd_pcm_hw_params_refine(params, links, sparams); | ||||||
| 	if (err < 0) | 	if (err < 0) | ||||||
| 		return err; | 		return err; | ||||||
| 	if (params->flags & SND_PCM_HW_PARAMS_NORESAMPLE) |  | ||||||
| 		snd_interval_copy((snd_interval_t *)snd_pcm_hw_param_get_interval(params, SND_PCM_HW_PARAM_RATE), snd_pcm_hw_param_get_interval(sparams, SND_PCM_HW_PARAM_RATE)); |  | ||||||
| 	/* FIXME */ | 	/* FIXME */ | ||||||
| 	params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); | 	params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); | ||||||
| 	return 0; | 	return 0; | ||||||
|  |  | ||||||
|  | @ -969,34 +969,43 @@ int _snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name, | ||||||
| 		SNDERR("Invalid resolution value %d", resolution); | 		SNDERR("Invalid resolution value %d", resolution); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 	err = snd_pcm_slave_conf(root, slave, &sconf, 1, | 	if (mode & SND_PCM_NO_SOFTVOL) { | ||||||
| 				 SND_PCM_HW_PARAM_FORMAT, 0, &sformat); | 		err = snd_pcm_slave_conf(root, slave, &sconf, 0); | ||||||
| 	if (err < 0) | 		if (err < 0) | ||||||
| 		return err; | 			return err; | ||||||
| 	if (sformat != SND_PCM_FORMAT_UNKNOWN && | 		err = snd_pcm_open_named_slave(pcmp, name, root, sconf, stream, | ||||||
| 	    sformat != SND_PCM_FORMAT_S16_LE && | 					       mode, conf); | ||||||
| 	    sformat != SND_PCM_FORMAT_S16_BE && |  | ||||||
| 	    sformat != SND_PCM_FORMAT_S24_3LE &&  |  | ||||||
| 	    sformat != SND_PCM_FORMAT_S32_LE && |  | ||||||
| 	    sformat != SND_PCM_FORMAT_S32_BE) { |  | ||||||
| 		SNDERR("only S16_LE, S16_BE, S24_3LE, S32_LE or S32_BE format " |  | ||||||
| 		       "is supported"); |  | ||||||
| 		snd_config_delete(sconf); | 		snd_config_delete(sconf); | ||||||
| 		return -EINVAL; | 	} else { | ||||||
|  | 		snd_ctl_elem_id_alloca(&ctl_id); | ||||||
|  | 		err = snd_pcm_slave_conf(root, slave, &sconf, 1, | ||||||
|  | 					 SND_PCM_HW_PARAM_FORMAT, 0, &sformat); | ||||||
|  | 		if (err < 0) | ||||||
|  | 			return err; | ||||||
|  | 		if (sformat != SND_PCM_FORMAT_UNKNOWN && | ||||||
|  | 		    sformat != SND_PCM_FORMAT_S16_LE && | ||||||
|  | 		    sformat != SND_PCM_FORMAT_S16_BE && | ||||||
|  | 		    sformat != SND_PCM_FORMAT_S24_3LE &&  | ||||||
|  | 		    sformat != SND_PCM_FORMAT_S32_LE && | ||||||
|  | 		    sformat != SND_PCM_FORMAT_S32_BE) { | ||||||
|  | 			SNDERR("only S16_LE, S16_BE, S24_3LE, S32_LE or S32_BE format " | ||||||
|  | 			       "is supported"); | ||||||
|  | 			snd_config_delete(sconf); | ||||||
|  | 			return -EINVAL; | ||||||
|  | 		} | ||||||
|  | 		err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf); | ||||||
|  | 		snd_config_delete(sconf); | ||||||
|  | 		if (err < 0) | ||||||
|  | 			return err; | ||||||
|  | 		if ((err = snd_pcm_parse_control_id(control, ctl_id, &card, &cchannels, NULL)) < 0) { | ||||||
|  | 			snd_pcm_close(spcm); | ||||||
|  | 			return err; | ||||||
|  | 		} | ||||||
|  | 		err = snd_pcm_softvol_open(pcmp, name, sformat, card, ctl_id, cchannels, | ||||||
|  | 					   min_dB, max_dB, resolution, spcm, 1); | ||||||
|  | 		if (err < 0) | ||||||
|  | 			snd_pcm_close(spcm); | ||||||
| 	} | 	} | ||||||
| 	err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf); |  | ||||||
| 	snd_config_delete(sconf); |  | ||||||
| 	if (err < 0) |  | ||||||
| 		return err; |  | ||||||
| 	snd_ctl_elem_id_alloca(&ctl_id); |  | ||||||
| 	if ((err = snd_pcm_parse_control_id(control, ctl_id, &card, &cchannels, NULL)) < 0) { |  | ||||||
| 		snd_pcm_close(spcm); |  | ||||||
| 		return err; |  | ||||||
| 	} |  | ||||||
| 	err = snd_pcm_softvol_open(pcmp, name, sformat, card, ctl_id, cchannels, |  | ||||||
| 				   min_dB, max_dB, resolution, spcm, 1); |  | ||||||
| 	if (err < 0) |  | ||||||
| 		snd_pcm_close(spcm); |  | ||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| #ifndef DOC_HIDDEN | #ifndef DOC_HIDDEN | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jaroslav Kysela
						Jaroslav Kysela