From b7aa8f5c8580d00852302e8c13789b0ae2ce013a Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 19 Nov 2019 16:08:40 +0100 Subject: [PATCH] media-session: subscribe to params when needed Subscribe to params and collect them. --- pipewire-pulseaudio/src/stream.c | 1 + src/examples/media-session/media-session.c | 89 +++++++++++++++++++++ src/examples/media-session/media-session.h | 9 +++ src/examples/media-session/stream-monitor.c | 4 +- 4 files changed, 101 insertions(+), 2 deletions(-) diff --git a/pipewire-pulseaudio/src/stream.c b/pipewire-pulseaudio/src/stream.c index 8d0f97bbc..0fa3bdce6 100644 --- a/pipewire-pulseaudio/src/stream.c +++ b/pipewire-pulseaudio/src/stream.c @@ -406,6 +406,7 @@ static void stream_control_info(void *data, uint32_t id, const struct pw_stream_ { pa_stream *s = data; + pw_log_debug("stream %p: control %d", s, id); switch (id) { case SPA_PROP_mute: if (control->n_values > 0) diff --git a/src/examples/media-session/media-session.c b/src/examples/media-session/media-session.c index 1c4ddf2aa..1d8054d1b 100644 --- a/src/examples/media-session/media-session.c +++ b/src/examples/media-session/media-session.c @@ -63,6 +63,11 @@ struct data { size_t size; }; +struct param { + struct sm_param this; + struct spa_list link; +}; + struct sync { struct spa_list link; int seq; @@ -227,6 +232,44 @@ static void client_destroy(void *object) pw_client_info_free(client->info); } +static struct param *add_param(struct spa_list *param_list, + uint32_t id, const struct spa_pod *param) +{ + struct param *p; + + if (param == NULL || !spa_pod_is_object(param)) { + errno = EINVAL; + return NULL; + } + if (id == SPA_ID_INVALID) + id = SPA_POD_OBJECT_ID(param); + + p = malloc(sizeof(struct param) + SPA_POD_SIZE(param)); + if (p == NULL) + return NULL; + + p->this.id = id; + p->this.param = SPA_MEMBER(p, sizeof(struct param), struct spa_pod); + memcpy(p->this.param, param, SPA_POD_SIZE(param)); + + spa_list_append(param_list, &p->link); + + return p; +} + + +static void clear_params(struct spa_list *param_list, uint32_t id) +{ + struct param *p, *t; + + spa_list_for_each_safe(p, t, param_list, link) { + if (id == SPA_ID_INVALID || p->this.id == id) { + spa_list_remove(&p->link); + free(p); + } + } +} + /** * Node */ @@ -234,6 +277,7 @@ static void node_event_info(void *object, const struct pw_node_info *info) { struct sm_node *node = object; struct impl *impl = SPA_CONTAINER_OF(node->obj.session, struct impl, this); + uint32_t i; pw_log_debug(NAME" %p: node %d info", impl, node->obj.id); node->info = pw_node_info_update(node->info, info); @@ -242,11 +286,53 @@ static void node_event_info(void *object, const struct pw_node_info *info) node->changed |= SM_NODE_CHANGE_MASK_INFO; sm_media_session_emit_update(impl, &node->obj); node->changed = 0; + + if (info->change_mask & PW_NODE_CHANGE_MASK_PARAMS && + (node->mask & SM_NODE_CHANGE_MASK_PARAMS) && + !node->subscribe) { + uint32_t subscribe[info->n_params], n_subscribe = 0; + + for (i = 0; i < info->n_params; i++) { + switch (info->params[i].id) { + case SPA_PARAM_PropInfo: + case SPA_PARAM_Props: + case SPA_PARAM_EnumFormat: + subscribe[n_subscribe++] = info->params[i].id; + break; + default: + break; + } + } + if (n_subscribe > 0) { + pw_node_proxy_subscribe_params((struct pw_node_proxy*)node->obj.proxy, + subscribe, n_subscribe); + node->subscribe = true; + } + } +} + +static void node_event_param(void *object, int seq, + uint32_t id, uint32_t index, uint32_t next, + const struct spa_pod *param) +{ + struct sm_node *node = object; + struct impl *impl = SPA_CONTAINER_OF(node->obj.session, struct impl, this); + + if (index == 0) + clear_params(&node->param_list, id); + + add_param(&node->param_list, id, param); + + node->avail |= SM_NODE_CHANGE_MASK_PARAMS; + node->changed |= SM_NODE_CHANGE_MASK_PARAMS; + sm_media_session_emit_update(impl, &node->obj); + node->changed = 0; } static const struct pw_node_proxy_events node_events = { PW_VERSION_NODE_PROXY_EVENTS, .info = node_event_info, + .param = node_event_param, }; static void node_destroy(void *object) @@ -258,6 +344,8 @@ static void node_destroy(void *object) port->node = NULL; spa_list_remove(&port->link); } + clear_params(&node->param_list, SPA_ID_INVALID); + if (node->info) pw_node_info_free(node->info); } @@ -556,6 +644,7 @@ registry_global(void *data,uint32_t id, { struct sm_node *node = (struct sm_node*) obj; spa_list_init(&node->port_list); + spa_list_init(&node->param_list); break; } case PW_TYPE_INTERFACE_Port: diff --git a/src/examples/media-session/media-session.h b/src/examples/media-session/media-session.h index 8ccf023f9..bc21b6786 100644 --- a/src/examples/media-session/media-session.h +++ b/src/examples/media-session/media-session.h @@ -53,6 +53,11 @@ struct sm_object { struct spa_list data; }; +struct sm_param { + uint32_t id; + struct spa_pod *param; +}; + /** get user data with \a id and \a size to an object */ void *sm_object_add_data(struct sm_object *obj, const char *id, size_t size); void *sm_object_get_data(struct sm_object *obj, const char *id); @@ -72,13 +77,17 @@ struct sm_client { struct sm_node { struct sm_object obj; + unsigned int subscribe:1; /**< if we subscribed to param changes */ + #define SM_NODE_CHANGE_MASK_INFO (1<<0) #define SM_NODE_CHANGE_MASK_PORTS (1<<1) +#define SM_NODE_CHANGE_MASK_PARAMS (1<<2) uint32_t mask; /**< monitored info */ uint32_t avail; /**< available info */ uint32_t changed; /**< changed since last update */ struct pw_node_info *info; struct spa_list port_list; + struct spa_list param_list; /**< list of sm_param */ }; struct sm_port { diff --git a/src/examples/media-session/stream-monitor.c b/src/examples/media-session/stream-monitor.c index 4a92f9ac3..89d72cdd6 100644 --- a/src/examples/media-session/stream-monitor.c +++ b/src/examples/media-session/stream-monitor.c @@ -323,10 +323,10 @@ static void node_event_param(void *object, int seq, struct impl *impl = n->impl; struct spa_audio_info_raw info = { 0, }; - pw_log_debug(NAME" %p: param for node %d, %d", impl, n->id, id); + pw_log_debug(NAME" %p: param for node %d %d", impl, n->id, id); if (id != SPA_PARAM_EnumFormat) - goto error; + return; if (spa_format_parse(param, &n->media_type, &n->media_subtype) < 0) goto error;