diff --git a/DOCS/client-api-changes.rst b/DOCS/client-api-changes.rst index 136e6a832e..ade0234e79 100644 --- a/DOCS/client-api-changes.rst +++ b/DOCS/client-api-changes.rst @@ -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 diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index 3e449ba81b..c19a8fdd65 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -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. diff --git a/common/playlist.c b/common/playlist.c index d7c752ad8d..b7398dd936 100644 --- a/common/playlist.c +++ b/common/playlist.c @@ -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. diff --git a/common/playlist.h b/common/playlist.h index f8dfbb2ba2..5f84e3b413 100644 --- a/common/playlist.h +++ b/common/playlist.h @@ -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); diff --git a/libmpv/client.h b/libmpv/client.h index ce11ae4872..d5f512003c 100644 --- a/libmpv/client.h +++ b/libmpv/client.h @@ -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 diff --git a/player/client.c b/player/client.c index d2a94cc0c9..0babacf147 100644 --- a/player/client.c +++ b/player/client.c @@ -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; diff --git a/player/loadfile.c b/player/loadfile.c index 46627a9b23..9efacea766 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -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: