From 7e885a3bc3af4df93681b6e760a34e59e2f47ef7 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 21 Mar 2020 17:45:30 +0100 Subject: [PATCH] client API: add a playlist entry unique ID This should make dealing with some async. things easier. It's intentionally not a globally unique ID. --- DOCS/client-api-changes.rst | 1 + DOCS/man/input.rst | 7 +++++++ common/playlist.c | 2 ++ common/playlist.h | 4 ++++ libmpv/client.h | 17 +++++++++++++++++ player/command.c | 14 ++++++++++++++ player/loadfile.c | 10 ++++++++-- 7 files changed, 53 insertions(+), 2 deletions(-) diff --git a/DOCS/client-api-changes.rst b/DOCS/client-api-changes.rst index b1a61fe865..9a224c9f5b 100644 --- a/DOCS/client-api-changes.rst +++ b/DOCS/client-api-changes.rst @@ -34,6 +34,7 @@ API changes --- mpv 0.33.0 --- 1.108 - Deprecate MPV_EVENT_IDLE + - add mpv_event_start_file, mpv_event_end_file.playlist_entry_id 1.107 - Remove the deprecated qthelper.hpp. This was obviously not part of the libmpv API, only an "additionally" provided helper, thus this is not considered an API change. If you are maintaining a project that relies diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index e58bd2c507..60e024ebc9 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -2351,6 +2351,12 @@ Property list such fields, and only if mpv's parser supports it for the given playlist format. + ``playlist/N/id`` + Unique ID for this entry. This is an automatically assigned integer ID + that is unique for the entire life time of the current mpv core + instance. Other commands, events, etc. use this as ``playlist_entry_id`` + fields. + When querying the property with the client API using ``MPV_FORMAT_NODE``, or with Lua ``mp.get_property_native``, this will return a mpv_node with the following contents: @@ -2363,6 +2369,7 @@ Property list "current" MPV_FORMAT_FLAG (might be missing; since mpv 0.7.0) "playing" MPV_FORMAT_FLAG (same) "title" MPV_FORMAT_STRING (optional) + "id" MPV_FORMAT_INT64 ``track-list`` List of audio/video/sub tracks, current entry marked. Currently, the raw diff --git a/common/playlist.c b/common/playlist.c index 89c644dc33..d7c752ad8d 100644 --- a/common/playlist.c +++ b/common/playlist.c @@ -66,6 +66,7 @@ void playlist_add(struct playlist *pl, struct playlist_entry *add) MP_TARRAY_APPEND(pl, pl->entries, pl->num_entries, add); add->pl = pl; add->pl_index = pl->num_entries - 1; + add->id = ++pl->id_alloc; talloc_steal(pl, add); } @@ -250,6 +251,7 @@ static void playlist_transfer_entries_to(struct playlist *pl, int dst_index, struct playlist_entry *e = source_pl->entries[n]; e->pl = pl; e->pl_index = dst_index + n; + e->id = ++pl->id_alloc; pl->entries[e->pl_index] = e; talloc_steal(pl, e); } diff --git a/common/playlist.h b/common/playlist.h index 8b014e864d..f8dfbb2ba2 100644 --- a/common/playlist.h +++ b/common/playlist.h @@ -30,6 +30,8 @@ struct playlist_entry { struct playlist *pl; int pl_index; + uint64_t id; + char *filename; struct playlist_param *params; @@ -71,6 +73,8 @@ struct playlist { // current_was_replaced is set to true. struct playlist_entry *current; bool current_was_replaced; + + uint64_t id_alloc; }; void playlist_entry_add_param(struct playlist_entry *e, bstr name, bstr value); diff --git a/libmpv/client.h b/libmpv/client.h index 8d3af89249..ef9ba0d423 100644 --- a/libmpv/client.h +++ b/libmpv/client.h @@ -1297,6 +1297,7 @@ typedef enum mpv_event_id { MPV_EVENT_COMMAND_REPLY = 5, /** * Notification before playback start of a file (before the file is loaded). + * See also mpv_event and mpv_event_start_file. */ MPV_EVENT_START_FILE = 6, /** @@ -1595,6 +1596,14 @@ typedef enum mpv_end_file_reason { MPV_END_FILE_REASON_REDIRECT = 5, } mpv_end_file_reason; +/// Since API version 1.108. +typedef struct mpv_event_start_file { + /** + * Playlist entry ID of the file being loaded now. + */ + int64_t playlist_entry_id; +} mpv_event_start_file; + typedef struct mpv_event_end_file { /** * Corresponds to the values in enum mpv_end_file_reason (the "int" type @@ -1610,6 +1619,13 @@ typedef struct mpv_event_end_file { * Since API version 1.9. */ int error; + /** + * Playlist entry ID of the file that was being played or attempted to be + * played. This has the same value as the playlist_entry_id field in the + * corresponding mpv_event_start_file event. + * Since API version 1.108. + */ + int64_t playlist_entry_id; } mpv_event_end_file; #if MPV_ENABLE_DEPRECATED @@ -1689,6 +1705,7 @@ typedef struct mpv_event { * MPV_EVENT_PROPERTY_CHANGE: mpv_event_property* * MPV_EVENT_LOG_MESSAGE: mpv_event_log_message* * MPV_EVENT_CLIENT_MESSAGE: mpv_event_client_message* + * MPV_EVENT_START_FILE: mpv_event_start_file* (since v1.108) * MPV_EVENT_END_FILE: mpv_event_end_file* * MPV_EVENT_HOOK: mpv_event_hook* * MPV_EVENT_COMMAND_REPLY* mpv_event_command* diff --git a/player/command.c b/player/command.c index f8e248880a..e567ffb032 100644 --- a/player/command.c +++ b/player/command.c @@ -2798,6 +2798,7 @@ static int get_playlist_entry(int item, int action, void *arg, void *ctx) {"current", SUB_PROP_FLAG(1), .unavailable = !current}, {"playing", SUB_PROP_FLAG(1), .unavailable = !playing}, {"title", SUB_PROP_STR(e->title), .unavailable = !e->title}, + {"id", SUB_PROP_INT64(e->id)}, {0} }; @@ -4881,6 +4882,10 @@ static void cmd_loadfile(void *p) } playlist_add(mpctx->playlist, entry); + struct mpv_node *res = &cmd->result; + node_init(res, MPV_FORMAT_NODE_MAP, NULL); + node_map_add_int64(res, "playlist_entry_id", entry->id); + if (!append || (append == 2 && !mpctx->playlist->current)) { if (mpctx->opts->position_save_on_quit) // requested in issue #1148 mp_write_watch_later_conf(mpctx); @@ -4904,6 +4909,8 @@ static void cmd_loadlist(void *p) struct playlist_entry *new = pl->current; if (!append) playlist_clear(mpctx->playlist); + struct playlist_entry *first = playlist_entry_from_index(pl, 0); + int num_entries = pl->num_entries; playlist_append_entries(mpctx->playlist, pl); talloc_free(pl); @@ -4913,6 +4920,13 @@ static void cmd_loadlist(void *p) if (!append && new) mp_set_playlist_entry(mpctx, new); + struct mpv_node *res = &cmd->result; + node_init(res, MPV_FORMAT_NODE_MAP, NULL); + if (num_entries) { + node_map_add_int64(res, "playlist_entry_id", first->id); + node_map_add_int64(res, "num_entries", num_entries); + } + mp_notify(mpctx, MP_EVENT_CHANGE_PLAYLIST, NULL); mp_wakeup_core(mpctx); } else { diff --git a/player/loadfile.c b/player/loadfile.c index 4d16a66376..46627a9b23 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -1381,7 +1381,11 @@ static void play_current_file(struct MPContext *mpctx) if (mpctx->stop_play || !mpctx->playlist->current) return; - mp_notify(mpctx, MPV_EVENT_START_FILE, NULL); + mpv_event_start_file start_event = { + .playlist_entry_id = mpctx->playlist->current->id, + }; + + mp_notify(mpctx, MPV_EVENT_START_FILE, &start_event); mp_cancel_reset(mpctx->playback_abort); @@ -1653,7 +1657,9 @@ terminate_playback: bool nothing_played = !mpctx->shown_aframes && !mpctx->shown_vframes && mpctx->error_playing <= 0; - struct mpv_event_end_file end_event = {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: