From 1d36955f70d27b5de6d323f23b94034221db0890 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 17 Apr 2015 22:56:19 +0200 Subject: player: allow playing directories If a directory is encountered, replace it with its contents in the internal playlist. This is messed into demux_playlist.c, because why not. STREAMTYPE_DIR could be avoided by unconditonally trying opendir() in demux_playlist.c, but it seems nicer not to do weird things like calling it on real files. This does not work on Windows, because msvcrt is retarded. --- demux/demux_playlist.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) (limited to 'demux/demux_playlist.c') diff --git a/demux/demux_playlist.c b/demux/demux_playlist.c index 381b50f269..6f73bea5ba 100644 --- a/demux/demux_playlist.c +++ b/demux/demux_playlist.c @@ -15,7 +15,10 @@ * with mpv. If not, see . */ +#include +#include #include +#include #include "common/common.h" #include "options/options.h" @@ -23,6 +26,7 @@ #include "common/playlist.h" #include "options/path.h" #include "stream/stream.h" +#include "osdep/io.h" #include "demux.h" #define PROBE_SIZE (8 * 1024) @@ -47,6 +51,7 @@ struct pl_parser { bool error; bool probing; bool force; + bool add_base; enum demux_check check_level; struct stream *real_stream; }; @@ -204,6 +209,51 @@ static int parse_txt(struct pl_parser *p) return 0; } +static int cmp_filename(const void *a, const void *b) +{ + return strcmp(*(char **)a, *(char **)b); +} + +static int parse_dir(struct pl_parser *p) +{ + if (p->real_stream->type != STREAMTYPE_DIR) + return -1; + if (p->probing) + 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 dirent *ep; + while ((ep = readdir(dp))) { + if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0) + continue; + MP_TARRAY_APPEND(p, files, num_files, talloc_strdup(p, ep->d_name)); + } + + 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, bstr0(path), bstr0(files[n]))); + + closedir(dp); + + p->add_base = false; + + return num_files > 0 ? 0 : -1; +} + #define MIME_TYPES(...) \ .mime_types = (const char*const[]){__VA_ARGS__, NULL} @@ -214,6 +264,7 @@ struct pl_format { }; static const struct pl_format formats[] = { + {"directory", parse_dir}, {"m3u", parse_m3u, MIME_TYPES("audio/mpegurl", "audio/x-mpegurl", "application/x-mpegurl")}, {"ini", parse_ref_init}, @@ -248,6 +299,7 @@ static int open_file(struct demuxer *demuxer, enum demux_check check) p->log = demuxer->log; p->pl = talloc_zero(p, struct playlist); p->real_stream = demuxer->stream; + p->add_base = true; bstr probe_buf = stream_peek(demuxer->stream, PROBE_SIZE); p->s = open_memory_stream(probe_buf.start, probe_buf.len); @@ -269,7 +321,7 @@ static int open_file(struct demuxer *demuxer, enum demux_check check) p->s = demuxer->stream; p->utf16 = stream_skip_bom(p->s); bool ok = fmt->parse(p) >= 0 && !p->error; - if (ok) + if (p->add_base) playlist_add_base_path(p->pl, mp_dirname(demuxer->filename)); demuxer->playlist = talloc_steal(demuxer, p->pl); demuxer->filetype = fmt->name; -- cgit v1.2.3