diff options
Diffstat (limited to 'common/playlist.c')
-rw-r--r-- | common/playlist.c | 118 |
1 files changed, 96 insertions, 22 deletions
diff --git a/common/playlist.c b/common/playlist.c index b7398dd936..39c49a5230 100644 --- a/common/playlist.c +++ b/common/playlist.c @@ -16,11 +16,11 @@ */ #include <assert.h> -#include "config.h" #include "playlist.h" #include "common/common.h" #include "common/global.h" #include "common/msg.h" +#include "misc/random.h" #include "mpv_talloc.h" #include "options/path.h" @@ -60,13 +60,23 @@ static void playlist_update_indexes(struct playlist *pl, int start, int end) pl->entries[n]->pl_index = n; } -void playlist_add(struct playlist *pl, struct playlist_entry *add) +// Inserts the entry so that it takes "at"'s place, shifting "at" and all +// further entires to the right (or append to end, if at==NULL). +void playlist_insert_at(struct playlist *pl, struct playlist_entry *add, + struct playlist_entry *at) { assert(add->filename); - MP_TARRAY_APPEND(pl, pl->entries, pl->num_entries, add); + assert(!at || at->pl == pl); + + int index = at ? at->pl_index : pl->num_entries; + MP_TARRAY_INSERT_AT(pl, pl->entries, pl->num_entries, index, add); + add->pl = pl; - add->pl_index = pl->num_entries - 1; + add->pl_index = index; add->id = ++pl->id_alloc; + + playlist_update_indexes(pl, index, pl->num_entries); + talloc_steal(pl, add); } @@ -137,9 +147,17 @@ void playlist_move(struct playlist *pl, struct playlist_entry *entry, MPMAX(index + 1, old_index + 1)); } -void playlist_add_file(struct playlist *pl, const char *filename) +void playlist_append_file(struct playlist *pl, const char *filename) +{ + playlist_insert_at(pl, playlist_entry_new(filename), NULL); +} + +void playlist_populate_playlist_path(struct playlist *pl, const char *path) { - playlist_add(pl, playlist_entry_new(filename)); + for (int n = 0; n < pl->num_entries; n++) { + struct playlist_entry *e = pl->entries[n]; + e->playlist_path = talloc_strdup(e, path); + } } void playlist_shuffle(struct playlist *pl) @@ -147,7 +165,7 @@ void playlist_shuffle(struct playlist *pl) for (int n = 0; n < pl->num_entries; n++) pl->entries[n]->original_index = n; for (int n = 0; n < pl->num_entries - 1; n++) { - int j = (int)((double)(pl->num_entries - n) * rand() / (RAND_MAX + 1.0)); + size_t j = (size_t)((pl->num_entries - n) * mp_rand_next_double()); MPSWAP(struct playlist_entry *, pl->entries[n], pl->entries[n + j]); } playlist_update_indexes(pl, 0, -1); @@ -206,6 +224,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 && pl->current->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) @@ -220,27 +306,14 @@ void playlist_add_base_path(struct playlist *pl, bstr base_path) } } -// Add redirected_from as new redirect entry to each item in pl. -void playlist_add_redirect(struct playlist *pl, const char *redirected_from) -{ - for (int n = 0; n < pl->num_entries; n++) { - struct playlist_entry *e = pl->entries[n]; - if (e->num_redirects >= 10) // arbitrary limit for sanity - continue; - char *s = talloc_strdup(e, redirected_from); - if (s) - MP_TARRAY_APPEND(e, e->redirects, e->num_redirects, s); - } -} - void playlist_set_stream_flags(struct playlist *pl, int flags) { for (int n = 0; n < pl->num_entries; n++) pl->entries[n]->stream_flags = flags; } -static int64_t playlist_transfer_entries_to(struct playlist *pl, int dst_index, - struct playlist *source_pl) +int64_t playlist_transfer_entries_to(struct playlist *pl, int dst_index, + struct playlist *source_pl) { assert(pl != source_pl); struct playlist_entry *first = playlist_get_first(source_pl); @@ -328,6 +401,7 @@ struct playlist *playlist_parse_file(const char *file, struct mp_cancel *cancel, struct playlist *ret = NULL; if (d && d->playlist) { ret = talloc_zero(NULL, struct playlist); + playlist_populate_playlist_path(d->playlist, file); playlist_transfer_entries(ret, d->playlist); if (d->filetype && strcmp(d->filetype, "hls") == 0) { mp_warn(log, "This might be a HLS stream. For correct operation, " |