demux: add --autocreate-playlist

This commit is contained in:
Kacper Michajłow 2024-07-15 23:22:39 +02:00
parent 4b97c23dac
commit bb9b862f0c
4 changed files with 42 additions and 9 deletions

View File

@ -67,6 +67,7 @@ static const demuxer_desc_t *const demuxer_list[] = {
&demuxer_desc_disc,
&demuxer_desc_edl,
&demuxer_desc_cue,
&demuxer_desc_playlist,
&demuxer_desc_rawaudio,
&demuxer_desc_rawvideo,
&demuxer_desc_matroska,
@ -75,7 +76,6 @@ static const demuxer_desc_t *const demuxer_list[] = {
#endif
&demuxer_desc_lavf,
&demuxer_desc_mf,
&demuxer_desc_playlist,
&demuxer_desc_null,
NULL
};
@ -117,6 +117,7 @@ const struct m_sub_options demux_conf = {
{"demuxer-backward-playback-step", OPT_DOUBLE(back_seek_size),
M_RANGE(0, DBL_MAX)},
{"metadata-codepage", OPT_STRING(meta_cp)},
{"autocreate-playlist", OPT_BOOL(autocreate_playlist)},
{0}
},
.size = sizeof(struct demux_opts),

View File

@ -86,6 +86,7 @@ struct demux_opts {
double back_seek_size;
char *meta_cp;
bool force_retry_eof;
bool autocreate_playlist;
};
#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
int stream_flags;
struct stream *external_stream; // if set, use this, don't open or close streams
bool has_playlist;
// result
bool demuxer_failed;
};

View File

@ -85,6 +85,7 @@ struct pl_parser {
bool force;
bool add_base;
bool line_allocated;
bool create_dir_playlist;
enum demux_check check_level;
struct stream *real_stream;
char *format;
@ -463,14 +464,25 @@ static bool scan_dir(struct pl_parser *p, char *path,
static int parse_dir(struct pl_parser *p)
{
if (!p->real_stream->is_directory)
return -1;
if (p->probing)
return 0;
int ret = -1;
struct stream *stream = p->real_stream;
if (p->create_dir_playlist && p->real_stream->is_local_file && !p->real_stream->is_directory) {
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)
return -1;
goto done;
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);
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(...) \
@ -497,7 +513,6 @@ struct pl_format {
};
static const struct pl_format formats[] = {
{"directory", parse_dir},
{"m3u", parse_m3u,
MIME_TYPES("audio/mpegurl", "audio/x-mpegurl", "application/x-mpegurl")},
{"ini", parse_ref_init},
@ -505,6 +520,7 @@ static const struct pl_format formats[] = {
MIME_TYPES("audio/x-scpls")},
{"url", parse_url},
{"txt", parse_txt},
{"directory", parse_dir},
};
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->check_level = check;
p->probing = true;
p->create_dir_playlist = !demuxer->params->has_playlist && opts->autocreate_playlist;
const struct pl_format *fmt = probe_pl(p);
free_stream(p->s);
playlist_clear(p->pl);

View File

@ -1041,6 +1041,17 @@ void prepare_playlist(struct MPContext *mpctx, struct playlist *pl)
if (opts->playlist_pos >= 0)
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)
playlist_shuffle(pl);
@ -1144,6 +1155,7 @@ static MP_THREAD_VOID open_demux_thread(void *ctx)
.stream_flags = mpctx->open_url_flags,
.stream_record = true,
.is_top_level = true,
.has_playlist = mpctx->playlist->num_entries > 1,
};
struct demuxer *demux =
demux_open_url(mpctx->open_url, &p, mpctx->open_cancel, mpctx->global);