mirror of https://github.com/mpv-player/mpv
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.
This commit is contained in:
parent
9624f10aa8
commit
39aa7d9846
|
@ -35,6 +35,9 @@ enum aocontrol {
|
||||||
// If there's only one volume, SET should use average of left/right.
|
// If there's only one volume, SET should use average of left/right.
|
||||||
AOCONTROL_GET_VOLUME,
|
AOCONTROL_GET_VOLUME,
|
||||||
AOCONTROL_SET_VOLUME,
|
AOCONTROL_SET_VOLUME,
|
||||||
|
// _MUTE commands take a pointer to bool
|
||||||
|
AOCONTROL_GET_MUTE,
|
||||||
|
AOCONTROL_SET_MUTE,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define AOPLAY_FINAL_CHUNK 1
|
#define AOPLAY_FINAL_CHUNK 1
|
||||||
|
|
31
mixer.c
31
mixer.c
|
@ -49,7 +49,7 @@ static void checkvolume(struct mixer *mixer)
|
||||||
}
|
}
|
||||||
float l = mixer->vol_l;
|
float l = mixer->vol_l;
|
||||||
float r = mixer->vol_r;
|
float r = mixer->vol_r;
|
||||||
if (mixer->muted)
|
if (mixer->muted_using_volume)
|
||||||
l = r = 0;
|
l = r = 0;
|
||||||
/* Try to detect cases where the volume has been changed by some external
|
/* Try to detect cases where the volume has been changed by some external
|
||||||
* action (such as something else changing a shared system-wide volume).
|
* 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) {
|
if (FFABS(vol.left - l) >= 3 || FFABS(vol.right - r) >= 3) {
|
||||||
mixer->vol_l = vol.left;
|
mixer->vol_l = vol.left;
|
||||||
mixer->vol_r = vol.right;
|
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)
|
void mixer_getvolume(mixer_t *mixer, float *l, float *r)
|
||||||
|
@ -130,8 +136,15 @@ void mixer_setmute(struct mixer *mixer, bool mute)
|
||||||
{
|
{
|
||||||
checkvolume(mixer);
|
checkvolume(mixer);
|
||||||
if (mute != mixer->muted) {
|
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;
|
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
|
/* Use checkvolume() to see if softvol needs to be enabled because of
|
||||||
* lacking AO support, but first store values it could overwrite. */
|
* lacking AO support, but first store values it could overwrite. */
|
||||||
float left = mixer->vol_l, right = mixer->vol_r;
|
float left = mixer->vol_l, right = mixer->vol_r;
|
||||||
bool muted = mixer->muted;
|
bool muted = mixer->muted_by_us;
|
||||||
checkvolume(mixer);
|
checkvolume(mixer);
|
||||||
/* Try to avoid restoring volume stored from one control method with
|
/* Try to avoid restoring volume stored from one control method with
|
||||||
* another. Especially, restoring softvol volume (typically high) on
|
* 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,
|
if (mixer->restore_volume && !strcmp(mixer->restore_volume,
|
||||||
restore_reason))
|
restore_reason))
|
||||||
mixer_setvolume(mixer, left, right);
|
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)
|
if (mixer->balance != 0)
|
||||||
mixer_setbalance(mixer, mixer->balance);
|
mixer_setbalance(mixer, mixer->balance);
|
||||||
}
|
}
|
||||||
|
@ -249,7 +266,7 @@ void mixer_reinit(struct mixer *mixer, struct ao *ao)
|
||||||
void mixer_uninit(struct mixer *mixer)
|
void mixer_uninit(struct mixer *mixer)
|
||||||
{
|
{
|
||||||
checkvolume(mixer);
|
checkvolume(mixer);
|
||||||
if (mixer->muted) {
|
if (mixer->muted_by_us) {
|
||||||
/* Current audio output API combines playing the remaining buffered
|
/* Current audio output API combines playing the remaining buffered
|
||||||
* audio and uninitializing the AO into one operation, even though
|
* audio and uninitializing the AO into one operation, even though
|
||||||
* ideally unmute would happen between those two steps. We can't do
|
* 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);
|
mixer_setmute(mixer, false);
|
||||||
/* We remember mute status and re-enable it if we play more audio
|
/* We remember mute status and re-enable it if we play more audio
|
||||||
* in the same process. */
|
* in the same process. */
|
||||||
mixer->muted = true;
|
mixer->muted_by_us = true;
|
||||||
}
|
}
|
||||||
mixer->ao = NULL;
|
mixer->ao = NULL;
|
||||||
}
|
}
|
||||||
|
|
2
mixer.h
2
mixer.h
|
@ -31,6 +31,8 @@ typedef struct mixer {
|
||||||
bool softvol;
|
bool softvol;
|
||||||
float softvol_max;
|
float softvol_max;
|
||||||
bool muted;
|
bool muted;
|
||||||
|
bool muted_by_us;
|
||||||
|
bool muted_using_volume;
|
||||||
float vol_l, vol_r;
|
float vol_l, vol_r;
|
||||||
/* Contains ao driver name or "softvol" if volume is not persistent
|
/* Contains ao driver name or "softvol" if volume is not persistent
|
||||||
* and needs to be restored after the driver is reinitialized. */
|
* and needs to be restored after the driver is reinitialized. */
|
||||||
|
|
Loading…
Reference in New Issue