summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/interface-changes.rst1
-rw-r--r--DOCS/man/options.rst7
-rw-r--r--demux/demux_playlist.c49
-rw-r--r--options/options.c2
-rw-r--r--options/options.h1
5 files changed, 51 insertions, 9 deletions
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst
index 0cbc4b6ea2..10c51fcf0e 100644
--- a/DOCS/interface-changes.rst
+++ b/DOCS/interface-changes.rst
@@ -84,6 +84,7 @@ Interface changes
passthrough the mpv window
- icc and gpu-shader cache are now saved by default (use --no-icc-shader-cache and
--no-gpu-shader-cache to disable)
+ - add `--directory-mode=recursive|lazy|ignore`
--- mpv 0.35.0 ---
- add the `--vo=gpu-next` video output driver, as well as the options
`--allow-delayed-peak-detect`, `--builtin-scalers`,
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index da163b9d88..ecb2c77383 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -3945,6 +3945,13 @@ Demuxer
libarchive opens all volumes anyway when playing the main file, even though
mpv iterated no archive entries yet.
+``--directory-mode=<recursive|lazy|ignore>``
+ When opening a directory, open subdirectories recursively, lazily or not at
+ all (default: recursive).
+
+ Values other then ``recursive`` can lead to problems with resuming playlists
+ (`RESUMING PLAYBACK`_) and possibly other things.
+
Input
-----
diff --git a/demux/demux_playlist.c b/demux/demux_playlist.c
index a5f9f0af35..6b6b2be144 100644
--- a/demux/demux_playlist.c
+++ b/demux/demux_playlist.c
@@ -24,6 +24,7 @@
#include "common/common.h"
#include "options/options.h"
+#include "options/m_config.h"
#include "common/msg.h"
#include "common/playlist.h"
#include "misc/thread_tools.h"
@@ -35,6 +36,31 @@
#define PROBE_SIZE (8 * 1024)
+enum dir_mode {
+ DIR_RECURSIVE,
+ DIR_LAZY,
+ DIR_IGNORE,
+};
+
+#define OPT_BASE_STRUCT struct demux_playlist_opts
+struct demux_playlist_opts {
+ int dir_mode;
+};
+
+struct m_sub_options demux_playlist_conf = {
+ .opts = (const struct m_option[]) {
+ {"directory-mode", OPT_CHOICE(dir_mode,
+ {"recursive", DIR_RECURSIVE},
+ {"lazy", DIR_LAZY},
+ {"ignore", DIR_IGNORE})},
+ {0}
+ },
+ .size = sizeof(struct demux_playlist_opts),
+ .defaults = &(const struct demux_playlist_opts){
+ .dir_mode = DIR_RECURSIVE,
+ },
+};
+
static bool check_mimetype(struct stream *s, const char *const *list)
{
if (s->mime_type) {
@@ -59,6 +85,7 @@ struct pl_parser {
enum demux_check check_level;
struct stream *real_stream;
char *format;
+ struct demux_playlist_opts *opts;
};
@@ -323,6 +350,7 @@ static bool scan_dir(struct pl_parser *p, char *path,
return false;
}
+ int dir_mode = p->opts->dir_mode;
struct dirent *ep;
while ((ep = readdir(dp))) {
if (ep->d_name[0] == '.')
@@ -334,16 +362,18 @@ static bool scan_dir(struct pl_parser *p, char *path,
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;
+ if (dir_mode != DIR_LAZY && 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)) {
+ 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);
+ 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);
}
@@ -458,6 +488,7 @@ static int open_file(struct demuxer *demuxer, enum demux_check check)
p->error = false;
p->s = demuxer->stream;
p->utf16 = stream_skip_bom(p->s);
+ p->opts = mp_get_config_group(demuxer, demuxer->global, &demux_playlist_conf);
bool ok = fmt->parse(p) >= 0 && !p->error;
if (p->add_base)
playlist_add_base_path(p->pl, mp_dirname(demuxer->filename));
@@ -471,7 +502,7 @@ static int open_file(struct demuxer *demuxer, enum demux_check check)
return ok ? 0 : -1;
}
-const struct demuxer_desc demuxer_desc_playlist = {
+const demuxer_desc_t demuxer_desc_playlist = {
.name = "playlist",
.desc = "Playlist file",
.open = open_file,
diff --git a/options/options.c b/options/options.c
index 92790dfb01..86e5a7b724 100644
--- a/options/options.c
+++ b/options/options.c
@@ -63,6 +63,7 @@ extern const struct m_sub_options zimg_conf;
extern const struct m_sub_options drm_conf;
extern const struct m_sub_options demux_rawaudio_conf;
extern const struct m_sub_options demux_rawvideo_conf;
+extern const struct m_sub_options demux_playlist_conf;
extern const struct m_sub_options demux_lavf_conf;
extern const struct m_sub_options demux_mkv_conf;
extern const struct m_sub_options demux_cue_conf;
@@ -591,6 +592,7 @@ static const m_option_t mp_opts[] = {
{"", OPT_SUBSTRUCT(demux_lavf, demux_lavf_conf)},
{"demuxer-rawaudio", OPT_SUBSTRUCT(demux_rawaudio, demux_rawaudio_conf)},
{"demuxer-rawvideo", OPT_SUBSTRUCT(demux_rawvideo, demux_rawvideo_conf)},
+ {"", OPT_SUBSTRUCT(demux_playlist, demux_playlist_conf)},
{"demuxer-mkv", OPT_SUBSTRUCT(demux_mkv, demux_mkv_conf)},
{"demuxer-cue", OPT_SUBSTRUCT(demux_cue, demux_cue_conf)},
diff --git a/options/options.h b/options/options.h
index 0125c433f5..0224e5609d 100644
--- a/options/options.h
+++ b/options/options.h
@@ -326,6 +326,7 @@ typedef struct MPOpts {
struct demux_rawaudio_opts *demux_rawaudio;
struct demux_rawvideo_opts *demux_rawvideo;
+ struct demux_playlist_opts *demux_playlist;
struct demux_lavf_opts *demux_lavf;
struct demux_mkv_opts *demux_mkv;
struct demux_cue_opts *demux_cue;