From 3d111fbf1ee2f0ba2ee62ce5df6e6dfdf916f468 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Mon, 18 May 2026 13:37:00 +0200 Subject: [PATCH] demux_libarchive: apply --directory-filter-types to files in archives Fixes #17931. --- DOCS/man/options.rst | 7 ++++--- demux/demux.c | 4 ++++ demux/demux.h | 1 + demux/demux_libarchive.c | 25 +++++++++++++++++++++++++ demux/demux_playlist.c | 20 ++++++++------------ 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index f97044ceb3..863168ccbf 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -4396,9 +4396,10 @@ Demuxer ``--shuffle``, and like ``lazy`` otherwise. ``--directory-filter-types=`` - Media file types to filter when opening directory. To have all files added - to the playlist, clear the list using ``--directory-filter-types-clr``. - (Default: ``video,audio,image,archive,playlist``) + Media file types to filter when opening directories and archives. To have + all files added to the playlist, clear the list using + ``--directory-filter-types-clr``. (Default: + ``video,audio,image,archive,playlist``) This is a string list option. See `List Options`_ for details. diff --git a/demux/demux.c b/demux/demux.c index ef1b403cf1..2cc5e8d487 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -130,6 +130,7 @@ const struct m_sub_options demux_conf = { {"demuxer-backward-playback-step", OPT_DOUBLE(back_seek_size), M_RANGE(0, DBL_MAX)}, {"metadata-codepage", OPT_STRING(meta_cp)}, + {"directory-filter-types", OPT_STRINGLIST(directory_filter)}, {"autocreate-playlist", OPT_CHOICE(autocreate_playlist, {"no", 0}, {"filter", 1}, {"same", 2})}, {0} @@ -154,6 +155,9 @@ const struct m_sub_options demux_conf = { [STREAM_AUDIO] = 10, }, .meta_cp = "auto", + .directory_filter = (char *[]){ + "video", "audio", "image", "archive", "playlist", NULL + }, }, .get_sub_options = get_demux_sub_opts, }; diff --git a/demux/demux.h b/demux/demux.h index b1a07444e4..6fabf64b99 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -87,6 +87,7 @@ struct demux_opts { double back_seek_size; char *meta_cp; bool force_retry_eof; + char **directory_filter; int autocreate_playlist; }; diff --git a/demux/demux_libarchive.c b/demux/demux_libarchive.c index 9aff92ae8c..e33afe0262 100644 --- a/demux/demux_libarchive.c +++ b/demux/demux_libarchive.c @@ -23,6 +23,7 @@ #include "misc/natural_sort.h" #include "misc/path_utils.h" #include "options/m_config.h" +#include "options/options.h" #include "stream/stream.h" #include "demux.h" @@ -65,6 +66,11 @@ static int open_file(struct demuxer *demuxer, enum demux_check check) struct demux_libarchive_opts *opts = mp_get_config_group(demuxer, demuxer->global, demuxer->desc->options); + struct demux_opts *demux_opts = + mp_get_config_group(demuxer, demuxer->global, &demux_conf); + struct MPOpts *mp_opts = + mp_get_config_group(demuxer, demuxer->global, &mp_opt_root); + char **filter = demux_opts->directory_filter; if (!opts->rar_list_all_volumes) flags |= MP_ARCHIVE_FLAG_NO_VOLUMES; @@ -82,6 +88,25 @@ static int open_file(struct demuxer *demuxer, enum demux_check check) int num_files = 0; while (mp_archive_next_entry(mpa)) { + if (filter && filter[0]) { + bstr ext = bstr_get_ext(bstr0(mpa->entry_filename)); + bool pass = false; + + if (bstr_in_list0(bstr0("video"), filter)) + pass |= bstr_in_list0(ext, mp_opts->video_exts); + if (bstr_in_list0(bstr0("audio"), filter)) + pass |= bstr_in_list0(ext, mp_opts->audio_exts); + if (bstr_in_list0(bstr0("image"), filter)) + pass |= bstr_in_list0(ext, mp_opts->image_exts); + if (bstr_in_list0(bstr0("archive"), filter)) + pass |= bstr_in_list0(ext, mp_opts->archive_exts); + if (bstr_in_list0(bstr0("playlist"), filter)) + pass |= bstr_in_list0(ext, mp_opts->playlist_exts); + + if (!pass) + continue; + } + // stream_libarchive.c does the real work char *f = talloc_asprintf(mpa, "archive://%s|/%s", prefix, mpa->entry_filename); diff --git a/demux/demux_playlist.c b/demux/demux_playlist.c index 8e4c2e6341..c223d4ee19 100644 --- a/demux/demux_playlist.c +++ b/demux/demux_playlist.c @@ -56,7 +56,6 @@ enum autocreate_mode { #define OPT_BASE_STRUCT struct demux_playlist_opts struct demux_playlist_opts { int dir_mode; - char **directory_filter; }; struct m_sub_options demux_playlist_conf = { @@ -66,16 +65,11 @@ struct m_sub_options demux_playlist_conf = { {"lazy", DIR_LAZY}, {"recursive", DIR_RECURSIVE}, {"ignore", DIR_IGNORE})}, - {"directory-filter-types", - OPT_STRINGLIST(directory_filter)}, {0} }, .size = sizeof(struct demux_playlist_opts), .defaults = &(const struct demux_playlist_opts){ .dir_mode = DIR_AUTO, - .directory_filter = (char *[]){ - "video", "audio", "image", "archive", "playlist", NULL - }, }, .change_flags = UPDATE_DEMUXER, }; @@ -107,6 +101,7 @@ struct pl_parser { struct stream *real_stream; const char *format; char *codepage; + char **directory_filter; struct demux_playlist_opts *opts; struct MPOpts *mp_opts; }; @@ -517,17 +512,17 @@ static bool scan_dir(struct pl_parser *p, char *path, static enum autocreate_mode get_directory_filter(struct pl_parser *p) { enum autocreate_mode autocreate = AUTO_NONE; - if (!p->opts->directory_filter || !p->opts->directory_filter[0]) + if (!p->directory_filter || !p->directory_filter[0]) autocreate = AUTO_ANY; - if (bstr_in_list0(bstr0("video"), p->opts->directory_filter)) + if (bstr_in_list0(bstr0("video"), p->directory_filter)) autocreate |= AUTO_VIDEO; - if (bstr_in_list0(bstr0("audio"), p->opts->directory_filter)) + if (bstr_in_list0(bstr0("audio"), p->directory_filter)) autocreate |= AUTO_AUDIO; - if (bstr_in_list0(bstr0("image"), p->opts->directory_filter)) + if (bstr_in_list0(bstr0("image"), p->directory_filter)) autocreate |= AUTO_IMAGE; - if (bstr_in_list0(bstr0("archive"), p->opts->directory_filter)) + if (bstr_in_list0(bstr0("archive"), p->directory_filter)) autocreate |= AUTO_ARCHIVE; - if (bstr_in_list0(bstr0("playlist"), p->opts->directory_filter)) + if (bstr_in_list0(bstr0("playlist"), p->directory_filter)) autocreate |= AUTO_PLAYLIST; return autocreate; } @@ -671,6 +666,7 @@ static int open_file(struct demuxer *demuxer, enum demux_check check) p->check_level = check; p->probing = true; p->autocreate_playlist = demuxer->params->allow_playlist_create ? opts->autocreate_playlist : 0; + p->directory_filter = opts->directory_filter; p->mp_opts = mp_get_config_group(demuxer, demuxer->global, &mp_opt_root); p->opts = mp_get_config_group(demuxer, demuxer->global, &demux_playlist_conf);