mirror of
https://github.com/mpv-player/mpv
synced 2025-04-18 05:07:18 +00:00
demux_playlist: add --directory-filter-types
This commit is contained in:
parent
c54ad6933b
commit
4f1e9e34c3
@ -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`
|
||||
|
1
DOCS/interface-changes/directory-filter-types.txt
Normal file
1
DOCS/interface-changes/directory-filter-types.txt
Normal file
@ -0,0 +1 @@
|
||||
add `--directory-filter-types`
|
@ -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>``.
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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),
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user