diff --git a/src/modules/module-protocol-native.c b/src/modules/module-protocol-native.c index e1df205b4..4eecc550b 100644 --- a/src/modules/module-protocol-native.c +++ b/src/modules/module-protocol-native.c @@ -527,14 +527,19 @@ static int impl_connect(struct pw_protocol_client *client) return -1; } -static int impl_get_fd(struct pw_protocol_client *client) +static int impl_steal_fd(struct pw_protocol_client *client) { struct client *impl = SPA_CONTAINER_OF(client, struct client, this); + int fd; if (impl->source == NULL) return -EIO; - return impl->source->fd; + fd = dup(impl->source->fd); + + pw_protocol_client_disconnect(client); + + return fd; } static void @@ -636,6 +641,8 @@ static int impl_connect_fd(struct pw_protocol_client *client, int fd) struct client *impl = SPA_CONTAINER_OF(client, struct client, this); struct pw_remote *remote = client->remote; + impl->disconnecting = false; + impl->connection = pw_protocol_native_connection_new(fd); if (impl->connection == NULL) goto error_close; @@ -707,7 +714,7 @@ impl_new_client(struct pw_protocol *protocol, impl->properties = properties ? pw_properties_copy(properties) : NULL; this->connect = impl_connect; - this->get_fd = impl_get_fd; + this->steal_fd = impl_steal_fd; this->connect_fd = impl_connect_fd; this->disconnect = impl_disconnect; this->destroy = impl_destroy; diff --git a/src/modules/module-protocol-native/protocol-native.c b/src/modules/module-protocol-native/protocol-native.c index e37f4b554..c07d5449a 100644 --- a/src/modules/module-protocol-native/protocol-native.c +++ b/src/modules/module-protocol-native/protocol-native.c @@ -30,6 +30,18 @@ #include "connection.h" +static void core_marshal_hello(void *object) +{ + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, PW_CORE_PROXY_METHOD_HELLO); + + spa_pod_builder_struct(b, "P", NULL); + + pw_protocol_native_end_proxy(proxy, b); +} + static void core_marshal_client_update(void *object, const struct spa_dict *props) { struct pw_proxy *proxy = object; @@ -403,6 +415,20 @@ static int core_demarshal_permissions(void *object, void *data, size_t size) return 0; } +static int core_demarshal_hello(void *object, void *data, size_t size) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs; + void *ptr; + + spa_pod_parser_init(&prs, data, size, 0); + if (spa_pod_parser_get(&prs, "[P]", &ptr, NULL) < 0) + return -EINVAL; + + pw_resource_do(resource, struct pw_core_proxy_methods, hello); + return 0; +} + static int core_demarshal_sync(void *object, void *data, size_t size) { struct pw_resource *resource = object; @@ -947,6 +973,7 @@ static void registry_marshal_bind(void *object, uint32_t id, static const struct pw_core_proxy_methods pw_protocol_native_core_method_marshal = { PW_VERSION_CORE_PROXY_METHODS, + &core_marshal_hello, &core_marshal_update_types_client, &core_marshal_sync, &core_marshal_get_registry, @@ -956,6 +983,7 @@ static const struct pw_core_proxy_methods pw_protocol_native_core_method_marshal }; static const struct pw_protocol_native_demarshal pw_protocol_native_core_method_demarshal[PW_CORE_PROXY_METHOD_NUM] = { + { &core_demarshal_hello, 0, }, { &core_demarshal_update_types_server, 0, }, { &core_demarshal_sync, 0, }, { &core_demarshal_get_registry, 0, }, diff --git a/src/pipewire/core.c b/src/pipewire/core.c index 24b899bcb..9935b843b 100644 --- a/src/pipewire/core.c +++ b/src/pipewire/core.c @@ -99,6 +99,18 @@ static const struct pw_resource_events resource_events = { .destroy = destroy_registry_resource }; +static void core_hello(void *object) +{ + struct pw_resource *resource = object; + struct pw_core *this = resource->core; + + pw_log_debug("core %p: hello from source %p", this, resource); + resource->client->n_types = 0; + + this->info.change_mask = PW_CORE_CHANGE_MASK_ALL; + pw_core_resource_info(resource, &this->info); +} + static void core_client_update(void *object, const struct spa_dict *props) { struct pw_resource *resource = object; @@ -248,6 +260,7 @@ static void core_update_types(void *object, uint32_t first_id, const char **type static const struct pw_core_proxy_methods core_methods = { PW_VERSION_CORE_PROXY_METHODS, + .hello = core_hello, .update_types = core_update_types, .sync = core_sync, .get_registry = core_get_registry, @@ -295,8 +308,6 @@ core_bind_func(struct pw_global *global, pw_log_debug("core %p: bound to %d", this, resource->id); - this->info.change_mask = PW_CORE_CHANGE_MASK_ALL; - pw_core_resource_info(resource, &this->info); return 0; diff --git a/src/pipewire/interfaces.h b/src/pipewire/interfaces.h index 37a18d7cc..0eeb8403e 100644 --- a/src/pipewire/interfaces.h +++ b/src/pipewire/interfaces.h @@ -66,13 +66,14 @@ struct pw_link_proxy; #define PW_VERSION_CORE 0 -#define PW_CORE_PROXY_METHOD_UPDATE_TYPES 0 -#define PW_CORE_PROXY_METHOD_SYNC 1 -#define PW_CORE_PROXY_METHOD_GET_REGISTRY 2 -#define PW_CORE_PROXY_METHOD_CLIENT_UPDATE 3 -#define PW_CORE_PROXY_METHOD_PERMISSIONS 4 -#define PW_CORE_PROXY_METHOD_CREATE_OBJECT 5 -#define PW_CORE_PROXY_METHOD_NUM 6 +#define PW_CORE_PROXY_METHOD_HELLO 0 +#define PW_CORE_PROXY_METHOD_UPDATE_TYPES 1 +#define PW_CORE_PROXY_METHOD_SYNC 2 +#define PW_CORE_PROXY_METHOD_GET_REGISTRY 3 +#define PW_CORE_PROXY_METHOD_CLIENT_UPDATE 4 +#define PW_CORE_PROXY_METHOD_PERMISSIONS 5 +#define PW_CORE_PROXY_METHOD_CREATE_OBJECT 6 +#define PW_CORE_PROXY_METHOD_NUM 7 /** * Key to update default permissions of globals without specific @@ -110,6 +111,11 @@ struct pw_link_proxy; struct pw_core_proxy_methods { #define PW_VERSION_CORE_PROXY_METHODS 0 uint32_t version; + /** + * Start a conversation with the server. This will send + * the core info and server types. + */ + void (*hello) (void *object); /** * Update the type map * @@ -179,6 +185,12 @@ struct pw_core_proxy_methods { uint32_t new_id); }; +static inline void +pw_core_proxy_hello(struct pw_core_proxy *core) +{ + pw_proxy_do((struct pw_proxy*)core, struct pw_core_proxy_methods, hello); +} + static inline void pw_core_proxy_update_types(struct pw_core_proxy *core, uint32_t first_id, const char **types, uint32_t n_types) { diff --git a/src/pipewire/main-loop.c b/src/pipewire/main-loop.c index 7c5fef140..b2497d7e0 100644 --- a/src/pipewire/main-loop.c +++ b/src/pipewire/main-loop.c @@ -24,6 +24,7 @@ static void do_stop(void *data, uint64_t count) { struct pw_main_loop *this = data; + pw_log_debug("main-loop %p: do stop", this); this->running = false; } diff --git a/src/pipewire/protocol.h b/src/pipewire/protocol.h index f0b0c3880..c7e00d1e4 100644 --- a/src/pipewire/protocol.h +++ b/src/pipewire/protocol.h @@ -42,14 +42,14 @@ struct pw_protocol_client { struct pw_remote *remote; /**< the associated remote */ int (*connect) (struct pw_protocol_client *client); - int (*get_fd) (struct pw_protocol_client *client); + int (*steal_fd) (struct pw_protocol_client *client); int (*connect_fd) (struct pw_protocol_client *client, int fd); void (*disconnect) (struct pw_protocol_client *client); void (*destroy) (struct pw_protocol_client *client); }; #define pw_protocol_client_connect(c) ((c)->connect(c)) -#define pw_protocol_client_get_fd(c) ((c)->get_fd(c)) +#define pw_protocol_client_steal_fd(c) ((c)->steal_fd(c)) #define pw_protocol_client_connect_fd(c,fd) ((c)->connect_fd(c,fd)) #define pw_protocol_client_disconnect(c) ((c)->disconnect(c)) #define pw_protocol_client_destroy(c) ((c)->destroy(c)) diff --git a/src/pipewire/remote.c b/src/pipewire/remote.c index 6ab0076e0..4f72166a1 100644 --- a/src/pipewire/remote.c +++ b/src/pipewire/remote.c @@ -350,6 +350,7 @@ static int do_connect(struct pw_remote *remote) pw_core_proxy_add_listener(remote->core_proxy, &impl->core_listener, &core_proxy_events, remote); + pw_core_proxy_hello(remote->core_proxy); pw_core_proxy_client_update(remote->core_proxy, &remote->properties->dict); pw_core_proxy_sync(remote->core_proxy, 0); @@ -404,9 +405,14 @@ int pw_remote_connect_fd(struct pw_remote *remote, int fd) return do_connect(remote); } -int pw_remote_get_fd(struct pw_remote *remote) +int pw_remote_steal_fd(struct pw_remote *remote) { - return pw_protocol_client_get_fd(remote->conn); + int fd; + + fd = pw_protocol_client_steal_fd(remote->conn); + pw_remote_update_state(remote, PW_REMOTE_STATE_UNCONNECTED, NULL); + + return fd; } int pw_remote_disconnect(struct pw_remote *remote) diff --git a/src/pipewire/remote.h b/src/pipewire/remote.h index 4463ca1ba..1921b68f7 100644 --- a/src/pipewire/remote.h +++ b/src/pipewire/remote.h @@ -178,8 +178,9 @@ int pw_remote_connect(struct pw_remote *remote); * \return 0 on success, < 0 on error */ int pw_remote_connect_fd(struct pw_remote *remote, int fd); -/** Get the fd of the remote connection or < 0 on error */ -int pw_remote_get_fd(struct pw_remote *remote); +/** Steal the fd of the remote connection or < 0 on error. The remote + * will be in the unconnected state after this call. */ +int pw_remote_steal_fd(struct pw_remote *remote); /** Get the core proxy, can only be called when connected */ struct pw_core_proxy * pw_remote_get_core_proxy(struct pw_remote *remote);