diff --git a/pipewire-jack b/pipewire-jack index 1887f17cc..cc9fd857a 160000 --- a/pipewire-jack +++ b/pipewire-jack @@ -1 +1 @@ -Subproject commit 1887f17cc8e829c3bca74bc3d4e37c267654b377 +Subproject commit cc9fd857ad106dcd74327ccfedc334aadd79caaa diff --git a/pipewire-pulseaudio b/pipewire-pulseaudio index bf91b8c00..83b2aca07 160000 --- a/pipewire-pulseaudio +++ b/pipewire-pulseaudio @@ -1 +1 @@ -Subproject commit bf91b8c002b51cf9af1c7be4b0e1e50bcc83cc1a +Subproject commit 83b2aca07236cd29a2f6d138cadd324571b1c8d0 diff --git a/src/pipewire/client.c b/src/pipewire/client.c index d05632b59..ddc1e317c 100644 --- a/src/pipewire/client.c +++ b/src/pipewire/client.c @@ -176,7 +176,7 @@ static const struct pw_resource_events resource_events = { .destroy = client_unbind_func, }; -static void +static int global_bind(void *_data, struct pw_client *client, uint32_t permissions, uint32_t version, uint32_t id) { @@ -202,13 +202,11 @@ global_bind(void *_data, struct pw_client *client, uint32_t permissions, pw_client_resource_info(resource, &this->info); this->info.change_mask = 0; - return; + return 0; no_mem: pw_log_error("can't create client resource"); - pw_core_resource_error(client->core_resource, id, client->seq, - -ENOMEM, "can't create client resource: no memory"); - return; + return -ENOMEM; } static void @@ -306,7 +304,6 @@ static void global_destroy(void *object) static const struct pw_global_events global_events = { PW_VERSION_GLOBAL_EVENTS, .destroy = global_destroy, - .bind = global_bind, }; SPA_EXPORT @@ -325,6 +322,7 @@ int pw_client_register(struct pw_client *client, client->global = pw_global_new(core, PW_TYPE_INTERFACE_Client, PW_VERSION_CLIENT, properties, + global_bind, client); if (client->global == NULL) return -ENOMEM; diff --git a/src/pipewire/core.c b/src/pipewire/core.c index 1bf71475b..a61a200ab 100644 --- a/src/pipewire/core.c +++ b/src/pipewire/core.c @@ -360,7 +360,7 @@ static const struct pw_resource_events core_resource_events = { .destroy = core_unbind_func, }; -static void +static int global_bind(void *_data, struct pw_client *client, uint32_t permissions, @@ -388,11 +388,11 @@ global_bind(void *_data, pw_log_debug("core %p: bound to %d", this, resource->id); - return; + return 0; no_mem: pw_log_error("can't create core resource"); - return; + return -ENOMEM; } static void global_destroy(void *object) @@ -406,7 +406,6 @@ static void global_destroy(void *object) static const struct pw_global_events global_events = { PW_VERSION_GLOBAL_EVENTS, .destroy = global_destroy, - .bind = global_bind, }; /** Create a new core object @@ -508,6 +507,7 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop, PW_CORE_PROP_NAME, this->info.name, PW_CORE_PROP_VERSION, this->info.version, NULL), + global_bind, this); if (this->global == NULL) goto no_mem; diff --git a/src/pipewire/device.c b/src/pipewire/device.c index 09a385f77..d7c7931e2 100644 --- a/src/pipewire/device.c +++ b/src/pipewire/device.c @@ -196,12 +196,10 @@ static int device_set_param(void *object, uint32_t id, uint32_t flags, struct resource_data *data = object; struct pw_resource *resource = data->resource; struct pw_device *device = data->device; - struct pw_client *client = resource->client; int res; if ((res = spa_device_set_param(device->implementation, id, flags, param)) < 0) - pw_core_resource_error(client->core_resource, - resource->id, client->seq, res, spa_strerror(res)); + pw_resource_error(resource, res, spa_strerror(res)); return res; } @@ -211,7 +209,7 @@ static const struct pw_device_proxy_methods device_methods = { .set_param = device_set_param }; -static void +static int global_bind(void *_data, struct pw_client *client, uint32_t permissions, uint32_t version, uint32_t id) { @@ -239,13 +237,11 @@ global_bind(void *_data, struct pw_client *client, uint32_t permissions, pw_device_resource_info(resource, &this->info); this->info.change_mask = 0; - return; + return 0; no_mem: pw_log_error("can't create device resource"); - pw_core_resource_error(client->core_resource, id, - client->seq, -ENOMEM, "no memory"); - return; + return -ENOMEM; } static void global_destroy(void *object) @@ -259,7 +255,6 @@ static void global_destroy(void *object) static const struct pw_global_events global_events = { PW_VERSION_GLOBAL_EVENTS, .destroy = global_destroy, - .bind = global_bind, }; SPA_EXPORT @@ -286,6 +281,7 @@ int pw_device_register(struct pw_device *device, device->global = pw_global_new(core, PW_TYPE_INTERFACE_Device, PW_VERSION_DEVICE, properties, + global_bind, device); if (device->global == NULL) return -ENOMEM; diff --git a/src/pipewire/factory.c b/src/pipewire/factory.c index 9d124197d..9fb6f189a 100644 --- a/src/pipewire/factory.c +++ b/src/pipewire/factory.c @@ -94,7 +94,7 @@ static const struct pw_resource_events resource_events = { .destroy = factory_unbind_func, }; -static void +static int global_bind(void *_data, struct pw_client *client, uint32_t permissions, uint32_t version, uint32_t id) { @@ -118,13 +118,11 @@ global_bind(void *_data, struct pw_client *client, uint32_t permissions, pw_factory_resource_info(resource, &this->info); this->info.change_mask = 0; - return; + return 0; no_mem: pw_log_error("can't create factory resource"); - pw_core_resource_error(client->core_resource, id, - client->seq, -ENOMEM, "no memory"); - return; + return -ENOMEM; } static void global_destroy(void *object) @@ -138,7 +136,6 @@ static void global_destroy(void *object) static const struct pw_global_events global_events = { PW_VERSION_GLOBAL_EVENTS, .destroy = global_destroy, - .bind = global_bind, }; SPA_EXPORT @@ -165,6 +162,7 @@ int pw_factory_register(struct pw_factory *factory, factory->global = pw_global_new(core, PW_TYPE_INTERFACE_Factory, PW_VERSION_FACTORY, properties, + global_bind, factory); if (factory->global == NULL) return -ENOMEM; diff --git a/src/pipewire/global.c b/src/pipewire/global.c index efd4c989f..be196b267 100644 --- a/src/pipewire/global.c +++ b/src/pipewire/global.c @@ -71,6 +71,7 @@ pw_global_new(struct pw_core *core, uint32_t type, uint32_t version, struct pw_properties *properties, + pw_global_bind_func_t func, void *object) { struct impl *impl; @@ -85,6 +86,7 @@ pw_global_new(struct pw_core *core, this->core = core; this->type = type; this->version = version; + this->func = func; this->object = object; this->properties = properties; this->id = pw_map_insert_new(&core->globals, this); @@ -259,15 +261,24 @@ pw_global_bind(struct pw_global *global, struct pw_client *client, uint32_t perm if (global->version < version) goto wrong_version; - pw_global_emit_bind(global, client, permissions, version, id); + if ((res = global->func(global->object, client, permissions, version, id)) < 0) + goto error; - return 0; + return res; wrong_version: - res = -EINVAL; - pw_core_resource_errorf(client->core_resource, id, 0, + res = -EPROTO; + pw_core_resource_errorf(client->core_resource, id, client->seq, res, "id %d: interface version %d < %d", id, global->version, version); + goto exit; + error: + pw_core_resource_errorf(client->core_resource, id, client->seq, + res, "can't bind global %u/%u: %d (%s)", id, version, res, spa_strerror(res)); + exit: + pw_log_error("can't bind global %u/%u: %d (%s)", id, version, res, spa_strerror(res)); + pw_map_insert_at(&client->objects, id, NULL); + pw_core_resource_remove_id(client->core_resource, id); return res; } diff --git a/src/pipewire/global.h b/src/pipewire/global.h index 3a1acddc5..6850a0543 100644 --- a/src/pipewire/global.h +++ b/src/pipewire/global.h @@ -60,6 +60,12 @@ struct pw_global; #include #include +typedef int (*pw_global_bind_func_t) (void *object, + struct pw_client *client, /**< client that binds */ + uint32_t permissions, /**< permissions for the bind */ + uint32_t version, /**< client interface version */ + uint32_t id /**< client proxy id */); + /** Global events, use \ref pw_global_add_listener */ struct pw_global_events { #define PW_VERSION_GLOBAL_EVENTS 0 @@ -70,13 +76,6 @@ struct pw_global_events { void (*destroy) (void *data); /** The global is freed */ void (*free) (void *data); - - /* bind the global */ - void (*bind) (void *data, - struct pw_client *client, /**< client that binds */ - uint32_t permissions, /**< permissions for the bind */ - uint32_t version, /**< client interface version */ - uint32_t id /**< client proxy id */); }; /** Create a new global object */ @@ -85,6 +84,7 @@ pw_global_new(struct pw_core *core, /**< the core */ uint32_t type, /**< the interface type of the global */ uint32_t version, /**< the interface version of the global */ struct pw_properties *properties, /**< extra properties */ + pw_global_bind_func_t func, /**< function to bind */ void *object /**< global object */); /** Register a global object to the core registry */ diff --git a/src/pipewire/link.c b/src/pipewire/link.c index 1966ce36a..6ada6067c 100644 --- a/src/pipewire/link.c +++ b/src/pipewire/link.c @@ -1067,7 +1067,7 @@ static const struct pw_resource_events resource_events = { .destroy = link_unbind_func, }; -static void +static int global_bind(void *_data, struct pw_client *client, uint32_t permissions, uint32_t version, uint32_t id) { @@ -1091,12 +1091,11 @@ global_bind(void *_data, struct pw_client *client, uint32_t permissions, pw_link_resource_info(resource, &this->info); this->info.change_mask = 0; - return; + return 0; no_mem: pw_log_error("can't create link resource"); - pw_core_resource_error(client->core_resource, id, client->seq, -ENOMEM, "no memory"); - return; + return -ENOMEM; } static const struct pw_port_events input_port_events = { @@ -1114,7 +1113,8 @@ static void input_node_result(void *data, int seq, int res, const void *result) struct impl *impl = data; struct pw_node *node = impl->this.input->node; pw_log_debug("link %p: input node %p result %d %d", impl, node, seq, res); - pw_work_queue_complete(impl->work, node, SPA_RESULT_ASYNC_SEQ(seq), res); + if (SPA_RESULT_IS_ASYNC(seq)) + pw_work_queue_complete(impl->work, node, SPA_RESULT_ASYNC_SEQ(seq), res); } static void output_node_result(void *data, int seq, int res, const void *result) @@ -1122,7 +1122,8 @@ static void output_node_result(void *data, int seq, int res, const void *result) struct impl *impl = data; struct pw_node *node = impl->this.output->node; pw_log_debug("link %p: output node %p result %d %d", impl, node, seq, res); - pw_work_queue_complete(impl->work, node, SPA_RESULT_ASYNC_SEQ(seq), res); + if (SPA_RESULT_IS_ASYNC(seq)) + pw_work_queue_complete(impl->work, node, SPA_RESULT_ASYNC_SEQ(seq), res); } static const struct pw_node_events input_node_events = { @@ -1362,7 +1363,6 @@ static void global_destroy(void *object) static const struct pw_global_events global_events = { PW_VERSION_GLOBAL_EVENTS, .destroy = global_destroy, - .bind = global_bind, }; SPA_EXPORT @@ -1396,6 +1396,7 @@ int pw_link_register(struct pw_link *link, link->global = pw_global_new(core, PW_TYPE_INTERFACE_Link, PW_VERSION_LINK, properties, + global_bind, link); if (link->global == NULL) return -ENOMEM; diff --git a/src/pipewire/module.c b/src/pipewire/module.c index 691b39263..023dd7ea4 100644 --- a/src/pipewire/module.c +++ b/src/pipewire/module.c @@ -110,7 +110,7 @@ static const struct pw_resource_events resource_events = { .destroy = module_unbind_func, }; -static void +static int global_bind(void *_data, struct pw_client *client, uint32_t permissions, uint32_t version, uint32_t id) { @@ -134,13 +134,11 @@ global_bind(void *_data, struct pw_client *client, uint32_t permissions, pw_module_resource_info(resource, &this->info); this->info.change_mask = 0; - return; + return 0; no_mem: pw_log_error("can't create module resource"); - pw_core_resource_error(client->core_resource, id, - client->seq, -ENOMEM, "no memory"); - return; + return -ENOMEM; } static void global_destroy(void *object) @@ -154,7 +152,6 @@ static void global_destroy(void *object) static const struct pw_global_events global_events = { PW_VERSION_GLOBAL_EVENTS, .destroy = global_destroy, - .bind = global_bind, }; /** Load a module @@ -247,6 +244,7 @@ pw_module_load(struct pw_core *core, pw_properties_new( PW_MODULE_PROP_NAME, name, NULL), + global_bind, this); if (this->global == NULL) diff --git a/src/pipewire/node.c b/src/pipewire/node.c index 156943b59..b312d3688 100644 --- a/src/pipewire/node.c +++ b/src/pipewire/node.c @@ -286,14 +286,12 @@ static int node_set_param(void *object, uint32_t id, uint32_t flags, struct pw_resource *resource = object; struct resource_data *data = pw_resource_get_user_data(resource); struct pw_node *node = data->node; - struct pw_client *client = resource->client; int res; if ((res = spa_node_set_param(node->node, id, flags, param)) < 0) { pw_log_error("resource %p: %d error %d (%s)", resource, resource->id, res, spa_strerror(res)); - pw_core_resource_error(client->core_resource, - resource->id, client->seq, res, spa_strerror(res)); + pw_resource_error(resource, res, spa_strerror(res)); } return 0; } @@ -322,7 +320,7 @@ static const struct pw_node_proxy_methods node_methods = { .send_command = node_send_command }; -static void +static int global_bind(void *_data, struct pw_client *client, uint32_t permissions, uint32_t version, uint32_t id) { @@ -349,13 +347,11 @@ global_bind(void *_data, struct pw_client *client, uint32_t permissions, this->info.change_mask = ~0; pw_node_resource_info(resource, &this->info); this->info.change_mask = 0; - return; + return 0; no_mem: pw_log_error("can't create node resource"); - pw_core_resource_error(client->core_resource, id, - client->seq, -ENOMEM, "no memory"); - return; + return -ENOMEM; } static void global_destroy(void *data) @@ -383,7 +379,6 @@ static const struct pw_global_events global_events = { PW_VERSION_GLOBAL_EVENTS, .registering = global_registering, .destroy = global_destroy, - .bind = global_bind, }; SPA_EXPORT @@ -417,6 +412,7 @@ int pw_node_register(struct pw_node *this, this->global = pw_global_new(core, PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, properties, + global_bind, this); if (this->global == NULL) return -ENOMEM; @@ -860,7 +856,10 @@ static int node_result(void *data, int seq, int res, const void *result) pw_log_trace("node %p: result seq:%d res:%d", node, seq, res); impl->last_error = res; spa_pending_queue_complete(&impl->pending, seq, res, result); - pw_work_queue_complete(impl->work, &impl->this, SPA_RESULT_ASYNC_SEQ(seq), res); + + if (SPA_RESULT_IS_ASYNC(seq)) + pw_work_queue_complete(impl->work, &impl->this, SPA_RESULT_ASYNC_SEQ(seq), res); + pw_node_emit_result(node, seq, res, result); return 0; diff --git a/src/pipewire/port.c b/src/pipewire/port.c index 2c3fad38a..84853547c 100644 --- a/src/pipewire/port.c +++ b/src/pipewire/port.c @@ -494,7 +494,7 @@ static const struct pw_port_proxy_methods port_methods = { .enum_params = port_enum_params }; -static void +static int global_bind(void *_data, struct pw_client *client, uint32_t permissions, uint32_t version, uint32_t id) { @@ -521,12 +521,11 @@ global_bind(void *_data, struct pw_client *client, uint32_t permissions, this->info.change_mask = ~0; pw_port_resource_info(resource, &this->info); this->info.change_mask = 0; - return; + return 0; no_mem: pw_log_error("can't create port resource"); - pw_core_resource_error(client->core_resource, id, client->seq, -ENOMEM, "no memory"); - return; + return -ENOMEM; } static void global_destroy(void *object) @@ -540,7 +539,6 @@ static void global_destroy(void *object) static const struct pw_global_events global_events = { PW_VERSION_GLOBAL_EVENTS, .destroy = global_destroy, - .bind = global_bind, }; int pw_port_register(struct pw_port *port, @@ -554,6 +552,7 @@ int pw_port_register(struct pw_port *port, port->global = pw_global_new(core, PW_TYPE_INTERFACE_Port, PW_VERSION_PORT, properties, + global_bind, port); if (port->global == NULL) return -ENOMEM; diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 4a57d8842..176f28c22 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -131,7 +131,6 @@ struct pw_client { #define pw_global_emit_registering(g) pw_global_emit(g, registering, 0) #define pw_global_emit_destroy(g) pw_global_emit(g, destroy, 0) #define pw_global_emit_free(g) pw_global_emit(g, free, 0) -#define pw_global_emit_bind(g,...) pw_global_emit(g, bind, 0, __VA_ARGS__) struct pw_global { struct pw_core *core; /**< the core */ @@ -149,6 +148,7 @@ struct pw_global { uint32_t type; /**< type of interface */ uint32_t version; /**< version of interface */ + pw_global_bind_func_t func; /**< bind function */ void *object; /**< object associated with the interface */ struct spa_list resource_list; /**< The list of resources of this global */