mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	Add boolean (mute) functionality to softvol plugin
When the resolution is set to 2, a boolean control is created as a mute switch instead of a volume control. Also, fixed the possible zero-division error. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
		
							parent
							
								
									e24cc8d247
								
							
						
					
					
						commit
						f78af4ab04
					
				
					 1 changed files with 43 additions and 16 deletions
				
			
		| 
						 | 
					@ -275,9 +275,15 @@ static void softvol_convert_stereo_vol(snd_pcm_softvol_t *svol,
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vol[0] = svol->dB_value[svol->cur_vol[0]];
 | 
						if (svol->max_val == 1) {
 | 
				
			||||||
	vol[1] = svol->dB_value[svol->cur_vol[1]];
 | 
							vol[0] = svol->cur_vol[0] ? 0xffff : 0;
 | 
				
			||||||
	vol_c = svol->dB_value[(svol->cur_vol[0] + svol->cur_vol[1]) / 2];
 | 
							vol[1] = svol->cur_vol[1] ? 0xffff : 0;
 | 
				
			||||||
 | 
							vol_c = vol[0] | vol[1];
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							vol[0] = svol->dB_value[svol->cur_vol[0]];
 | 
				
			||||||
 | 
							vol[1] = svol->dB_value[svol->cur_vol[1]];
 | 
				
			||||||
 | 
							vol_c = svol->dB_value[(svol->cur_vol[0] + svol->cur_vol[1]) / 2];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	switch (svol->sformat) {
 | 
						switch (svol->sformat) {
 | 
				
			||||||
	case SND_PCM_FORMAT_S16_LE:
 | 
						case SND_PCM_FORMAT_S16_LE:
 | 
				
			||||||
	case SND_PCM_FORMAT_S16_BE:
 | 
						case SND_PCM_FORMAT_S16_BE:
 | 
				
			||||||
| 
						 | 
					@ -325,7 +331,10 @@ static void softvol_convert_mono_vol(snd_pcm_softvol_t *svol,
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vol_scale = svol->dB_value[svol->cur_vol[0]];
 | 
						if (svol->max_val == 1)
 | 
				
			||||||
 | 
							vol_scale = svol->cur_vol[0] ? 0xffff : 0;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							vol_scale = svol->dB_value[svol->cur_vol[0]];
 | 
				
			||||||
	switch (svol->sformat) {
 | 
						switch (svol->sformat) {
 | 
				
			||||||
	case SND_PCM_FORMAT_S16_LE:
 | 
						case SND_PCM_FORMAT_S16_LE:
 | 
				
			||||||
	case SND_PCM_FORMAT_S16_BE:
 | 
						case SND_PCM_FORMAT_S16_BE:
 | 
				
			||||||
| 
						 | 
					@ -569,9 +578,13 @@ static void snd_pcm_softvol_dump(snd_pcm_t *pcm, snd_output_t *out)
 | 
				
			||||||
	snd_pcm_softvol_t *svol = pcm->private_data;
 | 
						snd_pcm_softvol_t *svol = pcm->private_data;
 | 
				
			||||||
	snd_output_printf(out, "Soft volume PCM\n");
 | 
						snd_output_printf(out, "Soft volume PCM\n");
 | 
				
			||||||
	snd_output_printf(out, "Control: %s\n", svol->elem.id.name);
 | 
						snd_output_printf(out, "Control: %s\n", svol->elem.id.name);
 | 
				
			||||||
	snd_output_printf(out, "min_dB: %g\n", svol->min_dB);
 | 
						if (svol->max_val == 1)
 | 
				
			||||||
	snd_output_printf(out, "max_dB: %g\n", svol->max_dB);
 | 
							snd_output_printf(out, "boolean\n");
 | 
				
			||||||
	snd_output_printf(out, "resolution: %d\n", svol->max_val + 1);
 | 
						else {
 | 
				
			||||||
 | 
							snd_output_printf(out, "min_dB: %g\n", svol->min_dB);
 | 
				
			||||||
 | 
							snd_output_printf(out, "max_dB: %g\n", svol->max_dB);
 | 
				
			||||||
 | 
							snd_output_printf(out, "resolution: %d\n", svol->max_val + 1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (pcm->setup) {
 | 
						if (pcm->setup) {
 | 
				
			||||||
		snd_output_printf(out, "Its setup is:\n");
 | 
							snd_output_printf(out, "Its setup is:\n");
 | 
				
			||||||
		snd_pcm_dump_setup(pcm, out);
 | 
							snd_pcm_dump_setup(pcm, out);
 | 
				
			||||||
| 
						 | 
					@ -596,13 +609,21 @@ static int add_user_ctl(snd_pcm_softvol_t *svol, snd_ctl_elem_info_t *cinfo, int
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
	unsigned int def_val;
 | 
						unsigned int def_val;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	err = snd_ctl_elem_add_integer(svol->ctl, &cinfo->id, count, 0, svol->max_val, 0);
 | 
						if (svol->max_val == 1)
 | 
				
			||||||
 | 
							err = snd_ctl_elem_add_boolean(svol->ctl, &cinfo->id, count);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							err = snd_ctl_elem_add_integer(svol->ctl, &cinfo->id, count,
 | 
				
			||||||
 | 
										       0, svol->max_val, 0);
 | 
				
			||||||
	if (err < 0)
 | 
						if (err < 0)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
	add_tlv_info(svol, cinfo);
 | 
						if (svol->max_val == 1)
 | 
				
			||||||
	/* set zero dB value as default, or max_val if
 | 
							def_val = 1;
 | 
				
			||||||
	   there is no 0 dB setting */
 | 
						else {
 | 
				
			||||||
	def_val = svol->zero_dB_val ? svol->zero_dB_val : svol->max_val;
 | 
							add_tlv_info(svol, cinfo);
 | 
				
			||||||
 | 
							/* set zero dB value as default, or max_val if
 | 
				
			||||||
 | 
							   there is no 0 dB setting */
 | 
				
			||||||
 | 
							def_val = svol->zero_dB_val ? svol->zero_dB_val : svol->max_val;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	for (i = 0; i < count; i++)
 | 
						for (i = 0; i < count; i++)
 | 
				
			||||||
		svol->elem.value.integer.value[i] = def_val;
 | 
							svol->elem.value.integer.value[i] = def_val;
 | 
				
			||||||
	return snd_ctl_elem_write(svol->ctl, &svol->elem);
 | 
						return snd_ctl_elem_write(svol->ctl, &svol->elem);
 | 
				
			||||||
| 
						 | 
					@ -647,7 +668,7 @@ static int softvol_load_control(snd_pcm_t *pcm, snd_pcm_softvol_t *svol,
 | 
				
			||||||
	svol->max_val = resolution - 1;
 | 
						svol->max_val = resolution - 1;
 | 
				
			||||||
	svol->min_dB = min_dB;
 | 
						svol->min_dB = min_dB;
 | 
				
			||||||
	svol->max_dB = max_dB;
 | 
						svol->max_dB = max_dB;
 | 
				
			||||||
	if (svol->max_dB == ZERO_DB)
 | 
						if (svol->max_val == 1 || svol->max_dB == ZERO_DB)
 | 
				
			||||||
		svol->zero_dB_val = svol->max_val;
 | 
							svol->zero_dB_val = svol->max_val;
 | 
				
			||||||
	else if (svol->max_dB < 0)
 | 
						else if (svol->max_dB < 0)
 | 
				
			||||||
		svol->zero_dB_val = 0; /* there is no 0 dB setting */
 | 
							svol->zero_dB_val = 0; /* there is no 0 dB setting */
 | 
				
			||||||
| 
						 | 
					@ -671,7 +692,8 @@ static int softvol_load_control(snd_pcm_t *pcm, snd_pcm_softvol_t *svol,
 | 
				
			||||||
			/* hardware control exists */
 | 
								/* hardware control exists */
 | 
				
			||||||
			return 1; /* notify */
 | 
								return 1; /* notify */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} else if (cinfo->type != SND_CTL_ELEM_TYPE_INTEGER ||
 | 
							} else if ((cinfo->type != SND_CTL_ELEM_TYPE_INTEGER &&
 | 
				
			||||||
 | 
								    cinfo->type != SND_CTL_ELEM_TYPE_BOOLEAN) ||
 | 
				
			||||||
			   cinfo->count != (unsigned int)cchannels ||
 | 
								   cinfo->count != (unsigned int)cchannels ||
 | 
				
			||||||
			   cinfo->value.integer.min != 0 ||
 | 
								   cinfo->value.integer.min != 0 ||
 | 
				
			||||||
			   cinfo->value.integer.max != resolution - 1) {
 | 
								   cinfo->value.integer.max != resolution - 1) {
 | 
				
			||||||
| 
						 | 
					@ -684,7 +706,7 @@ static int softvol_load_control(snd_pcm_t *pcm, snd_pcm_softvol_t *svol,
 | 
				
			||||||
				SNDERR("Cannot add a control");
 | 
									SNDERR("Cannot add a control");
 | 
				
			||||||
				return err;
 | 
									return err;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else if (svol->max_val > 1) {
 | 
				
			||||||
			/* check TLV availability */
 | 
								/* check TLV availability */
 | 
				
			||||||
			unsigned int tlv[4];
 | 
								unsigned int tlv[4];
 | 
				
			||||||
			err = snd_ctl_elem_tlv_read(svol->ctl, &cinfo->id, tlv, sizeof(tlv));
 | 
								err = snd_ctl_elem_tlv_read(svol->ctl, &cinfo->id, tlv, sizeof(tlv));
 | 
				
			||||||
| 
						 | 
					@ -693,6 +715,10 @@ static int softvol_load_control(snd_pcm_t *pcm, snd_pcm_softvol_t *svol,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (svol->max_val == 1)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* set up dB table */
 | 
				
			||||||
	if (min_dB == PRESET_MIN_DB && max_dB == ZERO_DB && resolution == PRESET_RESOLUTION)
 | 
						if (min_dB == PRESET_MIN_DB && max_dB == ZERO_DB && resolution == PRESET_RESOLUTION)
 | 
				
			||||||
		svol->dB_value = preset_dB_value;
 | 
							svol->dB_value = preset_dB_value;
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
| 
						 | 
					@ -863,6 +889,7 @@ pcm.name {
 | 
				
			||||||
	[min_dB REAL]           # minimal dB value (default: -51.0)
 | 
						[min_dB REAL]           # minimal dB value (default: -51.0)
 | 
				
			||||||
	[max_dB REAL]           # maximal dB value (default:   0.0)
 | 
						[max_dB REAL]           # maximal dB value (default:   0.0)
 | 
				
			||||||
	[resolution INT]        # resolution (default: 256)
 | 
						[resolution INT]        # resolution (default: 256)
 | 
				
			||||||
 | 
									# resolution = 2 means a mute switch
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
\endcode
 | 
					\endcode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -965,7 +992,7 @@ int _snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name,
 | 
				
			||||||
		       MAX_DB_UPPER_LIMIT);
 | 
							       MAX_DB_UPPER_LIMIT);
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (resolution < 0 || resolution > 1024) {
 | 
						if (resolution <= 1 || resolution > 1024) {
 | 
				
			||||||
		SNDERR("Invalid resolution value %d", resolution);
 | 
							SNDERR("Invalid resolution value %d", resolution);
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue