From 157a8b6ddf51d2293b0a21b4d0a06ca27e054e0a Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 14 Nov 2017 10:59:10 +0100 Subject: [PATCH] factory: add events Add events to the factory and use the destroy event to clean up. --- src/modules/spa/module-node-factory.c | 59 ++++++++++++++++++++++++--- src/pipewire/factory.c | 10 +++++ src/pipewire/factory.h | 15 +++++++ src/pipewire/private.h | 2 + 4 files changed, 80 insertions(+), 6 deletions(-) diff --git a/src/modules/spa/module-node-factory.c b/src/modules/spa/module-node-factory.c index 544f68096..ebe22f242 100644 --- a/src/modules/spa/module-node-factory.c +++ b/src/modules/spa/module-node-factory.c @@ -35,6 +35,16 @@ struct factory_data { struct pw_core *core; struct pw_factory *this; struct pw_properties *properties; + + struct spa_hook factory_listener; + struct spa_hook module_listener; + + struct spa_list node_list; +}; + +struct node_data { + struct spa_list link; + struct pw_node *node; }; static void *create_object(void *_data, @@ -47,6 +57,7 @@ static void *create_object(void *_data, struct factory_data *data = _data; struct pw_node *node; const char *lib, *factory_name, *name; + struct node_data *nd; if (properties == NULL) goto no_properties; @@ -68,10 +79,15 @@ static void *create_object(void *_data, factory_name, name, 0, - properties, 0); + properties, + sizeof(struct node_data)); if (node == NULL) goto no_mem; + nd = pw_spa_node_get_user_data(node); + nd->node = node; + spa_list_append(&data->node_list, &nd->link); + if (resource) pw_global_bind(pw_node_get_global(node), pw_resource_get_client(resource), @@ -97,11 +113,41 @@ static void *create_object(void *_data, return NULL; } -static const struct pw_factory_implementation impl_factory = { +static const struct pw_factory_implementation factory_impl = { PW_VERSION_FACTORY_IMPLEMENTATION, .create_object = create_object, }; +static void factory_destroy(void *_data) +{ + struct factory_data *data = _data; + struct node_data *nd, *t; + + spa_hook_remove(&data->module_listener); + + spa_list_for_each_safe(nd, t, &data->node_list, link) + pw_node_destroy(nd->node); + + if (data->properties) + pw_properties_free(data->properties); +} + +static const struct pw_factory_events factory_events = { + PW_VERSION_FACTORY_IMPLEMENTATION, + .destroy = factory_destroy, +}; + +static void module_destroy(void *_data) +{ + struct factory_data *data = _data; + pw_factory_destroy(data->this); +} + +static const struct pw_module_events module_events = { + PW_VERSION_MODULE_EVENTS, + .destroy = module_destroy, +}; + static bool module_init(struct pw_module *module, struct pw_properties *properties) { struct pw_core *core = pw_module_get_core(module); @@ -122,12 +168,13 @@ static bool module_init(struct pw_module *module, struct pw_properties *properti data->this = factory; data->core = core; data->properties = properties; + spa_list_init(&data->node_list); + + pw_factory_add_listener(factory, &data->factory_listener, &factory_events, data); + pw_factory_set_implementation(factory, &factory_impl, data); pw_log_debug("module %p: new", module); - - pw_factory_set_implementation(factory, - &impl_factory, - data); + pw_module_add_listener(module, &data->module_listener, &module_events, data); pw_factory_register(factory, NULL, pw_module_get_global(module)); diff --git a/src/pipewire/factory.c b/src/pipewire/factory.c index 22de78b79..baa80bde7 100644 --- a/src/pipewire/factory.c +++ b/src/pipewire/factory.c @@ -45,6 +45,7 @@ struct pw_factory *pw_factory_new(struct pw_core *core, this->info.type = type; this->info.version = version; this->info.props = properties ? &properties->dict : NULL; + spa_hook_list_init(&this->listener_list); if (user_data_size > 0) this->user_data = SPA_MEMBER(this, sizeof(*this), void); @@ -57,6 +58,7 @@ struct pw_factory *pw_factory_new(struct pw_core *core, void pw_factory_destroy(struct pw_factory *factory) { pw_log_debug("factory %p: destroy", factory); + spa_hook_list_call(&factory->listener_list, struct pw_factory_events, destroy); if (factory->global) { spa_list_remove(&factory->link); @@ -134,6 +136,14 @@ struct pw_global *pw_factory_get_global(struct pw_factory *factory) return factory->global; } +void pw_factory_add_listener(struct pw_factory *factory, + struct spa_hook *listener, + const struct pw_factory_events *events, + void *data) +{ + spa_hook_list_append(&factory->listener_list, listener, events, data); +} + void pw_factory_set_implementation(struct pw_factory *factory, const struct pw_factory_implementation *implementation, void *data) diff --git a/src/pipewire/factory.h b/src/pipewire/factory.h index 5324d8715..7caf0087c 100644 --- a/src/pipewire/factory.h +++ b/src/pipewire/factory.h @@ -41,6 +41,15 @@ struct pw_factory; #include #include +/** Factory events, listen to them with \ref pw_factory_add_listener */ +struct pw_factory_events { +#define PW_VERSION_FACRORY_EVENTS 0 + uint32_t version; + + /** the factory is destroyed */ + void (*destroy) (void *data); +}; + struct pw_factory_implementation { #define PW_VERSION_FACTORY_IMPLEMENTATION 0 uint32_t version; @@ -72,6 +81,12 @@ void *pw_factory_get_user_data(struct pw_factory *factory); /** Get the global of this factory */ struct pw_global *pw_factory_get_global(struct pw_factory *factory); +/** Add an event listener */ +void pw_factory_add_listener(struct pw_factory *factory, + struct spa_hook *listener, + const struct pw_factory_events *events, + void *data); + void pw_factory_set_implementation(struct pw_factory *factory, const struct pw_factory_implementation *implementation, void *data); diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 93363aed1..7b53d4bc5 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -381,6 +381,8 @@ struct pw_factory { struct pw_factory_info info; /**< introspectable factory info */ struct pw_properties *properties; /**< properties of the factory */ + struct spa_hook_list listener_list; /**< event listeners */ + const struct pw_factory_implementation *implementation; void *implementation_data;