| @@ -53,9 +53,10 @@ enum autocreate_mode { · 52 unmodified lines |
| 53 | #define OPT_BASE_STRUCT struct demux_playlist_opts | 53 | #define OPT_BASE_STRUCT struct demux_playlist_opts |
| 54 | struct demux_playlist_opts { | 54 | struct 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 | |
| 61 | struct m_sub_options demux_playlist_conf = { | 62 | struct 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", NULL | 87 | "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", NULL | 91 | "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", NULL | 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 | 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 | |
| 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 | 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: // any | 537 | case 1: // any |
| 531 | autocreate = AUTO_ANY; | 538 | autocreate = AUTO_ANY; |
| 532 | break; | 539 | break; |
| 533 | case 2: // exts | 540 | 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: // same | 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 | 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 | |
| 579 | done: | 600 | done: |