diff --git a/src/examples/export-spa.c b/src/examples/export-spa.c index 8ab7d453f..e08e95682 100644 --- a/src/examples/export-spa.c +++ b/src/examples/export-spa.c @@ -48,10 +48,11 @@ struct data { static int make_node(struct data *data) { - struct pw_node_factory *factory; + struct pw_factory *factory; + struct pw_type *t = data->t; struct pw_properties *props; - factory = pw_core_find_node_factory(data->core, "spa-node-factory"); + factory = pw_core_find_factory(data->core, "spa-node-factory"); if (factory == NULL) return -1; @@ -63,7 +64,11 @@ static int make_node(struct data *data) pw_properties_set(props, "pipewire.target.node", data->path); } - data->node = pw_node_factory_create_node(factory, NULL, data->factory, props); + data->node = pw_factory_create_object(factory, + NULL, + t->node, + PW_VERSION_NODE, + props, SPA_ID_INVALID); pw_remote_export(data->remote, data->node); diff --git a/src/examples/local-v4l2.c b/src/examples/local-v4l2.c index b29f0c065..cd4c47e84 100644 --- a/src/examples/local-v4l2.c +++ b/src/examples/local-v4l2.c @@ -447,7 +447,7 @@ static const struct spa_node impl_node = { static void make_nodes(struct data *data) { - struct pw_node_factory *factory; + struct pw_factory *factory; struct pw_properties *props; data->node = pw_node_new(data->core, NULL, NULL, "SDL-sink", NULL, 0); @@ -456,10 +456,15 @@ static void make_nodes(struct data *data) pw_node_register(data->node); - factory = pw_core_find_node_factory(data->core, "spa-node-factory"); + factory = pw_core_find_factory(data->core, "spa-node-factory"); props = pw_properties_new("spa.library.name", "v4l2/libspa-v4l2", "spa.factory.name", "v4l2-source", NULL); - data->v4l2 = pw_node_factory_create_node(factory, NULL, "v4l2-source", props); + data->v4l2 = pw_factory_create_object(factory, + NULL, + data->t->node, + PW_VERSION_NODE, + props, + SPA_ID_INVALID); data->link = pw_link_new(data->core, NULL, diff --git a/src/modules/module-client-node.c b/src/modules/module-client-node.c index 0306d406b..5522f16dc 100644 --- a/src/modules/module-client-node.c +++ b/src/modules/module-client-node.c @@ -34,36 +34,54 @@ struct pw_protocol *pw_protocol_native_ext_client_node_init(struct pw_core *core); struct factory_data { - struct pw_node_factory *this; + struct pw_factory *this; struct pw_properties *properties; struct spa_hook module_listener; + uint32_t type_client_node; }; -static struct pw_node *create_node(void *_data, - struct pw_resource *resource, - const char *name, - struct pw_properties *properties) +static void *create_object(void *_data, + struct pw_resource *resource, + uint32_t type, + uint32_t version, + struct pw_properties *properties, + uint32_t new_id) { struct pw_client_node *node; + struct pw_resource *node_resource; - node = pw_client_node_new(resource, name, properties); + if (resource == NULL) + goto no_resource; + + node_resource = pw_resource_new(pw_resource_get_client(resource), + new_id, PW_PERM_RWX, type, version, 0); + if (node_resource == NULL) + goto no_mem; + + node = pw_client_node_new(node_resource, properties); if (node == NULL) goto no_mem; - return node->node; + return node; + no_resource: + pw_log_error("client-node needs a resource"); + pw_resource_error(resource, SPA_RESULT_INVALID_ARGUMENTS, "no resource"); + goto done; no_mem: pw_log_error("can't create node"); pw_resource_error(resource, SPA_RESULT_NO_MEMORY, "no memory"); + goto done; + done: if (properties) pw_properties_free(properties); return NULL; } -static const struct pw_node_factory_implementation impl_factory = { - PW_VERSION_NODE_FACRORY_IMPLEMENTATION, - .create_node = create_node, +static const struct pw_factory_implementation impl_factory = { + PW_VERSION_FACTORY_IMPLEMENTATION, + .create_object = create_object, }; static void module_destroy(void *data) @@ -75,7 +93,7 @@ static void module_destroy(void *data) if (d->properties) pw_properties_free(d->properties); - pw_node_factory_destroy(d->this); + pw_factory_destroy(d->this); } const struct pw_module_events module_events = { @@ -86,26 +104,36 @@ const struct pw_module_events module_events = { static bool module_init(struct pw_module *module, struct pw_properties *properties) { struct pw_core *core = pw_module_get_core(module); - struct pw_node_factory *factory; + struct pw_type *t = pw_core_get_type(core); + struct pw_factory *factory; struct factory_data *data; + uint32_t type_client_node; - factory = pw_node_factory_new(core, "client-node", sizeof(*data)); + type_client_node = spa_type_map_get_id(t->map, PW_TYPE_INTERFACE__ClientNode); + + factory = pw_factory_new(core, + "client-node", + type_client_node, + PW_VERSION_CLIENT_NODE, + NULL, + sizeof(*data)); if (factory == NULL) return false; - data = pw_node_factory_get_user_data(factory); + data = pw_factory_get_user_data(factory); data->this = factory; data->properties = properties; + data->type_client_node = type_client_node; pw_log_debug("module %p: new", module); - pw_node_factory_set_implementation(factory, - &impl_factory, - data); + pw_factory_set_implementation(factory, + &impl_factory, + data); pw_protocol_native_ext_client_node_init(core); - pw_node_factory_export(factory, NULL, pw_module_get_global(module)); + pw_factory_register(factory, NULL, pw_module_get_global(module)); pw_module_add_listener(module, &data->module_listener, &module_events, data); diff --git a/src/modules/module-client-node/client-node.c b/src/modules/module-client-node/client-node.c index ce4432984..96788d8ec 100644 --- a/src/modules/module-client-node/client-node.c +++ b/src/modules/module-client-node/client-node.c @@ -1133,7 +1133,6 @@ static const struct pw_resource_events resource_events = { * \memberof pw_client_node */ struct pw_client_node *pw_client_node_new(struct pw_resource *resource, - const char *name, struct pw_properties *properties) { struct impl *impl; @@ -1142,7 +1141,7 @@ struct pw_client_node *pw_client_node_new(struct pw_resource *resource, struct pw_core *core = pw_client_get_core(client); const struct spa_support *support; uint32_t n_support; - + const char *name = "client-node"; impl = calloc(1, sizeof(struct impl)); if (impl == NULL) diff --git a/src/modules/module-client-node/client-node.h b/src/modules/module-client-node/client-node.h index ee372456e..e51f475e1 100644 --- a/src/modules/module-client-node/client-node.h +++ b/src/modules/module-client-node/client-node.h @@ -39,7 +39,6 @@ struct pw_client_node { struct pw_client_node * pw_client_node_new(struct pw_resource *resource, - const char *name, struct pw_properties *properties); void diff --git a/src/modules/module-flatpak.c b/src/modules/module-flatpak.c index 5e80a62db..d04c21373 100644 --- a/src/modules/module-flatpak.c +++ b/src/modules/module-flatpak.c @@ -77,7 +77,6 @@ struct async_pending { bool handled; char *handle; char *factory_name; - char *name; uint32_t type; uint32_t version; struct pw_properties *properties; @@ -135,7 +134,6 @@ static void free_pending(struct async_pending *p) spa_list_remove(&p->link); free(p->handle); free(p->factory_name); - free(p->name); if (p->properties) pw_properties_free(p->properties); free(p); @@ -305,9 +303,8 @@ portal_response(DBusConnection *connection, DBusMessage *msg, void *user_data) pw_resource_do_parent(p->resource->resource, &p->resource->override, struct pw_core_proxy_methods, - create_node, + create_object, p->factory_name, - p->name, p->type, p->version, &p->properties->dict, @@ -325,13 +322,12 @@ portal_response(DBusConnection *connection, DBusMessage *msg, void *user_data) } -static void do_create_node(void *data, - const char *factory_name, - const char *name, - uint32_t type, - uint32_t version, - const struct spa_dict *props, - uint32_t new_id) +static void do_create_object(void *data, + const char *factory_name, + uint32_t type, + uint32_t version, + const struct spa_dict *props, + uint32_t new_id) { struct resource *resource = data; struct client_info *cinfo = resource->cinfo; @@ -350,9 +346,8 @@ static void do_create_node(void *data, pw_resource_do_parent(resource->resource, &resource->override, struct pw_core_proxy_methods, - create_node, + create_object, factory_name, - name, type, version, props, @@ -411,7 +406,6 @@ static void do_create_node(void *data, p->handle = strdup(handle); p->handled = false; p->factory_name = strdup(factory_name); - p->name = strdup(name); p->type = type; p->version = version; p->properties = props ? pw_properties_new_dict(props) : NULL; @@ -479,7 +473,7 @@ do_create_link(void *data, static const struct pw_core_proxy_methods core_override = { PW_VERSION_CORE_PROXY_METHODS, - .create_node = do_create_node, + .create_object = do_create_object, .create_link = do_create_link, }; diff --git a/src/modules/module-protocol-native/protocol-native.c b/src/modules/module-protocol-native/protocol-native.c index 31c0ba351..754d396be 100644 --- a/src/modules/module-protocol-native/protocol-native.c +++ b/src/modules/module-protocol-native/protocol-native.c @@ -82,10 +82,10 @@ static void core_marshal_get_registry(void *object, uint32_t version, uint32_t n } static void -core_marshal_create_node(void *object, - const char *factory_name, const char *name, - uint32_t type, uint32_t version, - const struct spa_dict *props, uint32_t new_id) +core_marshal_create_object(void *object, + const char *factory_name, + uint32_t type, uint32_t version, + const struct spa_dict *props, uint32_t new_id) { struct pw_proxy *proxy = object; struct spa_pod_builder *b; @@ -99,7 +99,6 @@ core_marshal_create_node(void *object, spa_pod_builder_add(b, SPA_POD_TYPE_STRUCT, &f, SPA_POD_TYPE_STRING, factory_name, - SPA_POD_TYPE_STRING, name, SPA_POD_TYPE_ID, type, SPA_POD_TYPE_INT, version, SPA_POD_TYPE_INT, n_items, 0); @@ -430,18 +429,17 @@ static bool core_demarshal_get_registry(void *object, void *data, size_t size) return true; } -static bool core_demarshal_create_node(void *object, void *data, size_t size) +static bool core_demarshal_create_object(void *object, void *data, size_t size) { struct pw_resource *resource = object; struct spa_pod_iter it; uint32_t version, type, new_id, i; - const char *factory_name, *name; + const char *factory_name; struct spa_dict props; if (!spa_pod_iter_struct(&it, data, size) || !spa_pod_iter_get(&it, SPA_POD_TYPE_STRING, &factory_name, - SPA_POD_TYPE_STRING, &name, SPA_POD_TYPE_ID, &type, SPA_POD_TYPE_INT, &version, SPA_POD_TYPE_INT, &props.n_items, 0)) @@ -458,7 +456,7 @@ static bool core_demarshal_create_node(void *object, void *data, size_t size) SPA_POD_TYPE_INT, &new_id, 0)) return false; - pw_resource_do(resource, struct pw_core_proxy_methods, create_node, factory_name, name, + pw_resource_do(resource, struct pw_core_proxy_methods, create_object, factory_name, type, version, &props, new_id); return true; @@ -904,7 +902,7 @@ static const struct pw_core_proxy_methods pw_protocol_native_core_method_marshal &core_marshal_sync, &core_marshal_get_registry, &core_marshal_client_update, - &core_marshal_create_node, + &core_marshal_create_object, &core_marshal_create_link }; @@ -913,7 +911,7 @@ static const struct pw_protocol_native_demarshal pw_protocol_native_core_method_ { &core_demarshal_sync, 0, }, { &core_demarshal_get_registry, 0, }, { &core_demarshal_client_update, 0, }, - { &core_demarshal_create_node, PW_PROTOCOL_NATIVE_REMAP, }, + { &core_demarshal_create_object, PW_PROTOCOL_NATIVE_REMAP, }, { &core_demarshal_create_link, PW_PROTOCOL_NATIVE_REMAP, } }; diff --git a/src/modules/spa/module-node-factory.c b/src/modules/spa/module-node-factory.c index 87e3f7e88..c4aa8cc45 100644 --- a/src/modules/spa/module-node-factory.c +++ b/src/modules/spa/module-node-factory.c @@ -33,28 +33,34 @@ struct factory_data { struct pw_core *core; - struct pw_node_factory *this; + struct pw_factory *this; struct pw_properties *properties; }; -static struct pw_node *create_node(void *_data, - struct pw_resource *resource, - const char *name, - struct pw_properties *properties) +static void *create_object(void *_data, + struct pw_resource *resource, + uint32_t type, + uint32_t version, + struct pw_properties *properties, + uint32_t new_id) { struct factory_data *data = _data; struct pw_node *node; - const char *lib, *factory_name; + const char *lib, *factory_name, *name; if (properties == NULL) goto no_properties; lib = pw_properties_get(properties, "spa.library.name"); factory_name = pw_properties_get(properties, "spa.factory.name"); + name = pw_properties_get(properties, "name"); if (lib == NULL || factory_name == NULL) goto no_properties; + if (name == NULL) + name = "spa-node"; + node = pw_spa_node_load(data->core, NULL, NULL, @@ -65,6 +71,12 @@ static struct pw_node *create_node(void *_data, if (node == NULL) goto no_mem; + if (resource) + pw_global_bind(pw_node_get_global(node), + pw_resource_get_client(resource), + PW_PERM_RWX, + version, new_id); + return node; no_properties: @@ -84,33 +96,39 @@ static struct pw_node *create_node(void *_data, return NULL; } -static const struct pw_node_factory_implementation impl_factory = { - PW_VERSION_NODE_FACRORY_IMPLEMENTATION, - .create_node = create_node, +static const struct pw_factory_implementation impl_factory = { + PW_VERSION_FACTORY_IMPLEMENTATION, + .create_object = create_object, }; static bool module_init(struct pw_module *module, struct pw_properties *properties) { struct pw_core *core = pw_module_get_core(module); - struct pw_node_factory *factory; + struct pw_type *t = pw_core_get_type(core); + struct pw_factory *factory; struct factory_data *data; - factory = pw_node_factory_new(core, "spa-node-factory", sizeof(*data)); + factory = pw_factory_new(core, + "spa-node-factory", + t->node, + PW_VERSION_NODE, + NULL, + sizeof(*data)); if (factory == NULL) return false; - data = pw_node_factory_get_user_data(factory); + data = pw_factory_get_user_data(factory); data->this = factory; data->core = core; data->properties = properties; pw_log_debug("module %p: new", module); - pw_node_factory_set_implementation(factory, - &impl_factory, - data); + pw_factory_set_implementation(factory, + &impl_factory, + data); - pw_node_factory_export(factory, NULL, pw_module_get_global(module)); + pw_factory_register(factory, NULL, pw_module_get_global(module)); return true; } diff --git a/src/pipewire/core.c b/src/pipewire/core.c index 51dcf0c47..701ded83b 100644 --- a/src/pipewire/core.c +++ b/src/pipewire/core.c @@ -164,31 +164,28 @@ static void core_get_registry(void *object, uint32_t version, uint32_t new_id) } static void -core_create_node(void *object, - const char *factory_name, - const char *name, - uint32_t type, - uint32_t version, - const struct spa_dict *props, - uint32_t new_id) +core_create_object(void *object, + const char *factory_name, + uint32_t type, + uint32_t version, + const struct spa_dict *props, + uint32_t new_id) { struct pw_resource *resource = object; - struct pw_resource *node_resource = NULL; struct pw_client *client = resource->client; - struct pw_node_factory *factory; - struct pw_node *node; + struct pw_factory *factory; + void *obj; struct pw_properties *properties; - int res; - factory = pw_core_find_node_factory(client->core, factory_name); + factory = pw_core_find_factory(client->core, factory_name); if (factory == NULL) goto no_factory; - if (type != client->core->type.node) { - node_resource = pw_resource_new(client, new_id, PW_PERM_RWX, type, version, 0); - if (node_resource == NULL) - goto no_resource; - } + if (factory->type != type) + goto wrong_type; + + if (factory->version < version) + goto wrong_version; if (props) { properties = pw_properties_new_dict(props); @@ -198,16 +195,10 @@ core_create_node(void *object, properties = NULL; /* error will be posted */ - node = pw_node_factory_create_node(factory, node_resource, name, properties); - if (node == NULL) + obj = pw_factory_create_object(factory, resource, type, version, properties, new_id); + if (obj == NULL) goto no_mem; - if (type == client->core->type.node) { - res = pw_global_bind(pw_node_get_global(node), client, PW_PERM_RWX, version, new_id); - if (res < 0) - goto no_bind; - } - properties = NULL; done: @@ -218,22 +209,19 @@ core_create_node(void *object, pw_core_resource_error(client->core_resource, resource->id, SPA_RESULT_INVALID_ARGUMENTS, "unknown factory name %s", factory_name); goto done; - - no_resource: - pw_log_error("can't create resource"); - goto no_mem; + wrong_version: + wrong_type: + pw_log_error("invalid resource type/version"); + pw_core_resource_error(client->core_resource, + resource->id, SPA_RESULT_INCOMPATIBLE_VERSION, "wrong resource type/version"); + goto done; no_properties: pw_log_error("can't create properties"); - pw_resource_destroy(node_resource); goto no_mem; no_mem: pw_core_resource_error(client->core_resource, resource->id, SPA_RESULT_NO_MEMORY, "no memory"); goto done; - no_bind: - pw_core_resource_error(client->core_resource, - resource->id, res, "can't bind node: %d", res); - goto done; } static void @@ -343,7 +331,7 @@ static const struct pw_core_proxy_methods core_methods = { .sync = core_sync, .get_registry = core_get_registry, .client_update = core_client_update, - .create_node = core_create_node, + .create_object = core_create_object, .create_link = core_create_link }; @@ -451,7 +439,7 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop, struct pw_properties *pro spa_list_init(&this->module_list); spa_list_init(&this->client_list); spa_list_init(&this->node_list); - spa_list_init(&this->node_factory_list); + spa_list_init(&this->factory_list); spa_list_init(&this->link_list); spa_hook_list_init(&this->listener_list); @@ -792,21 +780,21 @@ struct spa_format *pw_core_find_format(struct pw_core *core, return NULL; } -/** Find a node by name +/** Find a factory by name * * \param core the core object - * \param name the name of the node to find + * \param name the name of the factory to find * - * Find in the list of nodes registered in \a core for one with + * Find in the list of factories registered in \a core for one with * the given \a name. * * \memberof pw_core */ -struct pw_node_factory *pw_core_find_node_factory(struct pw_core *core, const char *name) +struct pw_factory *pw_core_find_factory(struct pw_core *core, const char *name) { - struct pw_node_factory *factory; + struct pw_factory *factory; - spa_list_for_each(factory, &core->node_factory_list, link) { + spa_list_for_each(factory, &core->factory_list, link) { if (strcmp(factory->name, name) == 0) return factory; } diff --git a/src/pipewire/core.h b/src/pipewire/core.h index 2781b47a0..021891986 100644 --- a/src/pipewire/core.h +++ b/src/pipewire/core.h @@ -41,7 +41,7 @@ struct pw_core; #include #include #include -#include +#include #include #include #include @@ -172,9 +172,9 @@ pw_core_find_port(struct pw_core *core, struct spa_format **format_filters, char **error); -/** Find a node factory by name */ -struct pw_node_factory * -pw_core_find_node_factory(struct pw_core *core, const char *name); +/** Find a factory by name */ +struct pw_factory * +pw_core_find_factory(struct pw_core *core, const char *name); #ifdef __cplusplus } diff --git a/src/pipewire/factory.c b/src/pipewire/factory.c new file mode 100644 index 000000000..1b556e0a2 --- /dev/null +++ b/src/pipewire/factory.c @@ -0,0 +1,143 @@ +/* PipeWire + * Copyright (C) 2016 Axis Communications AB + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "pipewire/pipewire.h" +#include "pipewire/factory.h" +#include "pipewire/private.h" + +struct resource_data { + struct spa_hook resource_listener; +}; + +struct pw_factory *pw_factory_new(struct pw_core *core, + const char *name, + uint32_t type, + uint32_t version, + struct pw_properties *properties, + size_t user_data_size) +{ + struct pw_factory *this; + + this = calloc(1, sizeof(*this) + user_data_size); + this->core = core; + this->name = strdup(name); + this->type = type; + this->version = version; + this->properties = properties; + spa_list_init(&this->resource_list); + + if (user_data_size > 0) + this->user_data = SPA_MEMBER(this, sizeof(*this), void); + + pw_log_debug("factory %p: new %s", this, name); + + return this; +} + +void pw_factory_destroy(struct pw_factory *factory) +{ + pw_log_debug("factory %p: destroy", factory); + + if (factory->global) { + spa_list_remove(&factory->link); + pw_global_destroy(factory->global); + } + if (factory->name) + free((char *)factory->name); + + free(factory); +} + +static void factory_unbind_func(void *data) +{ + struct pw_resource *resource = data; + spa_list_remove(&resource->link); +} + +static const struct pw_resource_events resource_events = { + PW_VERSION_RESOURCE_EVENTS, + .destroy = factory_unbind_func, +}; + +static int +factory_bind_func(struct pw_global *global, + struct pw_client *client, uint32_t permissions, + uint32_t version, uint32_t id) +{ + struct pw_factory *this = global->object; + struct pw_resource *resource; + struct resource_data *data; + + resource = pw_resource_new(client, id, permissions, global->type, version, sizeof(*data)); + if (resource == NULL) + goto no_mem; + + data = pw_resource_get_user_data(resource); + pw_resource_add_listener(resource, &data->resource_listener, &resource_events, resource); + + pw_log_debug("factory %p: bound to %d", this, resource->id); + + spa_list_insert(this->resource_list.prev, &resource->link); + + this->info.change_mask = ~0; + pw_factory_resource_info(resource, &this->info); + this->info.change_mask = 0; + + return SPA_RESULT_OK; + + no_mem: + pw_log_error("can't create factory resource"); + pw_core_resource_error(client->core_resource, + client->core_resource->id, SPA_RESULT_NO_MEMORY, "no memory"); + return SPA_RESULT_NO_MEMORY; +} + +void pw_factory_register(struct pw_factory *factory, + struct pw_client *owner, + struct pw_global *parent) +{ + struct pw_core *core = factory->core; + spa_list_append(&core->factory_list, &factory->link); + factory->global = pw_core_add_global(core, owner, parent, + core->type.factory, 0, factory_bind_func, factory); +} + +void *pw_factory_get_user_data(struct pw_factory *factory) +{ + return factory->user_data; +} + +void pw_factory_set_implementation(struct pw_factory *factory, + const struct pw_factory_implementation *implementation, + void *data) +{ + factory->implementation = implementation; + factory->implementation_data = data; +} + +void *pw_factory_create_object(struct pw_factory *factory, + struct pw_resource *resource, + uint32_t type, + uint32_t version, + struct pw_properties *properties, + uint32_t new_id) +{ + return factory->implementation->create_object(factory->implementation_data, + resource, type, version, properties, new_id); +} diff --git a/src/pipewire/factory.h b/src/pipewire/factory.h new file mode 100644 index 000000000..def1e66c2 --- /dev/null +++ b/src/pipewire/factory.h @@ -0,0 +1,87 @@ +/* PipeWire + * Copyright (C) 2016 Axis Communications AB + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __PIPEWIRE_FACTORY_H__ +#define __PIPEWIRE_FACTORY_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define PW_TYPE_INTERFACE__Factory PW_TYPE_INTERFACE_BASE "Factory" +#define PW_TYPE_FACTORY_BASE PW_TYPE_INTERFACE__Factory ":" + +/** \class pw_factory + * + * \brief PipeWire factory interface. + * + * The factory is used to make objects on demand. + */ +struct pw_factory; + +#include +#include +#include +#include +#include + +struct pw_factory_implementation { +#define PW_VERSION_FACTORY_IMPLEMENTATION 0 + uint32_t version; + + /** The function to create an object from this factory */ + void *(*create_object) (void *data, + struct pw_resource *resource, + uint32_t type, + uint32_t version, + struct pw_properties *properties, + uint32_t new_id); +}; + +struct pw_factory *pw_factory_new(struct pw_core *core, + const char *name, + uint32_t type, + uint32_t version, + struct pw_properties *properties, + size_t user_data_size); + +void pw_factory_register(struct pw_factory *factory, + struct pw_client *owner, + struct pw_global *parent); + +void pw_factory_destroy(struct pw_factory *factory); + +void *pw_factory_get_user_data(struct pw_factory *factory); + +void pw_factory_set_implementation(struct pw_factory *factory, + const struct pw_factory_implementation *implementation, + void *data); + +void *pw_factory_create_object(struct pw_factory *factory, + struct pw_resource *resource, + uint32_t type, + uint32_t version, + struct pw_properties *properties, + uint32_t new_id); + +#ifdef __cplusplus +} +#endif + +#endif /* __PIPEWIRE_FACTORY_H__ */ diff --git a/src/pipewire/interfaces.h b/src/pipewire/interfaces.h index df0f4fbf4..de26f89d7 100644 --- a/src/pipewire/interfaces.h +++ b/src/pipewire/interfaces.h @@ -37,6 +37,7 @@ struct pw_core_proxy; struct pw_registry_proxy; struct pw_module_proxy; struct pw_node_proxy; +struct pw_factory_proxy; struct pw_client_proxy; struct pw_link_proxy; @@ -124,24 +125,22 @@ struct pw_core_proxy_methods { */ void (*client_update) (void *object, const struct spa_dict *props); /** - * Create a new node on the PipeWire server from a factory. + * Create a new object on the PipeWire server from a factory. * Use a \a factory_name of "client-node" to create a * \ref pw_client_node. * * \param factory_name the factory name to use - * \param name the node name * \param type the interface to bind to * \param version the version of the interface * \param props extra properties * \param new_id the client proxy id */ - void (*create_node) (void *object, - const char *factory_name, - const char *name, - uint32_t type, - uint32_t version, - const struct spa_dict *props, - uint32_t new_id); + void (*create_object) (void *object, + const char *factory_name, + uint32_t type, + uint32_t version, + const struct spa_dict *props, + uint32_t new_id); /** * Create a new link between two node ports * @@ -190,17 +189,16 @@ pw_core_proxy_client_update(struct pw_core_proxy *core, const struct spa_dict *p } static inline void * -pw_core_proxy_create_node(struct pw_core_proxy *core, - const char *factory_name, - const char *name, - uint32_t type, - uint32_t version, - const struct spa_dict *props, - size_t user_data_size) +pw_core_proxy_create_object(struct pw_core_proxy *core, + const char *factory_name, + uint32_t type, + uint32_t version, + const struct spa_dict *props, + size_t user_data_size) { struct pw_proxy *p = pw_proxy_new((struct pw_proxy*)core, type, user_data_size); - pw_proxy_do((struct pw_proxy*)core, struct pw_core_proxy_methods, create_node, factory_name, - name, type, version, props, pw_proxy_get_id(p)); + pw_proxy_do((struct pw_proxy*)core, struct pw_core_proxy_methods, create_object, factory_name, + type, version, props, pw_proxy_get_id(p)); return p; } @@ -471,6 +469,35 @@ pw_node_proxy_add_listener(struct pw_node_proxy *node, #define pw_node_resource_info(r,...) pw_resource_notify(r,struct pw_node_proxy_events,info,__VA_ARGS__) +#define PW_VERSION_FACTORY 0 + +#define PW_FACTORY_PROXY_EVENT_INFO 0 +#define PW_FACTORY_PROXY_EVENT_NUM 1 + +/** Factory events */ +struct pw_factory_proxy_events { +#define PW_VERSION_FACTORY_PROXY_EVENTS 0 + uint32_t version; + /** + * Notify factory info + * + * \param info info about the factory + */ + void (*info) (void *object, struct pw_factory_info *info); +}; + +/** Factory */ +static inline void +pw_factory_proxy_add_listener(struct pw_factory_proxy *factory, + struct spa_hook *listener, + const struct pw_factory_proxy_events *events, + void *data) +{ + pw_proxy_add_proxy_listener((struct pw_proxy*)factory, listener, events, data); +} + +#define pw_factory_resource_info(r,...) pw_resource_notify(r,struct pw_factory_proxy_events,info,__VA_ARGS__) + #define PW_VERSION_CLIENT 0 #define PW_CLIENT_PROXY_EVENT_INFO 0 diff --git a/src/pipewire/introspect.h b/src/pipewire/introspect.h index a46bf630c..f71dcdd97 100644 --- a/src/pipewire/introspect.h +++ b/src/pipewire/introspect.h @@ -170,6 +170,23 @@ pw_node_info_update(struct pw_node_info *info, void pw_node_info_free(struct pw_node_info *info); +/** The factory information. Extra information can be added in later versions \memberof pw_introspect */ +struct pw_factory_info { + uint32_t id; /**< id of the global */ + const char *name; /**< name the factory */ + uint32_t type; /**< type of the factory */ + uint32_t version; /**< version of the objects */ +#define PW_FACTORY_CHANGE_MASK_PROPS (1 << 0) + uint64_t change_mask; /**< bitfield of changed fields since last call */ + struct spa_dict *props; /**< the properties of the factory */ +}; + +struct pw_factory_info * +pw_factory_info_update(struct pw_factory_info *info, + const struct pw_factory_info *update); + +void +pw_factory_info_free(struct pw_factory_info *info); /** The link information. Extra information can be added in later versions \memberof pw_introspect */ struct pw_link_info { diff --git a/src/pipewire/meson.build b/src/pipewire/meson.build index 40ab2afe9..30d4ff152 100644 --- a/src/pipewire/meson.build +++ b/src/pipewire/meson.build @@ -15,7 +15,7 @@ pipewire_headers = [ 'mem.h', 'module.h', 'node.h', - 'node-factory.h', + 'factory.h', 'pipewire.h', 'port.h', 'properties.h', @@ -45,7 +45,7 @@ pipewire_sources = [ 'mem.c', 'module.c', 'node.c', - 'node-factory.c', + 'factory.c', 'pipewire.c', 'port.c', 'properties.c', diff --git a/src/pipewire/module.c b/src/pipewire/module.c index a4fdbf333..8ac8620a1 100644 --- a/src/pipewire/module.c +++ b/src/pipewire/module.c @@ -123,7 +123,7 @@ module_bind_func(struct pw_global *global, pw_log_debug("module %p: bound to %d", this, resource->id); - spa_list_insert(this->resource_list.prev, &resource->link); + spa_list_append(&this->resource_list, &resource->link); this->info.change_mask = ~0; pw_module_resource_info(resource, &this->info); diff --git a/src/pipewire/node-factory.c b/src/pipewire/node-factory.c deleted file mode 100644 index 0169ea287..000000000 --- a/src/pipewire/node-factory.c +++ /dev/null @@ -1,85 +0,0 @@ -/* PipeWire - * Copyright (C) 2016 Axis Communications AB - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "pipewire/pipewire.h" -#include "pipewire/node-factory.h" -#include "pipewire/private.h" - -struct pw_node_factory *pw_node_factory_new(struct pw_core *core, - const char *name, - size_t user_data_size) -{ - struct pw_node_factory *this; - - this = calloc(1, sizeof(*this) + user_data_size); - this->core = core; - this->name = strdup(name); - - if (user_data_size > 0) - this->user_data = SPA_MEMBER(this, sizeof(*this), void); - - pw_log_debug("node-factory %p: new", this); - - return this; -} - -void pw_node_factory_destroy(struct pw_node_factory *factory) -{ - pw_log_debug("node-factory %p: destroy", factory); - - if (factory->global) { - spa_list_remove(&factory->link); - pw_global_destroy(factory->global); - } - if (factory->name) - free((char *)factory->name); - - free(factory); -} - -void pw_node_factory_export(struct pw_node_factory *factory, - struct pw_client *owner, - struct pw_global *parent) -{ - struct pw_core *core = factory->core; - spa_list_append(&core->node_factory_list, &factory->link); - factory->global = pw_core_add_global(core, owner, parent, core->type.node_factory, 0, NULL, factory); -} - -void *pw_node_factory_get_user_data(struct pw_node_factory *factory) -{ - return factory->user_data; -} - -void pw_node_factory_set_implementation(struct pw_node_factory *factory, - const struct pw_node_factory_implementation *implementation, - void *data) -{ - factory->implementation = implementation; - factory->implementation_data = data; -} - -struct pw_node *pw_node_factory_create_node(struct pw_node_factory *factory, - struct pw_resource *resource, - const char *name, - struct pw_properties *properties) -{ - return factory->implementation->create_node(factory->implementation_data, - resource, name, properties); -} diff --git a/src/pipewire/node-factory.h b/src/pipewire/node-factory.h deleted file mode 100644 index 0dc702043..000000000 --- a/src/pipewire/node-factory.h +++ /dev/null @@ -1,80 +0,0 @@ -/* PipeWire - * Copyright (C) 2016 Axis Communications AB - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __PIPEWIRE_NODE_FACTORY_H__ -#define __PIPEWIRE_NODE_FACTORY_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define PW_TYPE_INTERFACE__NodeFactory PW_TYPE_INTERFACE_BASE "NodeFactory" -#define PW_TYPE_NODE_FACTORY_BASE PW_TYPE_INTERFACE__NodeFactory ":" - -/** \class pw_node_factory - * - * \brief PipeWire node factory interface. - * - * The factory object is used to make nodes on demand. - */ -struct pw_node_factory; - -#include -#include -#include -#include -#include - -struct pw_node_factory_implementation { -#define PW_VERSION_NODE_FACRORY_IMPLEMENTATION 0 - uint32_t version; - - /** The function to create a node from this factory */ - struct pw_node *(*create_node) (void *data, - struct pw_resource *resource, - const char *name, - struct pw_properties *properties); -}; - -struct pw_node_factory *pw_node_factory_new(struct pw_core *core, - const char *name, - size_t user_data_size); - -void pw_node_factory_export(struct pw_node_factory *factory, - struct pw_client *owner, - struct pw_global *parent); - -void pw_node_factory_destroy(struct pw_node_factory *factory); - -void *pw_node_factory_get_user_data(struct pw_node_factory *factory); - -void pw_node_factory_set_implementation(struct pw_node_factory *factory, - const struct pw_node_factory_implementation *implementation, - void *data); - -struct pw_node *pw_node_factory_create_node(struct pw_node_factory *factory, - struct pw_resource *resource, - const char *name, - struct pw_properties *properties); - -#ifdef __cplusplus -} -#endif - -#endif /* __PIPEWIRE_NODE_FACTORY_H__ */ diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 376611227..8c5d22f8c 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -130,7 +130,7 @@ struct pw_core { struct spa_list global_list; /**< list of globals */ struct spa_list client_list; /**< list of clients */ struct spa_list node_list; /**< list of nodes */ - struct spa_list node_factory_list; /**< list of node factories */ + struct spa_list factory_list; /**< list of factories */ struct spa_list link_list; /**< list of links */ struct spa_hook_list listener_list; @@ -368,16 +368,22 @@ struct pw_stream { struct spa_hook_list listener_list; }; -struct pw_node_factory { +struct pw_factory { struct pw_core *core; /**< the core */ struct spa_list link; /**< link in core node_factory_list */ struct pw_global *global; /**< global for this factory */ + struct pw_factory_info info; /**< introspectable factory info */ const char *name; /**< the factory name */ + uint32_t type; /**< the type produced by the factory*/ + uint32_t version; /**< the version of the produced object */ + struct pw_properties *properties; /**< properties of the factory */ - const struct pw_node_factory_implementation *implementation; + const struct pw_factory_implementation *implementation; void *implementation_data; + struct spa_list resource_list; /**< The list of resources of this factory */ + void *user_data; }; diff --git a/src/pipewire/remote.c b/src/pipewire/remote.c index 5b5e2c63e..1262848cf 100644 --- a/src/pipewire/remote.c +++ b/src/pipewire/remote.c @@ -1084,13 +1084,12 @@ struct pw_proxy *pw_remote_export(struct pw_remote *remote, struct pw_proxy *proxy; struct node_data *data; - proxy = pw_core_proxy_create_node(remote->core_proxy, - "client-node", - "client-node", - impl->type_client_node, - PW_VERSION_CLIENT_NODE, - &node->properties->dict, - sizeof(struct node_data)); + proxy = pw_core_proxy_create_object(remote->core_proxy, + "client-node", + impl->type_client_node, + PW_VERSION_CLIENT_NODE, + &node->properties->dict, + sizeof(struct node_data)); if (proxy == NULL) return NULL; diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index e8d5cb24d..a4604a119 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -957,8 +957,7 @@ pw_stream_connect(struct pw_stream *stream, if (flags & PW_STREAM_FLAG_AUTOCONNECT) pw_properties_set(stream->properties, "pipewire.autoconnect", "1"); - impl->node_proxy = pw_core_proxy_create_node(stream->remote->core_proxy, - "client-node", + impl->node_proxy = pw_core_proxy_create_object(stream->remote->core_proxy, "client-node", impl->type_client_node, PW_VERSION_CLIENT_NODE, diff --git a/src/pipewire/type.c b/src/pipewire/type.c index ba37734f6..48b288791 100644 --- a/src/pipewire/type.c +++ b/src/pipewire/type.c @@ -42,7 +42,7 @@ void pw_type_init(struct pw_type *type) type->core = spa_type_map_get_id(type->map, PW_TYPE_INTERFACE__Core); type->registry = spa_type_map_get_id(type->map, PW_TYPE_INTERFACE__Registry); type->node = spa_type_map_get_id(type->map, PW_TYPE_INTERFACE__Node); - type->node_factory = spa_type_map_get_id(type->map, PW_TYPE_INTERFACE__NodeFactory); + type->factory = spa_type_map_get_id(type->map, PW_TYPE_INTERFACE__Factory); type->link = spa_type_map_get_id(type->map, PW_TYPE_INTERFACE__Link); type->client = spa_type_map_get_id(type->map, PW_TYPE_INTERFACE__Client); type->module = spa_type_map_get_id(type->map, PW_TYPE_INTERFACE__Module); diff --git a/src/pipewire/type.h b/src/pipewire/type.h index 9378da5ba..77243a7ac 100644 --- a/src/pipewire/type.h +++ b/src/pipewire/type.h @@ -51,7 +51,7 @@ struct pw_type { uint32_t core; uint32_t registry; uint32_t node; - uint32_t node_factory; + uint32_t factory; uint32_t link; uint32_t client; uint32_t module; diff --git a/src/tools/pipewire-cli.c b/src/tools/pipewire-cli.c index e450b9fe6..91e11d56d 100644 --- a/src/tools/pipewire-cli.c +++ b/src/tools/pipewire-cli.c @@ -811,7 +811,7 @@ static bool do_info(struct data *data, const char *cmd, char *args, char **error static bool do_create_node(struct data *data, const char *cmd, char *args, char **error) { struct remote_data *rd = data->current; - char *a[3]; + char *a[2]; int n; uint32_t id; struct pw_type *t = data->t; @@ -819,18 +819,18 @@ static bool do_create_node(struct data *data, const char *cmd, char *args, char struct pw_properties *props = NULL; struct proxy_data *pd; - n = pw_split_ip(args, WHITESPACE, 3, a); - if (n < 2) { - asprintf(error, "%s []", cmd); + n = pw_split_ip(args, WHITESPACE, 2, a); + if (n < 1) { + asprintf(error, "%s []", cmd); return false; } - if (n == 3) - props = parse_props(a[2]); + if (n == 2) + props = parse_props(a[1]); - proxy = pw_core_proxy_create_node(rd->core_proxy, a[0], a[1], - t->node, PW_VERSION_NODE, - props ? &props->dict : NULL, - sizeof(struct proxy_data)); + proxy = pw_core_proxy_create_object(rd->core_proxy, a[0], + t->node, PW_VERSION_NODE, + props ? &props->dict : NULL, + sizeof(struct proxy_data)); pd = pw_proxy_get_user_data(proxy); pd->rd = rd;