diff --git a/pipewire-jack/src/pipewire-jack.c b/pipewire-jack/src/pipewire-jack.c index 25f5599b6..d9559f8cb 100644 --- a/pipewire-jack/src/pipewire-jack.c +++ b/pipewire-jack/src/pipewire-jack.c @@ -898,17 +898,19 @@ static void on_node_destroy(void *data) spa_hook_remove(&client->node_listener); } -static void on_node_bound(void *data, uint32_t global_id) +static void on_node_bound_props(void *data, uint32_t global_id, const struct spa_dict *props) { struct client *client = data; client->node_id = global_id; + if (props) + pw_properties_update(client->props, props); } static const struct pw_proxy_events node_proxy_events = { PW_VERSION_PROXY_EVENTS, .removed = on_node_removed, .destroy = on_node_destroy, - .bound = on_node_bound, + .bound_props = on_node_bound_props, }; static struct link *find_activation(struct spa_list *links, uint32_t node_id) diff --git a/src/examples/export-spa.c b/src/examples/export-spa.c index 56b08d2d1..db721693b 100644 --- a/src/examples/export-spa.c +++ b/src/examples/export-spa.c @@ -36,7 +36,7 @@ struct data { uint32_t id; }; -static void proxy_event_bound(void *_data, uint32_t global_id) +static void proxy_event_bound_props(void *_data, uint32_t global_id, const struct spa_dict *props) { struct data *data = _data; if (data->id != global_id) { @@ -47,7 +47,7 @@ static void proxy_event_bound(void *_data, uint32_t global_id) static const struct pw_proxy_events proxy_events = { PW_VERSION_PROXY_EVENTS, - .bound = proxy_event_bound, + .bound_props = proxy_event_bound_props, }; static int make_node(struct data *data) diff --git a/src/modules/module-client-node/remote-node.c b/src/modules/module-client-node/remote-node.c index f1fa1f100..2dc1aa078 100644 --- a/src/modules/module-client-node/remote-node.c +++ b/src/modules/module-client-node/remote-node.c @@ -1143,18 +1143,20 @@ static void client_node_destroy(void *_data) client_node_removed(_data); } -static void client_node_bound(void *_data, uint32_t global_id) +static void client_node_bound_props(void *_data, uint32_t global_id, const struct spa_dict *props) { struct node_data *data = _data; pw_log_debug("%p: bound %u", data, global_id); data->remote_id = global_id; + if (props) + pw_properties_update(data->node->properties, props); } static const struct pw_proxy_events proxy_client_node_events = { PW_VERSION_PROXY_EVENTS, .removed = client_node_removed, .destroy = client_node_destroy, - .bound = client_node_bound, + .bound_props = client_node_bound_props, }; static int node_ready(void *d, int status) diff --git a/src/modules/module-fallback-sink.c b/src/modules/module-fallback-sink.c index e4eb4ce69..4474fc124 100644 --- a/src/modules/module-fallback-sink.c +++ b/src/modules/module-fallback-sink.c @@ -162,7 +162,7 @@ static void sink_proxy_removed(void *data) pw_proxy_destroy(impl->sink); } -static void sink_proxy_bound(void *data, uint32_t id) +static void sink_proxy_bound_props(void *data, uint32_t id, const struct spa_dict *props) { struct impl *impl = data; @@ -186,7 +186,7 @@ static void sink_proxy_destroy(void *data) static const struct pw_proxy_events sink_proxy_events = { PW_VERSION_PROXY_EVENTS, .removed = sink_proxy_removed, - .bound = sink_proxy_bound, + .bound_props = sink_proxy_bound_props, .destroy = sink_proxy_destroy, }; diff --git a/src/modules/module-protocol-native/protocol-native.c b/src/modules/module-protocol-native/protocol-native.c index 447d7ffe2..e4c2f6ad0 100644 --- a/src/modules/module-protocol-native/protocol-native.c +++ b/src/modules/module-protocol-native/protocol-native.c @@ -395,6 +395,27 @@ static int core_event_demarshal_bound_id(void *data, const struct pw_protocol_na return pw_proxy_notify(proxy, struct pw_core_events, bound_id, 0, id, global_id); } +static int core_event_demarshal_bound_props(void *data, const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + uint32_t id, global_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) + return -EINVAL; + if (spa_pod_parser_get(&prs, + SPA_POD_Int(&id), + SPA_POD_Int(&global_id), NULL) < 0) + return -EINVAL; + + parse_dict_struct(&prs, &f[1], &props); + + return pw_proxy_notify(proxy, struct pw_core_events, bound_props, 1, id, global_id, &props); +} + static int core_event_demarshal_add_mem(void *data, const struct pw_protocol_native_message *msg) { struct pw_proxy *proxy = data; @@ -526,6 +547,25 @@ static void core_event_marshal_bound_id(void *data, uint32_t id, uint32_t global pw_protocol_native_end_resource(resource, b); } +static void core_event_marshal_bound_props(void *data, uint32_t id, uint32_t global_id, const struct spa_dict *props) +{ + struct pw_resource *resource = data; + struct spa_pod_builder *b; + struct spa_pod_frame f; + + b = pw_protocol_native_begin_resource(resource, PW_CORE_EVENT_BOUND_PROPS, NULL); + + spa_pod_builder_push_struct(b, &f); + spa_pod_builder_add(b, + SPA_POD_Int(id), + SPA_POD_Int(global_id), + NULL); + push_dict(b, props); + spa_pod_builder_pop(b, &f); + + pw_protocol_native_end_resource(resource, b); +} + static void core_event_marshal_add_mem(void *data, uint32_t id, uint32_t type, int fd, uint32_t flags) { struct pw_resource *resource = data; @@ -1863,6 +1903,7 @@ static const struct pw_core_events pw_protocol_native_core_event_marshal = { .bound_id = &core_event_marshal_bound_id, .add_mem = &core_event_marshal_add_mem, .remove_mem = &core_event_marshal_remove_mem, + .bound_props = &core_event_marshal_bound_props, }; static const struct pw_protocol_native_demarshal @@ -1876,6 +1917,7 @@ pw_protocol_native_core_event_demarshal[PW_CORE_EVENT_NUM] = [PW_CORE_EVENT_BOUND_ID] = { &core_event_demarshal_bound_id, 0, }, [PW_CORE_EVENT_ADD_MEM] = { &core_event_demarshal_add_mem, 0, }, [PW_CORE_EVENT_REMOVE_MEM] = { &core_event_demarshal_remove_mem, 0, }, + [PW_CORE_EVENT_BOUND_PROPS] = { &core_event_demarshal_bound_props, 0, }, }; static const struct pw_protocol_marshal pw_protocol_native_core_marshal = { diff --git a/src/modules/module-protocol-pulse/modules/module-null-sink.c b/src/modules/module-protocol-pulse/modules/module-null-sink.c index b3fcd3715..5af46aac6 100644 --- a/src/modules/module-protocol-pulse/modules/module-null-sink.c +++ b/src/modules/module-protocol-pulse/modules/module-null-sink.c @@ -40,7 +40,7 @@ static void module_null_sink_proxy_destroy(void *data) module_schedule_unload(module); } -static void module_null_sink_proxy_bound(void *data, uint32_t global_id) +static void module_null_sink_proxy_bound_props(void *data, uint32_t global_id, const struct spa_dict *props) { struct module *module = data; struct module_null_sink_data *d = module->user_data; @@ -63,7 +63,7 @@ static void module_null_sink_proxy_error(void *data, int seq, int res, const cha static const struct pw_proxy_events proxy_events = { PW_VERSION_PROXY_EVENTS, .removed = module_null_sink_proxy_removed, - .bound = module_null_sink_proxy_bound, + .bound_props = module_null_sink_proxy_bound_props, .error = module_null_sink_proxy_error, .destroy = module_null_sink_proxy_destroy, }; diff --git a/src/pipewire/core.c b/src/pipewire/core.c index 4b68c8251..fe6ea2c77 100644 --- a/src/pipewire/core.c +++ b/src/pipewire/core.c @@ -63,7 +63,7 @@ static void core_event_remove_id(void *data, uint32_t id) pw_proxy_remove(proxy); } -static void core_event_bound_id(void *data, uint32_t id, uint32_t global_id) +static void bound_props(void *data, uint32_t id, uint32_t global_id, const struct spa_dict *props) { struct pw_core *this = data; struct pw_proxy *proxy; @@ -71,9 +71,20 @@ static void core_event_bound_id(void *data, uint32_t id, uint32_t global_id) pw_log_debug("%p: proxy id %u bound %u", this, id, global_id); if ((proxy = pw_map_lookup(&this->objects, id)) != NULL) { pw_proxy_set_bound_id(proxy, global_id); + pw_proxy_emit_bound_props(proxy, global_id, props); } } +static void core_event_bound_props(void *data, uint32_t id, uint32_t global_id, const struct spa_dict *props) +{ + bound_props(data, id, global_id, props); +} + +static void core_event_bound_id(void *data, uint32_t id, uint32_t global_id) +{ + bound_props(data, id, global_id, NULL); +} + static void core_event_add_mem(void *data, uint32_t id, uint32_t type, int fd, uint32_t flags) { struct pw_core *this = data; @@ -106,6 +117,7 @@ static const struct pw_core_events core_events = { .bound_id = core_event_bound_id, .add_mem = core_event_add_mem, .remove_mem = core_event_remove_mem, + .bound_props = core_event_bound_props, }; SPA_EXPORT diff --git a/src/pipewire/core.h b/src/pipewire/core.h index 33babab7c..757270824 100644 --- a/src/pipewire/core.h +++ b/src/pipewire/core.h @@ -34,7 +34,7 @@ extern "C" { #define PW_TYPE_INTERFACE_Core PW_TYPE_INFO_INTERFACE_BASE "Core" #define PW_TYPE_INTERFACE_Registry PW_TYPE_INFO_INTERFACE_BASE "Registry" -#define PW_VERSION_CORE 3 +#define PW_VERSION_CORE 4 struct pw_core; #define PW_VERSION_REGISTRY 3 struct pw_registry; @@ -80,21 +80,22 @@ void pw_core_info_free(struct pw_core_info *info); /** Core */ -#define PW_CORE_EVENT_INFO 0 -#define PW_CORE_EVENT_DONE 1 -#define PW_CORE_EVENT_PING 2 -#define PW_CORE_EVENT_ERROR 3 -#define PW_CORE_EVENT_REMOVE_ID 4 -#define PW_CORE_EVENT_BOUND_ID 5 -#define PW_CORE_EVENT_ADD_MEM 6 +#define PW_CORE_EVENT_INFO 0 +#define PW_CORE_EVENT_DONE 1 +#define PW_CORE_EVENT_PING 2 +#define PW_CORE_EVENT_ERROR 3 +#define PW_CORE_EVENT_REMOVE_ID 4 +#define PW_CORE_EVENT_BOUND_ID 5 +#define PW_CORE_EVENT_ADD_MEM 6 #define PW_CORE_EVENT_REMOVE_MEM 7 -#define PW_CORE_EVENT_NUM 8 +#define PW_CORE_EVENT_BOUND_PROPS 8 +#define PW_CORE_EVENT_NUM 9 /** \struct pw_core_events * \brief Core events */ struct pw_core_events { -#define PW_VERSION_CORE_EVENTS 0 +#define PW_VERSION_CORE_EVENTS 1 uint32_t version; /** @@ -188,6 +189,8 @@ struct pw_core_events { * \param id the memory id to remove */ void (*remove_mem) (void *data, uint32_t id); + + void (*bound_props) (void *data, uint32_t id, uint32_t global_id, const struct spa_dict *props); }; #define PW_CORE_METHOD_ADD_LISTENER 0 diff --git a/src/pipewire/filter.c b/src/pipewire/filter.c index df8a82e13..4b574c3a5 100644 --- a/src/pipewire/filter.c +++ b/src/pipewire/filter.c @@ -1132,10 +1132,12 @@ static void proxy_error(void *_data, int seq, int res, const char *message) PW_FILTER_STATE_ERROR, message); } -static void proxy_bound(void *_data, uint32_t global_id) +static void proxy_bound_props(void *_data, uint32_t global_id, const struct spa_dict *props) { struct pw_filter *filter = _data; filter->node_id = global_id; + if (props) + pw_properties_update(filter->properties, props); filter_set_state(filter, PW_FILTER_STATE_PAUSED, NULL); } @@ -1144,7 +1146,7 @@ static const struct pw_proxy_events proxy_events = { .removed = proxy_removed, .destroy = proxy_destroy, .error = proxy_error, - .bound = proxy_bound, + .bound_props = proxy_bound_props, }; static void on_core_error(void *_data, uint32_t id, int seq, int res, const char *message) diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 3d95922eb..da55332ca 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -346,6 +346,7 @@ struct pw_global { #define pw_core_resource_bound_id(r,...) pw_core_resource(r,bound_id,0,__VA_ARGS__) #define pw_core_resource_add_mem(r,...) pw_core_resource(r,add_mem,0,__VA_ARGS__) #define pw_core_resource_remove_mem(r,...) pw_core_resource(r,remove_mem,0,__VA_ARGS__) +#define pw_core_resource_bound_props(r,...) pw_core_resource(r,bound_props,1,__VA_ARGS__) static inline SPA_PRINTF_FUNC(5,0) void pw_core_resource_errorv(struct pw_resource *resource, uint32_t id, int seq, @@ -965,6 +966,7 @@ struct pw_resource { #define pw_proxy_emit_removed(p) pw_proxy_emit(p, removed, 0) #define pw_proxy_emit_done(p,s) pw_proxy_emit(p, done, 0, s) #define pw_proxy_emit_error(p,s,r,m) pw_proxy_emit(p, error, 0, s, r, m) +#define pw_proxy_emit_bound_props(p,g,r) pw_proxy_emit(p, bound_props, 1, g, r) struct pw_proxy { struct spa_interface impl; /**< object implementation */ diff --git a/src/pipewire/proxy.h b/src/pipewire/proxy.h index 6cb6ca292..e92a44e43 100644 --- a/src/pipewire/proxy.h +++ b/src/pipewire/proxy.h @@ -89,7 +89,7 @@ struct pw_proxy; /** Proxy events, use \ref pw_proxy_add_listener */ struct pw_proxy_events { -#define PW_VERSION_PROXY_EVENTS 0 +#define PW_VERSION_PROXY_EVENTS 1 uint32_t version; /** The proxy is destroyed */ @@ -107,6 +107,8 @@ struct pw_proxy_events { /** an error occurred on the proxy */ void (*error) (void *data, int seq, int res, const char *message); + + void (*bound_props) (void *data, uint32_t global_id, const struct spa_dict *props); }; /* Make a new proxy object. The id can be used to bind to a remote object and diff --git a/src/pipewire/resource.c b/src/pipewire/resource.c index b4c717f6c..dd3e7597e 100644 --- a/src/pipewire/resource.c +++ b/src/pipewire/resource.c @@ -194,9 +194,19 @@ int pw_resource_set_bound_id(struct pw_resource *resource, uint32_t global_id) struct pw_impl_client *client = resource->client; resource->bound_id = global_id; + if (client->core_resource != NULL) { - pw_log_debug("%p: %u global_id:%u", resource, resource->id, global_id); - pw_core_resource_bound_id(client->core_resource, resource->id, global_id); + struct pw_global *global = pw_map_lookup(&resource->context->globals, global_id); + const struct spa_dict *dict = global ? &global->properties->dict : NULL; + + pw_log_debug("%p: %u global_id:%u %d", resource, resource->id, global_id, + client->core_resource->version); + + if (client->core_resource->version >= 4) + pw_core_resource_bound_props(client->core_resource, resource->id, global_id, + dict); + else + pw_core_resource_bound_id(client->core_resource, resource->id, global_id); } return 0; } diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index 22ccbfb0a..df5916ffd 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -17,6 +17,7 @@ #include #include #include +#include #define PW_ENABLE_DEPRECATED @@ -1137,10 +1138,12 @@ static void proxy_error(void *_data, int seq, int res, const char *message) PW_STREAM_STATE_ERROR, message); } -static void proxy_bound(void *data, uint32_t global_id) +static void proxy_bound_props(void *data, uint32_t global_id, const struct spa_dict *props) { struct pw_stream *stream = data; stream->node_id = global_id; + if (props) + pw_properties_update(stream->properties, props); stream_set_state(stream, PW_STREAM_STATE_PAUSED, NULL); } @@ -1149,7 +1152,7 @@ static const struct pw_proxy_events proxy_events = { .removed = proxy_removed, .destroy = proxy_destroy, .error = proxy_error, - .bound = proxy_bound, + .bound_props = proxy_bound_props, }; static struct control *find_control(struct pw_stream *stream, uint32_t id) diff --git a/src/tests/test-interfaces.c b/src/tests/test-interfaces.c index ddce0359c..3b3f47ab9 100644 --- a/src/tests/test-interfaces.c +++ b/src/tests/test-interfaces.c @@ -42,6 +42,7 @@ static void test_core_abi(void) void (*bound_id) (void *data, uint32_t id, uint32_t global_id); void (*add_mem) (void *data, uint32_t id, uint32_t type, int fd, uint32_t flags); void (*remove_mem) (void *data, uint32_t id); + void (*bound_props) (void *data, uint32_t id, uint32_t global_id, const struct spa_dict *props); } events = { PW_VERSION_CORE_EVENTS, }; struct pw_core_events e; @@ -68,7 +69,8 @@ static void test_core_abi(void) TEST_FUNC(e, events, bound_id); TEST_FUNC(e, events, add_mem); TEST_FUNC(e, events, remove_mem); - spa_assert_se(PW_VERSION_CORE_EVENTS == 0); + TEST_FUNC(e, events, bound_props); + spa_assert_se(PW_VERSION_CORE_EVENTS == 1); spa_assert_se(sizeof(e) == sizeof(events)); }