From 39aa7d9846a8a04e8f08acc0ea9e2ce38336e523 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Tue, 10 Apr 2012 04:45:53 +0300 Subject: [PATCH] mixer: support native audio driver mute Make mixer support setting the mute attribute at audio driver level, if one exists separately from volume. As of this commit, no libao2 driver exposes such an attribute yet; that will be added in later commits. Since the mute status can now be set externally, it's no longer completely obvious when the player should automatically disable mute when uninitializing an audio output. The implemented behavior is to turn mute off at uninitialization if we turned it on and haven't noticed it turn off (by external means) since. --- libao2/audio_out.h | 3 +++ mixer.c | 31 ++++++++++++++++++++++++------- mixer.h | 2 ++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/libao2/audio_out.h b/libao2/audio_out.h index 5a9d52def3..955376d460 100644 --- a/libao2/audio_out.h +++ b/libao2/audio_out.h @@ -35,6 +35,9 @@ enum aocontrol { // If there's only one volume, SET should use average of left/right. AOCONTROL_GET_VOLUME, AOCONTROL_SET_VOLUME, + // _MUTE commands take a pointer to bool + AOCONTROL_GET_MUTE, + AOCONTROL_SET_MUTE, }; #define AOPLAY_FINAL_CHUNK 1 diff --git a/mixer.c b/mixer.c index 793a6ac58e..7be2179384 100644 --- a/mixer.c +++ b/mixer.c @@ -49,7 +49,7 @@ static void checkvolume(struct mixer *mixer) } float l = mixer->vol_l; float r = mixer->vol_r; - if (mixer->muted) + if (mixer->muted_using_volume) l = r = 0; /* Try to detect cases where the volume has been changed by some external * action (such as something else changing a shared system-wide volume). @@ -61,8 +61,14 @@ static void checkvolume(struct mixer *mixer) if (FFABS(vol.left - l) >= 3 || FFABS(vol.right - r) >= 3) { mixer->vol_l = vol.left; mixer->vol_r = vol.right; - mixer->muted = false; + if (mixer->muted_using_volume) + mixer->muted = false; } + if (!mixer->softvol) + // Rely on the value not changing if the query is not supported + ao_control(mixer->ao, AOCONTROL_GET_MUTE, &mixer->muted); + mixer->muted_by_us &= mixer->muted; + mixer->muted_using_volume &= mixer->muted; } void mixer_getvolume(mixer_t *mixer, float *l, float *r) @@ -130,8 +136,15 @@ void mixer_setmute(struct mixer *mixer, bool mute) { checkvolume(mixer); if (mute != mixer->muted) { + if (!mixer->softvol && !mixer->muted_using_volume && ao_control( + mixer->ao, AOCONTROL_SET_MUTE, &mute) == CONTROL_OK) { + mixer->muted_using_volume = false; + } else { + setvolume_internal(mixer, mixer->vol_l*!mute, mixer->vol_r*!mute); + mixer->muted_using_volume = mute; + } mixer->muted = mute; - setvolume_internal(mixer, mixer->vol_l * !mute, mixer->vol_r * !mute); + mixer->muted_by_us = mute; } } @@ -227,7 +240,7 @@ void mixer_reinit(struct mixer *mixer, struct ao *ao) /* Use checkvolume() to see if softvol needs to be enabled because of * lacking AO support, but first store values it could overwrite. */ float left = mixer->vol_l, right = mixer->vol_r; - bool muted = mixer->muted; + bool muted = mixer->muted_by_us; checkvolume(mixer); /* Try to avoid restoring volume stored from one control method with * another. Especially, restoring softvol volume (typically high) on @@ -237,7 +250,11 @@ void mixer_reinit(struct mixer *mixer, struct ao *ao) if (mixer->restore_volume && !strcmp(mixer->restore_volume, restore_reason)) mixer_setvolume(mixer, left, right); - mixer_setmute(mixer, muted); + /* We turn mute off at AO uninit, so it has to be restored (unless + * we're reinitializing filter chain while keeping AO); but we only + * enable mute, not turn external mute off. */ + if (muted) + mixer_setmute(mixer, true); if (mixer->balance != 0) mixer_setbalance(mixer, mixer->balance); } @@ -249,7 +266,7 @@ void mixer_reinit(struct mixer *mixer, struct ao *ao) void mixer_uninit(struct mixer *mixer) { checkvolume(mixer); - if (mixer->muted) { + if (mixer->muted_by_us) { /* Current audio output API combines playing the remaining buffered * audio and uninitializing the AO into one operation, even though * ideally unmute would happen between those two steps. We can't do @@ -260,7 +277,7 @@ void mixer_uninit(struct mixer *mixer) mixer_setmute(mixer, false); /* We remember mute status and re-enable it if we play more audio * in the same process. */ - mixer->muted = true; + mixer->muted_by_us = true; } mixer->ao = NULL; } diff --git a/mixer.h b/mixer.h index c1903750f1..efeb62856f 100644 --- a/mixer.h +++ b/mixer.h @@ -31,6 +31,8 @@ typedef struct mixer { bool softvol; float softvol_max; bool muted; + bool muted_by_us; + bool muted_using_volume; float vol_l, vol_r; /* Contains ao driver name or "softvol" if volume is not persistent * and needs to be restored after the driver is reinitialized. */