Take advantage of the mute capability of a device that mutes at its lowest setting
This commit is contained in:
+37
-14
@@ -88,9 +88,13 @@ static char *alsa_mix_ctrl = "Master";
|
||||
static int alsa_mix_index = 0;
|
||||
static int hardware_mixer = 0;
|
||||
static int has_softvol = 0;
|
||||
|
||||
static int volume_set_request = 0; // set when an external request is made to set the volume.
|
||||
int mute_request_pending = 0; // set when an external request is made to mute or unmute.
|
||||
int overriding_mute_state_requested = 0; // 1 = mute; 0 = unmute requested
|
||||
int mixer_volume_setting_gives_mute = 0; // set when it is discovered that particular mixer volume setting causes a mute.
|
||||
long alsa_mix_mute; // setting the volume to this value mutes output, if mixer_volume_setting_gives_mute is true
|
||||
int volume_based_mute_is_active = 0; // set when muting is being done by a setting the volume to a magic value
|
||||
|
||||
static snd_pcm_sframes_t (*alsa_pcm_write)(snd_pcm_t *, const void *,
|
||||
snd_pcm_uframes_t) = snd_pcm_writei;
|
||||
@@ -148,9 +152,14 @@ void close_mixer() {
|
||||
}
|
||||
}
|
||||
|
||||
#define RELEASE_ALSA_MUTEX_AND_DIE(X) \
|
||||
pthread_mutex_unlock(&alsa_mutex); \
|
||||
die(X);
|
||||
void do_snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t * mix_elem, double vol) {
|
||||
if (snd_mixer_selem_set_playback_dB_all(mix_elem, vol, 0) != 0) {
|
||||
debug(1, "Can't set playback volume accurately to %f dB.", vol);
|
||||
if (snd_mixer_selem_set_playback_dB_all(mix_elem, vol, -1) != 0)
|
||||
if (snd_mixer_selem_set_playback_dB_all(mix_elem, vol, 1) != 0)
|
||||
debug(1, "Could not set playback dB volume on the mixer.");
|
||||
}
|
||||
}
|
||||
|
||||
static int init(int argc, char **argv) {
|
||||
pthread_mutex_lock(&alsa_mutex);
|
||||
@@ -365,8 +374,11 @@ static int init(int argc, char **argv) {
|
||||
audio_alsa.volume = &volume; // insert the volume function now we know it can do dB stuff
|
||||
audio_alsa.parameters = ¶meters; // likewise the parameters stuff
|
||||
if (alsa_mix_mindb == SND_CTL_TLV_DB_GAIN_MUTE) {
|
||||
// Raspberry Pi does this
|
||||
debug(1, "Lowest dB value is a mute -- try minimum volume +1");
|
||||
// For instance, the Raspberry Pi does this
|
||||
debug(1, "Lowest dB value is a mute");
|
||||
mixer_volume_setting_gives_mute = 1;
|
||||
alsa_mix_mute = SND_CTL_TLV_DB_GAIN_MUTE; // this may not be necessary -- it's always going to be SND_CTL_TLV_DB_GAIN_MUTE, right?
|
||||
debug(1, "Lowest dB value is a mute -- try minimum volume + 1 as lowest true attenuation value");
|
||||
if (snd_mixer_selem_ask_playback_vol_dB(alsa_mix_elem, alsa_mix_minv + 1,
|
||||
&alsa_mix_mindb) != 0)
|
||||
debug(1, "Can't get dB value corresponding to a minimum volume + 1.");
|
||||
@@ -417,7 +429,7 @@ static int init(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
if ((config.alsa_use_playback_switch_for_mute == 1) &&
|
||||
(snd_mixer_selem_has_playback_switch(alsa_mix_elem))) {
|
||||
(snd_mixer_selem_has_playback_switch(alsa_mix_elem)) || mixer_volume_setting_gives_mute) {
|
||||
audio_alsa.mute = &mute; // insert the mute function now we know it can do muting stuff
|
||||
// debug(1, "Has mixer and mute ability we will use.");
|
||||
} else {
|
||||
@@ -949,11 +961,10 @@ void do_volume(double vol) { // caller is assumed to have the alsa_mutex when us
|
||||
"control.");
|
||||
}
|
||||
} else {
|
||||
if (snd_mixer_selem_set_playback_dB_all(alsa_mix_elem, vol, 0) != 0) {
|
||||
debug(1, "Can't set playback volume accurately to %f dB.", vol);
|
||||
if (snd_mixer_selem_set_playback_dB_all(alsa_mix_elem, vol, -1) != 0)
|
||||
if (snd_mixer_selem_set_playback_dB_all(alsa_mix_elem, vol, 1) != 0)
|
||||
debug(1, "Could not set playback dB volume on the mixer.");
|
||||
if (volume_based_mute_is_active==0)
|
||||
do_snd_mixer_selem_set_playback_dB_all(alsa_mix_elem, vol);
|
||||
else {
|
||||
debug(1,"Not setting volume because volume-based mute is active");
|
||||
}
|
||||
}
|
||||
volume_set_request = 0; // any external request that has been made is now satisfied
|
||||
@@ -1011,16 +1022,28 @@ void do_mute(int mute_state_requested) {
|
||||
// If the hardware isn't there, or we are not allowed to use it, nothing will be done
|
||||
// The caller must have the alsa mutex
|
||||
|
||||
if (config.alsa_use_playback_switch_for_mute == 1) {
|
||||
if ((config.alsa_use_playback_switch_for_mute == 1) || mixer_volume_setting_gives_mute){
|
||||
if (mute_request_pending == 0)
|
||||
local_mute_state_requested = mute_state_requested;
|
||||
if (open_mixer()) {
|
||||
if (local_mute_state_requested) {
|
||||
// debug(1,"Playback Switch mute actually done");
|
||||
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 0);
|
||||
if (config.alsa_use_playback_switch_for_mute == 1)
|
||||
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 0);
|
||||
else {
|
||||
debug(1,"Activating volume-based mute.");
|
||||
volume_based_mute_is_active = 1;
|
||||
do_snd_mixer_selem_set_playback_dB_all(alsa_mix_elem, alsa_mix_mute);
|
||||
}
|
||||
} else if (overriding_mute_state_requested == 0) {
|
||||
// debug(1,"Playback Switch unmute actually done");
|
||||
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 1);
|
||||
if (config.alsa_use_playback_switch_for_mute == 1)
|
||||
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 1);
|
||||
else {
|
||||
debug(1,"Deactivating volume-based mute.");
|
||||
volume_based_mute_is_active = 0;
|
||||
do_snd_mixer_selem_set_playback_dB_all(alsa_mix_elem, set_volume);
|
||||
}
|
||||
}
|
||||
close_mixer();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user