summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-01-06 22:40:55 +0100
committerwm4 <wm4@nowhere>2016-01-06 22:40:55 +0100
commit35f43dfacbe3abc000c1f35e36355613cb7da896 (patch)
treef21cae6345df3d6fa3a75b41444676a95b40ba2a /player
parentb7e179f6d3dc13d76bfdf4d5712e23328219c603 (diff)
downloadmpv-35f43dfacbe3abc000c1f35e36355613cb7da896.tar.bz2
mpv-35f43dfacbe3abc000c1f35e36355613cb7da896.tar.xz
player: make watch later/resume work when "playing" directories
If you do "mpv /bla/", and then branch out into sub-directories using playlist navigation, and then used quit and watch later, then playing the same directory did not resume from the previous point. This was because resuming is based on the path hash, so a path prefix can't be detected when resuming the parent directory. Solve this by writing each path prefix when playing directories is involved. (This includes all parent paths, so interestingly, "mpv /" would also resume in the above example.) Something like this was requested multiple times, and I want it too.
Diffstat (limited to 'player')
-rw-r--r--player/configfiles.c70
-rw-r--r--player/loadfile.c2
2 files changed, 63 insertions, 9 deletions
diff --git a/player/configfiles.c b/player/configfiles.c
index db19685c0f..678d60ddc0 100644
--- a/player/configfiles.c
+++ b/player/configfiles.c
@@ -273,11 +273,35 @@ static bool needs_config_quoting(const char *s)
return false;
}
+static void write_filename(struct MPContext *mpctx, FILE *file, char *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++)
+ write_name[n] = (unsigned char)filename[n] < 32 ? '_' : filename[n];
+ fprintf(file, "# %s\n", write_name);
+ }
+}
+
+static void write_redirect(struct MPContext *mpctx, char *path)
+{
+ char *conffile = mp_get_playback_resume_config_filename(mpctx, path);
+ if (conffile) {
+ FILE *file = fopen(conffile, "wb");
+ if (file) {
+ fprintf(file, "# redirect entry\n");
+ write_filename(mpctx, file, path);
+ fclose(file);
+ }
+ talloc_free(conffile);
+ }
+}
+
void mp_write_watch_later_conf(struct MPContext *mpctx)
{
- char *filename = mpctx->filename;
+ struct playlist_entry *cur = mpctx->playing;
char *conffile = NULL;
- if (!filename)
+ if (!cur)
goto exit;
struct demuxer *demux = mpctx->demuxer;
@@ -288,7 +312,7 @@ void mp_write_watch_later_conf(struct MPContext *mpctx)
mp_mk_config_dir(mpctx->global, MP_WATCH_LATER_CONF);
- conffile = mp_get_playback_resume_config_filename(mpctx, filename);
+ conffile = mp_get_playback_resume_config_filename(mpctx, cur->filename);
if (!conffile)
goto exit;
@@ -297,12 +321,9 @@ void mp_write_watch_later_conf(struct MPContext *mpctx)
FILE *file = fopen(conffile, "wb");
if (!file)
goto exit;
- 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++)
- write_name[n] = (unsigned char)filename[n] < 32 ? '_' : filename[n];
- fprintf(file, "# %s\n", write_name);
- }
+
+ write_filename(mpctx, file, cur->filename);
+
double pos = get_current_time(mpctx);
if (pos != MP_NOPTS_VALUE)
fprintf(file, "start=%f\n", pos);
@@ -328,6 +349,37 @@ void mp_write_watch_later_conf(struct MPContext *mpctx)
}
fclose(file);
+ // 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);
+ }
+ }
+ }
+
exit:
talloc_free(conffile);
}
diff --git a/player/loadfile.c b/player/loadfile.c
index 4a7a71f421..ec4d19d3c5 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -836,6 +836,8 @@ static void transfer_playlist(struct MPContext *mpctx, struct playlist *pl)
if (pl->first) {
prepare_playlist(mpctx, pl);
struct playlist_entry *new = pl->current;
+ if (mpctx->playlist->current)
+ playlist_add_redirect(pl, mpctx->playlist->current->filename);
playlist_transfer_entries(mpctx->playlist, pl);
// current entry is replaced
if (mpctx->playlist->current)