mirror of https://github.com/mpv-player/mpv
demux_playlist: read directories recursive
demux_playlist.c recognizes if the source stream points to a directory, and adds its directory entries. Until now, only 1 level was added. During playback, further directory entries could be resolved as directory paths were "played". While this worked fine, it lead to frequent user confusion, because playlist resuming and other things didn't work as expected. So just recursively scan everything. I'm unsure whether it's a good fix, but at least it gets rid of the complaints. (And probably will add others.)
This commit is contained in:
parent
382bafcb13
commit
503dada42f
|
@ -20,6 +20,7 @@
|
|||
#include <strings.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "common/common.h"
|
||||
#include "options/options.h"
|
||||
#include "common/msg.h"
|
||||
|
@ -209,6 +210,59 @@ static int parse_txt(struct pl_parser *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_DIR_STACK 20
|
||||
|
||||
static bool same_st(struct stat *st1, struct stat *st2)
|
||||
{
|
||||
return HAVE_POSIX && st1->st_dev == st2->st_dev && st1->st_ino == st2->st_ino;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
if (strlen(path) >= 8192 || num_dir_stack == MAX_DIR_STACK)
|
||||
return false; // things like mount bind loops
|
||||
|
||||
DIR *dp = opendir(path);
|
||||
if (!dp) {
|
||||
MP_ERR(p, "Could not read directory.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct dirent *ep;
|
||||
while ((ep = readdir(dp))) {
|
||||
if (ep->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
if (mp_cancel_test(p->s->cancel))
|
||||
break;
|
||||
|
||||
char *file = mp_path_join(p, path, ep->d_name);
|
||||
|
||||
struct stat st;
|
||||
if (stat(file, &st) == 0 && S_ISDIR(st.st_mode)) {
|
||||
for (int n = 0; n < num_dir_stack; n++) {
|
||||
if (same_st(&dir_stack[n], &st)) {
|
||||
MP_VERBOSE(p, "Skip recursive entry: %s\n", file);
|
||||
goto skip;
|
||||
}
|
||||
}
|
||||
|
||||
dir_stack[num_dir_stack] = st;
|
||||
scan_dir(p, file, dir_stack, num_dir_stack + 1, files, num_files);
|
||||
} else {
|
||||
MP_TARRAY_APPEND(p, *files, *num_files, file);
|
||||
}
|
||||
|
||||
skip: ;
|
||||
}
|
||||
|
||||
closedir(dp);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int cmp_filename(const void *a, const void *b)
|
||||
{
|
||||
return strcmp(*(char **)a, *(char **)b);
|
||||
|
@ -222,32 +276,18 @@ static int parse_dir(struct pl_parser *p)
|
|||
return 0;
|
||||
|
||||
char *path = mp_file_get_path(p, bstr0(p->real_stream->url));
|
||||
if (strlen(path) >= 8192)
|
||||
return -1; // things like mount bind loops
|
||||
|
||||
DIR *dp = opendir(path);
|
||||
if (!dp) {
|
||||
MP_ERR(p, "Could not read directory.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char **files = NULL;
|
||||
int num_files = 0;
|
||||
struct stat dir_stack[MAX_DIR_STACK];
|
||||
|
||||
struct dirent *ep;
|
||||
while ((ep = readdir(dp))) {
|
||||
if (ep->d_name[0] == '.')
|
||||
continue;
|
||||
MP_TARRAY_APPEND(p, files, num_files, talloc_strdup(p, ep->d_name));
|
||||
}
|
||||
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, mp_path_join(p, path, files[n]));
|
||||
|
||||
closedir(dp);
|
||||
playlist_add_file(p->pl, files[n]);
|
||||
|
||||
p->add_base = false;
|
||||
|
||||
|
|
Loading…
Reference in New Issue