diff options
-rw-r--r-- | DOCS/interface-changes.rst | 2 | ||||
-rw-r--r-- | DOCS/man/options.rst | 7 | ||||
-rw-r--r-- | options/options.c | 1 | ||||
-rw-r--r-- | options/options.h | 1 | ||||
-rw-r--r-- | osdep/io.h | 3 | ||||
-rw-r--r-- | player/configfiles.c | 44 |
6 files changed, 58 insertions, 0 deletions
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index 26337e9713..3a399fb265 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -25,6 +25,8 @@ Interface changes :: --- mpv 0.31.0 --- + - add `--resume-playback-check-mtime` to check consistent mtime when + restoring playback state. - add `--d3d11-output-csp` to enable explicit selection of a D3D11 swap chain color space. - the --sws- options and similar now affect vo_image and screenshot diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 3c52acec00..b2ba69ff26 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -714,6 +714,13 @@ Program Behavior subdirectory (usually ``~/.config/mpv/watch_later/``). See ``quit-watch-later`` input command. +``--resume-playback-check-mtime`` + Only restore the playback position from the ``watch_later`` configuration + subdirectory (usually ``~/.config/mpv/watch_later/``) if the file's + modification time is the same as at the time of saving. This may prevent + skipping forward in files with the same name which have different content. + (Default: ``no``) + ``--profile=<profile1,profile2,...>`` Use the given profile(s), ``--profile=help`` displays a list of the defined profiles. diff --git a/options/options.c b/options/options.c index 480186a908..1f0c9b1ef3 100644 --- a/options/options.c +++ b/options/options.c @@ -631,6 +631,7 @@ const m_option_t mp_opts[] = { OPT_ALIAS("loop", "loop-file"), OPT_FLAG("resume-playback", position_resume, 0), + OPT_FLAG("resume-playback-check-mtime", position_check_mtime, 0), OPT_FLAG("save-position-on-quit", position_save_on_quit, 0), OPT_FLAG("write-filename-in-watch-later-config", write_filename_in_watch_later_config, 0), OPT_FLAG("ignore-path-in-watch-later-config", ignore_path_in_watch_later_config, 0), diff --git a/options/options.h b/options/options.h index 2f7e368446..126e4cb59a 100644 --- a/options/options.h +++ b/options/options.h @@ -232,6 +232,7 @@ typedef struct MPOpts { double ab_loop[2]; double step_sec; int position_resume; + int position_check_mtime; int position_save_on_quit; int write_filename_in_watch_later_config; int ignore_path_in_watch_later_config; diff --git a/osdep/io.h b/osdep/io.h index 8699fb3e4a..12907e5cc9 100644 --- a/osdep/io.h +++ b/osdep/io.h @@ -172,6 +172,9 @@ void mp_globfree(mp_glob_t *pglob); #undef fstat #define fstat(...) mp_fstat(__VA_ARGS__) +#define utime(...) _utime(__VA_ARGS__) +#define utimbuf _utimbuf + void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); int munmap(void *addr, size_t length); int msync(void *addr, size_t length, int flags); diff --git a/player/configfiles.c b/player/configfiles.c index 668b34c542..d9a1e7d9f1 100644 --- a/player/configfiles.c +++ b/player/configfiles.c @@ -15,12 +15,14 @@ * License along with mpv. If not, see <http://www.gnu.org/licenses/>. */ +#include <errno.h> #include <stddef.h> #include <stdbool.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> +#include <utime.h> #include <libavutil/md5.h> @@ -155,6 +157,32 @@ void mp_load_auto_profiles(struct MPContext *mpctx) #define MP_WATCH_LATER_CONF "watch_later" +static bool check_mtime(const char *f1, const char *f2) +{ + struct stat st1, st2; + if (stat(f1, &st1) != 0 || stat(f2, &st2) != 0) + return false; + return st1.st_mtime == st2.st_mtime; +} + +static bool copy_mtime(const char *f1, const char *f2) +{ + struct stat st1, st2; + + if (stat(f1, &st1) != 0 || stat(f2, &st2) != 0) + return false; + + struct utimbuf ut = { + .actime = st2.st_atime, // we want to pass this through intact + .modtime = st1.st_mtime, + }; + + if (!utime(f2, &ut)) + return false; + + return true; +} + static char *mp_get_playback_resume_config_filename(struct MPContext *mpctx, const char *fname) { @@ -290,6 +318,10 @@ static void write_redirect(struct MPContext *mpctx, char *path) write_filename(mpctx, file, path); fclose(file); } + + if (mpctx->opts->position_check_mtime && !copy_mtime(path, conffile)) + MP_WARN(mpctx, "Can't copy mtime from %s to %s\n", path, conffile); + talloc_free(conffile); } } @@ -346,6 +378,13 @@ void mp_write_watch_later_conf(struct MPContext *mpctx) } fclose(file); + if (mpctx->opts->position_check_mtime && + !copy_mtime(cur->filename, 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 @@ -387,6 +426,11 @@ void mp_load_playback_resume(struct MPContext *mpctx, const char *file) return; char *fname = mp_get_playback_resume_config_filename(mpctx, file); if (fname && mp_path_exists(fname)) { + if (mpctx->opts->position_check_mtime && !check_mtime(file, fname)) { + talloc_free(fname); + return; + } + // Never apply the saved start position to following files m_config_backup_opt(mpctx->mconfig, "start"); MP_INFO(mpctx, "Resuming playback. This behavior can " |