summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--command.c9
-rw-r--r--mixer.c110
-rw-r--r--mixer.h7
-rw-r--r--mplayer.c2
4 files changed, 75 insertions, 53 deletions
diff --git a/command.c b/command.c
index 7ce0e7e924..3c1805b412 100644
--- a/command.c
+++ b/command.c
@@ -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));
}
}
diff --git a/mixer.c b/mixer.c
index f28fea7b09..25fb79f76c 100644
--- a/mixer.c
+++ b/mixer.c
@@ -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;
diff --git a/mixer.h b/mixer.h
index eaf81c1ba1..0c6d6a91db 100644
--- a/mixer.h
+++ b/mixer.h
@@ -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);
diff --git a/mplayer.c b/mplayer.c
index d410008dff..7696b92ce8 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -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);