Skip to content

Commit

Permalink
demux_playlist: add --directory-filter-types
Browse files Browse the repository at this point in the history
  • Loading branch information
kasper93 committed Jul 17, 2024
1 parent 4ae79aa commit e7d7e7b
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 43 deletions.
6 changes: 3 additions & 3 deletions DOCS/interface-changes/autocreate-playlist.txt
Original file line number Diff line number Diff line change
@@ -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`
1 change: 1 addition & 0 deletions DOCS/interface-changes/directory-filter-types.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add `--directory-filter-types`
34 changes: 19 additions & 15 deletions DOCS/man/options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4115,30 +4115,34 @@ Demuxer
all. The default is ``auto``, which behaves like ``recursive`` with
``--shuffle``, and like ``lazy`` otherwise.

``--autocreate-playlist=<no|any|exts|same>``
``--directory-filter-types=<video,audio,image>``
Media file types to filter when opening directory. If the list is empty,
all files are added to the playlist.

``--autocreate-playlist=<no|any|filter|same>``
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=<ext-list>``
: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=<cmd1,cmd2,...>``
Video file extension list that is used to match files when using
``--autocreate-playlist=<exts|same>``.

``--autocreate-playlist-audio-exts=<ext-list>``
``--directory-playlist-audio-exts=<cmd1,cmd2,...>``
Audio file extension list that is used to match files when using
``--autocreate-playlist=<exts|same>``.

``--autocreate-playlist-image-exts=<ext-list>``
``--directory-playlist-image-exts=<cmd1,cmd2,...>``
Image file extension list that is used to match files when using
``--autocreate-playlist=<exts|same>``.

Expand Down
2 changes: 1 addition & 1 deletion demux/demux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
70 changes: 46 additions & 24 deletions demux/demux_playlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand All @@ -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
},
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
}
}
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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) {
Expand All @@ -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:
Expand Down

0 comments on commit e7d7e7b

Please sign in to comment.