mirror of
https://github.com/mpv-player/mpv
synced 2025-01-01 12:22:22 +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
|
||||
defaults to the equivalent of the old `--icc-contrast=inf`, and can
|
||||
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 ---
|
||||
- add `--d3d11-exclusive-fs` flag to enable D3D11 exclusive fullscreen mode
|
||||
when the player enters fullscreen.
|
||||
|
@ -851,6 +851,28 @@ Program Behavior
|
||||
- ``--reset-on-next-file=all``
|
||||
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``
|
||||
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.
|
||||
|
@ -244,6 +244,28 @@ void m_config_restore_backups(struct m_config *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)
|
||||
{
|
||||
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]);
|
||||
}
|
||||
|
||||
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 bstr name)
|
||||
@ -509,6 +537,13 @@ static void config_destroy(void *p)
|
||||
config->option_change_callback = NULL;
|
||||
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->shadow);
|
||||
}
|
||||
|
@ -75,6 +75,7 @@ typedef struct m_config {
|
||||
int profile_backup_flags;
|
||||
|
||||
struct m_opt_backup *backup_opts;
|
||||
struct m_opt_backup *watch_later_backup_opts;
|
||||
|
||||
bool use_profiles;
|
||||
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.
|
||||
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
|
||||
// backups afterwards.
|
||||
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 {
|
||||
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
|
||||
|
@ -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);
|
||||
|
||||
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++) {
|
||||
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)},
|
||||
{"watch-later-directory", OPT_STRING(watch_later_directory),
|
||||
.flags = M_OPT_FILE},
|
||||
{"watch-later-options", OPT_STRINGLIST(watch_later_options)},
|
||||
|
||||
{"ordered-chapters", OPT_FLAG(ordered_chapters)},
|
||||
{"ordered-chapters-files", OPT_STRING(ordered_chapters_files),
|
||||
@ -1043,6 +1044,44 @@ static const struct MPOpts mp_default_opts = {
|
||||
},
|
||||
|
||||
.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 = {
|
||||
|
@ -252,6 +252,7 @@ typedef struct MPOpts {
|
||||
int write_filename_in_watch_later_config;
|
||||
int ignore_path_in_watch_later_config;
|
||||
char *watch_later_directory;
|
||||
char **watch_later_options;
|
||||
int pause;
|
||||
int keep_open;
|
||||
int keep_open_pause;
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "misc/ctype.h"
|
||||
#include "options/path.h"
|
||||
#include "options/m_config.h"
|
||||
#include "options/m_config_frontend.h"
|
||||
#include "options/parse_configfile.h"
|
||||
#include "common/playlist.h"
|
||||
#include "options/options.h"
|
||||
@ -237,63 +238,6 @@ exit:
|
||||
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
|
||||
static bool needs_config_quoting(const char *s)
|
||||
{
|
||||
@ -368,25 +312,21 @@ void mp_write_watch_later_conf(struct MPContext *mpctx)
|
||||
} else {
|
||||
fprintf(file, "start=%f\n", pos);
|
||||
}
|
||||
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) {
|
||||
if (strncmp(pname, "options/", 8) == 0)
|
||||
pname += 8;
|
||||
// Only store it if it's different from the initial value.
|
||||
char *prev = mpctx->resume_defaults[i];
|
||||
if (!prev || strcmp(prev, val) != 0) {
|
||||
if (needs_config_quoting(val)) {
|
||||
// e.g. '%6%STRING'
|
||||
fprintf(file, "%s=%%%d%%%s\n", pname, (int)strlen(val), val);
|
||||
} else {
|
||||
fprintf(file, "%s=%s\n", pname, val);
|
||||
}
|
||||
char **watch_later_options = mpctx->opts->watch_later_options;
|
||||
for (int i = 0; watch_later_options && watch_later_options[i]; i++) {
|
||||
char *pname = watch_later_options[i];
|
||||
// Only store it if it's different from the initial value.
|
||||
if (m_config_watch_later_backup_opt_changed(mpctx->mconfig, pname)) {
|
||||
char *val = NULL;
|
||||
mp_property_do(pname, M_PROPERTY_GET_STRING, &val, mpctx);
|
||||
if (needs_config_quoting(val)) {
|
||||
// e.g. '%6%STRING'
|
||||
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);
|
||||
|
||||
|
@ -295,7 +295,6 @@ typedef struct MPContext {
|
||||
// Return code to use with PT_QUIT
|
||||
int quit_custom_rc;
|
||||
bool has_quit_custom_rc;
|
||||
char **resume_defaults;
|
||||
|
||||
// Global file statistics
|
||||
int files_played; // played without issues (even if stopped by user)
|
||||
@ -511,7 +510,6 @@ void audio_start_ao(struct MPContext *mpctx);
|
||||
// configfiles.c
|
||||
void mp_parse_cfgfiles(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_write_watch_later_conf(struct MPContext *mpctx);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user