mirror of
https://github.com/mpv-player/mpv
synced 2025-01-04 05:52:09 +00:00
options: add watch-later-options
This allows configuring which options are saved by quit-watch-later. Fixes #4126, #4641 and #5567. Toggling a video or audio filter twice would treat the option as changed because the backup value is NULL, and the current value of vf/af is a list with one empty item, so obj_settings_list_equal had to be changed.
This commit is contained in:
parent
ccb87ad637
commit
1d1d1fbff9
@ -40,6 +40,8 @@ Interface changes
|
|||||||
- remove `--icc-contrast` and introduce `--icc-force-contrast`. The latter
|
- remove `--icc-contrast` and introduce `--icc-force-contrast`. The latter
|
||||||
defaults to the equivalent of the old `--icc-contrast=inf`, and can
|
defaults to the equivalent of the old `--icc-contrast=inf`, and can
|
||||||
instead be used to specifically set the contrast to any value.
|
instead be used to specifically set the contrast to any value.
|
||||||
|
- add a `--watch-later-options` option to allow configuring which
|
||||||
|
options quit-watch-later saves
|
||||||
--- mpv 0.33.0 ---
|
--- mpv 0.33.0 ---
|
||||||
- add `--d3d11-exclusive-fs` flag to enable D3D11 exclusive fullscreen mode
|
- add `--d3d11-exclusive-fs` flag to enable D3D11 exclusive fullscreen mode
|
||||||
when the player enters fullscreen.
|
when the player enters fullscreen.
|
||||||
|
@ -851,6 +851,28 @@ Program Behavior
|
|||||||
- ``--reset-on-next-file=all``
|
- ``--reset-on-next-file=all``
|
||||||
Try to reset all settings that were changed during playback.
|
Try to reset all settings that were changed during playback.
|
||||||
|
|
||||||
|
``--watch-later-options=option1,option2,...``
|
||||||
|
The options that are saved in "watch later" files if they have been changed
|
||||||
|
since when mpv started. These values will be restored the next time the
|
||||||
|
files are played. The playback position is always saved as ``start``, so
|
||||||
|
adding ``start`` to this list has no effect.
|
||||||
|
|
||||||
|
When removing options, existing watch later data won't be modified and will
|
||||||
|
still be applied fully, but new watch later data won't contain these
|
||||||
|
options.
|
||||||
|
|
||||||
|
This is a string list option. See `List Options`_ for details.
|
||||||
|
|
||||||
|
.. admonition:: Examples
|
||||||
|
|
||||||
|
- ``--watch-later-options-remove=fullscreen``
|
||||||
|
Resuming a file won't restore the fullscreen state.
|
||||||
|
- ``--watch-later-options-remove=volume,mute``
|
||||||
|
Resuming a file won't restore the volume or mute state.
|
||||||
|
- ``--watch-later-options=``
|
||||||
|
Resuming a file won't restore any option except the starting
|
||||||
|
position.
|
||||||
|
|
||||||
``--write-filename-in-watch-later-config``
|
``--write-filename-in-watch-later-config``
|
||||||
Prepend the watch later config files with the name of the file they refer
|
Prepend the watch later config files with the name of the file they refer
|
||||||
to. This is simply written as comment on the top of the file.
|
to. This is simply written as comment on the top of the file.
|
||||||
|
@ -244,6 +244,28 @@ void m_config_restore_backups(struct m_config *config)
|
|||||||
restore_backups(&config->backup_opts, config);
|
restore_backups(&config->backup_opts, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool m_config_watch_later_backup_opt_changed(struct m_config *config,
|
||||||
|
char *opt_name)
|
||||||
|
{
|
||||||
|
struct m_config_option *co = m_config_get_co(config, bstr0(opt_name));
|
||||||
|
if (!co) {
|
||||||
|
// --watch-later-options= makes the first list item an empty string.
|
||||||
|
if (strcmp(opt_name, "") != 0)
|
||||||
|
MP_ERR(config, "Option %s not found.\n", opt_name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (struct m_opt_backup *bc = config->watch_later_backup_opts; bc;
|
||||||
|
bc = bc->next) {
|
||||||
|
if (strcmp(bc->co->name, co->name) == 0) {
|
||||||
|
struct m_config_option *bc_co = (struct m_config_option *)bc->backup;
|
||||||
|
return !m_option_equal(co->opt, co->data, bc_co);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void m_config_backup_opt(struct m_config *config, const char *opt)
|
void m_config_backup_opt(struct m_config *config, const char *opt)
|
||||||
{
|
{
|
||||||
struct m_config_option *co = m_config_get_co(config, bstr0(opt));
|
struct m_config_option *co = m_config_get_co(config, bstr0(opt));
|
||||||
@ -260,6 +282,12 @@ void m_config_backup_all_opts(struct m_config *config)
|
|||||||
ensure_backup(&config->backup_opts, BACKUP_LOCAL, &config->opts[n]);
|
ensure_backup(&config->backup_opts, BACKUP_LOCAL, &config->opts[n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void m_config_backup_watch_later_opts(struct m_config *config)
|
||||||
|
{
|
||||||
|
for (int n = 0; n < config->num_opts; n++)
|
||||||
|
ensure_backup(&config->watch_later_backup_opts, BACKUP_LOCAL,
|
||||||
|
&config->opts[n]);
|
||||||
|
}
|
||||||
|
|
||||||
struct m_config_option *m_config_get_co_raw(const struct m_config *config,
|
struct m_config_option *m_config_get_co_raw(const struct m_config *config,
|
||||||
struct bstr name)
|
struct bstr name)
|
||||||
@ -509,6 +537,13 @@ static void config_destroy(void *p)
|
|||||||
config->option_change_callback = NULL;
|
config->option_change_callback = NULL;
|
||||||
m_config_restore_backups(config);
|
m_config_restore_backups(config);
|
||||||
|
|
||||||
|
struct m_opt_backup **list = &config->watch_later_backup_opts;
|
||||||
|
while (*list) {
|
||||||
|
struct m_opt_backup *bc = *list;
|
||||||
|
*list = bc->next;
|
||||||
|
talloc_free(bc);
|
||||||
|
}
|
||||||
|
|
||||||
talloc_free(config->cache);
|
talloc_free(config->cache);
|
||||||
talloc_free(config->shadow);
|
talloc_free(config->shadow);
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,7 @@ typedef struct m_config {
|
|||||||
int profile_backup_flags;
|
int profile_backup_flags;
|
||||||
|
|
||||||
struct m_opt_backup *backup_opts;
|
struct m_opt_backup *backup_opts;
|
||||||
|
struct m_opt_backup *watch_later_backup_opts;
|
||||||
|
|
||||||
bool use_profiles;
|
bool use_profiles;
|
||||||
bool is_toplevel;
|
bool is_toplevel;
|
||||||
@ -134,10 +135,18 @@ void m_config_backup_opt(struct m_config *config, const char *opt);
|
|||||||
// Call m_config_backup_opt() on all options.
|
// Call m_config_backup_opt() on all options.
|
||||||
void m_config_backup_all_opts(struct m_config *config);
|
void m_config_backup_all_opts(struct m_config *config);
|
||||||
|
|
||||||
|
// Backup options on startup so that quit-watch-later can compare the current
|
||||||
|
// values to their backups, and save them only if they have been changed.
|
||||||
|
void m_config_backup_watch_later_opts(struct m_config *config);
|
||||||
|
|
||||||
// Restore all options backed up with m_config_backup_opt(), and delete the
|
// Restore all options backed up with m_config_backup_opt(), and delete the
|
||||||
// backups afterwards.
|
// backups afterwards.
|
||||||
void m_config_restore_backups(struct m_config *config);
|
void m_config_restore_backups(struct m_config *config);
|
||||||
|
|
||||||
|
// Whether opt_name is different from its initial value.
|
||||||
|
bool m_config_watch_later_backup_opt_changed(struct m_config *config,
|
||||||
|
char *opt_name);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
M_SETOPT_PRE_PARSE_ONLY = 1, // Silently ignore non-M_OPT_PRE_PARSE opt.
|
M_SETOPT_PRE_PARSE_ONLY = 1, // Silently ignore non-M_OPT_PRE_PARSE opt.
|
||||||
M_SETOPT_CHECK_ONLY = 2, // Don't set, just check name/value
|
M_SETOPT_CHECK_ONLY = 2, // Don't set, just check name/value
|
||||||
|
@ -3668,7 +3668,7 @@ static bool obj_settings_list_equal(const m_option_t *opt, void *pa, void *pb)
|
|||||||
struct m_obj_settings *b = VAL(pb);
|
struct m_obj_settings *b = VAL(pb);
|
||||||
|
|
||||||
if (a == b || !a || !b)
|
if (a == b || !a || !b)
|
||||||
return a == b;
|
return a == b || (!a && !b[0].name) || (!b && !a[0].name);
|
||||||
|
|
||||||
for (int n = 0; a[n].name || b[n].name; n++) {
|
for (int n = 0; a[n].name || b[n].name; n++) {
|
||||||
if (!a[n].name || !b[n].name)
|
if (!a[n].name || !b[n].name)
|
||||||
|
@ -695,6 +695,7 @@ static const m_option_t mp_opts[] = {
|
|||||||
OPT_FLAG(ignore_path_in_watch_later_config)},
|
OPT_FLAG(ignore_path_in_watch_later_config)},
|
||||||
{"watch-later-directory", OPT_STRING(watch_later_directory),
|
{"watch-later-directory", OPT_STRING(watch_later_directory),
|
||||||
.flags = M_OPT_FILE},
|
.flags = M_OPT_FILE},
|
||||||
|
{"watch-later-options", OPT_STRINGLIST(watch_later_options)},
|
||||||
|
|
||||||
{"ordered-chapters", OPT_FLAG(ordered_chapters)},
|
{"ordered-chapters", OPT_FLAG(ordered_chapters)},
|
||||||
{"ordered-chapters-files", OPT_STRING(ordered_chapters_files),
|
{"ordered-chapters-files", OPT_STRING(ordered_chapters_files),
|
||||||
@ -1043,6 +1044,44 @@ static const struct MPOpts mp_default_opts = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
.cuda_device = -1,
|
.cuda_device = -1,
|
||||||
|
|
||||||
|
.watch_later_options = (char **)(const char*[]){
|
||||||
|
"osd-level",
|
||||||
|
"speed",
|
||||||
|
"edition",
|
||||||
|
"pause",
|
||||||
|
"volume",
|
||||||
|
"mute",
|
||||||
|
"audio-delay",
|
||||||
|
"fullscreen",
|
||||||
|
"ontop",
|
||||||
|
"border",
|
||||||
|
"gamma",
|
||||||
|
"brightness",
|
||||||
|
"contrast",
|
||||||
|
"saturation",
|
||||||
|
"hue",
|
||||||
|
"deinterlace",
|
||||||
|
"vf",
|
||||||
|
"af",
|
||||||
|
"panscan",
|
||||||
|
"aid",
|
||||||
|
"vid",
|
||||||
|
"sid",
|
||||||
|
"sub-delay",
|
||||||
|
"sub-speed",
|
||||||
|
"sub-pos",
|
||||||
|
"sub-visibility",
|
||||||
|
"sub-scale",
|
||||||
|
"sub-use-margins",
|
||||||
|
"sub-ass-force-margins",
|
||||||
|
"sub-ass-vsfilter-aspect-compat",
|
||||||
|
"sub-ass-override",
|
||||||
|
"ab-loop-a",
|
||||||
|
"ab-loop-b",
|
||||||
|
"video-aspect-override",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct m_sub_options mp_opt_root = {
|
const struct m_sub_options mp_opt_root = {
|
||||||
|
@ -252,6 +252,7 @@ typedef struct MPOpts {
|
|||||||
int write_filename_in_watch_later_config;
|
int write_filename_in_watch_later_config;
|
||||||
int ignore_path_in_watch_later_config;
|
int ignore_path_in_watch_later_config;
|
||||||
char *watch_later_directory;
|
char *watch_later_directory;
|
||||||
|
char **watch_later_options;
|
||||||
int pause;
|
int pause;
|
||||||
int keep_open;
|
int keep_open;
|
||||||
int keep_open_pause;
|
int keep_open_pause;
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "misc/ctype.h"
|
#include "misc/ctype.h"
|
||||||
#include "options/path.h"
|
#include "options/path.h"
|
||||||
#include "options/m_config.h"
|
#include "options/m_config.h"
|
||||||
|
#include "options/m_config_frontend.h"
|
||||||
#include "options/parse_configfile.h"
|
#include "options/parse_configfile.h"
|
||||||
#include "common/playlist.h"
|
#include "common/playlist.h"
|
||||||
#include "options/options.h"
|
#include "options/options.h"
|
||||||
@ -237,63 +238,6 @@ exit:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *const backup_properties[] = {
|
|
||||||
"osd-level",
|
|
||||||
//"loop",
|
|
||||||
"speed",
|
|
||||||
"options/edition",
|
|
||||||
"pause",
|
|
||||||
"volume",
|
|
||||||
"mute",
|
|
||||||
"audio-delay",
|
|
||||||
//"balance",
|
|
||||||
"fullscreen",
|
|
||||||
"ontop",
|
|
||||||
"border",
|
|
||||||
"gamma",
|
|
||||||
"brightness",
|
|
||||||
"contrast",
|
|
||||||
"saturation",
|
|
||||||
"hue",
|
|
||||||
"options/deinterlace",
|
|
||||||
"vf",
|
|
||||||
"af",
|
|
||||||
"panscan",
|
|
||||||
"options/aid",
|
|
||||||
"options/vid",
|
|
||||||
"options/sid",
|
|
||||||
"sub-delay",
|
|
||||||
"sub-speed",
|
|
||||||
"sub-pos",
|
|
||||||
"sub-visibility",
|
|
||||||
"sub-scale",
|
|
||||||
"sub-use-margins",
|
|
||||||
"sub-ass-force-margins",
|
|
||||||
"sub-ass-vsfilter-aspect-compat",
|
|
||||||
"sub-ass-override",
|
|
||||||
"ab-loop-a",
|
|
||||||
"ab-loop-b",
|
|
||||||
"options/video-aspect-override",
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
// Used to retrieve default settings, which should not be stored in the
|
|
||||||
// resume config. Uses backup_properties[] meaning/order of values.
|
|
||||||
// This explicitly includes values set by config files and command line.
|
|
||||||
void mp_get_resume_defaults(struct MPContext *mpctx)
|
|
||||||
{
|
|
||||||
char **list =
|
|
||||||
talloc_zero_array(mpctx, char*, MP_ARRAY_SIZE(backup_properties));
|
|
||||||
for (int i = 0; backup_properties[i]; i++) {
|
|
||||||
const char *pname = backup_properties[i];
|
|
||||||
char *val = NULL;
|
|
||||||
int r = mp_property_do(pname, M_PROPERTY_GET_STRING, &val, mpctx);
|
|
||||||
if (r == M_PROPERTY_OK)
|
|
||||||
list[i] = talloc_steal(list, val);
|
|
||||||
}
|
|
||||||
mpctx->resume_defaults = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should follow what parser-cfg.c does/needs
|
// Should follow what parser-cfg.c does/needs
|
||||||
static bool needs_config_quoting(const char *s)
|
static bool needs_config_quoting(const char *s)
|
||||||
{
|
{
|
||||||
@ -368,25 +312,21 @@ void mp_write_watch_later_conf(struct MPContext *mpctx)
|
|||||||
} else {
|
} else {
|
||||||
fprintf(file, "start=%f\n", pos);
|
fprintf(file, "start=%f\n", pos);
|
||||||
}
|
}
|
||||||
for (int i = 0; backup_properties[i]; i++) {
|
char **watch_later_options = mpctx->opts->watch_later_options;
|
||||||
const char *pname = backup_properties[i];
|
for (int i = 0; watch_later_options && watch_later_options[i]; i++) {
|
||||||
char *val = NULL;
|
char *pname = watch_later_options[i];
|
||||||
int r = mp_property_do(pname, M_PROPERTY_GET_STRING, &val, mpctx);
|
// Only store it if it's different from the initial value.
|
||||||
if (r == M_PROPERTY_OK) {
|
if (m_config_watch_later_backup_opt_changed(mpctx->mconfig, pname)) {
|
||||||
if (strncmp(pname, "options/", 8) == 0)
|
char *val = NULL;
|
||||||
pname += 8;
|
mp_property_do(pname, M_PROPERTY_GET_STRING, &val, mpctx);
|
||||||
// Only store it if it's different from the initial value.
|
if (needs_config_quoting(val)) {
|
||||||
char *prev = mpctx->resume_defaults[i];
|
// e.g. '%6%STRING'
|
||||||
if (!prev || strcmp(prev, val) != 0) {
|
fprintf(file, "%s=%%%d%%%s\n", pname, (int)strlen(val), val);
|
||||||
if (needs_config_quoting(val)) {
|
} else {
|
||||||
// e.g. '%6%STRING'
|
fprintf(file, "%s=%s\n", pname, val);
|
||||||
fprintf(file, "%s=%%%d%%%s\n", pname, (int)strlen(val), val);
|
|
||||||
} else {
|
|
||||||
fprintf(file, "%s=%s\n", pname, val);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
talloc_free(val);
|
||||||
}
|
}
|
||||||
talloc_free(val);
|
|
||||||
}
|
}
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
|
@ -295,7 +295,6 @@ typedef struct MPContext {
|
|||||||
// Return code to use with PT_QUIT
|
// Return code to use with PT_QUIT
|
||||||
int quit_custom_rc;
|
int quit_custom_rc;
|
||||||
bool has_quit_custom_rc;
|
bool has_quit_custom_rc;
|
||||||
char **resume_defaults;
|
|
||||||
|
|
||||||
// Global file statistics
|
// Global file statistics
|
||||||
int files_played; // played without issues (even if stopped by user)
|
int files_played; // played without issues (even if stopped by user)
|
||||||
@ -511,7 +510,6 @@ void audio_start_ao(struct MPContext *mpctx);
|
|||||||
// configfiles.c
|
// configfiles.c
|
||||||
void mp_parse_cfgfiles(struct MPContext *mpctx);
|
void mp_parse_cfgfiles(struct MPContext *mpctx);
|
||||||
void mp_load_auto_profiles(struct MPContext *mpctx);
|
void mp_load_auto_profiles(struct MPContext *mpctx);
|
||||||
void mp_get_resume_defaults(struct MPContext *mpctx);
|
|
||||||
void mp_load_playback_resume(struct MPContext *mpctx, const char *file);
|
void mp_load_playback_resume(struct MPContext *mpctx, const char *file);
|
||||||
void mp_write_watch_later_conf(struct MPContext *mpctx);
|
void mp_write_watch_later_conf(struct MPContext *mpctx);
|
||||||
void mp_delete_watch_later_conf(struct MPContext *mpctx, const char *file);
|
void mp_delete_watch_later_conf(struct MPContext *mpctx, const char *file);
|
||||||
|
@ -353,7 +353,10 @@ int mp_initialize(struct MPContext *mpctx, char **options)
|
|||||||
m_config_set_profile(mpctx->mconfig, "pseudo-gui", 0);
|
m_config_set_profile(mpctx->mconfig, "pseudo-gui", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_get_resume_defaults(mpctx);
|
// Backup the default settings, which should not be stored in the resume
|
||||||
|
// config files. This explicitly includes values set by config files and
|
||||||
|
// the command line.
|
||||||
|
m_config_backup_watch_later_opts(mpctx->mconfig);
|
||||||
|
|
||||||
mp_input_load_config(mpctx->input);
|
mp_input_load_config(mpctx->input);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user