From e7d7e7b5b385d09891d4208b34048fbf4f252c52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Wed, 17 Jul 2024 00:58:59 +0200 Subject: [PATCH] demux_playlist: add --directory-filter-types --- .../interface-changes/autocreate-playlist.txt | 6 +- .../directory-filter-types.txt | 1 + DOCS/man/options.rst | 34 +++++---- demux/demux.c | 2 +- demux/demux_playlist.c | 70 ++++++++++++------- 5 files changed, 70 insertions(+), 43 deletions(-) create mode 100644 DOCS/interface-changes/directory-filter-types.txt diff --git a/DOCS/interface-changes/autocreate-playlist.txt b/DOCS/interface-changes/autocreate-playlist.txt index f2d1d1113a477..e470e2278b9f8 100644 --- a/DOCS/interface-changes/autocreate-playlist.txt +++ b/DOCS/interface-changes/autocreate-playlist.txt @@ -1,4 +1,4 @@ add `--autocreate-playlist` -add `--autocreate-playlist-video-exts` -add `--autocreate-playlist-audio-exts` -add `--autocreate-playlist-image-exts` +add `--directory-playlist-video-exts` +add `--directory-playlist-audio-exts` +add `--directory-playlist-image-exts` diff --git a/DOCS/interface-changes/directory-filter-types.txt b/DOCS/interface-changes/directory-filter-types.txt new file mode 100644 index 0000000000000..bb7aa3e8b8732 --- /dev/null +++ b/DOCS/interface-changes/directory-filter-types.txt @@ -0,0 +1 @@ +add `--directory-filter-types` diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 33511c0f8121a..e65c64d871930 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -4115,30 +4115,34 @@ Demuxer all. The default is ``auto``, which behaves like ``recursive`` with ``--shuffle``, and like ``lazy`` otherwise. -``--autocreate-playlist=`` +``--directory-filter-types=`` + Media file types to filter when opening directory. If the list is empty, + all files are added to the playlist. + +``--autocreate-playlist=`` When opening a local file, act as if the parent directory is opened and create a playlist automatically. - :no: Load a single file (default). - :any: Create a playlist from the parent directory with any file type. - :exts: Create a playlist from the parent directory with files matching - extensions from any list ``autocreate-playlist-*-exts``. - :same: Create a playlist from the parent directory with files matching the - same category as the currently loaded file. One of the - ``autocreate-playlist-*-exts`` is selected based on the input file - and only files with matching extensions are added to the playlist. - If the input file itself is not matched to any extension list, - the playlist is not autogenerated. - -``--autocreate-playlist-video-exts=`` + :no: Load a single file (default). + :any: Create a playlist from the parent directory with any file type. + :filter: Create a playlist from the parent directory with files matching + extensions from any list ``autocreate-playlist-*-exts``. + :same: Create a playlist from the parent directory with files matching the + same category as the currently loaded file. One of the + ``autocreate-playlist-*-exts`` is selected based on the input file + and only files with matching extensions are added to the playlist. + If the input file itself is not matched to any extension list, + the playlist is not autogenerated. + +``--directory-playlist-video-exts=`` Video file extension list that is used to match files when using ``--autocreate-playlist=``. -``--autocreate-playlist-audio-exts=`` +``--directory-playlist-audio-exts=`` Audio file extension list that is used to match files when using ``--autocreate-playlist=``. -``--autocreate-playlist-image-exts=`` +``--directory-playlist-image-exts=`` Image file extension list that is used to match files when using ``--autocreate-playlist=``. diff --git a/demux/demux.c b/demux/demux.c index 842d8e7731b7c..f74836a3c3db9 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -120,7 +120,7 @@ const struct m_sub_options demux_conf = { M_RANGE(0, DBL_MAX)}, {"metadata-codepage", OPT_STRING(meta_cp)}, {"autocreate-playlist", OPT_CHOICE(autocreate_playlist, - {"no", 0}, {"any", 1}, {"exts", 2}, {"same", 3})}, + {"no", 0}, {"any", 1}, {"filter", 2}, {"same", 3})}, {0} }, .size = sizeof(struct demux_opts), diff --git a/demux/demux_playlist.c b/demux/demux_playlist.c index cf1a0499b58c5..a4a978aa9c405 100644 --- a/demux/demux_playlist.c +++ b/demux/demux_playlist.c @@ -53,9 +53,10 @@ enum autocreate_mode { #define OPT_BASE_STRUCT struct demux_playlist_opts struct demux_playlist_opts { int dir_mode; - char **autocreate_playlist_vid_exts; - char **autocreate_playlist_aud_exts; - char **autocreate_playlist_img_exts; + char **directory_filter; + char **directory_playlist_vid_exts; + char **directory_playlist_aud_exts; + char **directory_playlist_img_exts; }; struct m_sub_options demux_playlist_conf = { @@ -65,26 +66,31 @@ struct m_sub_options demux_playlist_conf = { {"lazy", DIR_LAZY}, {"recursive", DIR_RECURSIVE}, {"ignore", DIR_IGNORE})}, - {"autocreate-playlist-video-exts", - OPT_STRINGLIST(autocreate_playlist_vid_exts)}, - {"autocreate-playlist-audio-exts", - OPT_STRINGLIST(autocreate_playlist_aud_exts)}, - {"autocreate-playlist-image-exts", - OPT_STRINGLIST(autocreate_playlist_img_exts)}, + {"directory-filter-types", + OPT_STRINGLIST(directory_filter)}, + {"directory-playlist-video-exts", + OPT_STRINGLIST(directory_playlist_vid_exts)}, + {"directory-playlist-audio-exts", + OPT_STRINGLIST(directory_playlist_aud_exts)}, + {"directory-playlist-image-exts", + OPT_STRINGLIST(directory_playlist_img_exts)}, {0} }, .size = sizeof(struct demux_playlist_opts), .defaults = &(const struct demux_playlist_opts){ .dir_mode = DIR_AUTO, - .autocreate_playlist_vid_exts = (char *[]){ + .directory_filter = (char *[]){ + NULL + }, + .directory_playlist_vid_exts = (char *[]){ "3g2", "3gp", "avi", "flv", "m2ts", "m4v", "mj2", "mkv", "mov", "mp4", "mpeg", "mpg", "ogv", "rmvb", "webm", "wmv", "y4m", NULL }, - .autocreate_playlist_aud_exts = (char *[]){ + .directory_playlist_aud_exts = (char *[]){ "aiff", "ape", "au", "flac", "m4a", "mka", "mp3", "oga", "ogg", "ogm", "opus", "wav", "wma", NULL }, - .autocreate_playlist_img_exts = (char *[]){ + .directory_playlist_img_exts = (char *[]){ "avif", "bmp", "gif", "j2k", "jp2", "jpeg", "jpg", "jxl", "png", "svg", "tga", "tif", "tiff", "webp", NULL }, @@ -424,7 +430,7 @@ static int cmp_dir_entry(const void *a, const void *b) } } -static bool has_ext(bstr ext, char **list) +static bool has_str(bstr ext, char **list) { if (!list) return false; @@ -435,17 +441,17 @@ static bool has_ext(bstr ext, char **list) return false; } -static bool test_autocreate_path(struct pl_parser *p, char *path, int autocreate) +static bool test_path(struct pl_parser *p, char *path, int autocreate) { if (autocreate & AUTO_ANY) return true; bstr ext = bstr_get_ext(bstr0(path)); - if (autocreate & AUTO_VIDEO && has_ext(ext, p->opts->autocreate_playlist_vid_exts)) + if (autocreate & AUTO_VIDEO && has_str(ext, p->opts->directory_playlist_vid_exts)) return true; - if (autocreate & AUTO_AUDIO && has_ext(ext, p->opts->autocreate_playlist_aud_exts)) + if (autocreate & AUTO_AUDIO && has_str(ext, p->opts->directory_playlist_aud_exts)) return true; - if (autocreate & AUTO_IMAGE && has_ext(ext, p->opts->autocreate_playlist_img_exts)) + if (autocreate & AUTO_IMAGE && has_str(ext, p->opts->directory_playlist_img_exts)) return true; return false; @@ -505,13 +511,13 @@ static bool scan_dir(struct pl_parser *p, char *path, qsort(dir_entries, num_dir_entries, sizeof(dir_entries[0]), cmp_dir_entry); for (int n = 0; n < num_dir_entries; n++) { + char *file = dir_entries[n].path; 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, autocreate); } else { - if (autocreate == AUTO_NONE || test_autocreate_path(p, dir_entries[n].path, autocreate)) + if (test_path(p, file, autocreate)) playlist_append_file(p->pl, dir_entries[n].path); } } @@ -524,21 +530,22 @@ static int parse_dir(struct pl_parser *p) int ret = -1; struct stream *stream = p->real_stream; int autocreate = AUTO_NONE; + bool autocreated = false; if (p->autocreate_playlist && p->real_stream->is_local_file && !p->real_stream->is_directory) { bstr ext = bstr_get_ext(bstr0(p->real_stream->url)); switch (p->autocreate_playlist) { case 1: // any autocreate = AUTO_ANY; break; - case 2: // exts + case 2: // filter autocreate = AUTO_VIDEO | AUTO_AUDIO | AUTO_IMAGE; break; case 3: // same - if (has_ext(ext, p->opts->autocreate_playlist_vid_exts)) { + if (has_str(ext, p->opts->directory_playlist_vid_exts)) { autocreate = AUTO_VIDEO; - } else if (has_ext(ext, p->opts->autocreate_playlist_aud_exts)) { + } else if (has_str(ext, p->opts->directory_playlist_aud_exts)) { autocreate = AUTO_AUDIO; - } else if (has_ext(ext, p->opts->autocreate_playlist_img_exts)) { + } else if (has_str(ext, p->opts->directory_playlist_img_exts)) { autocreate = AUTO_IMAGE; } break; @@ -550,6 +557,18 @@ static int parse_dir(struct pl_parser *p) autocreate = AUTO_NONE; if (autocreate != AUTO_NONE) stream = stream_create(bstrdup0(p, dir), flags, NULL, p->global); + autocreated = true; + } else { + autocreate = AUTO_NONE; + if (!p->opts->directory_filter[0]) + autocreate = AUTO_ANY; + if (has_str(bstr0("video"), p->opts->directory_filter)) + autocreate |= AUTO_VIDEO; + if (has_str(bstr0("audio"), p->opts->directory_filter)) + autocreate |= AUTO_AUDIO; + if (has_str(bstr0("image"), p->opts->directory_filter)) + autocreate |= AUTO_IMAGE; + autocreated = false; } if (!stream->is_directory) goto done; @@ -562,6 +581,9 @@ static int parse_dir(struct pl_parser *p) if (!path) goto done; + if (autocreate == AUTO_NONE) + goto done; + struct stat dir_stack[MAX_DIR_STACK]; if (p->opts->dir_mode == DIR_AUTO) { @@ -573,7 +595,7 @@ static int parse_dir(struct pl_parser *p) scan_dir(p, path, dir_stack, 0, autocreate); p->add_base = false; - p->pl->autocreated = autocreate != AUTO_NONE; + p->pl->autocreated = autocreated; ret = p->pl->num_entries > 0 ? 0 : -1; done: