summaryrefslogtreecommitdiffstats
path: root/common/playlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/playlist.c')
-rw-r--r--common/playlist.c118
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, "