diff --git a/src/modules/module-client-node/client-node.c b/src/modules/module-client-node/client-node.c index f42a6fae8..c15191f05 100644 --- a/src/modules/module-client-node/client-node.c +++ b/src/modules/module-client-node/client-node.c @@ -83,6 +83,7 @@ struct mix { unsigned int valid:1; uint32_t id; struct port *port; + uint32_t peer_id; uint32_t n_buffers; struct buffer buffers[MAX_BUFFERS]; }; @@ -188,6 +189,8 @@ struct impl { pw_client_node_resource(r,port_set_io,0,__VA_ARGS__) #define pw_client_node_resource_set_activation(r,...) \ pw_client_node_resource(r,set_activation,0,__VA_ARGS__) +#define pw_client_node_resource_port_set_mix_info(r,...) \ + pw_client_node_resource(r,port_set_mix_info,1,__VA_ARGS__) static int do_port_use_buffers(struct impl *impl, @@ -866,6 +869,10 @@ do_port_use_buffers(struct impl *impl, } mix->n_buffers = n_buffers; + if (this->resource->version >= 4) + pw_client_node_resource_port_set_mix_info(this->resource, + direction, port_id, mix_id, + mix->peer_id, NULL); return pw_client_node_resource_port_use_buffers(this->resource, direction, port_id, mix_id, flags, n_buffers, mb); @@ -1376,6 +1383,8 @@ static int port_init_mix(void *data, struct pw_impl_port_mix *mix) mix->id * sizeof(struct spa_io_buffers), void); *mix->io = SPA_IO_BUFFERS_INIT; + m->peer_id = mix->peer_id; + pw_log_debug(NAME " %p: init mix id:%d io:%p base:%p", impl, mix->id, mix->io, impl->io_areas->map->ptr); diff --git a/src/modules/module-client-node/protocol-native.c b/src/modules/module-client-node/protocol-native.c index 550e7683a..f1ece54da 100644 --- a/src/modules/module-client-node/protocol-native.c +++ b/src/modules/module-client-node/protocol-native.c @@ -574,6 +574,39 @@ static int client_node_demarshal_set_activation(void *object, const struct pw_pr return 0; } +static int client_node_demarshal_port_set_mix_info(void *object, const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + uint32_t direction, port_id, mix_id, peer_id; + struct spa_pod_frame f[2]; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || + spa_pod_parser_get(&prs, + SPA_POD_Int(&direction), + SPA_POD_Int(&port_id), + SPA_POD_Int(&mix_id), + SPA_POD_Int(&peer_id), 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) + return -EINVAL; + + props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); + if (parse_dict(&prs, &props) < 0) + return -EINVAL; + + pw_proxy_notify(proxy, struct pw_client_node_events, port_set_mix_info, 1, + direction, port_id, mix_id, + peer_id, &props); + return 0; +} + static int client_node_demarshal_set_io(void *object, const struct pw_protocol_native_message *msg) { struct pw_proxy *proxy = object; @@ -841,6 +874,33 @@ client_node_marshal_set_io(void *object, return pw_protocol_native_end_resource(resource, b); } +static int +client_node_marshal_port_set_mix_info(void *object, + uint32_t direction, + uint32_t port_id, + uint32_t mix_id, + uint32_t peer_id, + const struct spa_dict *props) +{ + struct pw_resource *resource = object; + struct spa_pod_builder *b; + struct spa_pod_frame f; + + b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_EVENT_PORT_SET_MIX_INFO, NULL); + + spa_pod_builder_push_struct(b, &f); + spa_pod_builder_add(b, + SPA_POD_Int(direction), + SPA_POD_Int(port_id), + SPA_POD_Int(mix_id), + SPA_POD_Int(peer_id), NULL); + push_dict(b, props); + spa_pod_builder_pop(b, &f); + + return pw_protocol_native_end_resource(resource, b); +} + + static int client_node_demarshal_get_node(void *object, const struct pw_protocol_native_message *msg) { struct pw_resource *resource = object; @@ -1128,6 +1188,7 @@ static const struct pw_client_node_events pw_protocol_native_client_node_event_m .port_use_buffers = &client_node_marshal_port_use_buffers, .port_set_io = &client_node_marshal_port_set_io, .set_activation = &client_node_marshal_set_activation, + .port_set_mix_info = &client_node_marshal_port_set_mix_info, }; static const struct pw_protocol_native_demarshal @@ -1143,7 +1204,8 @@ pw_protocol_native_client_node_event_demarshal[PW_CLIENT_NODE_EVENT_NUM] = [PW_CLIENT_NODE_EVENT_PORT_SET_PARAM] = { &client_node_demarshal_port_set_param, 0 }, [PW_CLIENT_NODE_EVENT_PORT_USE_BUFFERS] = { &client_node_demarshal_port_use_buffers, 0 }, [PW_CLIENT_NODE_EVENT_PORT_SET_IO] = { &client_node_demarshal_port_set_io, 0 }, - [PW_CLIENT_NODE_EVENT_SET_ACTIVATION] = { &client_node_demarshal_set_activation, 0 } + [PW_CLIENT_NODE_EVENT_SET_ACTIVATION] = { &client_node_demarshal_set_activation, 0 }, + [PW_CLIENT_NODE_EVENT_PORT_SET_MIX_INFO] = { &client_node_demarshal_port_set_mix_info, 0 } }; static const struct pw_protocol_marshal pw_protocol_native_client_node_marshal = { diff --git a/src/pipewire/extensions/client-node.h b/src/pipewire/extensions/client-node.h index 3e4511b6f..1efd13389 100644 --- a/src/pipewire/extensions/client-node.h +++ b/src/pipewire/extensions/client-node.h @@ -34,7 +34,7 @@ extern "C" { #define PW_TYPE_INTERFACE_ClientNode PW_TYPE_INFO_INTERFACE_BASE "ClientNode" -#define PW_VERSION_CLIENT_NODE 3 +#define PW_VERSION_CLIENT_NODE 4 struct pw_client_node; #define PW_EXTENSION_MODULE_CLIENT_NODE PIPEWIRE_MODULE_PREFIX "module-client-node" @@ -58,11 +58,12 @@ struct pw_client_node_buffer { #define PW_CLIENT_NODE_EVENT_PORT_USE_BUFFERS 8 #define PW_CLIENT_NODE_EVENT_PORT_SET_IO 9 #define PW_CLIENT_NODE_EVENT_SET_ACTIVATION 10 -#define PW_CLIENT_NODE_EVENT_NUM 11 +#define PW_CLIENT_NODE_EVENT_PORT_SET_MIX_INFO 11 +#define PW_CLIENT_NODE_EVENT_NUM 12 /** \ref pw_client_node events */ struct pw_client_node_events { -#define PW_VERSION_CLIENT_NODE_EVENTS 0 +#define PW_VERSION_CLIENT_NODE_EVENTS 1 uint32_t version; /** * Notify of a new transport area @@ -193,12 +194,40 @@ struct pw_client_node_events { uint32_t offset, uint32_t size); + /** + * Notify the activation record of the next + * node to trigger + * + * \param node_id the peer node id + * \param signalfd the fd to wake up the peer + * \param mem_id the mem id of the memory + * \param the offset in \a mem_id to map + * \param the size of \a mem_id to map + */ int (*set_activation) (void *object, uint32_t node_id, int signalfd, uint32_t mem_id, uint32_t offset, uint32_t size); + + /** + * Notify about the peer of mix_id + * + * \param direction the direction of the port + * \param port_id the port id + * \param mix_id the mix id + * \param peer_id the id of the peer port + * \param props extra properties + * + * Since version 4:1 + */ + int (*port_set_mix_info) (void *object, + enum spa_direction direction, + uint32_t port_id, + uint32_t mix_id, + uint32_t peer_id, + const struct spa_dict *props); }; #define PW_CLIENT_NODE_METHOD_ADD_LISTENER 0