summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/interface-changes.rst17
-rw-r--r--DOCS/man/input.rst36
-rw-r--r--DOCS/man/options.rst35
-rw-r--r--audio/mixer.c278
-rw-r--r--audio/mixer.h11
-rw-r--r--options/options.c13
-rw-r--r--options/options.h5
-rw-r--r--player/audio.c2
-rw-r--r--player/command.c108
-rw-r--r--player/configfiles.c3
10 files changed, 145 insertions, 363 deletions
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst
index 99f426be14..d2e1ee4e7f 100644
--- a/DOCS/interface-changes.rst
+++ b/DOCS/interface-changes.rst
@@ -21,6 +21,23 @@ Interface changes
--- mpv 0.18.1 ---
- deprecate --heartbeat-cmd
+ - remove --softvol=no capability:
+ - deprecate --softvol, it now does nothing
+ - --volume, --mute, and the corrsponding properties now always control
+ softvol, and behave as expected without surprises (e.g. you can set
+ them normally while no audio is initialized)
+ - rename --softvol-max to --volume-max (deprecated alias is added)
+ - the --volume-restore-data option and property are removed without
+ replacement. They were _always_ internal, and used for watch-later
+ resume/restore. Now --volume/--mute are saved directly instead.
+ - the previous point means resuming files with older watch-later configs
+ will print an error about missing --volume-restore-data (which you can
+ ignore), and will not restore the previous value
+ - as a consequence, volume controls will no longer control PulseAudio
+ per-application value, or use the system mixer's per-application
+ volume processing
+ - system or per-application volume can still be controlled with the
+ ao-volume and ao-mute properties (there are no command line options)
--- mpv 0.18.0 ---
- now ab-loops are active even if one of the "ab-loop-a"/"-b" properties is
unset ("no"), in which case the start of the file is used if the A loop
diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst
index 74f7815d40..1d8bfe30cd 100644
--- a/DOCS/man/input.rst
+++ b/DOCS/man/input.rst
@@ -1234,29 +1234,31 @@ Property list
See ``--hr-seek``.
``mixer-active``
- Return ``yes`` if the audio mixer is active, ``no`` otherwise. This has
- implications for ``--softvol=no`` mode: if the mixer is inactive, changing
- ``volume`` doesn't actually change anything on the system mixer. If the
- ``--volume`` or ``--mute`` option are used, these might not be applied
- properly until the mixer becomes active either. (The options, if set, will
- just overwrite the mixer state at audio initialization.)
+ Return ``yes`` if the audio mixer is active, ``no`` otherwise.
- While the behavior with ``mixer-active==yes`` is relatively well-defined,
- the ``no`` case will provide possibly wrong or insignificant values.
-
- Note that an active mixer does not necessarily imply active audio output,
- although this is implied in the current implementation.
+ This option is relatively useless. Before mpv 0.18.1, it could be used to
+ infer behavior of the ``volume`` property.
``volume`` (RW)
- Current volume (see ``--volume`` for details). Also see ``mixer-active``
- property.
+ Current volume (see ``--volume`` for details).
-``volume-max``
- Current maximum value the volume property can be set to. (This may depend
- on the ``--softvol-max`` option.)
+``volume-max`` (RW)
+ Current maximum value the volume property can be set to. (Equivalent to the
+ ``--volume-max`` property.)
``mute`` (RW)
- Current mute status (``yes``/``no``). Also see ``mixer-active`` property.
+ Current mute status (``yes``/``no``).
+
+``ao-volume`` (RW)
+ System volume. This property is available only if mpv audio output is
+ currently active, and only if the underlying implementation supports volume
+ control. What this option does depends on the API. For example, on ALSA
+ this usually changes system-wide audio, while with PulseAudio this controls
+ per-application volume.
+
+``ao-mute`` (RW)
+ Similar to ``ao-volume``, but controls the mute state. May be unimplemented
+ even if ``ao-volume`` works.
``audio-delay`` (RW)
See ``--audio-delay``.
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 1a5298f903..f9c32e5a9d 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -1072,14 +1072,10 @@ Audio
``--volume=<value>``
Set the startup volume. 0 means silence, 100 means no volume reduction or
- amplification. A value of -1 (the default) will not change the volume. See
- also ``--softvol``.
+ amplification. Negative values can be passed for compatibility, but are
+ treated as 0.
- .. note::
-
- This was changed after the mpv 0.9 release. Before that, 100 actually
- meant maximum volume. At the same time, the volume scale was made cubic,
- so the old values won't match up with the new ones anyway.
+ Since mpv 0.18.1, this always controls the internal mixer (aka "softvol").
``--audio-delay=<sec>``
Audio delay in seconds (positive or negative float value). Positive values
@@ -1094,20 +1090,17 @@ Audio
See also: ``--volume``.
-``--softvol=<mode>``
- Control whether to use the volume controls of the audio output driver or
- the internal mpv volume filter.
+``--softvol=<no|yes|auto>``
+ Deprecated/unfunctional. Before mpv 0.18.1, this used to control whether
+ to use the volume controls of the audio output driver or the internal mpv
+ volume filter.
- :no: prefer audio driver controls, use the volume filter only if
- absolutely needed
- :yes: always use the volume filter
- :auto: prefer the volume filter if the audio driver uses the system mixer
- (default)
+ The current behavior is as if this option was set to ``yes``. The other
+ behaviors are not available anymore, although ``auto`` almost matches
+ current behavior in most cases.
- The intention of ``auto`` is to avoid changing system mixer settings from
- within mpv with default settings. mpv is a video player, not a mixer panel.
- On the other hand, mixer controls are enabled for sound servers like
- PulseAudio, which provide per-application volume.
+ The ``no`` behavior is still partially available through the ``ao-volume``
+ and ``ao-mute`` properties. But there are no options to reset these.
``--audio-demuxer=<[+]name>``
Use this audio demuxer type when using ``--audio-file``. Use a '+' before
@@ -1264,10 +1257,12 @@ Audio
their start timestamps differ, and then video timing is gradually adjusted
if necessary to reach correct synchronization later.
-``--softvol-max=<100.0-1000.0>``
+``--volume-max=<100.0-1000.0>``, ``--softvol-max=<...>``
Set the maximum amplification level in percent (default: 130). A value of
130 will allow you to adjust the volume up to about double the normal level.
+ ``--softvol-max`` is a deprecated alias and should not be used.
+
``--audio-file-auto=<no|exact|fuzzy|all>``, ``--no-audio-file-auto``
Load additional audio files matching the video filename. The parameter
specifies how external audio files are matched. ``exact`` is enabled by
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 */
diff --git a/options/options.c b/options/options.c
index 0304d4e0c7..e58eea1bc9 100644
--- a/options/options.c
+++ b/options/options.c
@@ -410,13 +410,13 @@ const m_option_t mp_opts[] = {
({"no", SOFTVOL_NO},
{"yes", SOFTVOL_YES},
{"auto", SOFTVOL_AUTO})),
- OPT_FLOATRANGE("softvol-max", softvol_max, 0, 100, 1000),
- OPT_FLOATRANGE("volume", mixer_init_volume, 0, -1, 1000),
- OPT_CHOICE("mute", mixer_init_mute, 0,
+ OPT_FLOATRANGE("volume-max", softvol_max, 0, 100, 1000),
+ // values <0 for volume and mute are legacy and ignored
+ OPT_FLOATRANGE("volume", softvol_volume, 0, -1, 1000),
+ OPT_CHOICE("mute", softvol_mute, 0,
({"auto", -1},
{"no", 0},
{"yes", 1})),
- OPT_STRING("volume-restore-data", mixer_restore_volume_data, 0),
OPT_CHOICE("gapless-audio", gapless_audio, 0,
({"no", 0},
{"yes", 1},
@@ -685,6 +685,7 @@ const m_option_t mp_opts[] = {
OPT_REPLACED("ass-use-margins", "sub-use-margins"),
OPT_REPLACED("media-title", "force-media-title"),
OPT_REPLACED("input-unix-socket", "input-ipc-server"),
+ OPT_REPLACED("softvol-max", "volume-max"),
{0}
};
@@ -698,8 +699,8 @@ const struct MPOpts mp_default_opts = {
.deinterlace = -1,
.softvol = SOFTVOL_AUTO,
.softvol_max = 130,
- .mixer_init_volume = -1,
- .mixer_init_mute = -1,
+ .softvol_volume = 100,
+ .softvol_mute = 0,
.gapless_audio = -1,
.audio_buffer = 0.2,
.audio_device = "auto",
diff --git a/options/options.h b/options/options.h
index 5dcc642222..3e8474fd75 100644
--- a/options/options.h
+++ b/options/options.h
@@ -89,9 +89,8 @@ typedef struct MPOpts {
int ao_null_fallback;
int force_vo;
int softvol;
- float mixer_init_volume;
- int mixer_init_mute;
- char *mixer_restore_volume_data;
+ float softvol_volume;
+ int softvol_mute;
float softvol_max;
int gapless_audio;
double audio_buffer;
diff --git a/player/audio.c b/player/audio.c
index 2ce1669366..b61e464090 100644
--- a/player/audio.c
+++ b/player/audio.c
@@ -132,7 +132,7 @@ static int recreate_audio_filters(struct MPContext *mpctx)
if (afs->initialized < 1 && af_init(afs) < 0)
goto fail;
- mixer_reinit_audio(mpctx->mixer, mpctx->ao, afs);
+ mixer_reinit_audio(mpctx->mixer, afs);
mp_notify(mpctx, MPV_EVENT_AUDIO_RECONFIG, NULL);
diff --git a/player/command.c b/player/command.c
index 9512e3d10f..3bca64bd5e 100644
--- a/player/command.c
+++ b/player/command.c
@@ -1569,44 +1569,29 @@ static int mp_property_volume(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
+ struct MPOpts *opts = mpctx->opts;
+
switch (action) {
- case M_PROPERTY_GET:
- mixer_getbothvolume(mpctx->mixer, arg);
- return M_PROPERTY_OK;
case M_PROPERTY_GET_TYPE:
*(struct m_option *)arg = (struct m_option){
.type = CONF_TYPE_FLOAT,
.flags = M_OPT_RANGE,
.min = 0,
- .max = mixer_getmaxvolume(mpctx->mixer),
+ .max = opts->softvol_max,
};
return M_PROPERTY_OK;
case M_PROPERTY_GET_NEUTRAL:
*(float *)arg = 100;
return M_PROPERTY_OK;
- case M_PROPERTY_PRINT: {
- float val;
- mixer_getbothvolume(mpctx->mixer, &val);
- *(char **)arg = talloc_asprintf(NULL, "%i", (int)val);
- return M_PROPERTY_OK;
- }
- case M_PROPERTY_SET:
- mixer_setvolume(mpctx->mixer, *(float *) arg, *(float *) arg);
- return M_PROPERTY_OK;
- case M_PROPERTY_SWITCH: {
- struct m_property_switch_arg *sarg = arg;
- mixer_addvolume(mpctx->mixer, sarg->inc);
+ case M_PROPERTY_PRINT:
+ *(char **)arg = talloc_asprintf(NULL, "%i", (int)opts->softvol_volume);
return M_PROPERTY_OK;
}
- }
- return M_PROPERTY_NOT_IMPLEMENTED;
-}
-static int mp_property_volume_max(void *ctx, struct m_property *prop,
- int action, void *arg)
-{
- MPContext *mpctx = ctx;
- return m_property_float_ro(action, arg, mixer_getmaxvolume(mpctx->mixer));
+ int r = mp_property_generic_option(mpctx, prop, action, arg);
+ if (action == M_PROPERTY_SET)
+ mixer_update_volume(mpctx->mixer);
+ return r;
}
/// Mute (RW)
@@ -1614,34 +1599,76 @@ static int mp_property_mute(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
+
+ if (action == M_PROPERTY_GET_TYPE) {
+ *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_FLAG};
+ return M_PROPERTY_OK;
+ }
+
+ int r = mp_property_generic_option(mpctx, prop, action, arg);
+ if (action == M_PROPERTY_SET)
+ mixer_update_volume(mpctx->mixer);
+ return r;
+}
+
+static int mp_property_ao_volume(void *ctx, struct m_property *prop,
+ int action, void *arg)
+{
+ MPContext *mpctx = ctx;
+ struct ao *ao = mpctx->ao;
+ if (!ao)
+ return M_PROPERTY_NOT_IMPLEMENTED;
+
switch (action) {
- case M_PROPERTY_SET:
- mixer_setmute(mpctx->mixer, *(int *) arg);
+ case M_PROPERTY_SET: {
+ float value = *(float *)arg;
+ ao_control_vol_t vol = {value, value};
+ if (ao_control(ao, AOCONTROL_SET_VOLUME, &vol) != CONTROL_OK)
+ return M_PROPERTY_UNAVAILABLE;
return M_PROPERTY_OK;
- case M_PROPERTY_GET:
- *(int *)arg = mixer_getmute(mpctx->mixer);
+ }
+ case M_PROPERTY_GET: {
+ ao_control_vol_t vol = {0};
+ if (ao_control(ao, AOCONTROL_GET_VOLUME, &vol) != CONTROL_OK)
+ return M_PROPERTY_UNAVAILABLE;
+ *(float *)arg = (vol.left + vol.right) / 2.0f;
return M_PROPERTY_OK;
+ }
case M_PROPERTY_GET_TYPE:
- *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_FLAG};
+ *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_FLOAT};
return M_PROPERTY_OK;
}
return M_PROPERTY_NOT_IMPLEMENTED;
}
-static int mp_property_volrestore(void *ctx, struct m_property *prop,
- int action, void *arg)
+
+static int mp_property_ao_mute(void *ctx, struct m_property *prop,
+ int action, void *arg)
{
MPContext *mpctx = ctx;
+ struct ao *ao = mpctx->ao;
+ if (!ao)
+ return M_PROPERTY_NOT_IMPLEMENTED;
+
switch (action) {
+ case M_PROPERTY_SET: {
+ bool value = *(int *)arg;
+ if (ao_control(ao, AOCONTROL_SET_MUTE, &value) != CONTROL_OK)
+ return M_PROPERTY_UNAVAILABLE;
+ return M_PROPERTY_OK;
+ }
case M_PROPERTY_GET: {
- char *s = mixer_get_volume_restore_data(mpctx->mixer);
- *(char **)arg = s;
- return s ? M_PROPERTY_OK : M_PROPERTY_UNAVAILABLE;
+ bool value = false;
+ if (ao_control(ao, AOCONTROL_GET_MUTE, &value) != CONTROL_OK)
+ return M_PROPERTY_UNAVAILABLE;
+ *(int *)arg = value;
+ return M_PROPERTY_OK;
}
- case M_PROPERTY_SET:
- return M_PROPERTY_NOT_IMPLEMENTED;
+ case M_PROPERTY_GET_TYPE:
+ *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_FLAG};
+ return M_PROPERTY_OK;
}
- return mp_property_generic_option(mpctx, prop, action, arg);
+ return M_PROPERTY_NOT_IMPLEMENTED;
}
static int get_device_entry(int item, int action, void *arg, void *ctx)
@@ -3670,8 +3697,10 @@ static const struct m_property mp_properties[] = {
// Audio
{"mixer-active", mp_property_mixer_active},
{"volume", mp_property_volume},
- {"volume-max", mp_property_volume_max},
+ {"volume-max", mp_property_generic_option},
{"mute", mp_property_mute},
+ {"ao-volume", mp_property_ao_volume},
+ {"ao-mute", mp_property_ao_mute},
{"audio-delay", mp_property_audio_delay},
{"audio-codec-name", mp_property_audio_codec_name},
{"audio-codec", mp_property_audio_codec},
@@ -3681,7 +3710,6 @@ static const struct m_property mp_properties[] = {
M_PROPERTY_DEPRECATED_ALIAS("audio-channels", "audio-params/channel-count"),
{"aid", mp_property_audio},
{"balance", mp_property_balance},
- {"volume-restore-data", mp_property_volrestore},
{"audio-device", mp_property_audio_device},
{"audio-device-list", mp_property_audio_devices},
{"current-ao", mp_property_ao},
@@ -3859,7 +3887,7 @@ static const char *const *const mp_event_property_change[] = {
"colormatrix-output-range", "colormatrix-primaries", "video-aspect"),
E(MPV_EVENT_AUDIO_RECONFIG, "audio-format", "audio-codec", "audio-bitrate",
"samplerate", "channels", "audio", "volume", "mute", "balance",
- "volume-restore-data", "current-ao", "audio-codec-name", "audio-params",
+ "current-ao", "audio-codec-name", "audio-params",
"audio-out-params", "volume-max", "mixer-active"),
E(MPV_EVENT_SEEK, "seeking", "core-idle", "eof-reached"),
E(MPV_EVENT_PLAYBACK_RESTART, "seeking", "core-idle", "eof-reached"),
diff --git a/player/configfiles.c b/player/configfiles.c
index 3c42331de0..7356a9a81b 100644
--- a/player/configfiles.c
+++ b/player/configfiles.c
@@ -208,7 +208,8 @@ static const char *const backup_properties[] = {
"options/speed",
"options/edition",
"options/pause",
- "volume-restore-data",
+ "volume",
+ "mute",
"options/audio-delay",
//"balance",
"options/fullscreen",