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:
@@ -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) {
|
||||
|
@@ -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,
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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 */
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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)) {
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user