summaryrefslogtreecommitdiffstats
path: root/player/configfiles.c
diff options
context:
space:
mode:
Diffstat (limited to 'player/configfiles.c')
-rw-r--r--player/configfiles.c266
1 files changed, 131 insertions, 135 deletions
diff --git a/player/configfiles.c b/player/configfiles.c
index 0150133dbd..2b94308baa 100644
--- a/player/configfiles.c
+++ b/player/configfiles.c
@@ -26,7 +26,6 @@
#include <libavutil/md5.h>
-#include "config.h"
#include "mpv_talloc.h"
#include "osdep/io.h"
@@ -37,6 +36,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"
@@ -52,7 +52,7 @@ static void load_all_cfgfiles(struct MPContext *mpctx, char *section,
{
char **cf = mp_find_all_config_files(NULL, mpctx->global, filename);
for (int i = 0; cf && cf[i]; i++)
- m_config_parse_config_file(mpctx->mconfig, cf[i], section, 0);
+ m_config_parse_config_file(mpctx->mconfig, mpctx->global, cf[i], section, 0);
talloc_free(cf);
}
@@ -63,7 +63,7 @@ void mp_parse_cfgfiles(struct MPContext *mpctx)
{
struct MPOpts *opts = mpctx->opts;
- mp_mk_config_dir(mpctx->global, "");
+ mp_mk_user_dir(mpctx->global, "home", "");
char *p1 = mp_get_user_path(NULL, mpctx->global, "~~home/");
char *p2 = mp_get_user_path(NULL, mpctx->global, "~~old_home/");
@@ -99,7 +99,7 @@ static int try_load_config(struct MPContext *mpctx, const char *file, int flags,
if (!mp_path_exists(file))
return 0;
MP_MSG(mpctx, msgl, "Loading config '%s'\n", file);
- m_config_parse_config_file(mpctx->mconfig, file, NULL, flags);
+ m_config_parse_config_file(mpctx->mconfig, mpctx->global, file, NULL, flags);
return 1;
}
@@ -192,6 +192,17 @@ static bool copy_mtime(const char *f1, const char *f2)
return true;
}
+static char *mp_get_playback_resume_dir(struct MPContext *mpctx)
+{
+ char *wl_dir = mpctx->opts->watch_later_dir;
+ if (wl_dir && wl_dir[0]) {
+ wl_dir = mp_get_user_path(mpctx, mpctx->global, wl_dir);
+ } else {
+ wl_dir = mp_find_user_file(mpctx, mpctx->global, "state", MP_WATCH_LATER_CONF);
+ }
+ return wl_dir;
+}
+
static char *mp_get_playback_resume_config_filename(struct MPContext *mpctx,
const char *fname)
{
@@ -216,84 +227,15 @@ static char *mp_get_playback_resume_config_filename(struct MPContext *mpctx,
for (int i = 0; i < 16; i++)
conf = talloc_asprintf_append(conf, "%02X", md5[i]);
- if (!mpctx->cached_watch_later_configdir) {
- char *wl_dir = mpctx->opts->watch_later_directory;
- if (wl_dir && wl_dir[0]) {
- mpctx->cached_watch_later_configdir =
- mp_get_user_path(mpctx, mpctx->global, wl_dir);
- }
- }
-
- if (!mpctx->cached_watch_later_configdir) {
- mpctx->cached_watch_later_configdir =
- mp_find_user_config_file(mpctx, mpctx->global, MP_WATCH_LATER_CONF);
- }
-
- if (mpctx->cached_watch_later_configdir)
- res = mp_path_join(NULL, mpctx->cached_watch_later_configdir, conf);
+ char *wl_dir = mp_get_playback_resume_dir(mpctx);
+ if (wl_dir && wl_dir[0])
+ res = mp_path_join(NULL, wl_dir, conf);
exit:
talloc_free(tmp);
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-style-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)
{
@@ -309,6 +251,9 @@ static bool needs_config_quoting(const char *s)
static void write_filename(struct MPContext *mpctx, FILE *file, char *filename)
{
+ if (mpctx->opts->ignore_path_in_watch_later_config && !mp_is_url(bstr0(filename)))
+ filename = mp_basename(filename);
+
if (mpctx->opts->write_filename_in_watch_later_config) {
char write_name[1024] = {0};
for (int n = 0; filename[n] && n < sizeof(write_name) - 1; n++)
@@ -336,114 +281,164 @@ static void write_redirect(struct MPContext *mpctx, char *path)
}
}
+static void write_redirects_for_parent_dirs(struct MPContext *mpctx, char *path)
+{
+ if (mp_is_url(bstr0(path)) || mpctx->opts->ignore_path_in_watch_later_config)
+ return;
+
+ // Write redirect entries for the file's parent directories to allow
+ // resuming playback when playing parent directories whose entries are
+ // expanded only the first time they are "played". For example, if
+ // "/a/b/c.mkv" is the current entry, also create resume files for /a/b and
+ // /a, so that "mpv --directory-mode=lazy /a" resumes playback from
+ // /a/b/c.mkv even when b isn't the first directory in /a.
+ bstr dir = mp_dirname(path);
+ // There is no need to write a redirect entry for "/".
+ while (dir.len > 1 && dir.len < strlen(path)) {
+ path[dir.len] = '\0';
+ mp_path_strip_trailing_separator(path);
+ write_redirect(mpctx, path);
+ dir = mp_dirname(path);
+ }
+}
+
void mp_write_watch_later_conf(struct MPContext *mpctx)
{
struct playlist_entry *cur = mpctx->playing;
char *conffile = NULL;
+ void *ctx = talloc_new(NULL);
+
if (!cur)
goto exit;
+ char *path = mp_normalize_path(ctx, cur->filename);
+
struct demuxer *demux = mpctx->demuxer;
- conffile = mp_get_playback_resume_config_filename(mpctx, cur->filename);
+ conffile = mp_get_playback_resume_config_filename(mpctx, path);
if (!conffile)
goto exit;
- mp_mk_config_dir(mpctx->global, mpctx->cached_watch_later_configdir);
+ char *wl_dir = mp_get_playback_resume_dir(mpctx);
+ mp_mkdirp(wl_dir);
MP_INFO(mpctx, "Saving state.\n");
FILE *file = fopen(conffile, "wb");
- if (!file)
+ if (!file) {
+ MP_WARN(mpctx, "Can't open %s for writing\n", conffile);
goto exit;
+ }
- write_filename(mpctx, file, cur->filename);
+ write_filename(mpctx, file, path);
+ bool write_start = true;
double pos = get_current_time(mpctx);
if ((demux && (!demux->seekable || demux->partially_seekable)) ||
pos == MP_NOPTS_VALUE)
{
+ write_start = false;
MP_INFO(mpctx, "Not seekable, or time unknown - not saving position.\n");
- } 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];
+ // Always save start if we have it in the array.
+ if (write_start && strcmp(pname, "start") == 0) {
+ fprintf(file, "%s=%f\n", pname, pos);
+ continue;
+ }
+ // 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);
- if (mpctx->opts->position_check_mtime &&
- !mp_is_url(bstr0(cur->filename)) &&
- !copy_mtime(cur->filename, conffile))
+ if (mpctx->opts->position_check_mtime && !mp_is_url(bstr0(path)) &&
+ !copy_mtime(path, conffile))
{
MP_WARN(mpctx, "Can't copy mtime from %s to %s\n", cur->filename,
conffile);
}
- // This allows us to recursively resume directories etc., whose entries are
- // expanded the first time it's "played". For example, if "/a/b/c.mkv" is
- // the current entry, then we want to resume this file if the user does
- // "mpv /a". This would expand to the directory entries in "/a", and if
- // "/a/a.mkv" is not the first entry, this would be played.
- // Here, we write resume entries for "/a" and "/a/b".
- // (Unfortunately, this will leave stray resume files on resume, because
- // obviously it resumes only from one of those paths.)
- for (int n = 0; n < cur->num_redirects; n++)
- write_redirect(mpctx, cur->redirects[n]);
- // And at last, for local directories, we write an entry for each path
- // prefix, so the user can resume from an arbitrary directory. This starts
- // with the first redirect (all other redirects are further prefixes).
- if (cur->num_redirects) {
- char *path = cur->redirects[0];
- char tmp[4096];
- if (!mp_is_url(bstr0(path)) && strlen(path) < sizeof(tmp)) {
- snprintf(tmp, sizeof(tmp), "%s", path);
- for (;;) {
- bstr dir = mp_dirname(tmp);
- if (dir.len == strlen(tmp) || !dir.len || bstr_equals0(dir, "."))
- break;
-
- tmp[dir.len] = '\0';
- if (strlen(tmp) >= 2) // keep "/"
- mp_path_strip_trailing_separator(tmp);
- write_redirect(mpctx, tmp);
- }
- }
+ write_redirects_for_parent_dirs(mpctx, path);
+
+ // Also write redirect entries for a playlist that mpv expanded if the
+ // current entry is a URL, this is mostly useful for playing multiple
+ // archives of images, e.g. with mpv 1.zip 2.zip and quit-watch-later
+ // on 2.zip, write redirect entries for 2.zip, not just for the archive://
+ // URL.
+ if (cur->playlist_path && mp_is_url(bstr0(path))) {
+ char *playlist_path = mp_normalize_path(ctx, cur->playlist_path);
+ write_redirect(mpctx, playlist_path);
+ write_redirects_for_parent_dirs(mpctx, playlist_path);
}
exit:
talloc_free(conffile);
+ talloc_free(ctx);
}
-void mp_load_playback_resume(struct MPContext *mpctx, const char *file)
+void mp_delete_watch_later_conf(struct MPContext *mpctx, const char *file)
{
- if (!mpctx->opts->position_resume)
+ if (!file) {
+ struct playlist_entry *cur = mpctx->playing;
+ if (!cur)
+ return;
+ file = cur->filename;
+ if (!file)
+ return;
+ }
+
+ char *fname = mp_get_playback_resume_config_filename(mpctx, file);
+ if (fname) {
+ unlink(fname);
+ talloc_free(fname);
+ }
+
+ if (mp_is_url(bstr0(file)) || mpctx->opts->ignore_path_in_watch_later_config)
return;
+
+ void *ctx = talloc_new(NULL);
+ char *path = mp_normalize_path(ctx, file);
+
+ bstr dir = mp_dirname(path);
+ while (dir.len > 1 && dir.len < strlen(path)) {
+ path[dir.len] = '\0';
+ mp_path_strip_trailing_separator(path);
+ fname = mp_get_playback_resume_config_filename(mpctx, path);
+ if (fname) {
+ unlink(fname);
+ talloc_free(fname);
+ }
+ dir = mp_dirname(path);
+ }
+
+ talloc_free(ctx);
+}
+
+bool mp_load_playback_resume(struct MPContext *mpctx, const char *file)
+{
+ bool resume = false;
+ if (!mpctx->opts->position_resume)
+ return resume;
char *fname = mp_get_playback_resume_config_filename(mpctx, file);
if (fname && mp_path_exists(fname)) {
if (mpctx->opts->position_check_mtime &&
!mp_is_url(bstr0(file)) && !check_mtime(file, fname))
{
talloc_free(fname);
- return;
+ return resume;
}
// Never apply the saved start position to following files
@@ -451,9 +446,10 @@ void mp_load_playback_resume(struct MPContext *mpctx, const char *file)
MP_INFO(mpctx, "Resuming playback. This behavior can "
"be disabled with --no-resume-playback.\n");
try_load_config(mpctx, fname, M_SETOPT_PRESERVE_CMDLINE, MSGL_V);
- unlink(fname);
+ resume = true;
}
talloc_free(fname);
+ return resume;
}
// Returns the first file that has a resume config.