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;
}
}
-#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);
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.");
}
}
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 {
"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
// 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();
}