diff options
-rw-r--r-- | DOCS/interface-changes.rst | 17 | ||||
-rw-r--r-- | DOCS/man/input.rst | 36 | ||||
-rw-r--r-- | DOCS/man/options.rst | 35 | ||||
-rw-r--r-- | audio/mixer.c | 278 | ||||
-rw-r--r-- | audio/mixer.h | 11 | ||||
-rw-r--r-- | options/options.c | 13 | ||||
-rw-r--r-- | options/options.h | 5 | ||||
-rw-r--r-- | player/audio.c | 2 | ||||
-rw-r--r-- | player/command.c | 108 | ||||
-rw-r--r-- | player/configfiles.c | 3 |
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", |