client API: report IDs of inserted playlist entries on loading playlist

May or may not help when dealing with playlist loading in scripts. It's
supposed to help with the mean fact that loading a recursive playlist
will essentially edit the playlist behind the API user's back.
This commit is contained in:
wm4 2020-03-27 00:57:11 +01:00
parent d3be6a6163
commit df0d8cda08
7 changed files with 70 additions and 15 deletions

View File

@ -34,7 +34,9 @@ API changes
--- mpv 0.33.0 ---
1.108 - Deprecate MPV_EVENT_IDLE
- add mpv_event_start_file, mpv_event_end_file.playlist_entry_id
- add mpv_event_start_file
- add the following fields to mpv_event_end_file: playlist_entry_id,
playlist_insert_id, playlist_insert_num_entries
- add mpv_event_to_node()
- add mpv_client_id()
1.107 - Remove the deprecated qthelper.hpp. This was obviously not part of the

View File

@ -1358,6 +1358,23 @@ This list uses the event name field value, and the C API symbol in brackets:
In the future, this ``error`` field will be unset for this specific
event.)
``playlist_insert_id``
If loading ended, because the playlist entry to be played was for example
a playlist, and the current playlist entry is replaced with a number of
other entries. This may happen at least with MPV_END_FILE_REASON_REDIRECT
(other event types may use this for similar but different purposes in the
future). In this case, playlist_insert_id will be set to the playlist
entry ID of the first inserted entry, and playlist_insert_num_entries to
the total number of inserted playlist entries. Note this in this specific
case, the ID of the last inserted entry is playlist_insert_id+num-1.
Beware that depending on circumstances, you may observe the new playlist
entries before seeing the event (e.g. reading the "playlist" property or
getting a property change notification before receiving the event).
If this is 0 in the C API, this field isn't added.
``playlist_insert_num_entries``
See playlist_insert_id. Only present if playlist_insert_id is present.
``file-loaded`` (``MPV_EVENT_FILE_LOADED``)
Happens after a file was loaded and begins playback.

View File

