summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-07-09 18:31:18 +0200
committerwm4 <wm4@nowhere>2016-07-09 18:31:18 +0200
commit995c47da9afacfcc30d8a17d2f2a2268fbf4fdb9 (patch)
tree0442a9134e89408c2d8a791fefc1559d04d2b76f /audio
parentda9590d3681c8779ac50d7722f8b8ad09a47024a (diff)
downloadmpv-995c47da9afacfcc30d8a17d2f2a2268fbf4fdb9.tar.bz2
mpv-995c47da9afacfcc30d8a17d2f2a2268fbf4fdb9.tar.xz
audio: drop --softvol=no and --softvol=auto
Drop the code for switching the volume options and properties between af_volume and AO volume controls. interface-changes.rst mentions the changes in detail. Do this because this was exceedingly complex and had other problems as well. It was also very hard to test. It's just not worth the trouble. Some leftovers like AOCONTROL_HAS_PER_APP_VOLUME will be removed at a later point. Fixes #3322.
Diffstat (limited to 'audio')
-rw-r--r--audio/mixer.c278
-rw-r--r--audio/mixer.h11
2 files changed, 14 insertions, 275 deletions
diff --git a/audio/mixer.c b/audio/mixer.c
index 01bb4d5088..a251a5aa60 100644
--- a/audio/mixer.c
+++ b/audio/mixer.c
@@ -35,18 +35,6 @@ struct mixer {
struct MPOpts *opts;
struct ao *ao;
struct af_stream *af;
- // Static, dependent on ao/softvol settings
- bool softvol; // use AO (false) or af_volume (true)
- bool persistent_volume; // volume does not need to be restored
- bool emulate_mute; // if true, emulate mute with volume=0
- // Last known values (possibly out of sync with reality)
- float vol_l, vol_r;
- bool muted;
- // Used to decide whether we should unmute on uninit
- bool muted_by_us;
- /* Contains ao driver name or "softvol" if volume is not persistent
- * and needs to be restored after the driver is reinitialized. */
- const char *driver;
// Other stuff
float balance;
};
@@ -57,82 +45,22 @@ struct mixer *mixer_init(void *talloc_ctx, struct mpv_global *global)
*mixer = (struct mixer) {
.log = mp_log_new(mixer, global->log, "mixer"),
.opts = global->opts,
- .vol_l = 100,
- .vol_r = 100,
- .driver = "",
};
return mixer;
}
bool mixer_audio_initialized(struct mixer *mixer)
{
- return !!mixer->ao;
+ return !!mixer->af;
}
-float mixer_getmaxvolume(struct mixer *mixer)
+// Called when opts->softvol_volume or opts->softvol_mute were changed.
+void mixer_update_volume(struct mixer *mixer)
{
- // gain == 1
- return mixer->softvol ? mixer->opts->softvol_max : 100;
-}
-
-static void checkvolume(struct mixer *mixer)
-{
- if (!mixer->ao)
- return;
-
- ao_control_vol_t vol = {mixer->vol_l, mixer->vol_r};
- if (mixer->softvol) {
- float gain;
- if (!af_control_any_rev(mixer->af, AF_CONTROL_GET_VOLUME, &gain))
- gain = 1.0;
- vol.left = gain * 100.0;
- vol.right = gain * 100.0;
- } else {
- MP_DBG(mixer, "Reading volume from AO.\n");
- // Rely on the values not changing if the query is not supported
- ao_control(mixer->ao, AOCONTROL_GET_VOLUME, &vol);
- ao_control(mixer->ao, AOCONTROL_GET_MUTE, &mixer->muted);
- }
- float l = mixer->vol_l;
- float r = mixer->vol_r;
- if (mixer->emulate_mute && 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;
- if (mixer->emulate_mute)
- mixer->muted = false;
- }
- mixer->muted_by_us &= mixer->muted;
-}
+ float gain = MPMAX(mixer->opts->softvol_volume / 100.0, 0);
+ if (mixer->opts->softvol_mute == 1)
+ gain = 0.0;
-void mixer_getvolume(struct mixer *mixer, float *l, float *r)
-{
- checkvolume(mixer);
- *l = mixer->vol_l;
- *r = mixer->vol_r;
-}
-
-static void setvolume_internal(struct mixer *mixer)
-{
- float l = mixer->vol_l, r = mixer->vol_r;
- if (mixer->emulate_mute && mixer->muted)
- l = r = 0;
- if (!mixer->softvol) {
- MP_DBG(mixer, "Setting volume on AO.\n");
- struct ao_control_vol vol = {.left = l, .right = r};
- if (ao_control(mixer->ao, AOCONTROL_SET_VOLUME, &vol) != CONTROL_OK)
- MP_ERR(mixer, "Failed to change audio output volume.\n");
- return;
- }
- float gain = (l + r) / 2.0 / 100.0;
if (!af_control_any_rev(mixer->af, AF_CONTROL_SET_VOLUME, &gain)) {
if (gain == 1.0)
return;
@@ -143,57 +71,6 @@ static void setvolume_internal(struct mixer *mixer)
}
}
-void mixer_setvolume(struct mixer *mixer, float l, float r)
-{
- checkvolume(mixer); // to check mute status
-
- float max = mixer_getmaxvolume(mixer);
- mixer->vol_l = MPCLAMP(l, 0, max);
- mixer->vol_r = MPCLAMP(r, 0, max);
- if (mixer->ao)
- setvolume_internal(mixer);
-}
-
-void mixer_getbothvolume(struct mixer *mixer, float *b)
-{
- float mixer_l, mixer_r;
- mixer_getvolume(mixer, &mixer_l, &mixer_r);
- *b = (mixer_l + mixer_r) / 2;
-}
-
-void mixer_setmute(struct mixer *mixer, bool mute)
-{
- checkvolume(mixer);
- if (mute == mixer->muted)
- return;
- if (mixer->ao) {
- mixer->muted = mute;
- mixer->muted_by_us = mute;
- if (mixer->emulate_mute) {
- setvolume_internal(mixer);
- } else {
- ao_control(mixer->ao, AOCONTROL_SET_MUTE, &mute);
- }
- checkvolume(mixer);
- } else {
- mixer->muted = mute;
- mixer->muted_by_us = mute;
- }
-}
-
-bool mixer_getmute(struct mixer *mixer)
-{
- checkvolume(mixer);
- return mixer->muted;
-}
-
-void mixer_addvolume(struct mixer *mixer, float step)
-{
- float vol_l, vol_r;
- mixer_getvolume(mixer, &vol_l, &vol_r);
- mixer_setvolume(mixer, vol_l + step, vol_r + step);
-}
-
void mixer_getbalance(struct mixer *mixer, float *val)
{
if (mixer->af)
@@ -242,130 +119,18 @@ void mixer_setbalance(struct mixer *mixer, float val)
af_pan_balance->control(af_pan_balance, AF_CONTROL_SET_PAN_BALANCE, &val);
}
-char *mixer_get_volume_restore_data(struct mixer *mixer)
-{
- if (!mixer->driver[0])
- return NULL;
- return talloc_asprintf(NULL, "%s:%f:%f:%d", mixer->driver, mixer->vol_l,
- mixer->vol_r, mixer->muted_by_us);
-}
-
-static void probe_softvol(struct mixer *mixer)
-{
- bool ao_perapp = ao_control(mixer->ao, AOCONTROL_HAS_PER_APP_VOLUME, 0) == 1;
- bool ao_softvol = ao_control(mixer->ao, AOCONTROL_HAS_SOFT_VOLUME, 0) == 1;
- assert(!(ao_perapp && ao_softvol));
- mixer->persistent_volume = !ao_softvol;
-
- if (mixer->opts->softvol == SOFTVOL_AUTO) {
- // No system-wide volume => fine with AO volume control.
- mixer->softvol = !ao_softvol && !ao_perapp;
- } else {
- mixer->softvol = mixer->opts->softvol == SOFTVOL_YES;
- }
-
- if (mixer->softvol)
- mixer->persistent_volume = false;
-
- MP_DBG(mixer, "Will use af_volume: %s\n", mixer->softvol ? "yes" : "no");
-
- // If we can't use real volume control => force softvol.
- if (!mixer->softvol) {
- ao_control_vol_t vol;
- if (ao_control(mixer->ao, AOCONTROL_GET_VOLUME, &vol) != CONTROL_OK) {
- mixer->softvol = true;
- MP_WARN(mixer, "Hardware volume control unavailable.\n");
- }
- }
-
- // Probe native mute support.
- mixer->emulate_mute = true;
- if (!mixer->softvol) {
- if (ao_control(mixer->ao, AOCONTROL_GET_MUTE, &(bool){0}) == CONTROL_OK)
- mixer->emulate_mute = false;
- }
-}
-
-static void restore_volume(struct mixer *mixer)
-{
- struct MPOpts *opts = mixer->opts;
- struct ao *ao = mixer->ao;
-
- float force_vol_l = -1, force_vol_r = -1;
- int force_mute = -1;
-
- const char *prev_driver = mixer->driver;
- mixer->driver = mixer->softvol ? "softvol" : ao_get_name(ao);
- if (!prev_driver[0])
- prev_driver = mixer->driver;
-
- // Restore old parameters if volume won't survive reinitialization.
- // But not if volume scale is possibly different.
- if (!mixer->persistent_volume && strcmp(mixer->driver, prev_driver) == 0) {
- force_vol_l = mixer->vol_l;
- force_vol_r = mixer->vol_r;
- }
-
- // Set mute if we disabled it on uninit last time.
- if (mixer->muted_by_us)
- force_mute = 1;
-
- // Set parameters from command line.
- if (opts->mixer_init_volume >= 0)
- force_vol_l = force_vol_r = opts->mixer_init_volume;
- if (opts->mixer_init_mute >= 0)
- force_mute = opts->mixer_init_mute;
-
- // Set parameters from playback resume.
- char *data = mixer->opts->mixer_restore_volume_data;
- if (!mixer->persistent_volume && data && data[0]) {
- char drv[40];
- float v_l, v_r;
- int m;
- if (sscanf(data, "%39[^:]:%f:%f:%d", drv, &v_l, &v_r, &m) == 4) {
- if (strcmp(mixer->driver, drv) == 0) {
- force_vol_l = v_l;
- force_vol_r = v_r;
- force_mute = !!m;
- MP_DBG(mixer, "Restoring volume from resume config.\n");
- }
- }
- talloc_free(mixer->opts->mixer_restore_volume_data);
- mixer->opts->mixer_restore_volume_data = NULL;
- }
-
- // Using --volume should not reset the volume on every file (i.e. reinit),
- // OTOH mpv --{ --volume 10 f1.mkv --} --{ --volume 20 f2.mkv --} must work.
- // Resetting the option volumes to "auto" (-1) is easiest. If file local
- // options (as shown above) are used, the option handler code will reset
- // them to other values, and force the volume to be reset as well.
- opts->mixer_init_volume = -1;
- opts->mixer_init_mute = -1;
-
- checkvolume(mixer);
- if (force_vol_l >= 0 && force_vol_r >= 0) {
- MP_DBG(mixer, "Restoring previous volume.\n");
- mixer_setvolume(mixer, force_vol_l, force_vol_r);
- }
- if (force_mute >= 0) {
- MP_DBG(mixer, "Restoring previous mute toggle.\n");
- mixer_setmute(mixer, force_mute);
- }
-}
-
// Called after the audio filter chain is built or rebuilt.
// (Can be called multiple times, even without mixer_uninit() in-between.)
-void mixer_reinit_audio(struct mixer *mixer, struct ao *ao, struct af_stream *af)
+void mixer_reinit_audio(struct mixer *mixer, struct af_stream *af)
{
- if (!ao || !af)
- return;
- mixer->ao = ao;
mixer->af = af;
+ if (!af)
+ return;
- MP_DBG(mixer, "Reinit...\n");
+ if (mixer->opts->softvol == SOFTVOL_NO)
+ MP_ERR(mixer, "--softvol=no is not supported anymore.\n");
- probe_softvol(mixer);
- restore_volume(mixer);
+ mixer_update_volume(mixer);
if (mixer->balance != 0)
mixer_setbalance(mixer, mixer->balance);
@@ -380,24 +145,5 @@ void mixer_uninit_audio(struct mixer *mixer)
if (!mixer->ao)
return;
- MP_DBG(mixer, "Uninit...\n");
-
- checkvolume(mixer);
- if (mixer->muted_by_us && mixer->persistent_volume) {
- MP_DBG(mixer, "Draining.\n");
- /* 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
- * volume changes after uninitialization, but we don't want the
- * remaining audio to play at full volume either. Thus this
- * workaround to drop remaining audio first. */
- ao_reset(mixer->ao);
- mixer_setmute(mixer, false);
- /* We remember mute status and re-enable it if we play more audio
- * in the same process. */
- mixer->muted_by_us = true;
- }
- mixer->ao = NULL;
mixer->af = NULL;
- mixer->softvol = false;
}
diff --git a/audio/mixer.h b/audio/mixer.h
index 4e2ff350ff..b475c12700 100644
--- a/audio/mixer.h
+++ b/audio/mixer.h
@@ -33,18 +33,11 @@ struct af_stream;
struct mixer;
struct mixer *mixer_init(void *talloc_ctx, struct mpv_global *global);
-void mixer_reinit_audio(struct mixer *mixer, struct ao *ao, struct af_stream *af);
+void mixer_reinit_audio(struct mixer *mixer, struct af_stream *af);
void mixer_uninit_audio(struct mixer *mixer);
bool mixer_audio_initialized(struct mixer *mixer);
-void mixer_getvolume(struct mixer *mixer, float *l, float *r);
-void mixer_setvolume(struct mixer *mixer, float l, float r);
-void mixer_addvolume(struct mixer *mixer, float step);
-void mixer_getbothvolume(struct mixer *mixer, float *b);
-void mixer_setmute(struct mixer *mixer, bool mute);
-bool mixer_getmute(struct mixer *mixer);
+void mixer_update_volume(struct mixer *mixer);
void mixer_getbalance(struct mixer *mixer, float *bal);
void mixer_setbalance(struct mixer *mixer, float bal);
-float mixer_getmaxvolume(struct mixer *mixer);
-char *mixer_get_volume_restore_data(struct mixer *mixer);
#endif /* MPLAYER_MIXER_H */