diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst index f9a75779f7..ac07a9a1ba 100644 --- a/DOCS/man/en/options.rst +++ b/DOCS/man/en/options.rst @@ -2596,6 +2596,18 @@ Set the startup volume. A value of -1 (the default) will not change the volume. See also ``--softvol``. +``--volume-restore-data=`` + Used internally for use by playback resume (e.g. with ``quit_watch_later``). + Restoring value has to be done carefully, because different AOs as well as + softvol can have different value ranges, and we don't want to restore + volume if setting the volume changes it system wide. The normal options + (like ``--volume``) would always set the volume. This option was added for + restoring volume in a safer way (by storing the method used to set the + volume), and is not generally useful. Its semantics are considered private + to mpv. + + Do not use. + ``--wid=`` (X11 and Windows only) This tells mpv to attach to an existing window. The ID is interpreted as diff --git a/audio/mixer.c b/audio/mixer.c index 4407e8969f..3e16ce5f8e 100644 --- a/audio/mixer.c +++ b/audio/mixer.c @@ -17,6 +17,7 @@ */ #include +#include #include @@ -24,6 +25,7 @@ #include "audio/out/ao.h" #include "audio/filter/af.h" #include "mpvcore/mp_msg.h" +#include "talloc.h" #include "mixer.h" void mixer_init(struct mixer *mixer, struct MPOpts *opts) @@ -228,6 +230,14 @@ void mixer_setbalance(mixer_t *mixer, float val) AF_CONTROL_PAN_BALANCE | AF_CONTROL_SET, &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) { if (mixer->opts->softvol == SOFTVOL_AUTO) { @@ -286,10 +296,28 @@ static void restore_volume(struct mixer *mixer) if (opts->mixer_init_mute >= 0) force_mute = opts->mixer_init_mute; + // Set parameters from playback resume. + char *restore_data = mixer->opts->mixer_restore_volume_data; + if (restore && restore_data && restore_data[0]) { + char drv[40]; + float v_l, v_r; + int m; + if (sscanf(restore_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; + } + } + talloc_free(restore_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, these are reset to other values. + // 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; diff --git a/audio/mixer.h b/audio/mixer.h index 6761be5da4..a636a2b418 100644 --- a/audio/mixer.h +++ b/audio/mixer.h @@ -59,5 +59,6 @@ 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); +char *mixer_get_volume_restore_data(struct mixer *mixer); #endif /* MPLAYER_MIXER_H */ diff --git a/mpvcore/command.c b/mpvcore/command.c index dedac9dc10..ea71b9e082 100644 --- a/mpvcore/command.c +++ b/mpvcore/command.c @@ -804,6 +804,21 @@ static int mp_property_mute(m_option_t *prop, int action, void *arg, return M_PROPERTY_NOT_IMPLEMENTED; } +static int mp_property_volrestore(m_option_t *prop, int action, + void *arg, MPContext *mpctx) +{ + switch (action) { + case M_PROPERTY_GET: { + char *s = mixer_get_volume_restore_data(&mpctx->mixer); + *(char **)arg = s; + return s ? M_PROPERTY_OK : M_PROPERTY_UNAVAILABLE; + } + case M_PROPERTY_SET: + return M_PROPERTY_NOT_IMPLEMENTED; + } + return mp_property_generic_option(prop, action, arg, mpctx); +} + /// Audio delay (RW) static int mp_property_audio_delay(m_option_t *prop, int action, void *arg, MPContext *mpctx) @@ -1806,6 +1821,7 @@ static const m_option_t mp_properties[] = { M_OPTION_PROPERTY_CUSTOM("aid", mp_property_audio), { "balance", mp_property_balance, CONF_TYPE_FLOAT, M_OPT_RANGE, -1, 1, NULL }, + M_OPTION_PROPERTY_CUSTOM("volume-restore-data", mp_property_volrestore), // Video M_OPTION_PROPERTY_CUSTOM("fullscreen", mp_property_fullscreen), diff --git a/mpvcore/mplayer.c b/mpvcore/mplayer.c index fafb88d022..00229364e6 100644 --- a/mpvcore/mplayer.c +++ b/mpvcore/mplayer.c @@ -809,8 +809,7 @@ static const char *backup_properties[] = { "speed", "edition", "pause", - //"volume", - //"mute", + "volume-restore-data", "audio-delay", //"balance", "fullscreen", diff --git a/mpvcore/options.c b/mpvcore/options.c index a09a28856f..e3b3137aed 100644 --- a/mpvcore/options.c +++ b/mpvcore/options.c @@ -565,6 +565,7 @@ const m_option_t mp_opts[] = { ({"auto", -1}, {"no", 0}, {"yes", 1}, {"", 1})), + OPT_STRING("volume-restore-data", mixer_restore_volume_data, 0), OPT_FLAG("gapless-audio", gapless_audio, 0), // set screen dimensions (when not detectable or virtual!=visible) diff --git a/mpvcore/options.h b/mpvcore/options.h index 67074de241..d425d0789b 100644 --- a/mpvcore/options.h +++ b/mpvcore/options.h @@ -51,6 +51,7 @@ typedef struct MPOpts { int softvol; float mixer_init_volume; int mixer_init_mute; + char *mixer_restore_volume_data; int volstep; float softvol_max; int gapless_audio;