| @@ -53,9 +53,10 @@ enum autocreate_mode { · 52 unmodified lines |
| 53 | 53 | #define OPT_BASE_STRUCT struct demux_playlist_opts |
| 54 | 54 | struct demux_playlist_opts { |
| 55 | 55 | int dir_mode; |
| 56 | | − char **autocreate_playlist_vid_exts; |
| 57 | | − char **autocreate_playlist_aud_exts; |
| 58 | | − char **autocreate_playlist_img_exts; |
| 56 | + char **directory_filter; |
| 57 | + char **directory_vid_exts; |
| 58 | + char **directory_aud_exts; |
| 59 | + char **directory_img_exts; |
| 59 | 60 | }; |
| 60 | 61 | |
| 61 | 62 | struct m_sub_options demux_playlist_conf = { |
| @@ -65,26 +66,31 @@ struct m_sub_options demux_playlist_conf = { · 3 unmodified lines |
| 65 | 66 | {"lazy", DIR_LAZY}, |
| 66 | 67 | {"recursive", DIR_RECURSIVE}, |
| 67 | 68 | {"ignore", DIR_IGNORE})}, |
| 68 | | − {"autocreate-playlist-video-exts", |
| 69 | | − OPT_STRINGLIST(autocreate_playlist_vid_exts)}, |
| 70 | | − {"autocreate-playlist-audio-exts", |
| 71 | | − OPT_STRINGLIST(autocreate_playlist_aud_exts)}, |
| 72 | | − {"autocreate-playlist-image-exts", |
| 73 | | − OPT_STRINGLIST(autocreate_playlist_img_exts)}, |
| 69 | + {"directory-filter-types", |
| 70 | + OPT_STRINGLIST(directory_filter)}, |
| 71 | + {"directory-video-exts", |
| 72 | + OPT_STRINGLIST(directory_vid_exts)}, |
| 73 | + {"directory-audio-exts", |
| 74 | + OPT_STRINGLIST(directory_aud_exts)}, |
| 75 | + {"directory-image-exts", |
| 76 | + OPT_STRINGLIST(directory_img_exts)}, |
| 74 | 77 | {0} |
| 75 | 78 | }, |
| 76 | 79 | .size = sizeof(struct demux_playlist_opts), |
| 77 | 80 | .defaults = &(const struct demux_playlist_opts){ |
| 78 | 81 | .dir_mode = DIR_AUTO, |
| 79 | | − .autocreate_playlist_vid_exts = (char *[]){ |
| 82 | + .directory_filter = (char *[]){ |
| 83 | + NULL |
| 84 | + }, |
| 85 | + .directory_vid_exts = (char *[]){ |
| 80 | 86 | "3g2", "3gp", "avi", "flv", "m2ts", "m4v", "mj2", "mkv", "mov", |
| 81 | 87 | "mp4", "mpeg", "mpg", "ogv", "rmvb", "webm", "wmv", "y4m", NULL |
| 82 | 88 | }, |
| 83 | | − .autocreate_playlist_aud_exts = (char *[]){ |
| 89 | + .directory_aud_exts = (char *[]){ |
| 84 | 90 | "aiff", "ape", "au", "flac", "m4a", "mka", "mp3", "oga", "ogg", |
| 85 | 91 | "ogm", "opus", "wav", "wma", NULL |
| 86 | 92 | }, |
| 87 | | − .autocreate_playlist_img_exts = (char *[]){ |
| 93 | + .directory_img_exts = (char *[]){ |
| 88 | 94 | "avif", "bmp", "gif", "j2k", "jp2", "jpeg", "jpg", "jxl", "png", |
| 89 | 95 | "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 | |
| 427 | | −static bool has_ext(bstr ext, char **list) |
| 433 | +static bool has_str(bstr ext, char **list) |
| 428 | 434 | { |
| 429 | 435 | if (!list) |
| 430 | 436 | return false; |
| @@ -435,17 +441,17 @@ static bool has_ext(bstr ext, char **list) · 4 unmodified lines |
| 435 | 441 | return false; |
| 436 | 442 | } |
| 437 | 443 | |
| 438 | | −static bool test_autocreate_path(struct pl_parser *p, char *path, int autocreate) |
| 444 | +static bool test_path(struct pl_parser *p, char *path, int autocreate) |
| 439 | 445 | { |
| 440 | 446 | if (autocreate & AUTO_ANY) |
| 441 | 447 | return true; |
| 442 | 448 | |
| 443 | 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 | 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 | 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 | 455 | return true; |
| 450 | 456 | |
| 451 | 457 | return false; |
| @@ -505,13 +511,13 @@ static bool scan_dir(struct pl_parser *p, char *path, · 53 unmodified lines |
| 505 | 511 | qsort(dir_entries, num_dir_entries, sizeof(dir_entries[0]), cmp_dir_entry); |
| 506 | 512 | |
| 507 | 513 | for (int n = 0; n < num_dir_entries; n++) { |
| 514 | + char *file = dir_entries[n].path; |
| 508 | 515 | if (dir_mode == DIR_RECURSIVE && dir_entries[n].is_dir) { |
| 509 | 516 | dir_stack[num_dir_stack] = dir_entries[n].st; |
| 510 | | − char *file = dir_entries[n].path; |
| 511 | 517 | scan_dir(p, file, dir_stack, num_dir_stack + 1, autocreate); |
| 512 | 518 | } |
| 513 | 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 | 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 | 530 | int ret = -1; |
| 525 | 531 | struct stream *stream = p->real_stream; |
| 526 | 532 | int autocreate = AUTO_NONE; |
| 533 | + p->pl->playlist_dir = NULL; |
| 527 | 534 | if (p->autocreate_playlist && p->real_stream->is_local_file && !p->real_stream->is_directory) { |
| 528 | 535 | bstr ext = bstr_get_ext(bstr0(p->real_stream->url)); |
| 529 | 536 | switch (p->autocreate_playlist) { |
| 530 | 537 | case 1: // any |
| 531 | 538 | autocreate = AUTO_ANY; |
| 532 | 539 | break; |
| 533 | | − case 2: // exts |
| 540 | + case 2: // filter |
| 534 | 541 | autocreate = AUTO_VIDEO | AUTO_AUDIO | AUTO_IMAGE; |
| 535 | 542 | break; |
| 536 | 543 | 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 | 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 | 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 | 549 | autocreate = AUTO_IMAGE; |
| 543 | 550 | } |
| 544 | 551 | break; |
| @@ -548,8 +555,20 @@ static int parse_dir(struct pl_parser *p) · 3 unmodified lines |
| 548 | 555 | bstr dir = mp_dirname(p->real_stream->url); |
| 549 | 556 | if (!dir.len) |
| 550 | 557 | autocreate = AUTO_NONE; |
| 551 | | − if (autocreate != AUTO_NONE) |
| 558 | + if (autocreate != AUTO_NONE) { |
| 552 | 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 | 573 | if (!stream->is_directory) |
| 555 | 574 | goto done; |
| @@ -562,6 +581,9 @@ static int parse_dir(struct pl_parser *p) · 6 unmodified lines |
| 562 | 581 | if (!path) |
| 563 | 582 | goto done; |
| 564 | 583 | |
| 584 | + if (autocreate == AUTO_NONE) |
| 585 | + goto done; |
| 586 | + |
| 565 | 587 | struct stat dir_stack[MAX_DIR_STACK]; |
| 566 | 588 | |
| 567 | 589 | if (p->opts->dir_mode == DIR_AUTO) { |
| @@ -573,7 +595,6 @@ static int parse_dir(struct pl_parser *p) · 5 unmodified lines |
| 573 | 595 | scan_dir(p, path, dir_stack, 0, autocreate); |
| 574 | 596 | |
| 575 | 597 | p->add_base = false; |
| 576 | | − p->pl->autocreated = autocreate != AUTO_NONE; |
| 577 | 598 | ret = p->pl->num_entries > 0 ? 0 : -1; |
| 578 | 599 | |
| 579 | 600 | done: |