Only set volume if it has been asked for externally. Clean up mute. Add ability do disable hardware mute

This commit is contained in:
Mike Brady
2017-04-30 15:29:22 +01:00
parent 74bbb9a3f2
commit fc492bea3a
+62 -27
View File
@@ -44,6 +44,9 @@ static void stop(void);
static void flush(void);
int delay(long *the_delay);
static void volume(double vol);
void do_volume(double vol);
void do_mute(int request);
static void linear_volume(double vol);
static void parameters(audio_parameters *info);
static void mute(int do_mute);
@@ -84,6 +87,10 @@ 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 mute_request_state = 0; // 1 = mute; 0 = unmute requested
int use_playback_switch_for_mute = 1; // set to 0 for some cards, e.g. VMWare Fusion's emulated sound card
static snd_pcm_sframes_t (*alsa_pcm_write)(snd_pcm_t *, const void *,
snd_pcm_uframes_t) = snd_pcm_writei;
@@ -138,6 +145,7 @@ static int init(int argc, char **argv) {
set_period_size_request = 0;
set_buffer_size_request = 0;
use_playback_switch_for_mute = 1;
config.audio_backend_latency_offset = 0;
config.audio_backend_buffer_desired_length = 0.15;
@@ -235,7 +243,17 @@ static int init(int argc, char **argv) {
else
die("Invalid disable_synchronization option choice \"%s\". It should be \"yes\" or \"no\"");
}
/* Get the mute_using_playback_switch setting. */
if (config_lookup_string(config.cfg, "alsa.mute_using_playback_switch", &str)) {
if (strcasecmp(str, "no") == 0)
use_playback_switch_for_mute = 0;
else if (strcasecmp(str, "yes") == 0)
use_playback_switch_for_mute = 1;
else
die("Invalid mute_use_playback_switch option choice \"%s\". It should be \"yes\" or \"no\"");
}
/* Get the output format, using the same names as aplay does*/
if (config_lookup_string(config.cfg, "alsa.output_format", &str)) {
if (strcasecmp(str, "S16") == 0)
@@ -411,9 +429,9 @@ static int init(int argc, char **argv) {
*/
}
}
if (snd_mixer_selem_has_playback_switch(alsa_mix_elem)) {
if ((use_playback_switch_for_mute==1) && (snd_mixer_selem_has_playback_switch(alsa_mix_elem))) {
audio_alsa.mute = &mute; // insert the mute function now we know it can do muting stuff
debug(1, "Has mute ability.");
debug(1, "Has mute ability we will use.");
}
snd_mixer_close(alsa_mix_handle);
@@ -806,16 +824,11 @@ static void play(short buf[], int samples) {
ret = open_alsa_device();
if (hardware_mixer)
open_mixer();
pthread_mutex_unlock(&alsa_mutex);
// the mutex must be unlocked for the following call to proceed
if ((hardware_mixer) && (ret == 0) && (audio_alsa.volume))
audio_alsa.volume(set_volume);
pthread_mutex_lock(&alsa_mutex);
int derr;
if (hardware_mixer && alsa_mix_handle) {
// debug(1,"unmute");
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 1);
do_volume(set_volume);
if ((hardware_mixer) && (audio_alsa.mute)) {
// debug(1,"Play unmute");
do_mute(0);
}
pthread_mutex_unlock(&alsa_mutex);
}
@@ -854,8 +867,8 @@ static void flush(void) {
pthread_mutex_lock(&alsa_mutex);
int derr;
if (hardware_mixer && alsa_mix_handle) {
// debug(1,"Mute");
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 0);
// debug(1,"Flush mute");
do_mute(1);
snd_mixer_close(alsa_mix_handle);
alsa_mix_handle = NULL;
}
@@ -918,8 +931,7 @@ static void parameters(audio_parameters *info) {
info->maximum_volume_dB = alsa_mix_maxdb;
}
static void volume(double vol) {
pthread_mutex_lock(&alsa_mutex);
void do_volume(double vol) { // caller is assumed to have the alsa_mutex when using this function
debug(3, "Setting volume db to %f.", vol);
set_volume = vol;
if (hardware_mixer && alsa_mix_handle) {
@@ -948,7 +960,15 @@ static void volume(double vol) {
debug(1,"Could not set playback dB volume on the mixer.");
}
}
volume_set_request = 0; // any external request that has been made is now satisfied
// debug(1,"Alsa volume actually set.");
}
}
void volume(double vol) {
pthread_mutex_lock(&alsa_mutex);
volume_set_request = 1; // an external request has been made to set the volume
do_volume(vol);
pthread_mutex_unlock(&alsa_mutex);
}
@@ -967,17 +987,32 @@ static void linear_volume(double vol) {
}
}
static void mute(int do_mute) {
static void mute(int mute_state_requested) {
// debug(1,"External Mute Request");
pthread_mutex_lock(&alsa_mutex);
// debug(2,"audio_alsa mute called.");
if (hardware_mixer && alsa_mix_handle) {
if (do_mute) {
// debug(1,"Mute");
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 0);
} else {
// debug(1,"Unmute");
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 1);
}
}
mute_request_pending = 1;
mute_request_state = mute_state_requested;
do_mute(mute_state_requested);
pthread_mutex_unlock(&alsa_mutex);
}
void do_mute(int mute_state_requested) {
// The mute state requested will be actioned unless mute_request_pending is set
// If it is set, then that will be actioned.
// 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 (hardware_mixer && alsa_mix_handle) {
if (use_playback_switch_for_mute==1) {
if (mute_request_pending==0)
mute_request_state = mute_state_requested;
if (mute_request_state) {
// debug(1,"Playback Switch mute actually done");
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 0);
} else {
// debug(1,"Playback Switch unmute actually done");
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 1);
}
}
mute_request_pending = 0;
}
}