From f56e4dbc4d4d9b401c03629b79ca0c6953199420 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 28 Nov 2019 11:50:17 +0100 Subject: [PATCH] interfaces: add event to notify of global bound id Make it possible to know when a proxy is bound to a global id before the global shows up in the registry. This makes it possible to match locally created objects to the one appearing in the registry and possibly avoid a second bind. --- .../module-protocol-native/protocol-native.c | 31 +++++++++++++++++++ src/pipewire/interfaces.h | 19 ++++++++++-- src/pipewire/private.h | 2 ++ src/pipewire/proxy.h | 3 ++ src/pipewire/remote.c | 12 +++++++ src/pipewire/resource.c | 12 +++++++ src/pipewire/resource.h | 3 ++ src/tests/test-interfaces.c | 2 ++ 8 files changed, 81 insertions(+), 3 deletions(-) diff --git a/src/modules/module-protocol-native/protocol-native.c b/src/modules/module-protocol-native/protocol-native.c index 8cbffe3df..befbdd15a 100644 --- a/src/modules/module-protocol-native/protocol-native.c +++ b/src/modules/module-protocol-native/protocol-native.c @@ -337,6 +337,21 @@ static int core_event_demarshal_remove_id(void *object, const struct pw_protocol return pw_proxy_notify(proxy, struct pw_core_proxy_events, remove_id, 0, id); } +static int core_event_demarshal_bound_id(void *object, const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + uint32_t id, global_id; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&id), + SPA_POD_Int(&global_id)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_core_proxy_events, bound_id, 0, id, global_id); +} + static int core_event_demarshal_add_mem(void *object, const struct pw_protocol_native_message *msg) { struct pw_proxy *proxy = object; @@ -454,6 +469,20 @@ static void core_event_marshal_remove_id(void *object, uint32_t id) pw_protocol_native_end_resource(resource, b); } +static void core_event_marshal_bound_id(void *object, uint32_t id, uint32_t global_id) +{ + struct pw_resource *resource = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, PW_CORE_PROXY_EVENT_BOUND_ID, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(id), + SPA_POD_Int(global_id)); + + pw_protocol_native_end_resource(resource, b); +} + static void core_event_marshal_add_mem(void *object, uint32_t id, uint32_t type, int fd, uint32_t flags) { struct pw_resource *resource = object; @@ -1894,6 +1923,7 @@ static const struct pw_core_proxy_events pw_protocol_native_core_event_marshal = .ping = &core_event_marshal_ping, .error = &core_event_marshal_error, .remove_id = &core_event_marshal_remove_id, + .bound_id = &core_event_marshal_bound_id, .add_mem = &core_event_marshal_add_mem, .remove_mem = &core_event_marshal_remove_mem, }; @@ -1906,6 +1936,7 @@ pw_protocol_native_core_event_demarshal[PW_CORE_PROXY_EVENT_NUM] = [PW_CORE_PROXY_EVENT_PING] = { &core_event_demarshal_ping, 0, }, [PW_CORE_PROXY_EVENT_ERROR] = { &core_event_demarshal_error, 0, }, [PW_CORE_PROXY_EVENT_REMOVE_ID] = { &core_event_demarshal_remove_id, 0, }, + [PW_CORE_PROXY_EVENT_BOUND_ID] = { &core_event_demarshal_bound_id, 0, }, [PW_CORE_PROXY_EVENT_ADD_MEM] = { &core_event_demarshal_add_mem, 0, }, [PW_CORE_PROXY_EVENT_REMOVE_MEM] = { &core_event_demarshal_remove_mem, 0, }, }; diff --git a/src/pipewire/interfaces.h b/src/pipewire/interfaces.h index 5c5042ed4..40e826e62 100644 --- a/src/pipewire/interfaces.h +++ b/src/pipewire/interfaces.h @@ -83,9 +83,10 @@ struct pw_link_proxy { struct spa_interface iface; }; #define PW_CORE_PROXY_EVENT_PING 2 #define PW_CORE_PROXY_EVENT_ERROR 3 #define PW_CORE_PROXY_EVENT_REMOVE_ID 4 -#define PW_CORE_PROXY_EVENT_ADD_MEM 5 -#define PW_CORE_PROXY_EVENT_REMOVE_MEM 6 -#define PW_CORE_PROXY_EVENT_NUM 7 +#define PW_CORE_PROXY_EVENT_BOUND_ID 5 +#define PW_CORE_PROXY_EVENT_ADD_MEM 6 +#define PW_CORE_PROXY_EVENT_REMOVE_MEM 7 +#define PW_CORE_PROXY_EVENT_NUM 8 /** \struct pw_core_proxy_events * \brief Core events @@ -152,6 +153,18 @@ struct pw_core_proxy_events { */ void (*remove_id) (void *object, uint32_t id); + /** + * Notify an object binding + * + * This event is emited when a local object ID is bound to a + * global ID. It is emited before the global becomes visible in the + * registry. + * + * \param id bound object ID + * \param global_id the global id bound to + */ + void (*bound_id) (void *object, uint32_t id, uint32_t global_id); + /** * Add memory for a client * diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 77b46b3a0..b1a0c40ca 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -180,6 +180,7 @@ struct pw_global { #define pw_core_resource_ping(r,...) pw_core_resource(r,ping,0,__VA_ARGS__) #define pw_core_resource_error(r,...) pw_core_resource(r,error,0,__VA_ARGS__) #define pw_core_resource_remove_id(r,...) pw_core_resource(r,remove_id,0,__VA_ARGS__) +#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__) @@ -705,6 +706,7 @@ struct pw_resource { #define pw_proxy_emit(o,m,v,...) spa_hook_list_call(&o->listener_list, struct pw_proxy_events, m, v, ##__VA_ARGS__) #define pw_proxy_emit_destroy(p) pw_proxy_emit(p, destroy, 0) +#define pw_proxy_emit_bound(p,g) pw_proxy_emit(p, bound, 0, g) #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) diff --git a/src/pipewire/proxy.h b/src/pipewire/proxy.h index 1a25959eb..6abea8846 100644 --- a/src/pipewire/proxy.h +++ b/src/pipewire/proxy.h @@ -111,6 +111,9 @@ struct pw_proxy_events { /** The proxy is destroyed */ void (*destroy) (void *data); + /** a proxy is bound to a global id */ + void (*bound) (void *data, uint32_t global_id); + /** a reply to a sync method completed */ void (*done) (void *data, int seq); diff --git a/src/pipewire/remote.c b/src/pipewire/remote.c index bb7153832..99d82aaad 100644 --- a/src/pipewire/remote.c +++ b/src/pipewire/remote.c @@ -145,6 +145,17 @@ static void core_event_remove_id(void *data, uint32_t id) } } +static void core_event_bound_id(void *data, uint32_t id, uint32_t global_id) +{ + struct pw_remote *this = data; + struct pw_proxy *proxy; + + pw_log_debug(NAME" %p: proxy %u bound %u", this, id, global_id); + if ((proxy = pw_map_lookup(&this->objects, id)) != NULL) { + pw_proxy_emit_bound(proxy, global_id); + } +} + static void core_event_add_mem(void *data, uint32_t id, uint32_t type, int fd, uint32_t flags) { struct pw_remote *this = data; @@ -173,6 +184,7 @@ static const struct pw_core_proxy_events core_events = { .ping = core_event_ping, .done = core_event_done, .remove_id = core_event_remove_id, + .bound_id = core_event_bound_id, .add_mem = core_event_add_mem, .remove_mem = core_event_remove_mem, }; diff --git a/src/pipewire/resource.c b/src/pipewire/resource.c index 550b95547..87a9ca67a 100644 --- a/src/pipewire/resource.c +++ b/src/pipewire/resource.c @@ -207,6 +207,18 @@ int pw_resource_ping(struct pw_resource *resource, int seq) return res; } +SPA_EXPORT +int pw_resource_bound_id(struct pw_resource *resource, uint32_t global_id) +{ + struct pw_client *client = resource->client; + + if (client->core_resource != NULL) { + pw_log_debug(NAME" %p: %u global_id:%u", resource, resource->id, global_id); + pw_core_resource_bound_id(client->core_resource, resource->id, global_id); + } + return 0; +} + SPA_EXPORT void pw_resource_errorf(struct pw_resource *resource, int res, const char *error, ...) { diff --git a/src/pipewire/resource.h b/src/pipewire/resource.h index 1882fda1e..b4e2eef5e 100644 --- a/src/pipewire/resource.h +++ b/src/pipewire/resource.h @@ -121,6 +121,9 @@ void pw_resource_add_object_listener(struct pw_resource *resource, * with the same \a sequence number in the return value. */ int pw_resource_ping(struct pw_resource *resource, int seq); +/** Notify global id this resource is bound to */ +int pw_resource_bound_id(struct pw_resource *resource, uint32_t global_id); + /** Generate an error for a resource */ void pw_resource_error(struct pw_resource *resource, int res, const char *error); void pw_resource_errorf(struct pw_resource *resource, int res, const char *error, ...) SPA_PRINTF_FUNC(3, 4); diff --git a/src/tests/test-interfaces.c b/src/tests/test-interfaces.c index f8f046c97..4062db9dd 100644 --- a/src/tests/test-interfaces.c +++ b/src/tests/test-interfaces.c @@ -62,6 +62,7 @@ static void test_core_abi(void) void (*ping) (void *object, uint32_t id, int seq); void (*error) (void *object, uint32_t id, int seq, int res, const char *error); void (*remove_id) (void *object, uint32_t id); + void (*bound_id) (void *object, uint32_t id, uint32_t global_id); void (*add_mem) (void *object, uint32_t id, uint32_t type, int fd, uint32_t flags); void (*remove_mem) (void *object, uint32_t id); } events = { PW_VERSION_CORE_PROXY_EVENTS, }; @@ -84,6 +85,7 @@ static void test_core_abi(void) TEST_FUNC(e, events, ping); TEST_FUNC(e, events, error); TEST_FUNC(e, events, remove_id); + TEST_FUNC(e, events, bound_id); TEST_FUNC(e, events, add_mem); TEST_FUNC(e, events, remove_mem); spa_assert(PW_VERSION_CORE_PROXY_EVENTS == 0);