mirror of https://github.com/mpv-player/mpv
demux_playlist: add --autocreate-playlist-{video,audio,image}-exts
This commit is contained in:
parent
bb9b862f0c
commit
c54ad6933b
|
@ -0,0 +1,4 @@
|
||||||
|
add `--autocreate-playlist`
|
||||||
|
add `--autocreate-playlist-video-exts`
|
||||||
|
add `--autocreate-playlist-audio-exts`
|
||||||
|
add `--autocreate-playlist-image-exts`
|
|
@ -4139,6 +4139,33 @@ Demuxer
|
||||||
all. The default is ``auto``, which behaves like ``recursive`` with
|
all. The default is ``auto``, which behaves like ``recursive`` with
|
||||||
``--shuffle``, and like ``lazy`` otherwise.
|
``--shuffle``, and like ``lazy`` otherwise.
|
||||||
|
|
||||||
|
``--autocreate-playlist=<no|any|exts|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.
|
||||||
|
|
||||||
|
``--autocreate-playlist-video-exts=<ext-list>``
|
||||||
|
Video file extension list that is used to match files when using
|
||||||
|
``--autocreate-playlist=<exts|same>``.
|
||||||
|
|
||||||
|
``--autocreate-playlist-audio-exts=<ext-list>``
|
||||||
|
Audio file extension list that is used to match files when using
|
||||||
|
``--autocreate-playlist=<exts|same>``.
|
||||||
|
|
||||||
|
``--autocreate-playlist-image-exts=<ext-list>``
|
||||||
|
Image file extension list that is used to match files when using
|
||||||
|
``--autocreate-playlist=<exts|same>``.
|
||||||
|
|
||||||
Input
|
Input
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ struct playlist {
|
||||||
bool current_was_replaced;
|
bool current_was_replaced;
|
||||||
bool playlist_completed;
|
bool playlist_completed;
|
||||||
bool playlist_started;
|
bool playlist_started;
|
||||||
|
bool autocreated;
|
||||||
|
|
||||||
uint64_t id_alloc;
|
uint64_t id_alloc;
|
||||||
};
|
};
|
||||||
|
|
|
@ -57,6 +57,7 @@ extern const demuxer_desc_t demuxer_desc_mf;
|
||||||
extern const demuxer_desc_t demuxer_desc_matroska;
|
extern const demuxer_desc_t demuxer_desc_matroska;
|
||||||
extern const demuxer_desc_t demuxer_desc_lavf;
|
extern const demuxer_desc_t demuxer_desc_lavf;
|
||||||
extern const demuxer_desc_t demuxer_desc_playlist;
|
extern const demuxer_desc_t demuxer_desc_playlist;
|
||||||
|
extern const demuxer_desc_t demuxer_desc_directory;
|
||||||
extern const demuxer_desc_t demuxer_desc_disc;
|
extern const demuxer_desc_t demuxer_desc_disc;
|
||||||
extern const demuxer_desc_t demuxer_desc_rar;
|
extern const demuxer_desc_t demuxer_desc_rar;
|
||||||
extern const demuxer_desc_t demuxer_desc_libarchive;
|
extern const demuxer_desc_t demuxer_desc_libarchive;
|
||||||
|
@ -64,10 +65,10 @@ extern const demuxer_desc_t demuxer_desc_null;
|
||||||
extern const demuxer_desc_t demuxer_desc_timeline;
|
extern const demuxer_desc_t demuxer_desc_timeline;
|
||||||
|
|
||||||
static const demuxer_desc_t *const demuxer_list[] = {
|
static const demuxer_desc_t *const demuxer_list[] = {
|
||||||
|
&demuxer_desc_directory,
|
||||||
&demuxer_desc_disc,
|
&demuxer_desc_disc,
|
||||||
&demuxer_desc_edl,
|
&demuxer_desc_edl,
|
||||||
&demuxer_desc_cue,
|
&demuxer_desc_cue,
|
||||||
&demuxer_desc_playlist,
|
|
||||||
&demuxer_desc_rawaudio,
|
&demuxer_desc_rawaudio,
|
||||||
&demuxer_desc_rawvideo,
|
&demuxer_desc_rawvideo,
|
||||||
&demuxer_desc_matroska,
|
&demuxer_desc_matroska,
|
||||||
|
@ -76,6 +77,7 @@ static const demuxer_desc_t *const demuxer_list[] = {
|
||||||
#endif
|
#endif
|
||||||
&demuxer_desc_lavf,
|
&demuxer_desc_lavf,
|
||||||
&demuxer_desc_mf,
|
&demuxer_desc_mf,
|
||||||
|
&demuxer_desc_playlist,
|
||||||
&demuxer_desc_null,
|
&demuxer_desc_null,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -117,7 +119,8 @@ const struct m_sub_options demux_conf = {
|
||||||
{"demuxer-backward-playback-step", OPT_DOUBLE(back_seek_size),
|
{"demuxer-backward-playback-step", OPT_DOUBLE(back_seek_size),
|
||||||
M_RANGE(0, DBL_MAX)},
|
M_RANGE(0, DBL_MAX)},
|
||||||
{"metadata-codepage", OPT_STRING(meta_cp)},
|
{"metadata-codepage", OPT_STRING(meta_cp)},
|
||||||
{"autocreate-playlist", OPT_BOOL(autocreate_playlist)},
|
{"autocreate-playlist", OPT_CHOICE(autocreate_playlist,
|
||||||
|
{"no", 0}, {"any", 1}, {"exts", 2}, {"same", 3})},
|
||||||
{0}
|
{0}
|
||||||
},
|
},
|
||||||
.size = sizeof(struct demux_opts),
|
.size = sizeof(struct demux_opts),
|
||||||
|
|
|
@ -86,7 +86,7 @@ struct demux_opts {
|
||||||
double back_seek_size;
|
double back_seek_size;
|
||||||
char *meta_cp;
|
char *meta_cp;
|
||||||
bool force_retry_eof;
|
bool force_retry_eof;
|
||||||
bool autocreate_playlist;
|
int autocreate_playlist;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SEEK_FACTOR (1 << 1) // argument is in range [0,1]
|
#define SEEK_FACTOR (1 << 1) // argument is in range [0,1]
|
||||||
|
@ -212,7 +212,7 @@ struct demuxer_params {
|
||||||
bool stream_record; // if true, enable stream recording if option is set
|
bool stream_record; // if true, enable stream recording if option is set
|
||||||
int stream_flags;
|
int stream_flags;
|
||||||
struct stream *external_stream; // if set, use this, don't open or close streams
|
struct stream *external_stream; // if set, use this, don't open or close streams
|
||||||
bool has_playlist;
|
bool allow_playlist_create;
|
||||||
// result
|
// result
|
||||||
bool demuxer_failed;
|
bool demuxer_failed;
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,9 +42,20 @@ enum dir_mode {
|
||||||
DIR_IGNORE,
|
DIR_IGNORE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum autocreate_mode {
|
||||||
|
AUTO_NONE = 0,
|
||||||
|
AUTO_VIDEO = 1 << 0,
|
||||||
|
AUTO_AUDIO = 1 << 1,
|
||||||
|
AUTO_IMAGE = 1 << 2,
|
||||||
|
AUTO_ANY = 1 << 3,
|
||||||
|
};
|
||||||
|
|
||||||
#define OPT_BASE_STRUCT struct demux_playlist_opts
|
#define OPT_BASE_STRUCT struct demux_playlist_opts
|
||||||
struct demux_playlist_opts {
|
struct demux_playlist_opts {
|
||||||
int dir_mode;
|
int dir_mode;
|
||||||
|
char **autocreate_playlist_vid_exts;
|
||||||
|
char **autocreate_playlist_aud_exts;
|
||||||
|
char **autocreate_playlist_img_exts;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct m_sub_options demux_playlist_conf = {
|
struct m_sub_options demux_playlist_conf = {
|
||||||
|
@ -54,11 +65,29 @@ struct m_sub_options demux_playlist_conf = {
|
||||||
{"lazy", DIR_LAZY},
|
{"lazy", DIR_LAZY},
|
||||||
{"recursive", DIR_RECURSIVE},
|
{"recursive", DIR_RECURSIVE},
|
||||||
{"ignore", DIR_IGNORE})},
|
{"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)},
|
||||||
{0}
|
{0}
|
||||||
},
|
},
|
||||||
.size = sizeof(struct demux_playlist_opts),
|
.size = sizeof(struct demux_playlist_opts),
|
||||||
.defaults = &(const struct demux_playlist_opts){
|
.defaults = &(const struct demux_playlist_opts){
|
||||||
.dir_mode = DIR_AUTO,
|
.dir_mode = DIR_AUTO,
|
||||||
|
.autocreate_playlist_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 *[]){
|
||||||
|
"aiff", "ape", "au", "flac", "m4a", "mka", "mp3", "oga", "ogg",
|
||||||
|
"ogm", "opus", "wav", "wma", NULL
|
||||||
|
},
|
||||||
|
.autocreate_playlist_img_exts = (char *[]){
|
||||||
|
"avif", "bmp", "gif", "j2k", "jp2", "jpeg", "jpg", "jxl", "png",
|
||||||
|
"svg", "tga", "tif", "tiff", "webp", NULL
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,7 +114,7 @@ struct pl_parser {
|
||||||
bool force;
|
bool force;
|
||||||
bool add_base;
|
bool add_base;
|
||||||
bool line_allocated;
|
bool line_allocated;
|
||||||
bool create_dir_playlist;
|
int autocreate_playlist;
|
||||||
enum demux_check check_level;
|
enum demux_check check_level;
|
||||||
struct stream *real_stream;
|
struct stream *real_stream;
|
||||||
char *format;
|
char *format;
|
||||||
|
@ -395,9 +424,36 @@ static int cmp_dir_entry(const void *a, const void *b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool has_ext(bstr ext, char **list)
|
||||||
|
{
|
||||||
|
if (!list)
|
||||||
|
return false;
|
||||||
|
while (*list) {
|
||||||
|
if (!bstrcasecmp0(ext, *list++))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool test_autocreate_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))
|
||||||
|
return true;
|
||||||
|
if (autocreate & AUTO_AUDIO && has_ext(ext, p->opts->autocreate_playlist_aud_exts))
|
||||||
|
return true;
|
||||||
|
if (autocreate & AUTO_IMAGE && has_ext(ext, p->opts->autocreate_playlist_img_exts))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Return true if this was a readable directory.
|
// Return true if this was a readable directory.
|
||||||
static bool scan_dir(struct pl_parser *p, char *path,
|
static bool scan_dir(struct pl_parser *p, char *path,
|
||||||
struct stat *dir_stack, int num_dir_stack)
|
struct stat *dir_stack, int num_dir_stack, int autocreate)
|
||||||
{
|
{
|
||||||
if (strlen(path) >= 8192 || num_dir_stack == MAX_DIR_STACK)
|
if (strlen(path) >= 8192 || num_dir_stack == MAX_DIR_STACK)
|
||||||
return false; // things like mount bind loops
|
return false; // things like mount bind loops
|
||||||
|
@ -452,10 +508,11 @@ static bool scan_dir(struct pl_parser *p, char *path,
|
||||||
if (dir_mode == DIR_RECURSIVE && dir_entries[n].is_dir) {
|
if (dir_mode == DIR_RECURSIVE && dir_entries[n].is_dir) {
|
||||||
dir_stack[num_dir_stack] = dir_entries[n].st;
|
dir_stack[num_dir_stack] = dir_entries[n].st;
|
||||||
char *file = dir_entries[n].path;
|
char *file = dir_entries[n].path;
|
||||||
scan_dir(p, file, dir_stack, num_dir_stack + 1);
|
scan_dir(p, file, dir_stack, num_dir_stack + 1, autocreate);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
playlist_append_file(p->pl, dir_entries[n].path);
|
if (autocreate == AUTO_NONE || test_autocreate_path(p, dir_entries[n].path, autocreate))
|
||||||
|
playlist_append_file(p->pl, dir_entries[n].path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,11 +523,32 @@ static int parse_dir(struct pl_parser *p)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
struct stream *stream = p->real_stream;
|
struct stream *stream = p->real_stream;
|
||||||
if (p->create_dir_playlist && p->real_stream->is_local_file && !p->real_stream->is_directory) {
|
int autocreate = AUTO_NONE;
|
||||||
|
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
|
||||||
|
autocreate = AUTO_VIDEO | AUTO_AUDIO | AUTO_IMAGE;
|
||||||
|
break;
|
||||||
|
case 3: // same
|
||||||
|
if (has_ext(ext, p->opts->autocreate_playlist_vid_exts)) {
|
||||||
|
autocreate = AUTO_VIDEO;
|
||||||
|
} else if (has_ext(ext, p->opts->autocreate_playlist_aud_exts)) {
|
||||||
|
autocreate = AUTO_AUDIO;
|
||||||
|
} else if (has_ext(ext, p->opts->autocreate_playlist_img_exts)) {
|
||||||
|
autocreate = AUTO_IMAGE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
int flags = STREAM_ORIGIN_DIRECT | STREAM_READ | STREAM_LOCAL_FS_ONLY |
|
int flags = STREAM_ORIGIN_DIRECT | STREAM_READ | STREAM_LOCAL_FS_ONLY |
|
||||||
STREAM_LESS_NOISE;
|
STREAM_LESS_NOISE;
|
||||||
bstr dir = mp_dirname(p->real_stream->url);
|
bstr dir = mp_dirname(p->real_stream->url);
|
||||||
if (dir.len)
|
if (!dir.len)
|
||||||
|
autocreate = AUTO_NONE;
|
||||||
|
if (autocreate != AUTO_NONE)
|
||||||
stream = stream_create(bstrdup0(p, dir), flags, NULL, p->global);
|
stream = stream_create(bstrdup0(p, dir), flags, NULL, p->global);
|
||||||
}
|
}
|
||||||
if (!stream->is_directory)
|
if (!stream->is_directory)
|
||||||
|
@ -492,9 +570,10 @@ static int parse_dir(struct pl_parser *p)
|
||||||
talloc_free(opts);
|
talloc_free(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
scan_dir(p, path, dir_stack, 0);
|
scan_dir(p, path, dir_stack, 0, autocreate);
|
||||||
|
|
||||||
p->add_base = false;
|
p->add_base = false;
|
||||||
|
p->pl->autocreated = autocreate != AUTO_NONE;
|
||||||
ret = p->pl->num_entries > 0 ? 0 : -1;
|
ret = p->pl->num_entries > 0 ? 0 : -1;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -512,7 +591,12 @@ struct pl_format {
|
||||||
const char *const *mime_types;
|
const char *const *mime_types;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pl_format formats[] = {
|
static const struct pl_format dir_formats[] = {
|
||||||
|
{"directory", parse_dir},
|
||||||
|
{0},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pl_format playlist_formats[] = {
|
||||||
{"m3u", parse_m3u,
|
{"m3u", parse_m3u,
|
||||||
MIME_TYPES("audio/mpegurl", "audio/x-mpegurl", "application/x-mpegurl")},
|
MIME_TYPES("audio/mpegurl", "audio/x-mpegurl", "application/x-mpegurl")},
|
||||||
{"ini", parse_ref_init},
|
{"ini", parse_ref_init},
|
||||||
|
@ -520,14 +604,14 @@ static const struct pl_format formats[] = {
|
||||||
MIME_TYPES("audio/x-scpls")},
|
MIME_TYPES("audio/x-scpls")},
|
||||||
{"url", parse_url},
|
{"url", parse_url},
|
||||||
{"txt", parse_txt},
|
{"txt", parse_txt},
|
||||||
{"directory", parse_dir},
|
{0},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pl_format *probe_pl(struct pl_parser *p)
|
static const struct pl_format *probe_pl(struct pl_parser *p, const struct pl_format *fmts)
|
||||||
{
|
{
|
||||||
int64_t start = stream_tell(p->s);
|
int64_t start = stream_tell(p->s);
|
||||||
for (int n = 0; n < MP_ARRAY_SIZE(formats); n++) {
|
const struct pl_format *fmt = fmts;
|
||||||
const struct pl_format *fmt = &formats[n];
|
while (fmt->name) {
|
||||||
stream_seek(p->s, start);
|
stream_seek(p->s, start);
|
||||||
if (check_mimetype(p->s, fmt->mime_types)) {
|
if (check_mimetype(p->s, fmt->mime_types)) {
|
||||||
MP_VERBOSE(p, "forcing format by mime-type.\n");
|
MP_VERBOSE(p, "forcing format by mime-type.\n");
|
||||||
|
@ -536,10 +620,14 @@ static const struct pl_format *probe_pl(struct pl_parser *p)
|
||||||
}
|
}
|
||||||
if (fmt->parse(p) >= 0)
|
if (fmt->parse(p) >= 0)
|
||||||
return fmt;
|
return fmt;
|
||||||
|
fmt++;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern const demuxer_desc_t demuxer_desc_playlist;
|
||||||
|
extern const demuxer_desc_t demuxer_desc_directory;
|
||||||
|
|
||||||
static int open_file(struct demuxer *demuxer, enum demux_check check)
|
static int open_file(struct demuxer *demuxer, enum demux_check check)
|
||||||
{
|
{
|
||||||
if (!demuxer->access_references)
|
if (!demuxer->access_references)
|
||||||
|
@ -565,9 +653,14 @@ static int open_file(struct demuxer *demuxer, enum demux_check check)
|
||||||
p->force = force;
|
p->force = force;
|
||||||
p->check_level = check;
|
p->check_level = check;
|
||||||
p->probing = true;
|
p->probing = true;
|
||||||
p->create_dir_playlist = !demuxer->params->has_playlist && opts->autocreate_playlist;
|
p->autocreate_playlist = demuxer->params->allow_playlist_create ? opts->autocreate_playlist : 0;
|
||||||
|
p->opts = mp_get_config_group(demuxer, demuxer->global, &demux_playlist_conf);
|
||||||
|
|
||||||
const struct pl_format *fmt = probe_pl(p);
|
const struct pl_format *fmts = playlist_formats;
|
||||||
|
if (demuxer->desc == &demuxer_desc_directory)
|
||||||
|
fmts = dir_formats;
|
||||||
|
|
||||||
|
const struct pl_format *fmt = probe_pl(p, fmts);
|
||||||
free_stream(p->s);
|
free_stream(p->s);
|
||||||
playlist_clear(p->pl);
|
playlist_clear(p->pl);
|
||||||
if (!fmt) {
|
if (!fmt) {
|
||||||
|
@ -579,7 +672,6 @@ static int open_file(struct demuxer *demuxer, enum demux_check check)
|
||||||
p->error = false;
|
p->error = false;
|
||||||
p->s = demuxer->stream;
|
p->s = demuxer->stream;
|
||||||
p->utf16 = stream_skip_bom(p->s);
|
p->utf16 = stream_skip_bom(p->s);
|
||||||
p->opts = mp_get_config_group(demuxer, demuxer->global, &demux_playlist_conf);
|
|
||||||
bool ok = fmt->parse(p) >= 0 && !p->error;
|
bool ok = fmt->parse(p) >= 0 && !p->error;
|
||||||
if (p->add_base) {
|
if (p->add_base) {
|
||||||
bstr proto = mp_split_proto(bstr0(demuxer->filename), NULL);
|
bstr proto = mp_split_proto(bstr0(demuxer->filename), NULL);
|
||||||
|
@ -600,6 +692,12 @@ static int open_file(struct demuxer *demuxer, enum demux_check check)
|
||||||
return ok ? 0 : -1;
|
return ok ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const demuxer_desc_t demuxer_desc_directory = {
|
||||||
|
.name = "directory",
|
||||||
|
.desc = "Playlist dir",
|
||||||
|
.open = open_file,
|
||||||
|
};
|
||||||
|
|
||||||
const demuxer_desc_t demuxer_desc_playlist = {
|
const demuxer_desc_t demuxer_desc_playlist = {
|
||||||
.name = "playlist",
|
.name = "playlist",
|
||||||
.desc = "Playlist file",
|
.desc = "Playlist file",
|
||||||
|
|
|
@ -881,6 +881,7 @@ int mp_add_external_file(struct MPContext *mpctx, char *filename,
|
||||||
struct demuxer_params params = {
|
struct demuxer_params params = {
|
||||||
.is_top_level = true,
|
.is_top_level = true,
|
||||||
.stream_flags = STREAM_ORIGIN_DIRECT,
|
.stream_flags = STREAM_ORIGIN_DIRECT,
|
||||||
|
.allow_playlist_create = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (filter) {
|
switch (filter) {
|
||||||
|
@ -1041,11 +1042,9 @@ void prepare_playlist(struct MPContext *mpctx, struct playlist *pl)
|
||||||
if (opts->playlist_pos >= 0)
|
if (opts->playlist_pos >= 0)
|
||||||
pl->current = playlist_entry_from_index(pl, opts->playlist_pos);
|
pl->current = playlist_entry_from_index(pl, opts->playlist_pos);
|
||||||
|
|
||||||
for (int i = 0; i < pl->num_entries; ++i) {
|
for (int i = 0; i < pl->num_entries && pl->autocreated; ++i) {
|
||||||
if (!pl->entries[i]->playlist_path)
|
if (!pl->entries[i]->playlist_path)
|
||||||
continue;
|
continue;
|
||||||
// If playlist_path exists as an element in the playlist itself, it means
|
|
||||||
// playlist was autogenerated.
|
|
||||||
if (!strcmp(pl->entries[i]->filename, pl->entries[i]->playlist_path)) {
|
if (!strcmp(pl->entries[i]->filename, pl->entries[i]->playlist_path)) {
|
||||||
pl->current = pl->entries[i];
|
pl->current = pl->entries[i];
|
||||||
break;
|
break;
|
||||||
|
@ -1080,6 +1079,7 @@ static void transfer_playlist(struct MPContext *mpctx, struct playlist *pl,
|
||||||
playlist_remove(mpctx->playlist, mpctx->playlist->current);
|
playlist_remove(mpctx->playlist, mpctx->playlist->current);
|
||||||
if (new)
|
if (new)
|
||||||
mpctx->playlist->current = new;
|
mpctx->playlist->current = new;
|
||||||
|
mpctx->playlist->autocreated = pl->autocreated;
|
||||||
} else {
|
} else {
|
||||||
MP_WARN(mpctx, "Empty playlist!\n");
|
MP_WARN(mpctx, "Empty playlist!\n");
|
||||||
}
|
}
|
||||||
|
@ -1155,7 +1155,8 @@ static MP_THREAD_VOID open_demux_thread(void *ctx)
|
||||||
.stream_flags = mpctx->open_url_flags,
|
.stream_flags = mpctx->open_url_flags,
|
||||||
.stream_record = true,
|
.stream_record = true,
|
||||||
.is_top_level = true,
|
.is_top_level = true,
|
||||||
.has_playlist = mpctx->playlist->num_entries > 1,
|
.allow_playlist_create = mpctx->playlist->num_entries <= 1 &&
|
||||||
|
!mpctx->playlist->autocreated,
|
||||||
};
|
};
|
||||||
struct demuxer *demux =
|
struct demuxer *demux =
|
||||||
demux_open_url(mpctx->open_url, &p, mpctx->open_cancel, mpctx->global);
|
demux_open_url(mpctx->open_url, &p, mpctx->open_cancel, mpctx->global);
|
||||||
|
|
Loading…
Reference in New Issue