global: pass bind function to _new

Make the bind function a callback instead of an event. We can then
get a return value and use that to clean up the pending proxy and
generate an error.
This commit is contained in:
Wim Taymans 2019-02-25 17:14:10 +01:00
parent f2ff6f393b
commit 245a0d5634
13 changed files with 67 additions and 67 deletions

@ -1 +1 @@
Subproject commit 1887f17cc8e829c3bca74bc3d4e37c267654b377 Subproject commit cc9fd857ad106dcd74327ccfedc334aadd79caaa

@ -1 +1 @@
Subproject commit bf91b8c002b51cf9af1c7be4b0e1e50bcc83cc1a Subproject commit 83b2aca07236cd29a2f6d138cadd324571b1c8d0

View file

@ -176,7 +176,7 @@ static const struct pw_resource_events resource_events = {
.destroy = client_unbind_func, .destroy = client_unbind_func,
}; };
static void static int
global_bind(void *_data, struct pw_client *client, uint32_t permissions, global_bind(void *_data, struct pw_client *client, uint32_t permissions,
uint32_t version, uint32_t id) 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); pw_client_resource_info(resource, &this->info);
this->info.change_mask = 0; this->info.change_mask = 0;
return; return 0;
no_mem: no_mem:
pw_log_error("can't create client resource"); pw_log_error("can't create client resource");
pw_core_resource_error(client->core_resource, id, client->seq, return -ENOMEM;
-ENOMEM, "can't create client resource: no memory");
return;
} }
static void static void
@ -306,7 +304,6 @@ static void global_destroy(void *object)
static const struct pw_global_events global_events = { static const struct pw_global_events global_events = {
PW_VERSION_GLOBAL_EVENTS, PW_VERSION_GLOBAL_EVENTS,
.destroy = global_destroy, .destroy = global_destroy,
.bind = global_bind,
}; };
SPA_EXPORT SPA_EXPORT
@ -325,6 +322,7 @@ int pw_client_register(struct pw_client *client,
client->global = pw_global_new(core, client->global = pw_global_new(core,
PW_TYPE_INTERFACE_Client, PW_VERSION_CLIENT, PW_TYPE_INTERFACE_Client, PW_VERSION_CLIENT,
properties, properties,
global_bind,
client); client);
if (client->global == NULL) if (client->global == NULL)
return -ENOMEM; return -ENOMEM;

View file

@ -360,7 +360,7 @@ static const struct pw_resource_events core_resource_events = {
.destroy = core_unbind_func, .destroy = core_unbind_func,
}; };
static void static int
global_bind(void *_data, global_bind(void *_data,
struct pw_client *client, struct pw_client *client,
uint32_t permissions, uint32_t permissions,
@ -388,11 +388,11 @@ global_bind(void *_data,
pw_log_debug("core %p: bound to %d", this, resource->id); pw_log_debug("core %p: bound to %d", this, resource->id);
return; return 0;
no_mem: no_mem:
pw_log_error("can't create core resource"); pw_log_error("can't create core resource");
return; return -ENOMEM;
} }
static void global_destroy(void *object) static void global_destroy(void *object)
@ -406,7 +406,6 @@ static void global_destroy(void *object)
static const struct pw_global_events global_events = { static const struct pw_global_events global_events = {
PW_VERSION_GLOBAL_EVENTS, PW_VERSION_GLOBAL_EVENTS,
.destroy = global_destroy, .destroy = global_destroy,
.bind = global_bind,
}; };
/** Create a new core object /** 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_NAME, this->info.name,
PW_CORE_PROP_VERSION, this->info.version, PW_CORE_PROP_VERSION, this->info.version,
NULL), NULL),
global_bind,
this); this);
if (this->global == NULL) if (this->global == NULL)
goto no_mem; goto no_mem;

View file

@ -196,12 +196,10 @@ static int device_set_param(void *object, uint32_t id, uint32_t flags,
struct resource_data *data = object; struct resource_data *data = object;
struct pw_resource *resource = data->resource; struct pw_resource *resource = data->resource;
struct pw_device *device = data->device; struct pw_device *device = data->device;
struct pw_client *client = resource->client;
int res; int res;
if ((res = spa_device_set_param(device->implementation, id, flags, param)) < 0) if ((res = spa_device_set_param(device->implementation, id, flags, param)) < 0)
pw_core_resource_error(client->core_resource, pw_resource_error(resource, res, spa_strerror(res));
resource->id, client->seq, res, spa_strerror(res));
return res; return res;
} }
@ -211,7 +209,7 @@ static const struct pw_device_proxy_methods device_methods = {
.set_param = device_set_param .set_param = device_set_param
}; };
static void static int
global_bind(void *_data, struct pw_client *client, uint32_t permissions, global_bind(void *_data, struct pw_client *client, uint32_t permissions,
uint32_t version, uint32_t id) 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); pw_device_resource_info(resource, &this->info);
this->info.change_mask = 0; this->info.change_mask = 0;
return; return 0;
no_mem: no_mem:
pw_log_error("can't create device resource"); pw_log_error("can't create device resource");
pw_core_resource_error(client->core_resource, id, return -ENOMEM;
client->seq, -ENOMEM, "no memory");
return;
} }
static void global_destroy(void *object) static void global_destroy(void *object)
@ -259,7 +255,6 @@ static void global_destroy(void *object)
static const struct pw_global_events global_events = { static const struct pw_global_events global_events = {
PW_VERSION_GLOBAL_EVENTS, PW_VERSION_GLOBAL_EVENTS,
.destroy = global_destroy, .destroy = global_destroy,
.bind = global_bind,
}; };
SPA_EXPORT SPA_EXPORT
@ -286,6 +281,7 @@ int pw_device_register(struct pw_device *device,
device->global = pw_global_new(core, device->global = pw_global_new(core,
PW_TYPE_INTERFACE_Device, PW_VERSION_DEVICE, PW_TYPE_INTERFACE_Device, PW_VERSION_DEVICE,
properties, properties,
global_bind,
device); device);
if (device->global == NULL) if (device->global == NULL)
return -ENOMEM; return -ENOMEM;

View file

@ -94,7 +94,7 @@ static const struct pw_resource_events resource_events = {
.destroy = factory_unbind_func, .destroy = factory_unbind_func,
}; };
static void static int
global_bind(void *_data, struct pw_client *client, uint32_t permissions, global_bind(void *_data, struct pw_client *client, uint32_t permissions,
uint32_t version, uint32_t id) 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); pw_factory_resource_info(resource, &this->info);
this->info.change_mask = 0; this->info.change_mask = 0;
return; return 0;
no_mem: no_mem:
pw_log_error("can't create factory resource"); pw_log_error("can't create factory resource");
pw_core_resource_error(client->core_resource, id, return -ENOMEM;
client->seq, -ENOMEM, "no memory");
return;
} }
static void global_destroy(void *object) static void global_destroy(void *object)
@ -138,7 +136,6 @@ static void global_destroy(void *object)
static const struct pw_global_events global_events = { static const struct pw_global_events global_events = {
PW_VERSION_GLOBAL_EVENTS, PW_VERSION_GLOBAL_EVENTS,
.destroy = global_destroy, .destroy = global_destroy,
.bind = global_bind,
}; };
SPA_EXPORT SPA_EXPORT
@ -165,6 +162,7 @@ int pw_factory_register(struct pw_factory *factory,
factory->global = pw_global_new(core, factory->global = pw_global_new(core,
PW_TYPE_INTERFACE_Factory, PW_VERSION_FACTORY, PW_TYPE_INTERFACE_Factory, PW_VERSION_FACTORY,
properties, properties,
global_bind,
factory); factory);
if (factory->global == NULL) if (factory->global == NULL)
return -ENOMEM; return -ENOMEM;

View file

@ -71,6 +71,7 @@ pw_global_new(struct pw_core *core,
uint32_t type, uint32_t type,
uint32_t version, uint32_t version,
struct pw_properties *properties, struct pw_properties *properties,
pw_global_bind_func_t func,
void *object) void *object)
{ {
struct impl *impl; struct impl *impl;
@ -85,6 +86,7 @@ pw_global_new(struct pw_core *core,
this->core = core; this->core = core;
this->type = type; this->type = type;
this->version = version; this->version = version;
this->func = func;
this->object = object; this->object = object;
this->properties = properties; this->properties = properties;
this->id = pw_map_insert_new(&core->globals, this); 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) if (global->version < version)
goto wrong_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: wrong_version:
res = -EINVAL; res = -EPROTO;
pw_core_resource_errorf(client->core_resource, id, 0, pw_core_resource_errorf(client->core_resource, id, client->seq,
res, "id %d: interface version %d < %d", res, "id %d: interface version %d < %d",
id, global->version, version); 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; return res;
} }

View file

@ -60,6 +60,12 @@ struct pw_global;
#include <pipewire/client.h> #include <pipewire/client.h>
#include <pipewire/properties.h> #include <pipewire/properties.h>
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 */ /** Global events, use \ref pw_global_add_listener */
struct pw_global_events { struct pw_global_events {
#define PW_VERSION_GLOBAL_EVENTS 0 #define PW_VERSION_GLOBAL_EVENTS 0
@ -70,13 +76,6 @@ struct pw_global_events {
void (*destroy) (void *data); void (*destroy) (void *data);
/** The global is freed */ /** The global is freed */
void (*free) (void *data); 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 */ /** 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 type, /**< the interface type of the global */
uint32_t version, /**< the interface version of the global */ uint32_t version, /**< the interface version of the global */
struct pw_properties *properties, /**< extra properties */ struct pw_properties *properties, /**< extra properties */
pw_global_bind_func_t func, /**< function to bind */
void *object /**< global object */); void *object /**< global object */);
/** Register a global object to the core registry */ /** Register a global object to the core registry */

View file

@ -1067,7 +1067,7 @@ static const struct pw_resource_events resource_events = {
.destroy = link_unbind_func, .destroy = link_unbind_func,
}; };
static void static int
global_bind(void *_data, struct pw_client *client, uint32_t permissions, global_bind(void *_data, struct pw_client *client, uint32_t permissions,
uint32_t version, uint32_t id) 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); pw_link_resource_info(resource, &this->info);
this->info.change_mask = 0; this->info.change_mask = 0;
return; return 0;
no_mem: no_mem:
pw_log_error("can't create link resource"); pw_log_error("can't create link resource");
pw_core_resource_error(client->core_resource, id, client->seq, -ENOMEM, "no memory"); return -ENOMEM;
return;
} }
static const struct pw_port_events input_port_events = { 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 impl *impl = data;
struct pw_node *node = impl->this.input->node; struct pw_node *node = impl->this.input->node;
pw_log_debug("link %p: input node %p result %d %d", impl, node, seq, res); 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) 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 impl *impl = data;
struct pw_node *node = impl->this.output->node; struct pw_node *node = impl->this.output->node;
pw_log_debug("link %p: output node %p result %d %d", impl, node, seq, res); 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 = { 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 = { static const struct pw_global_events global_events = {
PW_VERSION_GLOBAL_EVENTS, PW_VERSION_GLOBAL_EVENTS,
.destroy = global_destroy, .destroy = global_destroy,
.bind = global_bind,
}; };
SPA_EXPORT SPA_EXPORT
@ -1396,6 +1396,7 @@ int pw_link_register(struct pw_link *link,
link->global = pw_global_new(core, link->global = pw_global_new(core,
PW_TYPE_INTERFACE_Link, PW_VERSION_LINK, PW_TYPE_INTERFACE_Link, PW_VERSION_LINK,
properties, properties,
global_bind,
link); link);
if (link->global == NULL) if (link->global == NULL)
return -ENOMEM; return -ENOMEM;

View file

@ -110,7 +110,7 @@ static const struct pw_resource_events resource_events = {
.destroy = module_unbind_func, .destroy = module_unbind_func,
}; };
static void static int
global_bind(void *_data, struct pw_client *client, uint32_t permissions, global_bind(void *_data, struct pw_client *client, uint32_t permissions,
uint32_t version, uint32_t id) 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); pw_module_resource_info(resource, &this->info);
this->info.change_mask = 0; this->info.change_mask = 0;
return; return 0;
no_mem: no_mem:
pw_log_error("can't create module resource"); pw_log_error("can't create module resource");
pw_core_resource_error(client->core_resource, id, return -ENOMEM;
client->seq, -ENOMEM, "no memory");
return;
} }
static void global_destroy(void *object) static void global_destroy(void *object)
@ -154,7 +152,6 @@ static void global_destroy(void *object)
static const struct pw_global_events global_events = { static const struct pw_global_events global_events = {
PW_VERSION_GLOBAL_EVENTS, PW_VERSION_GLOBAL_EVENTS,
.destroy = global_destroy, .destroy = global_destroy,
.bind = global_bind,
}; };
/** Load a module /** Load a module
@ -247,6 +244,7 @@ pw_module_load(struct pw_core *core,
pw_properties_new( pw_properties_new(
PW_MODULE_PROP_NAME, name, PW_MODULE_PROP_NAME, name,
NULL), NULL),
global_bind,
this); this);
if (this->global == NULL) if (this->global == NULL)

View file

@ -286,14 +286,12 @@ static int node_set_param(void *object, uint32_t id, uint32_t flags,
struct pw_resource *resource = object; struct pw_resource *resource = object;
struct resource_data *data = pw_resource_get_user_data(resource); struct resource_data *data = pw_resource_get_user_data(resource);
struct pw_node *node = data->node; struct pw_node *node = data->node;
struct pw_client *client = resource->client;
int res; int res;
if ((res = spa_node_set_param(node->node, id, flags, param)) < 0) { if ((res = spa_node_set_param(node->node, id, flags, param)) < 0) {
pw_log_error("resource %p: %d error %d (%s)", resource, pw_log_error("resource %p: %d error %d (%s)", resource,
resource->id, res, spa_strerror(res)); resource->id, res, spa_strerror(res));
pw_core_resource_error(client->core_resource, pw_resource_error(resource, res, spa_strerror(res));
resource->id, client->seq, res, spa_strerror(res));
} }
return 0; return 0;
} }
@ -322,7 +320,7 @@ static const struct pw_node_proxy_methods node_methods = {
.send_command = node_send_command .send_command = node_send_command
}; };
static void static int
global_bind(void *_data, struct pw_client *client, uint32_t permissions, global_bind(void *_data, struct pw_client *client, uint32_t permissions,
uint32_t version, uint32_t id) 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; this->info.change_mask = ~0;
pw_node_resource_info(resource, &this->info); pw_node_resource_info(resource, &this->info);
this->info.change_mask = 0; this->info.change_mask = 0;
return; return 0;
no_mem: no_mem:
pw_log_error("can't create node resource"); pw_log_error("can't create node resource");
pw_core_resource_error(client->core_resource, id, return -ENOMEM;
client->seq, -ENOMEM, "no memory");
return;
} }
static void global_destroy(void *data) static void global_destroy(void *data)
@ -383,7 +379,6 @@ static const struct pw_global_events global_events = {
PW_VERSION_GLOBAL_EVENTS, PW_VERSION_GLOBAL_EVENTS,
.registering = global_registering, .registering = global_registering,
.destroy = global_destroy, .destroy = global_destroy,
.bind = global_bind,
}; };
SPA_EXPORT SPA_EXPORT
@ -417,6 +412,7 @@ int pw_node_register(struct pw_node *this,
this->global = pw_global_new(core, this->global = pw_global_new(core,
PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, PW_TYPE_INTERFACE_Node, PW_VERSION_NODE,
properties, properties,
global_bind,
this); this);
if (this->global == NULL) if (this->global == NULL)
return -ENOMEM; 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); pw_log_trace("node %p: result seq:%d res:%d", node, seq, res);
impl->last_error = res; impl->last_error = res;
spa_pending_queue_complete(&impl->pending, seq, res, result); 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); pw_node_emit_result(node, seq, res, result);
return 0; return 0;

View file

@ -494,7 +494,7 @@ static const struct pw_port_proxy_methods port_methods = {
.enum_params = port_enum_params .enum_params = port_enum_params
}; };
static void static int
global_bind(void *_data, struct pw_client *client, uint32_t permissions, global_bind(void *_data, struct pw_client *client, uint32_t permissions,
uint32_t version, uint32_t id) 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; this->info.change_mask = ~0;
pw_port_resource_info(resource, &this->info); pw_port_resource_info(resource, &this->info);
this->info.change_mask = 0; this->info.change_mask = 0;
return; return 0;
no_mem: no_mem:
pw_log_error("can't create port resource"); pw_log_error("can't create port resource");
pw_core_resource_error(client->core_resource, id, client->seq, -ENOMEM, "no memory"); return -ENOMEM;
return;
} }
static void global_destroy(void *object) static void global_destroy(void *object)
@ -540,7 +539,6 @@ static void global_destroy(void *object)
static const struct pw_global_events global_events = { static const struct pw_global_events global_events = {
PW_VERSION_GLOBAL_EVENTS, PW_VERSION_GLOBAL_EVENTS,
.destroy = global_destroy, .destroy = global_destroy,
.bind = global_bind,
}; };
int pw_port_register(struct pw_port *port, 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, port->global = pw_global_new(core,
PW_TYPE_INTERFACE_Port, PW_VERSION_PORT, PW_TYPE_INTERFACE_Port, PW_VERSION_PORT,
properties, properties,
global_bind,
port); port);
if (port->global == NULL) if (port->global == NULL)
return -ENOMEM; return -ENOMEM;

View file

@ -131,7 +131,6 @@ struct pw_client {
#define pw_global_emit_registering(g) pw_global_emit(g, registering, 0) #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_destroy(g) pw_global_emit(g, destroy, 0)
#define pw_global_emit_free(g) pw_global_emit(g, free, 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_global {
struct pw_core *core; /**< the core */ struct pw_core *core; /**< the core */
@ -149,6 +148,7 @@ struct pw_global {
uint32_t type; /**< type of interface */ uint32_t type; /**< type of interface */
uint32_t version; /**< version of interface */ uint32_t version; /**< version of interface */
pw_global_bind_func_t func; /**< bind function */
void *object; /**< object associated with the interface */ void *object; /**< object associated with the interface */
struct spa_list resource_list; /**< The list of resources of this global */ struct spa_list resource_list; /**< The list of resources of this global */