0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-19 19:42:24 +02:00

demux_playlist: add --directory-filter-types

This commit is contained in:
Kacper Michajłow 2024-07-17 00:58:59 +02:00
parent c54ad6933b
commit 4f1e9e34c3
7 changed files with 82 additions and 48 deletions

View File

@ -1,4 +1,4 @@
add `--autocreate-playlist`
add `--autocreate-playlist-video-exts`
add `--autocreate-playlist-audio-exts`
add `--autocreate-playlist-image-exts`
add `--directory-video-exts`
add `--directory-audio-exts`
add `--directory-image-exts`

View File

@ -0,0 +1 @@
add `--directory-filter-types`

View File

@ -4139,30 +4139,36 @@ 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.
This is a string list option. See `List Options`_ for details.
``--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.
: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 ``directory-*-exts``.
:same: Create a playlist from the parent directory with files matching the
same category as the currently loaded file. One of the
``directory-*-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>``
``--directory-video-exts=<ext1,ext2,...>``
Video file extension list that is used to match files when using
``--autocreate-playlist=<exts|same>``.
``--autocreate-playlist-audio-exts=<ext-list>``
``--directory-audio-exts=<ext1,ext2,...>``
Audio file extension list that is used to match files when using
``--autocreate-playlist=<exts|same>``.
``--autocreate-playlist-image-exts=<ext-list>``
``--directory-image-exts=<ext1,ext2,...>``
Image file extension list that is used to match files when using
``--autocreate-playlist=<exts|same>``.

View File

@ -72,7 +72,7 @@ struct playlist {
bool current_was_replaced;
bool playlist_completed;
bool playlist_started;
bool autocreated;
char *playlist_dir;
uint64_t id_alloc;
};

View File

@ -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),

View File

@ -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_vid_exts;
char **directory_aud_exts;
char **directory_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-video-exts",
OPT_STRINGLIST(directory_vid_exts)},
{"directory-audio-exts",
OPT_STRINGLIST(directory_aud_exts)},
{"directory-image-exts",
OPT_STRINGLIST(directory_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_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_aud_exts = (char *[]){
"aiff", "ape", "au", "flac", "m4a", "mka", "mp3", "oga", "ogg",
"ogm", "opus", "wav", "wma", NULL
},
.autocreate_playlist_img_exts = (char *[]){
.directory_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_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_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_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 (dir_entries[n].is_dir || 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;
p->pl->playlist_dir = NULL;
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_vid_exts)) {
autocreate = AUTO_VIDEO;
} else if (has_ext(ext, p->opts->autocreate_playlist_aud_exts)) {
} else if (has_str(ext, p->opts->directory_aud_exts)) {
autocreate = AUTO_AUDIO;
} else if (has_ext(ext, p->opts->autocreate_playlist_img_exts)) {
} else if (has_str(ext, p->opts->directory_img_exts)) {
autocreate = AUTO_IMAGE;
}
break;
@ -548,8 +555,20 @@ static int parse_dir(struct pl_parser *p)
bstr dir = mp_dirname(p->real_stream->url);
if (!dir.len)
autocreate = AUTO_NONE;
if (autocreate != AUTO_NONE)
if (autocreate != AUTO_NONE) {
stream = stream_create(bstrdup0(p, dir), flags, NULL, p->global);
p->pl->playlist_dir = bstrdup0(p->pl, dir);
}
} 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;
}
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,6 @@ 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;
ret = p->pl->num_entries > 0 ? 0 : -1;
done:

View File

@ -1042,10 +1042,16 @@ void prepare_playlist(struct MPContext *mpctx, struct playlist *pl)
if (opts->playlist_pos >= 0)
pl->current = playlist_entry_from_index(pl, opts->playlist_pos);
for (int i = 0; i < pl->num_entries && pl->autocreated; ++i) {
for (int i = 0; i < pl->num_entries && pl->playlist_dir; ++i) {
if (!pl->entries[i]->playlist_path)
continue;
if (!strcmp(pl->entries[i]->filename, pl->entries[i]->playlist_path)) {
char *path = pl->entries[i]->playlist_path;
if (path[0] != '.')
path = mp_path_join(NULL, pl->playlist_dir, pl->entries[i]->playlist_path);
bool same = !strcmp(pl->entries[i]->filename, path);
if (path != pl->entries[i]->playlist_path)
talloc_free(path);
if (same) {
pl->current = pl->entries[i];
break;
}
@ -1079,7 +1085,7 @@ static void transfer_playlist(struct MPContext *mpctx, struct playlist *pl,
playlist_remove(mpctx->playlist, mpctx->playlist->current);
if (new)
mpctx->playlist->current = new;
mpctx->playlist->autocreated = pl->autocreated;
mpctx->playlist->playlist_dir = talloc_steal(mpctx->playlist, pl->playlist_dir);
} else {
MP_WARN(mpctx, "Empty playlist!\n");
}
@ -1156,7 +1162,7 @@ static MP_THREAD_VOID open_demux_thread(void *ctx)
.stream_record = true,
.is_top_level = true,
.allow_playlist_create = mpctx->playlist->num_entries <= 1 &&
!mpctx->playlist->autocreated,
!mpctx->playlist->playlist_dir,
};
struct demuxer *demux =
demux_open_url(mpctx->open_url, &p, mpctx->open_cancel, mpctx->global);