From ed988788fd0ef809ead4daa11da176a06aa80445 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 4 Mar 2019 12:30:45 +0100 Subject: [PATCH] client-node: pass spa_node_info along Pass the complete spa_node_info to update node information. Remove the redundant max/min port info. Update the remote node based on port and node update events. --- pipewire-jack | 2 +- src/extensions/client-node.h | 30 ++--- src/modules/module-client-node/client-node.c | 23 +--- .../module-client-node/protocol-native.c | 123 +++++++++++++----- src/modules/module-client-node/remote-node.c | 109 ++++++++++++---- src/pipewire/node.h | 3 + src/pipewire/port.c | 2 + src/pipewire/private.h | 1 + src/pipewire/stream.c | 2 + 9 files changed, 205 insertions(+), 90 deletions(-) diff --git a/pipewire-jack b/pipewire-jack index 6ca80e4ec..53693d1e3 160000 --- a/pipewire-jack +++ b/pipewire-jack @@ -1 +1 @@ -Subproject commit 6ca80e4ec7abb48ef19423b405c0add9f98f93a0 +Subproject commit 53693d1e328c2dde8fc167579f077e2e876c78d4 diff --git a/src/extensions/client-node.h b/src/extensions/client-node.h index 99eccfd53..7ebc02ed2 100644 --- a/src/extensions/client-node.h +++ b/src/extensions/client-node.h @@ -70,16 +70,12 @@ struct pw_client_node_proxy_methods { * \param params new params */ int (*update) (void *object, -#define PW_CLIENT_NODE_UPDATE_MAX_INPUTS (1 << 0) -#define PW_CLIENT_NODE_UPDATE_MAX_OUTPUTS (1 << 1) -#define PW_CLIENT_NODE_UPDATE_PARAMS (1 << 2) -#define PW_CLIENT_NODE_UPDATE_PROPS (1 << 3) +#define PW_CLIENT_NODE_UPDATE_PARAMS (1 << 0) +#define PW_CLIENT_NODE_UPDATE_INFO (1 << 1) uint32_t change_mask, - uint32_t max_input_ports, - uint32_t max_output_ports, uint32_t n_params, const struct spa_pod **params, - const struct spa_dict *props); + const struct spa_node_info *info); /** * Update a node port @@ -115,16 +111,13 @@ struct pw_client_node_proxy_methods { static inline int pw_client_node_proxy_update(struct pw_client_node_proxy *p, uint32_t change_mask, - uint32_t max_input_ports, - uint32_t max_output_ports, uint32_t n_params, const struct spa_pod **params, - const struct spa_dict *props) + const struct spa_node_info *info) { - return pw_proxy_do((struct pw_proxy*)p, struct pw_client_node_proxy_methods, update, change_mask, - max_input_ports, - max_output_ports, - n_params, params, props); + return pw_proxy_do((struct pw_proxy*)p, struct pw_client_node_proxy_methods, + update, + change_mask, n_params, params, info); } static inline int @@ -136,12 +129,9 @@ pw_client_node_proxy_port_update(struct pw_client_node_proxy *p, const struct spa_pod **params, const struct spa_port_info *info) { - return pw_proxy_do((struct pw_proxy*)p, struct pw_client_node_proxy_methods, port_update, direction, - port_id, - change_mask, - n_params, - params, - info); + return pw_proxy_do((struct pw_proxy*)p, struct pw_client_node_proxy_methods, + port_update, direction, port_id, change_mask, + n_params, params, info); } static inline int diff --git a/src/modules/module-client-node/client-node.c b/src/modules/module-client-node/client-node.c index f05581602..a6f85089e 100644 --- a/src/modules/module-client-node/client-node.c +++ b/src/modules/module-client-node/client-node.c @@ -136,9 +136,7 @@ struct node { struct spa_source data_source; int writefd; - uint32_t max_inputs; uint32_t n_inputs; - uint32_t max_outputs; uint32_t n_outputs; struct port *in_ports[MAX_INPUTS]; struct port *out_ports[MAX_OUTPUTS]; @@ -583,6 +581,7 @@ do_update_port(struct node *this, port->properties = pw_properties_new_dict(info->props); port->info.props = &port->properties->dict; } + spa_node_emit_port_info(&this->hooks, port->direction, port->id, info); } } } @@ -995,19 +994,13 @@ static int impl_node_process(struct spa_node *node) static int client_node_update(void *data, uint32_t change_mask, - uint32_t max_input_ports, - uint32_t max_output_ports, uint32_t n_params, const struct spa_pod **params, - const struct spa_dict *props) + const struct spa_node_info *info) { struct impl *impl = data; struct node *this = &impl->node; - if (change_mask & PW_CLIENT_NODE_UPDATE_MAX_INPUTS) - this->max_inputs = max_input_ports; - if (change_mask & PW_CLIENT_NODE_UPDATE_MAX_OUTPUTS) - this->max_outputs = max_output_ports; if (change_mask & PW_CLIENT_NODE_UPDATE_PARAMS) { uint32_t i; spa_log_debug(this->log, "node %p: update %d params", this, n_params); @@ -1020,11 +1013,10 @@ client_node_update(void *data, for (i = 0; i < this->n_params; i++) this->params[i] = params[i] ? spa_pod_copy(params[i]) : NULL; } - if (change_mask & PW_CLIENT_NODE_UPDATE_PROPS) { - pw_node_update_properties(impl->this.node, props); + if (change_mask & PW_CLIENT_NODE_UPDATE_INFO) { + spa_node_emit_info(&this->hooks, info); } - spa_log_debug(this->log, "node %p: got node update max_in %u, max_out %u", this, - this->max_inputs, this->max_outputs); + spa_log_debug(this->log, "node %p: got node update", this); return 0; } @@ -1058,6 +1050,8 @@ client_node_port_update(void *data, if (port == NULL) { target = &this->dummy; spa_zero(this->dummy); + target->direction = direction; + target->id = port_id; } else target = port; @@ -1066,9 +1060,6 @@ client_node_port_update(void *data, change_mask, n_params, params, info); - - if (info && (change_mask & PW_CLIENT_NODE_PORT_UPDATE_INFO)) - spa_node_emit_port_info(&this->hooks, direction, port_id, info); } return 0; } diff --git a/src/modules/module-client-node/protocol-native.c b/src/modules/module-client-node/protocol-native.c index f71080964..f3c347968 100644 --- a/src/modules/module-client-node/protocol-native.c +++ b/src/modules/module-client-node/protocol-native.c @@ -50,31 +50,60 @@ static void push_dict(struct spa_pod_builder *b, const struct spa_dict *dict) static int client_node_marshal_update(void *object, uint32_t change_mask, - uint32_t max_input_ports, - uint32_t max_output_ports, uint32_t n_params, const struct spa_pod **params, - const struct spa_dict *props) + const struct spa_node_info *info) { struct pw_proxy *proxy = object; struct spa_pod_builder *b; - struct spa_pod_frame f; - uint32_t i; + struct spa_pod_frame f[2]; + uint32_t i, n_items; b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_NODE_PROXY_METHOD_UPDATE, NULL); - spa_pod_builder_push_struct(b, &f); + spa_pod_builder_push_struct(b, &f[0]); spa_pod_builder_add(b, SPA_POD_Int(change_mask), - SPA_POD_Int(max_input_ports), - SPA_POD_Int(max_output_ports), SPA_POD_Int(n_params), NULL); for (i = 0; i < n_params; i++) spa_pod_builder_add(b, SPA_POD_Pod(params[i]), NULL); - push_dict(b, props); - spa_pod_builder_pop(b, &f); + if (info) { + uint64_t change_mask = info->change_mask; + + n_items = info->props ? info->props->n_items : 0; + + change_mask &= SPA_NODE_CHANGE_MASK_FLAGS | + SPA_NODE_CHANGE_MASK_PROPS | + SPA_NODE_CHANGE_MASK_PARAMS; + + spa_pod_builder_push_struct(b, &f[1]); + spa_pod_builder_add(b, + SPA_POD_Int(info->max_input_ports), + SPA_POD_Int(info->max_output_ports), + SPA_POD_Long(change_mask), + SPA_POD_Long(info->flags), + SPA_POD_Int(n_items), NULL); + for (i = 0; i < n_items; i++) { + spa_pod_builder_add(b, + SPA_POD_String(info->props->items[i].key), + SPA_POD_String(info->props->items[i].value), NULL); + } + spa_pod_builder_add(b, + SPA_POD_Int(info->n_params), NULL); + for (i = 0; i < info->n_params; i++) { + spa_pod_builder_add(b, + SPA_POD_Id(info->params[i].id), + SPA_POD_Int(info->params[i].flags), NULL); + } + spa_pod_builder_pop(b, &f[1]); + + } else { + spa_pod_builder_add(b, + SPA_POD_Pod(NULL), NULL); + } + spa_pod_builder_pop(b, &f[0]); return pw_protocol_native_end_proxy(proxy, b); } @@ -119,8 +148,9 @@ client_node_marshal_port_update(void *object, spa_pod_builder_push_struct(b, &f[1]); spa_pod_builder_add(b, SPA_POD_Long(change_mask), - SPA_POD_Int(info->flags), - SPA_POD_Int(info->rate), + SPA_POD_Long(info->flags), + SPA_POD_Int(info->rate.num), + SPA_POD_Int(info->rate.denom), SPA_POD_Int(n_items), NULL); for (i = 0; i < n_items; i++) { spa_pod_builder_add(b, @@ -745,8 +775,10 @@ static int client_node_demarshal_update(void *object, void *data, size_t size) struct pw_resource *resource = object; struct spa_pod_parser prs; struct spa_pod_frame f[2]; - uint32_t change_mask, max_input_ports, max_output_ports, n_params; + uint32_t change_mask, n_params; const struct spa_pod **params; + struct spa_node_info info = SPA_NODE_INFO_INIT(), *infop = NULL; + struct spa_pod *ipod; struct spa_dict props; uint32_t i; @@ -754,8 +786,6 @@ static int client_node_demarshal_update(void *object, void *data, size_t size) if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || spa_pod_parser_get(&prs, SPA_POD_Int(&change_mask), - SPA_POD_Int(&max_input_ports), - SPA_POD_Int(&max_output_ports), SPA_POD_Int(&n_params), NULL) < 0) return -EINVAL; @@ -765,28 +795,58 @@ static int client_node_demarshal_update(void *object, void *data, size_t size) SPA_POD_PodObject(¶ms[i]), NULL) < 0) return -EINVAL; - if (spa_pod_parser_push_struct(&prs, &f[1]) < 0) - return -EINVAL; if (spa_pod_parser_get(&prs, - SPA_POD_Int(&props.n_items), NULL) < 0) + SPA_POD_PodStruct(&ipod), NULL) < 0) return -EINVAL; - props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); - for (i = 0; i < props.n_items; i++) { - if (spa_pod_parser_get(&prs, - SPA_POD_String(&props.items[i].key), - SPA_POD_String(&props.items[i].value), - NULL) < 0) + if (ipod) { + struct spa_pod_parser p2; + struct spa_pod_frame f2; + infop = &info; + + spa_pod_parser_pod(&p2, ipod); + if (spa_pod_parser_push_struct(&p2, &f2) < 0 || + spa_pod_parser_get(&p2, + SPA_POD_Int(&info.max_input_ports), + SPA_POD_Int(&info.max_output_ports), + SPA_POD_Long(&info.change_mask), + SPA_POD_Long(&info.flags), + SPA_POD_Int(&props.n_items), NULL) < 0) return -EINVAL; + + info.change_mask &= SPA_NODE_CHANGE_MASK_FLAGS | + SPA_NODE_CHANGE_MASK_PROPS | + SPA_NODE_CHANGE_MASK_PARAMS; + + if (props.n_items > 0) { + info.props = &props; + + props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); + for (i = 0; i < props.n_items; i++) { + if (spa_pod_parser_get(&p2, + SPA_POD_String(&props.items[i].key), + SPA_POD_String(&props.items[i].value), NULL) < 0) + return -EINVAL; + } + } + if (spa_pod_parser_get(&p2, + SPA_POD_Int(&info.n_params), NULL) < 0) + return -EINVAL; + + if (info.n_params > 0) { + info.params = alloca(info.n_params * sizeof(struct spa_param_info)); + for (i = 0; i < info.n_params; i++) { + if (spa_pod_parser_get(&p2, + SPA_POD_Id(&info.params[i].id), + SPA_POD_Int(&info.params[i].flags), NULL) < 0) + return -EINVAL; + } + } } pw_resource_do(resource, struct pw_client_node_proxy_methods, update, 0, change_mask, - max_input_ports, - max_output_ports, n_params, - params, - props.n_items > 0 ? - &props : NULL); + params, infop); return 0; } @@ -829,8 +889,9 @@ static int client_node_demarshal_port_update(void *object, void *data, size_t si if (spa_pod_parser_push_struct(&p2, &f2) < 0 || spa_pod_parser_get(&p2, SPA_POD_Long(&info.change_mask), - SPA_POD_Int(&info.flags), - SPA_POD_Int(&info.rate), + SPA_POD_Long(&info.flags), + SPA_POD_Int(&info.rate.num), + SPA_POD_Int(&info.rate.denom), SPA_POD_Int(&props.n_items), NULL) < 0) return -EINVAL; diff --git a/src/modules/module-client-node/remote-node.c b/src/modules/module-client-node/remote-node.c index b21220482..e358bcc76 100644 --- a/src/modules/module-client-node/remote-node.c +++ b/src/modules/module-client-node/remote-node.c @@ -397,6 +397,64 @@ static int client_node_transport(void *object, uint32_t node_id, return 0; } +static int add_node_update(struct pw_proxy *proxy, uint32_t change_mask) +{ + struct node_data *data = proxy->user_data; + struct pw_node *node = data->node; + struct spa_node_info ni = SPA_NODE_INFO_INIT(); + uint32_t n_params = 0; + struct spa_pod **params = NULL; + int res; + + if (change_mask & PW_CLIENT_NODE_UPDATE_PARAMS) { + uint32_t i, idx, id; + uint8_t buf[2048]; + struct spa_pod_builder b = { 0 }; + + for (i = 0; i < node->info.n_params; i++) { + struct spa_pod *param; + + id = node->info.params[i].id; + + for (idx = 0;;) { + spa_pod_builder_init(&b, buf, sizeof(buf)); + if (spa_node_enum_params_sync(node->node, + id, &idx, + NULL, ¶m, &b) != 1) + break; + + params = realloc(params, sizeof(struct spa_pod *) * (n_params + 1)); + params[n_params++] = spa_pod_copy(param); + } + } + } + if (change_mask & PW_CLIENT_NODE_UPDATE_INFO) { + ni.max_input_ports = node->info.max_input_ports; + ni.max_output_ports = node->info.max_output_ports; + ni.change_mask = SPA_NODE_CHANGE_MASK_FLAGS | + SPA_NODE_CHANGE_MASK_PROPS | + SPA_NODE_CHANGE_MASK_PARAMS; + ni.flags = 0; + ni.props = node->info.props; + ni.params = node->info.params; + ni.n_params = node->info.n_params; + + } + + res = pw_client_node_proxy_update(data->node_proxy, + change_mask, + n_params, + (const struct spa_pod **)params, + &ni); + + if (params) { + while (n_params > 0) + free(params[--n_params]); + free(params); + } + return res; +} + static int add_port_update(struct pw_proxy *proxy, struct pw_port *port, uint32_t change_mask) { struct node_data *data = proxy->user_data; @@ -406,7 +464,7 @@ static int add_port_update(struct pw_proxy *proxy, struct pw_port *port, uint32_ int res; if (change_mask & PW_CLIENT_NODE_PORT_UPDATE_PARAMS) { - uint32_t i, idx2, id; + uint32_t i, idx, id; uint8_t buf[2048]; struct spa_pod_builder b = { 0 }; @@ -415,11 +473,11 @@ static int add_port_update(struct pw_proxy *proxy, struct pw_port *port, uint32_ id = port->info.params[i].id; - for (idx2 = 0;;) { + for (idx = 0;;) { spa_pod_builder_init(&b, buf, sizeof(buf)); if (spa_node_port_enum_params_sync(port->node->node, port->direction, port->port_id, - id, &idx2, + id, &idx, NULL, ¶m, &b) != 1) break; @@ -649,11 +707,6 @@ client_node_port_set_param(void *object, goto done; } - if ((res = add_port_update(proxy, port, - PW_CLIENT_NODE_PORT_UPDATE_PARAMS | - PW_CLIENT_NODE_PORT_UPDATE_INFO)) < 0) - pw_proxy_error(proxy, res, "can't add port update"); - done: return res; } @@ -967,13 +1020,8 @@ static void do_node_init(struct pw_proxy *proxy) struct pw_port *port; pw_log_debug("%p: init", data); - pw_client_node_proxy_update(data->node_proxy, - PW_CLIENT_NODE_UPDATE_MAX_INPUTS | - PW_CLIENT_NODE_UPDATE_MAX_OUTPUTS | - PW_CLIENT_NODE_UPDATE_PARAMS, - data->node->info.max_input_ports, - data->node->info.max_output_ports, - 0, NULL, NULL); + add_node_update(proxy, PW_CLIENT_NODE_UPDATE_PARAMS | + PW_CLIENT_NODE_UPDATE_INFO); spa_list_for_each(port, &data->node->input_ports, link) { add_port_update(proxy, port, @@ -1034,14 +1082,30 @@ static void node_info_changed(void *data, const struct pw_node_info *info) pw_log_debug("info changed %p", d); - if (info->change_mask & PW_NODE_CHANGE_MASK_PROPS) { - change_mask |= PW_CLIENT_NODE_UPDATE_PROPS; + if (info->change_mask & PW_NODE_CHANGE_MASK_PROPS) + change_mask |= PW_CLIENT_NODE_UPDATE_INFO; + if (info->change_mask & PW_NODE_CHANGE_MASK_PARAMS) { + change_mask |= PW_CLIENT_NODE_UPDATE_PARAMS; + change_mask |= PW_CLIENT_NODE_UPDATE_INFO; } - pw_client_node_proxy_update(d->node_proxy, - change_mask, - 0, 0, - 0, NULL, - info->props); + add_node_update((struct pw_proxy*)d->node_proxy, change_mask); +} + +static void node_port_info_changed(void *data, struct pw_port *port, + const struct pw_port_info *info) +{ + struct node_data *d = data; + uint32_t change_mask = 0; + + pw_log_debug("info changed %p", d); + + if (info->change_mask & PW_PORT_CHANGE_MASK_PROPS) + change_mask |= PW_CLIENT_NODE_PORT_UPDATE_INFO; + if (info->change_mask & PW_PORT_CHANGE_MASK_PARAMS) { + change_mask |= PW_CLIENT_NODE_PORT_UPDATE_PARAMS; + change_mask |= PW_CLIENT_NODE_PORT_UPDATE_INFO; + } + add_port_update((struct pw_proxy*)d->node_proxy, port, change_mask); } static void node_active_changed(void *data, bool active) @@ -1056,6 +1120,7 @@ static const struct pw_node_events node_events = { PW_VERSION_NODE_EVENTS, .destroy = node_destroy, .info_changed = node_info_changed, + .port_info_changed = node_port_info_changed, .active_changed = node_active_changed, }; diff --git a/src/pipewire/node.h b/src/pipewire/node.h index d54be79e0..9188fc173 100644 --- a/src/pipewire/node.h +++ b/src/pipewire/node.h @@ -72,6 +72,9 @@ struct pw_node_events { /** the node info changed */ void (*info_changed) (void *data, const struct pw_node_info *info); + /** a port on the node changed info */ + void (*port_info_changed) (void *data, struct pw_port *port, + const struct pw_port_info *info); /** the node active state changed */ void (*active_changed) (void *data, bool active); /** the node enabled state changed */ diff --git a/src/pipewire/port.c b/src/pipewire/port.c index db7fd5a32..ea8de3515 100644 --- a/src/pipewire/port.c +++ b/src/pipewire/port.c @@ -87,6 +87,8 @@ static void emit_info_changed(struct pw_port *port) return; pw_port_emit_info_changed(port, &port->info); + if (port->node) + pw_node_emit_port_info_changed(port->node, port, &port->info); if (port->global) spa_list_for_each(resource, &port->global->resource_list, link) diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 39b376212..3ae975a07 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -316,6 +316,7 @@ struct pw_node_activation { #define pw_node_emit_port_added(n,p) pw_node_emit(n, port_added, 0, p) #define pw_node_emit_port_removed(n,p) pw_node_emit(n, port_removed, 0, p) #define pw_node_emit_info_changed(n,i) pw_node_emit(n, info_changed, 0, i) +#define pw_node_emit_port_info_changed(n,p,i) pw_node_emit(n, port_info_changed, 0, p, i) #define pw_node_emit_active_changed(n,a) pw_node_emit(n, active_changed, 0, a) #define pw_node_emit_enabled_changed(n,e) pw_node_emit(n, enabled_changed, 0, e) #define pw_node_emit_state_request(n,s) pw_node_emit(n, state_request, 0, s) diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index a235be432..a6c452a33 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -492,6 +492,8 @@ static int port_set_format(struct spa_node *node, if (stream->state == PW_STREAM_STATE_ERROR) return -EIO; + emit_port_info(impl); + stream_set_state(stream, p ? PW_STREAM_STATE_READY :