@ -239,10 +239,11 @@ void playlist_set_stream_flags(struct playlist *pl, int flags)
pl->entries[n]->stream_flags = flags;
}
static void playlist_transfer_entries_to(struct playlist *pl, int dst_index,
struct playlist *source_pl)
static int64_t playlist_transfer_entries_to(struct playlist *pl, int dst_index,
struct playlist *source_pl)
{
assert(pl != source_pl);
struct playlist_entry *first = playlist_get_first(source_pl);
int count = source_pl->num_entries;
MP_TARRAY_INSERT_N_AT(pl, pl->entries, pl->num_entries, dst_index, count);
@ -258,11 +259,16 @@ static void playlist_transfer_entries_to(struct playlist *pl, int dst_index,
playlist_update_indexes(pl, dst_index + count, -1);
source_pl->num_entries = 0;
return first ? first->id : 0;
}
// Move all entries from source_pl to pl, appending them after the current entry
// of pl. source_pl will be empty, and all entries have changed ownership to pl.
void playlist_transfer_entries(struct playlist *pl, struct playlist *source_pl)
// Return the new ID of the first added entry within pl (0 if source_pl was
// empty). The IDs of all added entries increase by 1 each entry (you can
// predict the ID of the last entry).
int64_t playlist_transfer_entries(struct playlist *pl, struct playlist *source_pl)
{
int add_at = pl->num_entries;
@ -274,12 +280,12 @@ void playlist_transfer_entries(struct playlist *pl, struct playlist *source_pl)
assert(add_at >= 0);
assert(add_at <= pl->num_entries);
playlist_transfer_entries_to(pl, add_at, source_pl);
return playlist_transfer_entries_to(pl, add_at, source_pl);
}
void playlist_append_entries(struct playlist *pl, struct playlist *source_pl)
int64_t playlist_append_entries(struct playlist *pl, struct playlist *source_pl)
{
playlist_transfer_entries_to(pl, pl->num_entries, source_pl);
return playlist_transfer_entries_to(pl, pl->num_entries, source_pl);
}
// Return number of entries between list start and e.

View File

@ -103,8 +103,8 @@ struct playlist_entry *playlist_entry_get_rel(struct playlist_entry *e,
void playlist_add_base_path(struct playlist *pl, bstr base_path);
void playlist_add_redirect(struct playlist *pl, const char *redirected_from);
void playlist_set_stream_flags(struct playlist *pl, int flags);
void playlist_transfer_entries(struct playlist *pl, struct playlist *source_pl);
void playlist_append_entries(struct playlist *pl, struct playlist *source_pl);
int64_t playlist_transfer_entries(struct playlist *pl, struct playlist *source_pl);
int64_t playlist_append_entries(struct playlist *pl, struct playlist *source_pl);
int playlist_entry_to_index(struct playlist *pl, struct playlist_entry *e);
int playlist_entry_count(struct playlist *pl);

View File

@ -1646,6 +1646,27 @@ typedef struct mpv_event_end_file {
* Since API version 1.108.
*/
int64_t playlist_entry_id;
/**
* If loading ended, because the playlist entry to be played was for example
* a playlist, and the current playlist entry is replaced with a number of
* other entries. This may happen at least with MPV_END_FILE_REASON_REDIRECT
* (other event types may use this for similar but different purposes in the
* future). In this case, playlist_insert_id will be set to the playlist
* entry ID of the first inserted entry, and playlist_insert_num_entries to
* the total number of inserted playlist entries. Note this in this specific
* case, the ID of the last inserted entry is playlist_insert_id+num-1.
* Beware that depending on circumstances, you may observe the new playlist
* entries before seeing the event (e.g. reading the "playlist" property or
* getting a property change notification before receiving the event).
* Since API version 1.108.
*/
int64_t playlist_insert_id;
/**
* See playlist_insert_id. Only non-0 if playlist_insert_id is valid. Never
* negative.
* Since API version 1.108.
*/
int playlist_insert_num_entries;
} mpv_event_end_file;
#if MPV_ENABLE_DEPRECATED

View File

@ -1979,6 +1979,12 @@ int mpv_event_to_node(mpv_node *dst, mpv_event *event)
node_map_add_int64(dst, "playlist_entry_id", eef->playlist_entry_id);
if (eef->playlist_insert_id) {
node_map_add_int64(dst, "playlist_insert_id", eef->playlist_insert_id);
node_map_add_int64(dst, "playlist_insert_num_entries",
eef->playlist_insert_num_entries);
}
if (eef->reason == MPV_END_FILE_REASON_ERROR)
node_map_add_string(dst, "file_error", mpv_error_string(eef->error));
break;

View File

@ -906,14 +906,16 @@ void prepare_playlist(struct MPContext *mpctx, struct playlist *pl)
// Replace the current playlist entry with playlist contents. Moves the entries
// from the given playlist pl, so the entries don't actually need to be copied.
static void transfer_playlist(struct MPContext *mpctx, struct playlist *pl)
static void transfer_playlist(struct MPContext *mpctx, struct playlist *pl,
int64_t *start_id, int *num_new_entries)
{
if (pl->num_entries) {
prepare_playlist(mpctx, pl);
struct playlist_entry *new = pl->current;
if (mpctx->playlist->current)
playlist_add_redirect(pl, mpctx->playlist->current->filename);
playlist_transfer_entries(mpctx->playlist, pl);
*num_new_entries = pl->num_entries;
*start_id = playlist_transfer_entries(mpctx->playlist, pl);
// current entry is replaced
if (mpctx->playlist->current)
playlist_remove(mpctx->playlist, mpctx->playlist->current);
@ -1384,6 +1386,9 @@ static void play_current_file(struct MPContext *mpctx)
mpv_event_start_file start_event = {
.playlist_entry_id = mpctx->playlist->current->id,
};
mpv_event_end_file end_event = {
.playlist_entry_id = start_event.playlist_entry_id,
};
mp_notify(mpctx, MPV_EVENT_START_FILE, &start_event);
@ -1477,7 +1482,8 @@ static void play_current_file(struct MPContext *mpctx)
if (mpctx->demuxer->playlist) {
struct playlist *pl = mpctx->demuxer->playlist;
transfer_playlist(mpctx, pl);
transfer_playlist(mpctx, pl, &end_event.playlist_insert_id,
&end_event.playlist_insert_num_entries);
mp_notify_property(mpctx, "playlist");
mpctx->error_playing = 2;
goto terminate_playback;
@ -1657,9 +1663,6 @@ terminate_playback:
bool nothing_played = !mpctx->shown_aframes && !mpctx->shown_vframes &&
mpctx->error_playing <= 0;
struct mpv_event_end_file end_event = {
.playlist_entry_id = start_event.playlist_entry_id,
};
switch (mpctx->stop_play) {
case PT_ERROR:
case AT_END_OF_FILE: