diff options
-rw-r--r-- | command.c | 9 | ||||
-rw-r--r-- | mixer.c | 110 | ||||
-rw-r--r-- | mixer.h | 7 | ||||
-rw-r--r-- | mplayer.c | 2 |
4 files changed, 75 insertions, 53 deletions
@@ -756,18 +756,17 @@ static int mp_property_mute(m_option_t *prop, int action, void *arg, case M_PROPERTY_SET: if (!arg) return M_PROPERTY_ERROR; - if ((!!*(int *) arg) != mpctx->mixer.muted) - mixer_mute(&mpctx->mixer); + mixer_setmute(&mpctx->mixer, *(int *) arg); mpctx->user_muted = mpctx->mixer.muted; return M_PROPERTY_OK; case M_PROPERTY_STEP_UP: case M_PROPERTY_STEP_DOWN: - mixer_mute(&mpctx->mixer); + mixer_setmute(&mpctx->mixer, !mixer_getmute(&mpctx->mixer)); mpctx->user_muted = mpctx->mixer.muted; return M_PROPERTY_OK; default: - return m_property_flag(prop, action, arg, &mpctx->mixer.muted); - + return m_property_flag_ro(prop, action, arg, + mixer_getmute(&mpctx->mixer)); } } @@ -18,6 +18,8 @@ #include <string.h> +#include <libavutil/common.h> + #include "config.h" #include "libao2/audio_out.h" #include "libaf/af.h" @@ -25,16 +27,16 @@ #include "mixer.h" -void mixer_getvolume(mixer_t *mixer, float *l, float *r) +static void checkvolume(struct mixer *mixer) { - *l = 0; - *r = 0; if (!mixer->ao) return; ao_control_vol_t vol; if (mixer->softvol || CONTROL_OK != ao_control(mixer->ao, AOCONTROL_GET_VOLUME, &vol)) { + if (!mixer->afilter) + return; float db_vals[AF_NCH]; if (!af_control_any_rev(mixer->afilter, AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_GET, db_vals)) @@ -44,19 +46,34 @@ void mixer_getvolume(mixer_t *mixer, float *l, float *r) vol.left = (db_vals[0] / (mixer->softvol_max / 100.0)) * 100.0; vol.right = (db_vals[1] / (mixer->softvol_max / 100.0)) * 100.0; } - *r = vol.right; - *l = vol.left; + float l = mixer->vol_l; + float r = mixer->vol_r; + if (mixer->muted) + 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). + * We don't test for exact equality, as some AOs may round the value + * we last set to some nearby supported value. 3 has been the default + * volume step for increase/decrease keys, and is apparently big enough + * to step to the next possible value in most setups. + */ + if (FFABS(vol.left - l) >= 3 || FFABS(vol.right - r) >= 3) { + mixer->vol_l = vol.left; + mixer->vol_r = vol.right; + mixer->muted = false; + } } -void mixer_setvolume(mixer_t *mixer, float l, float r) +void mixer_getvolume(mixer_t *mixer, float *l, float *r) { - if (!mixer->ao) { - mixer->muted = 0; - return; - } - ao_control_vol_t vol; - vol.right = r; - vol.left = l; + checkvolume(mixer); + *l = mixer->vol_l; + *r = mixer->vol_r; +} + +static void setvolume_internal(mixer_t *mixer, float l, float r) +{ + struct ao_control_vol vol = {.left = l, .right = r}; if (mixer->softvol || CONTROL_OK != ao_control(mixer->ao, AOCONTROL_SET_VOLUME, &vol)) { // af_volume uses values in dB @@ -81,33 +98,16 @@ void mixer_setvolume(mixer_t *mixer, float l, float r) } } } - mixer->muted = 0; } -void mixer_incvolume(mixer_t *mixer) -{ - float mixer_l, mixer_r; - mixer_getvolume(mixer, &mixer_l, &mixer_r); - mixer_l += mixer->volstep; - if (mixer_l > 100) - mixer_l = 100; - mixer_r += mixer->volstep; - if (mixer_r > 100) - mixer_r = 100; - mixer_setvolume(mixer, mixer_l, mixer_r); -} - -void mixer_decvolume(mixer_t *mixer) +void mixer_setvolume(mixer_t *mixer, float l, float r) { - float mixer_l, mixer_r; - mixer_getvolume(mixer, &mixer_l, &mixer_r); - mixer_l -= mixer->volstep; - if (mixer_l < 0) - mixer_l = 0; - mixer_r -= mixer->volstep; - if (mixer_r < 0) - mixer_r = 0; - mixer_setvolume(mixer, mixer_l, mixer_r); + checkvolume(mixer); // to check mute status + mixer->vol_l = av_clip(l, 0, 100); + mixer->vol_r = av_clip(r, 0, 100); + if (!mixer->ao || mixer->muted) + return; + setvolume_internal(mixer, mixer->vol_l, mixer->vol_r); } void mixer_getbothvolume(mixer_t *mixer, float *b) @@ -117,17 +117,39 @@ void mixer_getbothvolume(mixer_t *mixer, float *b) *b = (mixer_l + mixer_r) / 2; } -void mixer_mute(mixer_t *mixer) +void mixer_setmute(struct mixer *mixer, bool mute) { - if (mixer->muted) { - mixer_setvolume(mixer, mixer->last_l, mixer->last_r); - } else { - mixer_getvolume(mixer, &mixer->last_l, &mixer->last_r); - mixer_setvolume(mixer, 0, 0); - mixer->muted = 1; + checkvolume(mixer); + if (mute != mixer->muted) { + mixer->muted = mute; + setvolume_internal(mixer, mixer->vol_l * !mute, mixer->vol_r * !mute); } } +bool mixer_getmute(struct mixer *mixer) +{ + checkvolume(mixer); + return mixer->muted; +} + +static void addvolume(struct mixer *mixer, float d) +{ + checkvolume(mixer); + mixer_setvolume(mixer, mixer->vol_l + d, mixer->vol_r + d); + if (d > 0) + mixer_setmute(mixer, false); +} + +void mixer_incvolume(mixer_t *mixer) +{ + addvolume(mixer, mixer->volstep); +} + +void mixer_decvolume(mixer_t *mixer) +{ + addvolume(mixer, -mixer->volstep); +} + void mixer_getbalance(mixer_t *mixer, float *val) { *val = 0.f; @@ -30,8 +30,8 @@ typedef struct mixer { int volstep; bool softvol; float softvol_max; - int muted; - float last_l, last_r; + bool muted; + float vol_l, vol_r; } mixer_t; void mixer_getvolume(mixer_t *mixer, float *l, float *r); @@ -39,7 +39,8 @@ void mixer_setvolume(mixer_t *mixer, float l, float r); void mixer_incvolume(mixer_t *mixer); void mixer_decvolume(mixer_t *mixer); void mixer_getbothvolume(mixer_t *mixer, float *b); -void mixer_mute(mixer_t *mixer); +void mixer_setmute(mixer_t *mixer, bool mute); +bool mixer_getmute(mixer_t *mixer); void mixer_getbalance(mixer_t *mixer, float *bal); void mixer_setbalance(mixer_t *mixer, float bal); @@ -692,7 +692,7 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask) void exit_player_with_rc(struct MPContext *mpctx, enum exit_reason how, int rc) { if (mpctx->user_muted) - mixer_mute(&mpctx->mixer); + mixer_setmute(&mpctx->mixer, false); uninit_player(mpctx, INITIALIZED_ALL); #if defined(__MINGW32__) || defined(__CYGWIN__) timeEndPeriod(1); |