Take advantage of the mute capability of a device that mutes at its lowest setting

This commit is contained in:
Mike Brady
2018-01-13 20:09:51 +00:00
parent a6080d7d7e
commit 8a4bfb0378
+37 -14
View File
@@ -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 = &parameters; // 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();
}