diff --git a/DOCS/interface-changes/track-metadata.txt b/DOCS/interface-changes/track-metadata.txt new file mode 100644 index 0000000000..6aa189ec42 --- /dev/null +++ b/DOCS/interface-changes/track-metadata.txt @@ -0,0 +1 @@ +add `metadata` sub-property for `track-list` diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index a0b4d80e81..6c270dc6d0 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -3373,6 +3373,10 @@ Property list Dolby Vision profile and level. May not be available if the container does not provide this information. + ``track-list/N/metadata``, + Works like the ``metadata`` property, but it accesses metadata that is + set per track/stream instead of global values for the entire file. + 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: @@ -3426,6 +3430,8 @@ Property list "replaygain-album-gain" MPV_FORMAT_DOUBLE "dolby-vision-profile" MPV_FORMAT_INT64 "dolby-vision-level" MPV_FORMAT_INT64 + "metadata" MPV_FORMAT_NODE_MAP + (key and string value for each metadata entry) ``current-tracks/...`` This gives access to currently selected tracks. It redirects to the correct diff --git a/options/m_property.h b/options/m_property.h index 9fa01e0ccc..8fbb83384d 100644 --- a/options/m_property.h +++ b/options/m_property.h @@ -220,6 +220,8 @@ struct m_sub_property { .type = {.type = CONF_TYPE_BOOL}, .value = {.bool_ = (f)} #define SUB_PROP_PTS(f) \ .type = {.type = &m_option_type_time}, .value = {.double_ = (f)} +#define SUB_PROP_KEYVALUE_LIST(l) \ + .type = {.type = &m_option_type_keyvalue_list}, .value = {.keyvalue_list = (l)} int m_property_read_sub_validate(void *ctx, struct m_property *prop, int action, void *arg); diff --git a/player/command.c b/player/command.c index ead4309501..a9c94fc0a0 100644 --- a/player/command.c +++ b/player/command.c @@ -2004,6 +2004,13 @@ static int get_track_entry(int item, int action, void *arg, void *ctx) struct replaygain_data rg = has_rg ? *track->stream->codec->replaygain_data : (struct replaygain_data){0}; + struct mp_tags *tags = track->stream ? track->stream->tags : &(struct mp_tags){0}; + char **tag_list = talloc_zero_array(NULL, char *, tags->num_keys * 2 + 1); + for (int i = 0; i < tags->num_keys; i++) { + tag_list[2 * i] = talloc_strdup(tag_list, tags->keys[i]); + tag_list[2 * i + 1] = talloc_strdup(tag_list, tags->values[i]); + } + double par = 0.0; if (p.par_h) par = p.par_w / (double) p.par_h; @@ -2087,10 +2094,37 @@ static int get_track_entry(int item, int action, void *arg, void *ctx) .unavailable = !p.dovi}, {"dolby-vision-level", SUB_PROP_INT(p.dv_level), .unavailable = !p.dovi}, + {"metadata", SUB_PROP_KEYVALUE_LIST(tag_list), + .unavailable = !tags->num_keys}, {0} }; - return m_property_read_sub(props, action, arg); + int ret = 0; + switch (action) { + case M_PROPERTY_KEY_ACTION: ; + struct m_property_action_arg *ka = arg; + if (!strncmp(ka->key, "metadata/", 9)) { + bstr key = {0}; + char *rem = ""; + m_property_split_path(ka->key, &key, &rem); + ka->key = !rem[0] ? "metadata" : rem; + if (rem[0]) { + if (!tags || tags->num_keys == 0) { + ret = M_PROPERTY_UNAVAILABLE; + } else { + ret = tag_property(action, (void *)ka, tags); + } + goto done; + } + } + MP_FALLTHROUGH; + default: + ret = m_property_read_sub(props, action, arg); + } + +done: + talloc_free(tag_list); + return ret; } static const char *track_type_name(struct track *t)