core: introduce the notion of provided features on components

Each component can optionally "provide" a feature, which is basically
a string that describes the feature (ex. "support.dbus"). If the
component loads successfully, the feature is marked as provided and
can be tested for its presence with wp_core_test_feature()
This commit is contained in:
George Kiagiadakis
2023-06-12 23:48:32 +03:00
parent f878e2f62d
commit c7cb193588
19 changed files with 67 additions and 27 deletions

View File

@@ -95,6 +95,8 @@ on_component_loader_load_done (WpComponentLoader * cl, GAsyncResult * res,
g_autoptr (GError) error = NULL;
g_autoptr (GObject) o = NULL;
WpCore *core = g_task_get_source_object (task);
WpRegistry *reg = wp_core_get_registry (core);
gchar *provides = g_task_get_task_data (task);
o = wp_component_loader_load_finish (cl, res, &error);
if (error) {
@@ -102,11 +104,14 @@ on_component_loader_load_done (WpComponentLoader * cl, GAsyncResult * res,
return;
}
if (provides)
wp_registry_mark_feature_provided (reg, provides);
if (o) {
wp_trace_object (cl, "loaded object " WP_OBJECT_FORMAT, WP_OBJECT_ARGS (o));
/* store object in the registry */
wp_registry_register_object (wp_core_get_registry (core), g_object_ref (o));
wp_registry_register_object (reg, g_object_ref (o));
if (WP_IS_OBJECT (o)) {
/* WpObject needs to be activated */
@@ -132,18 +137,21 @@ on_component_loader_load_done (WpComponentLoader * cl, GAsyncResult * res,
*
* \ingroup wpcomponentloader
* \param self the core
* \param component the module name or file name
* \param component (nullable): the module name or file name
* \param type the type of the component
* \param args (transfer none)(nullable): additional arguments for the component,
* expected to be a JSON object
* \param provides (nullable): the name of the feature that this component will
* provide if it loads successfully; this can be queried later with
* wp_core_test_feature()
* \param cancellable (nullable): optional GCancellable
* \param callback (scope async): the callback to call when the operation is done
* \param data (closure): data to pass to \a callback
*/
void
wp_core_load_component (WpCore * self, const gchar * component,
const gchar * type, WpSpaJson * args, GCancellable * cancellable,
GAsyncReadyCallback callback, gpointer data)
const gchar * type, WpSpaJson * args, const gchar * provides,
GCancellable * cancellable, GAsyncReadyCallback callback, gpointer data)
{
g_autoptr (GTask) task = NULL;
g_autoptr (WpComponentLoader) cl = NULL;
@@ -151,6 +159,9 @@ wp_core_load_component (WpCore * self, const gchar * component,
task = g_task_new (self, cancellable, callback, data);
g_task_set_source_tag (task, wp_core_load_component);
if (provides)
g_task_set_task_data (task, g_strdup (provides), g_free);
/* find a component loader for that type and load the component */
cl = wp_component_loader_find (self, type);
if (!cl) {

View File

@@ -42,8 +42,8 @@ struct _WpComponentLoaderInterface
WP_API
void wp_core_load_component (WpCore * self, const gchar * component,
const gchar * type, WpSpaJson * args, GCancellable * cancellable,
GAsyncReadyCallback callback, gpointer data);
const gchar * type, WpSpaJson * args, const gchar * provides,
GCancellable * cancellable, GAsyncReadyCallback callback, gpointer data);
WP_API
gboolean wp_core_load_component_finish (WpCore * self, GAsyncResult * res,

View File

@@ -1052,6 +1052,21 @@ wp_core_sync_finish (WpCore * self, GAsyncResult * res, GError ** error)
return g_task_propagate_boolean (G_TASK (res), error);
}
/*!
* \brief Test if a global feature is provided
*
* \ingroup wpcore
* \param self the core
* \param feature the feature name
* \returns TRUE if the feature is provided, FALSE otherwise
*/
gboolean
wp_core_test_feature (WpCore * self, const gchar * feature)
{
return g_ptr_array_find_with_equal_func (self->registry.features, feature,
g_str_equal, NULL);
}
WpRegistry *
wp_core_get_registry (WpCore * self)
{

View File

@@ -120,6 +120,11 @@ gboolean wp_core_sync_finish (WpCore * self, GAsyncResult * res,
WP_API
void wp_core_install_object_manager (WpCore * self, WpObjectManager * om);
/* Global Features */
WP_API
gboolean wp_core_test_feature (WpCore * self, const gchar * feature);
G_END_DECLS
#endif

View File

@@ -961,6 +961,7 @@ wp_registry_init (WpRegistry *self)
g_ptr_array_new_with_free_func ((GDestroyNotify) wp_global_unref);
self->objects = g_ptr_array_new_with_free_func (g_object_unref);
self->object_managers = g_ptr_array_new ();
self->features = g_ptr_array_new_with_free_func (g_free);
}
void
@@ -969,6 +970,7 @@ wp_registry_clear (WpRegistry *self)
wp_registry_detach (self);
g_clear_pointer (&self->globals, g_ptr_array_unref);
g_clear_pointer (&self->tmp_globals, g_ptr_array_unref);
g_clear_pointer (&self->features, g_ptr_array_unref);
/* remove all the registered objects
this will normally also destroy the object managers, eventually, since

View File

@@ -292,7 +292,7 @@ wp_component_array_load_task_execute_step (WpTransition * transition, guint step
self->curr_component->name, self->curr_component->type,
self->curr_component->priority, self->curr_component->flags);
wp_core_load_component (core, self->curr_component->name,
self->curr_component->type, NULL, NULL,
self->curr_component->type, NULL, NULL, NULL,
(GAsyncReadyCallback) on_component_loaded, self);
break;

View File

@@ -30,6 +30,7 @@ struct _WpRegistry
GPtrArray *tmp_globals; // elementy-type: WpGlobal*
GPtrArray *objects; // element-type: GObject*
GPtrArray *object_managers; // element-type: WpObjectManager*
GPtrArray *features; // element-type: gchar*
};
void wp_registry_init (WpRegistry *self);
@@ -47,6 +48,12 @@ gpointer wp_registry_find_object (WpRegistry *reg, GEqualFunc func,
void wp_registry_register_object (WpRegistry *reg, gpointer obj);
void wp_registry_remove_object (WpRegistry *reg, gpointer obj);
static inline void
wp_registry_mark_feature_provided (WpRegistry * reg, const gchar * feature)
{
g_ptr_array_add (reg->features, g_strdup (feature));
}
WpCore * wp_registry_get_core (WpRegistry * self) G_GNUC_CONST;
/* core */

View File

@@ -92,7 +92,7 @@ wp_require_api_transition_execute_step (WpTransition * transition, guint step)
"libwireplumber-module-%s", api_name);
self->pending_plugins++;
wp_core_load_component (core, module_name, "module", NULL, NULL,
wp_core_load_component (core, module_name, "module", NULL, NULL, NULL,
(GAsyncReadyCallback) on_plugin_loaded, self);
}
}

View File

@@ -190,7 +190,7 @@ wp_init_transition_execute_step (WpTransition * transition, guint step)
/* Load components that are defined in the configuration section */
json_comps = wp_conf_get_section (conf, "wireplumber.components", NULL);
wp_core_load_component (core, NULL, "array", json_comps, NULL,
wp_core_load_component (core, NULL, "array", json_comps, NULL, NULL,
(GAsyncReadyCallback) on_components_loaded, self);
break;
}

View File

@@ -1407,10 +1407,10 @@ main (gint argc, gchar **argv)
/* load required API modules */
ctl.pending_plugins++;
wp_core_load_component (ctl.core, "libwireplumber-module-default-nodes-api",
"module", NULL, NULL, (GAsyncReadyCallback) on_plugin_loaded, &ctl);
"module", NULL, NULL, NULL, (GAsyncReadyCallback) on_plugin_loaded, &ctl);
ctl.pending_plugins++;
wp_core_load_component (ctl.core, "libwireplumber-module-mixer-api",
"module", NULL, NULL, (GAsyncReadyCallback) on_plugin_loaded, &ctl);
"module", NULL, NULL, NULL, (GAsyncReadyCallback) on_plugin_loaded, &ctl);
/* connect */
if (!wp_core_connect (ctl.core)) {

View File

@@ -138,14 +138,14 @@ wp_init_transition_execute_step (WpTransition * transition, guint step)
case STEP_ACTIVATE_PLUGINS: {
wp_core_load_component (core, "libwireplumber-module-lua-scripting",
"module", NULL, NULL, (GAsyncReadyCallback) on_plugin_loaded, self);
"module", NULL, NULL, NULL, (GAsyncReadyCallback) on_plugin_loaded, self);
wp_core_load_component (core, "libwireplumber-module-standard-event-source",
"module", NULL, NULL, (GAsyncReadyCallback) on_plugin_loaded, self);
"module", NULL, NULL, NULL, (GAsyncReadyCallback) on_plugin_loaded, self);
break;
}
case STEP_ACTIVATE_SCRIPT: {
wp_core_load_component (core, exec_script, "script/lua", exec_args, NULL,
wp_core_load_component (core, exec_script, "script/lua", exec_args, NULL, NULL,
(GAsyncReadyCallback) on_plugin_loaded, self);
break;
}

View File

@@ -62,7 +62,7 @@ test_dbus_connection (TestFixture *f, gconstpointer user_data)
WpDBusConnectionState state = -1;
wp_core_load_component (f->base.core,
"libwireplumber-module-dbus-connection", "module", NULL, NULL,
"libwireplumber-module-dbus-connection", "module", NULL, NULL, NULL,
(GAsyncReadyCallback) on_plugin_loaded, f);
g_main_loop_run (f->base.loop);

View File

@@ -38,7 +38,7 @@ test_file_monitor_setup (TestFixture * f, gconstpointer user_data)
wp_base_test_fixture_setup (&f->base, WP_BASE_TEST_FLAG_DONT_CONNECT);
wp_core_load_component (f->base.core,
"libwireplumber-module-file-monitor-api", "module", NULL, NULL,
"libwireplumber-module-file-monitor-api", "module", NULL, NULL, NULL,
(GAsyncReadyCallback) on_plugin_loaded, f);
g_main_loop_run (f->base.loop);

View File

@@ -47,25 +47,25 @@ test_rd_setup (RdTestFixture *f, gconstpointer data)
{
wp_core_load_component (f->base.core,
"libwireplumber-module-dbus-connection", "module", NULL, NULL,
"libwireplumber-module-dbus-connection", "module", NULL, NULL, NULL,
(GAsyncReadyCallback) on_plugin_loaded, f);
g_main_loop_run (f->base.loop);
}
{
wp_core_load_component (f->base.client_core,
"libwireplumber-module-dbus-connection", "module", NULL, NULL,
"libwireplumber-module-dbus-connection", "module", NULL, NULL, NULL,
(GAsyncReadyCallback) on_plugin_loaded, f);
g_main_loop_run (f->base.loop);
}
{
wp_core_load_component (f->base.core,
"libwireplumber-module-reserve-device", "module", NULL, NULL,
"libwireplumber-module-reserve-device", "module", NULL, NULL, NULL,
(GAsyncReadyCallback) on_plugin_loaded, f);
g_main_loop_run (f->base.loop);
}
{
wp_core_load_component (f->base.client_core,
"libwireplumber-module-reserve-device", "module", NULL, NULL,
"libwireplumber-module-reserve-device", "module", NULL, NULL, NULL,
(GAsyncReadyCallback) on_plugin_loaded, f);
g_main_loop_run (f->base.loop);
}

View File

@@ -44,7 +44,7 @@ test_si_audio_adapter_setup (TestFixture * f, gconstpointer user_data)
}
{
wp_core_load_component (f->base.core,
"libwireplumber-module-si-audio-adapter", "module", NULL, NULL,
"libwireplumber-module-si-audio-adapter", "module", NULL, NULL, NULL,
(GAsyncReadyCallback) on_plugin_loaded, f);
g_main_loop_run (f->base.loop);
}

View File

@@ -42,13 +42,13 @@ test_si_audio_virtual_setup (TestFixture * f, gconstpointer user_data)
}
{
wp_core_load_component (f->base.core,
"libwireplumber-module-si-audio-adapter", "module", NULL, NULL,
"libwireplumber-module-si-audio-adapter", "module", NULL, NULL, NULL,
(GAsyncReadyCallback) on_plugin_loaded, f);
g_main_loop_run (f->base.loop);
}
{
wp_core_load_component (f->base.core,
"libwireplumber-module-si-audio-virtual", "module", NULL, NULL,
"libwireplumber-module-si-audio-virtual", "module", NULL, NULL, NULL,
(GAsyncReadyCallback) on_plugin_loaded, f);
g_main_loop_run (f->base.loop);
}

View File

@@ -50,7 +50,7 @@ test_si_node_setup (TestFixture * f, gconstpointer user_data)
}
{
wp_core_load_component (f->base.core,
"libwireplumber-module-si-node", "module", NULL, NULL,
"libwireplumber-module-si-node", "module", NULL, NULL, NULL,
(GAsyncReadyCallback) on_plugin_loaded, f);
g_main_loop_run (f->base.loop);
}

View File

@@ -97,12 +97,12 @@ test_si_standard_link_setup (TestFixture * f, gconstpointer user_data)
}
{
wp_core_load_component (f->base.core,
"libwireplumber-module-si-audio-adapter", "module", NULL, NULL,
"libwireplumber-module-si-audio-adapter", "module", NULL, NULL, NULL,
(GAsyncReadyCallback) on_plugin_loaded, f);
g_main_loop_run (f->base.loop);
wp_core_load_component (f->base.core,
"libwireplumber-module-si-standard-link", "module", NULL, NULL,
"libwireplumber-module-si-standard-link", "module", NULL, NULL, NULL,
(GAsyncReadyCallback) on_plugin_loaded, f);
g_main_loop_run (f->base.loop);
}

View File

@@ -204,7 +204,7 @@ load_component (ScriptRunnerFixture *f, const gchar *name, const gchar *type)
plugin_name = g_strdup (name);
}
wp_core_load_component (f->base.core, component_name, type, NULL, NULL,
wp_core_load_component (f->base.core, component_name, type, NULL, NULL, NULL,
(GAsyncReadyCallback) on_plugin_loaded, f);
g_main_loop_run (f->base.loop);
}