History

demux_playlist: add --directory-filter-types

Kacper Michajłow committed 2 years ago

Commit 4f1e9e31 parent c54ad697 files · +83 −49Browse files

Unified · Split

7 files
  1. DOCS/interface-changes/autocreate-playlist.txt +3 −3
  2. DOCS/interface-changes/directory-filter-types.txt +1 −0
  3. DOCS/man/options.rst +21 −15
  4. common/playlist.h +1 −1
  5. demux/demux.c +1 −1
  6. demux/demux_playlist.c +46 −25
  7. player/loadfile.c +10 −4
DOCS/interface-changes/autocreate-playlist.txt+3−3
@@ -1,4 +1,4 @@
1add `--autocreate-playlist`1add `--autocreate-playlist`
2add `--autocreate-playlist-video-exts`2add `--directory-video-exts`
3add `--autocreate-playlist-audio-exts`3add `--directory-audio-exts`
4add `--autocreate-playlist-image-exts`4add `--directory-image-exts`
DOCS/interface-changes/directory-filter-types.txt+1−0
@@ -0,0 +1 @@
1add `--directory-filter-types`
DOCS/man/options.rst+21−15
@@ -4139,30 +4139,36 @@ Demuxer · 4138 unmodified lines
4139 all. The default is ``auto``, which behaves like ``recursive`` with4139 all. The default is ``auto``, which behaves like ``recursive`` with
4140 ``--shuffle``, and like ``lazy`` otherwise.4140 ``--shuffle``, and like ``lazy`` otherwise.
4141 4141
4142``--autocreate-playlist=<no|any|exts|same>``4142``--directory-filter-types=<video,audio,image>``
4143 Media file types to filter when opening directory. If the list is empty,
4144 all files are added to the playlist.
4145
4146 This is a string list option. See `List Options`_ for details.
4147
4148``--autocreate-playlist=<no|any|filter|same>``
4143 When opening a local file, act as if the parent directory is opened and4149 When opening a local file, act as if the parent directory is opened and
4144 create a playlist automatically.4150 create a playlist automatically.
4145 4151
4146 :no: Load a single file (default).4152 :no: Load a single file (default).
4147 :any: Create a playlist from the parent directory with any file type.4153 :any: Create a playlist from the parent directory with any file type.
4148 :exts: Create a playlist from the parent directory with files matching4154 :filter: Create a playlist from the parent directory with files matching
4149 extensions from any list ``autocreate-playlist-*-exts``.4155 extensions from any list ``directory-*-exts``.
4150 :same: Create a playlist from the parent directory with files matching the4156 :same: Create a playlist from the parent directory with files matching the
4151 same category as the currently loaded file. One of the4157 same category as the currently loaded file. One of the
4152 ``autocreate-playlist-*-exts`` is selected based on the input file4158 ``directory-*-exts`` is selected based on the input file
4153 and only files with matching extensions are added to the playlist.4159 and only files with matching extensions are added to the playlist.
4154 If the input file itself is not matched to any extension list,4160 If the input file itself is not matched to any extension list,
4155 the playlist is not autogenerated.4161 the playlist is not autogenerated.
4156 4162
4157``--autocreate-playlist-video-exts=<ext-list>``4163``--directory-video-exts=<ext1,ext2,...>``
4158 Video file extension list that is used to match files when using4164 Video file extension list that is used to match files when using
4159 ``--autocreate-playlist=<exts|same>``.4165 ``--autocreate-playlist=<exts|same>``.
4160 4166
4161``--autocreate-playlist-audio-exts=<ext-list>``4167``--directory-audio-exts=<ext1,ext2,...>``
4162 Audio file extension list that is used to match files when using4168 Audio file extension list that is used to match files when using
4163 ``--autocreate-playlist=<exts|same>``.4169 ``--autocreate-playlist=<exts|same>``.
4164 4170
4165``--autocreate-playlist-image-exts=<ext-list>``4171``--directory-image-exts=<ext1,ext2,...>``
4166 Image file extension list that is used to match files when using4172 Image file extension list that is used to match files when using
4167 ``--autocreate-playlist=<exts|same>``.4173 ``--autocreate-playlist=<exts|same>``.
4168 4174
common/playlist.h+1−1
@@ -72,7 +72,7 @@ struct playlist { · 71 unmodified lines
72 bool current_was_replaced;72 bool current_was_replaced;
73 bool playlist_completed;73 bool playlist_completed;
74 bool playlist_started;74 bool playlist_started;
75 bool autocreated;75 char *playlist_dir;
76 76
77 uint64_t id_alloc;77 uint64_t id_alloc;
78};78};
demux/demux.c+1−1
@@ -120,7 +120,7 @@ const struct m_sub_options demux_conf = { · 119 unmodified lines
120 M_RANGE(0, DBL_MAX)},120 M_RANGE(0, DBL_MAX)},
121 {"metadata-codepage", OPT_STRING(meta_cp)},121 {"metadata-codepage", OPT_STRING(meta_cp)},
122 {"autocreate-playlist", OPT_CHOICE(autocreate_playlist,122 {"autocreate-playlist", OPT_CHOICE(autocreate_playlist,
123 {"no", 0}, {"any", 1}, {"exts", 2}, {"same", 3})},123 {"no", 0}, {"any", 1}, {"filter", 2}, {"same", 3})},
124 {0}124 {0}
125 },125 },
126 .size = sizeof(struct demux_opts),126 .size = sizeof(struct demux_opts),
demux/demux_playlist.c+46−25
@@ -53,9 +53,10 @@ enum autocreate_mode { · 52 unmodified lines
53#define OPT_BASE_STRUCT struct demux_playlist_opts53#define OPT_BASE_STRUCT struct demux_playlist_opts
54struct demux_playlist_opts {54struct demux_playlist_opts {
55 int dir_mode;55 int dir_mode;
56 char **autocreate_playlist_vid_exts;56 char **directory_filter;
57 char **autocreate_playlist_aud_exts;57 char **directory_vid_exts;
58 char **autocreate_playlist_img_exts;58 char **directory_aud_exts;
59 char **directory_img_exts;
59};60};
60 61
61struct m_sub_options demux_playlist_conf = {62struct m_sub_options demux_playlist_conf = {
@@ -65,26 +66,31 @@ struct m_sub_options demux_playlist_conf = { · 3 unmodified lines
65 {"lazy", DIR_LAZY},66 {"lazy", DIR_LAZY},
66 {"recursive", DIR_RECURSIVE},67 {"recursive", DIR_RECURSIVE},
67 {"ignore", DIR_IGNORE})},68 {"ignore", DIR_IGNORE})},
68 {"autocreate-playlist-video-exts",69 {"directory-filter-types",
69 OPT_STRINGLIST(autocreate_playlist_vid_exts)},70 OPT_STRINGLIST(directory_filter)},
70 {"autocreate-playlist-audio-exts",71 {"directory-video-exts",
71 OPT_STRINGLIST(autocreate_playlist_aud_exts)},72 OPT_STRINGLIST(directory_vid_exts)},
72 {"autocreate-playlist-image-exts",73 {"directory-audio-exts",
73 OPT_STRINGLIST(autocreate_playlist_img_exts)},74 OPT_STRINGLIST(directory_aud_exts)},
75 {"directory-image-exts",
76 OPT_STRINGLIST(directory_img_exts)},
74 {0}77 {0}
75 },78 },
76 .size = sizeof(struct demux_playlist_opts),79 .size = sizeof(struct demux_playlist_opts),
77 .defaults = &(const struct demux_playlist_opts){80 .defaults = &(const struct demux_playlist_opts){
78 .dir_mode = DIR_AUTO,81 .dir_mode = DIR_AUTO,
79 .autocreate_playlist_vid_exts = (char *[]){82 .directory_filter = (char *[]){
83 NULL
84 },
85 .directory_vid_exts = (char *[]){
80 "3g2", "3gp", "avi", "flv", "m2ts", "m4v", "mj2", "mkv", "mov",86 "3g2", "3gp", "avi", "flv", "m2ts", "m4v", "mj2", "mkv", "mov",
81 "mp4", "mpeg", "mpg", "ogv", "rmvb", "webm", "wmv", "y4m", NULL87 "mp4", "mpeg", "mpg", "ogv", "rmvb", "webm", "wmv", "y4m", NULL
82 },88 },
83 .autocreate_playlist_aud_exts = (char *[]){89 .directory_aud_exts = (char *[]){
84 "aiff", "ape", "au", "flac", "m4a", "mka", "mp3", "oga", "ogg",90 "aiff", "ape", "au", "flac", "m4a", "mka", "mp3", "oga", "ogg",
85 "ogm", "opus", "wav", "wma", NULL91 "ogm", "opus", "wav", "wma", NULL
86 },92 },
87 .autocreate_playlist_img_exts = (char *[]){93 .directory_img_exts = (char *[]){
88 "avif", "bmp", "gif", "j2k", "jp2", "jpeg", "jpg", "jxl", "png",94 "avif", "bmp", "gif", "j2k", "jp2", "jpeg", "jpg", "jxl", "png",
89 "svg", "tga", "tif", "tiff", "webp", NULL95 "svg", "tga", "tif", "tiff", "webp", NULL
90 },96 },
@@ -424,7 +430,7 @@ static int cmp_dir_entry(const void *a, const void *b) · 333 unmodified lines
424 }430 }
425}431}
426 432
427static bool has_ext(bstr ext, char **list)433static bool has_str(bstr ext, char **list)
428{434{
429 if (!list)435 if (!list)
430 return false;436 return false;
@@ -435,17 +441,17 @@ static bool has_ext(bstr ext, char **list) · 4 unmodified lines
435 return false;441 return false;
436}442}
437 443
438static bool test_autocreate_path(struct pl_parser *p, char *path, int autocreate)444static bool test_path(struct pl_parser *p, char *path, int autocreate)
439{445{
440 if (autocreate & AUTO_ANY)446 if (autocreate & AUTO_ANY)
441 return true;447 return true;
442 448
443 bstr ext = bstr_get_ext(bstr0(path));449 bstr ext = bstr_get_ext(bstr0(path));
444 if (autocreate & AUTO_VIDEO && has_ext(ext, p->opts->autocreate_playlist_vid_exts))450 if (autocreate & AUTO_VIDEO && has_str(ext, p->opts->directory_vid_exts))
445 return true;451 return true;
446 if (autocreate & AUTO_AUDIO && has_ext(ext, p->opts->autocreate_playlist_aud_exts))452 if (autocreate & AUTO_AUDIO && has_str(ext, p->opts->directory_aud_exts))
447 return true;453 return true;
448 if (autocreate & AUTO_IMAGE && has_ext(ext, p->opts->autocreate_playlist_img_exts))454 if (autocreate & AUTO_IMAGE && has_str(ext, p->opts->directory_img_exts))
449 return true;455 return true;
450 456
451 return false;457 return false;
@@ -505,13 +511,13 @@ static bool scan_dir(struct pl_parser *p, char *path, · 53 unmodified lines
505 qsort(dir_entries, num_dir_entries, sizeof(dir_entries[0]), cmp_dir_entry);511 qsort(dir_entries, num_dir_entries, sizeof(dir_entries[0]), cmp_dir_entry);
506 512
507 for (int n = 0; n < num_dir_entries; n++) {513 for (int n = 0; n < num_dir_entries; n++) {
514 char *file = dir_entries[n].path;
508 if (dir_mode == DIR_RECURSIVE && dir_entries[n].is_dir) {515 if (dir_mode == DIR_RECURSIVE && dir_entries[n].is_dir) {
509 dir_stack[num_dir_stack] = dir_entries[n].st;516 dir_stack[num_dir_stack] = dir_entries[n].st;
510 char *file = dir_entries[n].path;
511 scan_dir(p, file, dir_stack, num_dir_stack + 1, autocreate);517 scan_dir(p, file, dir_stack, num_dir_stack + 1, autocreate);
512 }518 }
513 else {519 else {
514 if (autocreate == AUTO_NONE || test_autocreate_path(p, dir_entries[n].path, autocreate))520 if (dir_entries[n].is_dir || test_path(p, file, autocreate))
515 playlist_append_file(p->pl, dir_entries[n].path);521 playlist_append_file(p->pl, dir_entries[n].path);
516 }522 }
517 }523 }
@@ -524,21 +530,22 @@ static int parse_dir(struct pl_parser *p) · 6 unmodified lines
524 int ret = -1;530 int ret = -1;
525 struct stream *stream = p->real_stream;531 struct stream *stream = p->real_stream;
526 int autocreate = AUTO_NONE;532 int autocreate = AUTO_NONE;
533 p->pl->playlist_dir = NULL;
527 if (p->autocreate_playlist && p->real_stream->is_local_file && !p->real_stream->is_directory) {534 if (p->autocreate_playlist && p->real_stream->is_local_file && !p->real_stream->is_directory) {
528 bstr ext = bstr_get_ext(bstr0(p->real_stream->url));535 bstr ext = bstr_get_ext(bstr0(p->real_stream->url));
529 switch (p->autocreate_playlist) {536 switch (p->autocreate_playlist) {
530 case 1: // any537 case 1: // any
531 autocreate = AUTO_ANY;538 autocreate = AUTO_ANY;
532 break;539 break;
533 case 2: // exts540 case 2: // filter
534 autocreate = AUTO_VIDEO | AUTO_AUDIO | AUTO_IMAGE;541 autocreate = AUTO_VIDEO | AUTO_AUDIO | AUTO_IMAGE;
535 break;542 break;
536 case 3: // same543 case 3: // same
537 if (has_ext(ext, p->opts->autocreate_playlist_vid_exts)) {544 if (has_str(ext, p->opts->directory_vid_exts)) {
538 autocreate = AUTO_VIDEO;545 autocreate = AUTO_VIDEO;
539 } else if (has_ext(ext, p->opts->autocreate_playlist_aud_exts)) {546 } else if (has_str(ext, p->opts->directory_aud_exts)) {
540 autocreate = AUTO_AUDIO;547 autocreate = AUTO_AUDIO;
541 } else if (has_ext(ext, p->opts->autocreate_playlist_img_exts)) {548 } else if (has_str(ext, p->opts->directory_img_exts)) {
542 autocreate = AUTO_IMAGE;549 autocreate = AUTO_IMAGE;
543 }550 }
544 break;551 break;
@@ -548,8 +555,20 @@ static int parse_dir(struct pl_parser *p) · 3 unmodified lines
548 bstr dir = mp_dirname(p->real_stream->url);555 bstr dir = mp_dirname(p->real_stream->url);
549 if (!dir.len)556 if (!dir.len)
550 autocreate = AUTO_NONE;557 autocreate = AUTO_NONE;
551 if (autocreate != AUTO_NONE)558 if (autocreate != AUTO_NONE) {
552 stream = stream_create(bstrdup0(p, dir), flags, NULL, p->global);559 stream = stream_create(bstrdup0(p, dir), flags, NULL, p->global);
560 p->pl->playlist_dir = bstrdup0(p->pl, dir);
561 }
562 } else {
563 autocreate = AUTO_NONE;
564 if (!p->opts->directory_filter[0])
565 autocreate = AUTO_ANY;
566 if (has_str(bstr0("video"), p->opts->directory_filter))
567 autocreate |= AUTO_VIDEO;
568 if (has_str(bstr0("audio"), p->opts->directory_filter))
569 autocreate |= AUTO_AUDIO;
570 if (has_str(bstr0("image"), p->opts->directory_filter))
571 autocreate |= AUTO_IMAGE;
553 }572 }
554 if (!stream->is_directory)573 if (!stream->is_directory)
555 goto done;574 goto done;
@@ -562,6 +581,9 @@ static int parse_dir(struct pl_parser *p) · 6 unmodified lines
562 if (!path)581 if (!path)
563 goto done;582 goto done;
564 583
584 if (autocreate == AUTO_NONE)
585 goto done;
586
565 struct stat dir_stack[MAX_DIR_STACK];587 struct stat dir_stack[MAX_DIR_STACK];
566 588
567 if (p->opts->dir_mode == DIR_AUTO) {589 if (p->opts->dir_mode == DIR_AUTO) {
@@ -573,7 +595,6 @@ static int parse_dir(struct pl_parser *p) · 5 unmodified lines
573 scan_dir(p, path, dir_stack, 0, autocreate);595 scan_dir(p, path, dir_stack, 0, autocreate);
574 596
575 p->add_base = false;597 p->add_base = false;
576 p->pl->autocreated = autocreate != AUTO_NONE;
577 ret = p->pl->num_entries > 0 ? 0 : -1;598 ret = p->pl->num_entries > 0 ? 0 : -1;
578 599
579done:600done:
player/loadfile.c+10−4
@@ -1042,10 +1042,16 @@ void prepare_playlist(struct MPContext *mpctx, struct playlist *pl) · 1041 unmodified lines
1042 if (opts->playlist_pos >= 0)1042 if (opts->playlist_pos >= 0)
1043 pl->current = playlist_entry_from_index(pl, opts->playlist_pos);1043 pl->current = playlist_entry_from_index(pl, opts->playlist_pos);
1044 1044
1045 for (int i = 0; i < pl->num_entries && pl->autocreated; ++i) {1045 for (int i = 0; i < pl->num_entries && pl->playlist_dir; ++i) {
1046 if (!pl->entries[i]->playlist_path)1046 if (!pl->entries[i]->playlist_path)
1047 continue;1047 continue;
1048 if (!strcmp(pl->entries[i]->filename, pl->entries[i]->playlist_path)) {1048 char *path = pl->entries[i]->playlist_path;
1049 if (path[0] != '.')
1050 path = mp_path_join(NULL, pl->playlist_dir, pl->entries[i]->playlist_path);
1051 bool same = !strcmp(pl->entries[i]->filename, path);
1052 if (path != pl->entries[i]->playlist_path)
1053 talloc_free(path);
1054 if (same) {
1049 pl->current = pl->entries[i];1055 pl->current = pl->entries[i];
1050 break;1056 break;
1051 }1057 }
@@ -1079,7 +1085,7 @@ static void transfer_playlist(struct MPContext *mpctx, struct playlist *pl, · 27 unmodified lines
1079 playlist_remove(mpctx->playlist, mpctx->playlist->current);1085 playlist_remove(mpctx->playlist, mpctx->playlist->current);
1080 if (new)1086 if (new)
1081 mpctx->playlist->current = new;1087 mpctx->playlist->current = new;
1082 mpctx->playlist->autocreated = pl->autocreated;1088 mpctx->playlist->playlist_dir = talloc_steal(mpctx->playlist, pl->playlist_dir);
1083 } else {1089 } else {
1084 MP_WARN(mpctx, "Empty playlist!\n");1090 MP_WARN(mpctx, "Empty playlist!\n");
1085 }1091 }
@@ -1156,7 +1162,7 @@ static MP_THREAD_VOID open_demux_thread(void *ctx) · 70 unmodified lines
1156 .stream_record = true,1162 .stream_record = true,
1157 .is_top_level = true,1163 .is_top_level = true,
1158 .allow_playlist_create = mpctx->playlist->num_entries <= 1 &&1164 .allow_playlist_create = mpctx->playlist->num_entries <= 1 &&
1159 !mpctx->playlist->autocreated,1165 !mpctx->playlist->playlist_dir,
1160 };1166 };
1161 struct demuxer *demux =1167 struct demuxer *demux =
1162 demux_open_url(mpctx->open_url, &p, mpctx->open_cancel, mpctx->global);1168 demux_open_url(mpctx->open_url, &p, mpctx->open_cancel, mpctx->global);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t