summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
authorChristoph Heinrich <christoph.heinrich@student.tugraz.at>2023-02-11 23:16:16 +0100
committerDudemanguy <random342@airmail.cc>2023-07-06 18:17:45 +0000
commit2da0c0b33f120180f96ea895aae0a6513177de64 (patch)
treec1156ff207f649c30ac2f4a5bb52d721f6c2a2a8 /demux
parentf266eadf1eae920d645477b9658c6847aca47ff5 (diff)
downloadmpv-2da0c0b33f120180f96ea895aae0a6513177de64.tar.bz2
mpv-2da0c0b33f120180f96ea895aae0a6513177de64.tar.xz
demux_playlist: sort files before directories
Diffstat (limited to 'demux')
-rw-r--r--demux/demux_playlist.c67
1 files changed, 45 insertions, 22 deletions
diff --git a/demux/demux_playlist.c b/demux/demux_playlist.c
index 6b6b2be144..a99d8be7c8 100644
--- a/demux/demux_playlist.c
+++ b/demux/demux_playlist.c
@@ -336,10 +336,27 @@ static bool same_st(struct stat *st1, struct stat *st2)
return st1->st_dev == st2->st_dev && st1->st_ino == st2->st_ino;
}
+struct pl_dir_entry {
+ char *path;
+ char *name;
+ struct stat st;
+ bool is_dir;
+};
+
+static int cmp_dir_entry(const void *a, const void *b)
+{
+ struct pl_dir_entry *a_entry = (struct pl_dir_entry*) a;
+ struct pl_dir_entry *b_entry = (struct pl_dir_entry*) b;
+ if (a_entry->is_dir == b_entry->is_dir) {
+ return mp_natural_sort_cmp(a_entry->name, b_entry->name);
+ } else {
+ return a_entry->is_dir ? 1 : -1;
+ }
+}
+
// Return true if this was a readable directory.
static bool scan_dir(struct pl_parser *p, char *path,
- struct stat *dir_stack, int num_dir_stack,
- char ***files, int *num_files)
+ struct stat *dir_stack, int num_dir_stack)
{
if (strlen(path) >= 8192 || num_dir_stack == MAX_DIR_STACK)
return false; // things like mount bind loops
@@ -350,7 +367,11 @@ static bool scan_dir(struct pl_parser *p, char *path,
return false;
}
+ struct pl_dir_entry *dir_entries = NULL;
+ int num_dir_entries = 0;
+ int path_len = strlen(path);
int dir_mode = p->opts->dir_mode;
+
struct dirent *ep;
while ((ep = readdir(dp))) {
if (ep->d_name[0] == '.')
@@ -362,7 +383,7 @@ static bool scan_dir(struct pl_parser *p, char *path,
char *file = mp_path_join(p, path, ep->d_name);
struct stat st;
- if (dir_mode != DIR_LAZY && stat(file, &st) == 0 && S_ISDIR(st.st_mode)) {
+ if (stat(file, &st) == 0 && S_ISDIR(st.st_mode)) {
if (dir_mode != DIR_IGNORE) {
for (int n = 0; n < num_dir_stack; n++) {
if (same_st(&dir_stack[n], &st)) {
@@ -371,23 +392,33 @@ static bool scan_dir(struct pl_parser *p, char *path,
}
}
- dir_stack[num_dir_stack] = st;
- scan_dir(p, file, dir_stack, num_dir_stack + 1, files, num_files);
+ struct pl_dir_entry d = {file, &file[path_len], st, true};
+ MP_TARRAY_APPEND(p, dir_entries, num_dir_entries, d);
}
} else {
- MP_TARRAY_APPEND(p, *files, *num_files, file);
+ struct pl_dir_entry f = {file, &file[path_len], .is_dir = false};
+ MP_TARRAY_APPEND(p, dir_entries, num_dir_entries, f);
}
skip: ;
}
-
closedir(dp);
- return true;
-}
-static int cmp_filename(const void *a, const void *b)
-{
- return mp_natural_sort_cmp(*(char **)a, *(char **)b);
+ if (dir_entries)
+ qsort(dir_entries, num_dir_entries, sizeof(dir_entries[0]), cmp_dir_entry);
+
+ for (int n = 0; n < num_dir_entries; n++) {
+ if (dir_mode == DIR_RECURSIVE && dir_entries[n].is_dir) {
+ dir_stack[num_dir_stack] = dir_entries[n].st;
+ char *file = dir_entries[n].path;
+ scan_dir(p, file, dir_stack, num_dir_stack + 1);
+ }
+ else {
+ playlist_add_file(p->pl, dir_entries[n].path);
+ }
+ }
+
+ return true;
}
static int parse_dir(struct pl_parser *p)
@@ -401,21 +432,13 @@ static int parse_dir(struct pl_parser *p)
if (!path)
return -1;
- char **files = NULL;
- int num_files = 0;
struct stat dir_stack[MAX_DIR_STACK];
- scan_dir(p, path, dir_stack, 0, &files, &num_files);
-
- if (files)
- qsort(files, num_files, sizeof(files[0]), cmp_filename);
-
- for (int n = 0; n < num_files; n++)
- playlist_add_file(p->pl, files[n]);
+ scan_dir(p, path, dir_stack, 0);
p->add_base = false;
- return num_files > 0 ? 0 : -1;
+ return p->pl->num_entries > 0 ? 0 : -1;
}
#define MIME_TYPES(...) \