mirror of https://github.com/mpv-player/mpv
demux: add --autocreate-playlist
This commit is contained in:
parent
4b97c23dac
commit
bb9b862f0c
|
@ -67,6 +67,7 @@ static const demuxer_desc_t *const demuxer_list[] = {
|
||||||
&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,
|
||||||
|
@ -75,7 +76,6 @@ 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,6 +117,7 @@ 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)},
|
||||||
{0}
|
{0}
|
||||||
},
|
},
|
||||||
.size = sizeof(struct demux_opts),
|
.size = sizeof(struct demux_opts),
|
||||||
|
|
|
@ -86,6 +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;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SEEK_FACTOR (1 << 1) // argument is in range [0,1]
|
#define SEEK_FACTOR (1 << 1) // argument is in range [0,1]
|
||||||
|
@ -211,6 +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;
|
||||||
// result
|
// result
|
||||||
bool demuxer_failed;
|
bool demuxer_failed;
|
||||||
};
|
};
|
||||||
|
|
|
@ -85,6 +85,7 @@ struct pl_parser {
|
||||||
bool force;
|
bool force;
|
||||||
bool add_base;
|
bool add_base;
|
||||||
bool line_allocated;
|
bool line_allocated;
|
||||||
|
bool create_dir_playlist;
|
||||||
enum demux_check check_level;
|
enum demux_check check_level;
|
||||||
struct stream *real_stream;
|
struct stream *real_stream;
|
||||||
char *format;
|
char *format;
|
||||||
|
@ -463,14 +464,25 @@ static bool scan_dir(struct pl_parser *p, char *path,
|
||||||
|
|
||||||
static int parse_dir(struct pl_parser *p)
|
static int parse_dir(struct pl_parser *p)
|
||||||
{
|
{
|
||||||
if (!p->real_stream->is_directory)
|
int ret = -1;
|
||||||
return -1;
|
struct stream *stream = p->real_stream;
|
||||||
if (p->probing)
|
if (p->create_dir_playlist && p->real_stream->is_local_file && !p->real_stream->is_directory) {
|
||||||
return 0;
|
int flags = STREAM_ORIGIN_DIRECT | STREAM_READ | STREAM_LOCAL_FS_ONLY |
|
||||||
|
STREAM_LESS_NOISE;
|
||||||
|
bstr dir = mp_dirname(p->real_stream->url);
|
||||||
|
if (dir.len)
|
||||||
|
stream = stream_create(bstrdup0(p, dir), flags, NULL, p->global);
|
||||||
|
}
|
||||||
|
if (!stream->is_directory)
|
||||||
|
goto done;
|
||||||
|
if (p->probing) {
|
||||||
|
ret = 0;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
char *path = mp_file_get_path(p, bstr0(p->real_stream->url));
|
char *path = mp_file_get_path(p, bstr0(stream->url));
|
||||||
if (!path)
|
if (!path)
|
||||||
return -1;
|
goto done;
|
||||||
|
|
||||||
struct stat dir_stack[MAX_DIR_STACK];
|
struct stat dir_stack[MAX_DIR_STACK];
|
||||||
|
|
||||||
|
@ -483,8 +495,12 @@ static int parse_dir(struct pl_parser *p)
|
||||||
scan_dir(p, path, dir_stack, 0);
|
scan_dir(p, path, dir_stack, 0);
|
||||||
|
|
||||||
p->add_base = false;
|
p->add_base = false;
|
||||||
|
ret = p->pl->num_entries > 0 ? 0 : -1;
|
||||||
|
|
||||||
return p->pl->num_entries > 0 ? 0 : -1;
|
done:
|
||||||
|
if (stream != p->real_stream)
|
||||||
|
free_stream(stream);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MIME_TYPES(...) \
|
#define MIME_TYPES(...) \
|
||||||
|
@ -497,7 +513,6 @@ struct pl_format {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pl_format formats[] = {
|
static const struct pl_format formats[] = {
|
||||||
{"directory", parse_dir},
|
|
||||||
{"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},
|
||||||
|
@ -505,6 +520,7 @@ 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},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pl_format *probe_pl(struct pl_parser *p)
|
static const struct pl_format *probe_pl(struct pl_parser *p)
|
||||||
|
@ -549,6 +565,8 @@ 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;
|
||||||
|
|
||||||
const struct pl_format *fmt = probe_pl(p);
|
const struct pl_format *fmt = probe_pl(p);
|
||||||
free_stream(p->s);
|
free_stream(p->s);
|
||||||
playlist_clear(p->pl);
|
playlist_clear(p->pl);
|
||||||
|
|
|
@ -1041,6 +1041,17 @@ 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) {
|
||||||
|
if (!pl->entries[i]->playlist_path)
|
||||||
|
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)) {
|
||||||
|
pl->current = pl->entries[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (opts->shuffle)
|
if (opts->shuffle)
|
||||||
playlist_shuffle(pl);
|
playlist_shuffle(pl);
|
||||||
|
|
||||||
|
@ -1144,6 +1155,7 @@ 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,
|
||||||
};
|
};
|
||||||
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