summaryrefslogtreecommitdiffstats
path: root/common/playlist.c
diff options
context:
space:
mode:
authorGuido Cella <guido@guidocella.xyz>2023-10-07 16:53:52 +0200
committerDudemanguy <random342@airmail.cc>2023-10-09 15:09:35 +0000
commit81dea9031dec05559624b6d2a8ea9bf89667f755 (patch)
treeba78bb2183bccf8e73fff01932e0029057888c82 /common/playlist.c
parentbcb9ed56fae7da59b495c5bddd7576821627dffb (diff)
downloadmpv-81dea9031dec05559624b6d2a8ea9bf89667f755.tar.bz2
mpv-81dea9031dec05559624b6d2a8ea9bf89667f755.tar.xz
command: add playlist-next-playlist and playlist-prev-playlist
playlist-prev-playlist goes to the beginning of the previous playlist because this seems more useful and symmetrical to playlist-next-playlist. It does not go to the beginning when the current playlist-path starts with the previous playlist-path, e.g. with mpv --loop-playlist foo/, which expands to foo/{1..9}.zip, the current playlist path foo/1.zip beings with the playlist-path foo/ of {2..9}.zip and thus playlist-prev-playlist goes to 9.zip rather than to 2.zip. Closes #12495.
Diffstat (limited to 'common/playlist.c')
-rw-r--r--common/playlist.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/common/playlist.c b/common/playlist.c
index 78a7713462..e79a96b402 100644
--- a/common/playlist.c
+++ b/common/playlist.c
@@ -214,6 +214,74 @@ struct playlist_entry *playlist_entry_get_rel(struct playlist_entry *e,
return playlist_entry_from_index(e->pl, e->pl_index + direction);
}
+struct playlist_entry *playlist_get_first_in_next_playlist(struct playlist *pl,
+ int direction)
+{
+ struct playlist_entry *entry = playlist_get_next(pl, direction);
+ if (!entry)
+ return NULL;
+
+ while (entry && entry->playlist_path &&
+ strcmp(entry->playlist_path, pl->current->playlist_path) == 0)
+ entry = playlist_entry_get_rel(entry, direction);
+
+ if (direction < 0)
+ entry = playlist_get_first_in_same_playlist(entry,
+ pl->current->playlist_path);
+
+ return entry;
+}
+
+struct playlist_entry *playlist_get_first_in_same_playlist(
+ struct playlist_entry *entry, char *current_playlist_path)
+{
+ void *tmp = talloc_new(NULL);
+
+ if (!entry || !entry->playlist_path)
+ goto exit;
+
+ // Don't go to the beginning of the playlist when the current playlist-path
+ // starts with the previous playlist-path, e.g. with mpv --loop-playlist
+ // archive_dir/, which expands to archive_dir/{1..9}.zip, the current
+ // playlist path "archive_dir/1.zip" begins with the playlist-path
+ // "archive_dir/" of {2..9}.zip, so go to 9.zip instead of 2.zip. But
+ // playlist-prev-playlist from e.g. the directory "foobar" to the directory
+ // "foo" should still go to the first entry in "foo/", and this should all
+ // work whether mpv's arguments have trailing slashes or not, e.g. in the
+ // first example:
+ // mpv archive_dir results in the playlist-paths "archive_dir/1.zip" and
+ // "archive_dir"
+ // mpv archive_dir/ in "archive_dir/1.zip" and "archive_dir/"
+ // mpv archive_dir// in "archive_dir//1.zip" and "archive_dir//"
+ // Always adding a separator to entry->playlist_path to fix the foobar foo
+ // case would break the previous 2 cases instead. Stripping the separator
+ // from entry->playlist_path if present and appending it again makes this
+ // work in all cases.
+ char* playlist_path = talloc_strdup(tmp, entry->playlist_path);
+ mp_path_strip_trailing_separator(playlist_path);
+ if (bstr_startswith(bstr0(current_playlist_path),
+ bstr0(talloc_strdup_append(playlist_path, "/")))
+#if HAVE_DOS_PATHS
+ ||
+ bstr_startswith(bstr0(current_playlist_path),
+ bstr0(talloc_strdup_append(playlist_path, "\\")))
+#endif
+ )
+ goto exit;
+
+ struct playlist_entry *prev = playlist_entry_get_rel(entry, -1);
+
+ while (prev && prev->playlist_path &&
+ strcmp(prev->playlist_path, entry->playlist_path) == 0) {
+ entry = prev;
+ prev = playlist_entry_get_rel(entry, -1);
+ }
+
+exit:
+ talloc_free(tmp);
+ return entry;
+}
+
void playlist_add_base_path(struct playlist *pl, bstr base_path)
{
if (base_path.len == 0 || bstrcmp0(base_path, ".") == 0)