main: move the code that loads the components section into the library

This allows it to be reused in other wireplumber clients and tests
This commit is contained in:
George Kiagiadakis
2023-05-29 15:48:39 +03:00
parent 55fc845098
commit b347415501
3 changed files with 379 additions and 271 deletions

View File

@@ -97,23 +97,26 @@ on_component_loader_load_done (WpComponentLoader * cl, GAsyncResult * res,
WpCore *core = g_task_get_source_object (task); WpCore *core = g_task_get_source_object (task);
o = wp_component_loader_load_finish (cl, res, &error); o = wp_component_loader_load_finish (cl, res, &error);
if (!o) { if (error) {
g_task_return_error (task, g_steal_pointer (&error)); g_task_return_error (task, g_steal_pointer (&error));
return; return;
} }
wp_trace_object (cl, "loaded object " WP_OBJECT_FORMAT, WP_OBJECT_ARGS (o)); if (o) {
wp_trace_object (cl, "loaded object " WP_OBJECT_FORMAT, WP_OBJECT_ARGS (o));
/* store object in the registry */ /* store object in the registry */
wp_registry_register_object (wp_core_get_registry (core), g_object_ref (o)); wp_registry_register_object (wp_core_get_registry (core), g_object_ref (o));
if (WP_IS_OBJECT (o)) { if (WP_IS_OBJECT (o)) {
/* WpObject needs to be activated */ /* WpObject needs to be activated */
wp_object_activate (WP_OBJECT (o), WP_OBJECT_FEATURES_ALL, NULL, wp_object_activate (WP_OBJECT (o), WP_OBJECT_FEATURES_ALL, NULL,
(GAsyncReadyCallback) on_object_activated, g_steal_pointer (&task)); (GAsyncReadyCallback) on_object_activated, g_steal_pointer (&task));
} else { return;
g_task_return_boolean (task, TRUE); }
} }
g_task_return_boolean (task, TRUE);
} }
/*! /*!
@@ -122,6 +125,10 @@ on_component_loader_load_done (WpComponentLoader * cl, GAsyncResult * res,
* The \a type will determine which component loader to use. The following types * The \a type will determine which component loader to use. The following types
* are built-in and will always work without a component loader: * are built-in and will always work without a component loader:
* - "module" - Loads a WirePlumber module * - "module" - Loads a WirePlumber module
* - "array" - Loads multiple components interpreting the \a args as a JSON
* array with component definitions, as they would appear in the
* configuration file. When this type is used, \a component is ignored and
* can be NULL
* *
* \ingroup wpcomponentloader * \ingroup wpcomponentloader
* \param self the core * \param self the core

View File

@@ -12,6 +12,324 @@
WP_DEFINE_LOCAL_LOG_TOPIC ("wp-internal-comp-loader") WP_DEFINE_LOCAL_LOG_TOPIC ("wp-internal-comp-loader")
/*** ComponentData ***/
enum
{
NO_FAIL = 0x1,
IF_EXISTS = 0x2
};
struct _ComponentData
{
gchar *name;
gchar *type;
gint priority;
gint flags;
WpSpaJson *deps;
};
typedef struct _ComponentData ComponentData;
static gint
component_cmp_func (const ComponentData *a, const ComponentData *b)
{
return b->priority - a->priority;
}
static gint
component_equal_func (const ComponentData *a, ComponentData * b)
{
return
g_str_equal (a->name, b->name) && g_str_equal (a->type, b->type) ? 0 : 1;
}
static void
component_data_free (ComponentData *self)
{
g_clear_pointer (&self->name, g_free);
g_clear_pointer (&self->type, g_free);
g_clear_pointer (&self->deps, wp_spa_json_unref);
g_slice_free (ComponentData, self);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ComponentData, component_data_free)
/*** components parser ***/
static gint
pick_default_component_priority (const char *type)
{
if (g_str_equal (type, "module"))
/* regular module default priority */
return 110;
else if (g_str_equal (type, "script/lua"))
/* Lua Script default priority */
return 100;
return 100;
}
static void
json_to_components_list (GList **list, WpSpaJson *json)
{
g_autoptr (WpIterator) it = NULL;
g_auto (GValue) item = G_VALUE_INIT;
it = wp_spa_json_new_iterator (json);
for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
WpSpaJson *cjson = g_value_get_boxed (&item);
g_autoptr (ComponentData) comp = g_slice_new0 (ComponentData);
g_autoptr (WpSpaJson) deps = NULL;
g_autoptr (WpSpaJson) flags = NULL;
/* Parse name and type (mandatory) */
if (!wp_spa_json_is_object (cjson) ||
!wp_spa_json_object_get (cjson,
"name", "s", &comp->name,
"type", "s", &comp->type,
NULL)) {
wp_warning ("component must have both a 'name' and a 'type'");
continue;
}
/* Parse priority (optional) */
if (!wp_spa_json_object_get (cjson, "priority", "i", &comp->priority,
NULL))
comp->priority = pick_default_component_priority (comp->type);
/* Parse deps (optional) */
if (wp_spa_json_object_get (cjson, "deps", "J", &deps, NULL)) {
if (wp_spa_json_is_array (deps)) {
comp->deps = g_steal_pointer (&deps);
} else {
wp_warning ("skipping component %s as its 'deps' is not a JSON array",
comp->name);
continue;
}
}
/* Parse flags (optional) */
if (wp_spa_json_object_get (cjson, "flags", "J", &flags, NULL)) {
if (flags && wp_spa_json_is_array (flags)) {
g_autoptr (WpIterator) it = wp_spa_json_new_iterator (flags);
g_auto (GValue) item = G_VALUE_INIT;
for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
WpSpaJson *flag = g_value_get_boxed (&item);
g_autofree gchar *flag_str = wp_spa_json_parse_string (flag);
if (g_str_equal (flag_str, "ifexists"))
comp->flags |= IF_EXISTS;
else if (g_str_equal (flag_str, "nofail"))
comp->flags |= NO_FAIL;
else
wp_warning ("flag '%s' is not valid for component '%s'", flag_str,
comp->name);
}
} else {
wp_warning ("skipping component %s as its 'flags' is not a JSON array",
comp->name);
continue;
}
}
/* Insert component into the list if it does not exist */
if (!g_list_find_custom (*list, comp,
(GCompareFunc) component_equal_func)) {
wp_trace ("appended component '%s' of type '%s' with priority '%d'",
comp->name, comp->type, comp->priority);
*list = g_list_insert_sorted (*list, g_steal_pointer (&comp),
(GCompareFunc) component_cmp_func);
} else {
wp_debug ("ignoring component '%s' as it is already defined previously",
comp->name);
}
}
}
/*** WpComponentArrayLoadTask ***/
struct _WpComponentArrayLoadTask
{
WpTransition parent;
WpSpaJson *json;
GList *components;
GList *components_iter;
ComponentData *curr_component;
};
enum {
STEP_PARSE = WP_TRANSITION_STEP_CUSTOM_START,
STEP_LOAD_NEXT_1,
STEP_LOAD_NEXT_2,
STEP_CLEANUP,
};
G_DECLARE_FINAL_TYPE (WpComponentArrayLoadTask, wp_component_array_load_task,
WP, COMPONENT_ARRAY_LOAD_TASK, WpTransition)
G_DEFINE_TYPE (WpComponentArrayLoadTask, wp_component_array_load_task,
WP_TYPE_TRANSITION)
static void
wp_component_array_load_task_init (WpComponentArrayLoadTask * self)
{
}
static gboolean
component_meets_dependencies (WpCore *core, ComponentData *comp)
{
g_autoptr (WpConf) conf = NULL;
g_autoptr (WpIterator) it = NULL;
g_auto (GValue) item = G_VALUE_INIT;
if (!comp->deps)
return TRUE;
/* Note that we consider the dependency valid by default if it is not
* found in the settings configuration section */
conf = wp_conf_get_instance (core);
it = wp_spa_json_new_iterator (comp->deps);
for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
WpSpaJson *dep = g_value_get_boxed (&item);
g_autofree gchar *dep_str = wp_spa_json_parse_string (dep);
gboolean value = wp_conf_get_value_boolean (conf,
"wireplumber.settings", dep_str, TRUE);
if (!value)
return FALSE;
}
return TRUE;
}
static guint
wp_component_array_load_task_get_next_step (WpTransition * transition, guint step)
{
WpComponentArrayLoadTask *self = WP_COMPONENT_ARRAY_LOAD_TASK (transition);
switch (step) {
case WP_TRANSITION_STEP_NONE: return STEP_PARSE;
case STEP_PARSE: return STEP_LOAD_NEXT_1;
case STEP_LOAD_NEXT_1:
return (self->components_iter) ? STEP_LOAD_NEXT_2 : STEP_CLEANUP;
case STEP_LOAD_NEXT_2:
return (self->components_iter) ? STEP_LOAD_NEXT_1 : STEP_CLEANUP;
case STEP_CLEANUP: return WP_TRANSITION_STEP_NONE;
default:
g_return_val_if_reached (WP_TRANSITION_STEP_ERROR);
}
}
static void
on_component_loaded (WpCore *core, GAsyncResult *res, gpointer data)
{
WpComponentArrayLoadTask *self = WP_COMPONENT_ARRAY_LOAD_TASK (data);
g_autoptr (GError) error = NULL;
g_return_if_fail (self->curr_component);
if (!wp_core_load_component_finish (core, res, &error)) {
if (self->curr_component->flags & IF_EXISTS &&
error->domain == G_IO_ERROR &&
error->code == G_IO_ERROR_NOT_FOUND) {
wp_info_object (self, "skipping component '%s' with 'ifexists' flag "
"because the file does not exist", self->curr_component->name);
goto next;
} else if (self->curr_component->flags & NO_FAIL) {
wp_info_object (self, "skipping component '%s' with 'nofail' flag "
"due to error: %s", self->curr_component->name, error->message);
goto next;
}
wp_transition_return_error (WP_TRANSITION (self), g_error_new (
WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
"failed to activate component '%s': %s", self->curr_component->name,
error->message));
return;
}
next:
wp_transition_advance (WP_TRANSITION (self));
}
static void
wp_component_array_load_task_execute_step (WpTransition * transition, guint step)
{
WpComponentArrayLoadTask *self = WP_COMPONENT_ARRAY_LOAD_TASK (transition);
WpCore *core = wp_transition_get_source_object (transition);
switch (step) {
case STEP_PARSE:
if (!wp_spa_json_is_array (self->json)) {
wp_transition_return_error (transition, g_error_new (
WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
"components section is not a JSON array"));
return;
}
json_to_components_list (&self->components, self->json);
self->components_iter = g_list_first (self->components);
wp_transition_advance (transition);
break;
case STEP_LOAD_NEXT_1:
case STEP_LOAD_NEXT_2:
self->curr_component = (ComponentData *) self->components_iter->data;
/* Advance iterator */
self->components_iter = g_list_next (self->components_iter);
/* Skip component if its dependencies are not met */
if (!component_meets_dependencies (core, self->curr_component)) {
wp_info_object (self, "... skipping component '%s' as its dependencies "
"are not met", self->curr_component->name);
wp_transition_advance (transition);
return;
}
/* Load the component */
wp_debug_object (self,
"... loading component '%s' ('%s') with priority '%d' and flags '%x'",
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,
(GAsyncReadyCallback) on_component_loaded, self);
break;
case STEP_CLEANUP:
case WP_TRANSITION_STEP_ERROR:
g_list_free_full (g_steal_pointer (&self->components),
(GDestroyNotify) component_data_free);
g_clear_pointer (&self->json, wp_spa_json_unref);
break;
default:
g_assert_not_reached ();
}
}
static void
wp_component_array_load_task_class_init (WpComponentArrayLoadTaskClass * klass)
{
WpTransitionClass * transition_class = (WpTransitionClass *) klass;
transition_class->get_next_step = wp_component_array_load_task_get_next_step;
transition_class->execute_step = wp_component_array_load_task_execute_step;
}
static WpTransition *
wp_component_array_load_task_new (WpSpaJson *json,
gpointer source_object, GCancellable * cancellable,
GAsyncReadyCallback callback, gpointer callback_data)
{
WpTransition *t = wp_transition_new (wp_component_array_load_task_get_type (),
source_object, cancellable, callback, callback_data);
WpComponentArrayLoadTask *task = WP_COMPONENT_ARRAY_LOAD_TASK (t);
task->json = wp_spa_json_ref (json);
return t;
}
/*** WpInternalCompLoader ***/
struct _WpInternalCompLoader struct _WpInternalCompLoader
{ {
GObject parent; GObject parent;
@@ -73,7 +391,7 @@ static gboolean
wp_internal_comp_loader_supports_type (WpComponentLoader * cl, wp_internal_comp_loader_supports_type (WpComponentLoader * cl,
const gchar * type) const gchar * type)
{ {
return g_str_equal (type, "module"); return g_str_equal (type, "module") || g_str_equal (type, "array");
} }
static void static void
@@ -81,18 +399,29 @@ wp_internal_comp_loader_load (WpComponentLoader * self, WpCore * core,
const gchar * component, const gchar * type, WpSpaJson * args, const gchar * component, const gchar * type, WpSpaJson * args,
GCancellable * cancellable, GAsyncReadyCallback callback, gpointer data) GCancellable * cancellable, GAsyncReadyCallback callback, gpointer data)
{ {
g_autoptr (GTask) task = g_task_new (self, cancellable, callback, data); if (g_str_equal (type, "module")) {
g_autoptr (GError) error = NULL; g_autoptr (GTask) task = g_task_new (self, cancellable, callback, data);
g_autoptr (GObject) o = NULL; g_autoptr (GError) error = NULL;
g_autoptr (GObject) o = NULL;
g_task_set_source_tag (task, wp_internal_comp_loader_load); g_task_set_source_tag (task, wp_internal_comp_loader_load);
/* load Module */ /* load module */
o = load_module (core, component, args, &error); o = load_module (core, component, args, &error);
if (o) if (o)
g_task_return_pointer (task, g_steal_pointer (&o), g_object_unref); g_task_return_pointer (task, g_steal_pointer (&o), g_object_unref);
else else
g_task_return_error (task, g_steal_pointer (&error)); g_task_return_error (task, g_steal_pointer (&error));
}
else if (g_str_equal (type, "array")) {
WpTransition *task = wp_component_array_load_task_new (args, core,
cancellable, callback, data);
wp_transition_set_source_tag (task, wp_internal_comp_loader_load);
wp_transition_advance (task);
}
else {
g_assert_not_reached ();
}
} }
static GObject * static GObject *
@@ -102,7 +431,12 @@ wp_internal_comp_loader_load_finish (WpComponentLoader * self,
g_return_val_if_fail ( g_return_val_if_fail (
g_async_result_is_tagged (res, wp_internal_comp_loader_load), NULL); g_async_result_is_tagged (res, wp_internal_comp_loader_load), NULL);
return g_task_propagate_pointer (G_TASK (res), error); if (G_IS_TASK (res))
return g_task_propagate_pointer (G_TASK (res), error);
else {
wp_transition_finish (res, error);
return NULL;
}
} }
static void static void

View File

@@ -38,65 +38,18 @@ static GOptionEntry entries[] =
{ NULL } { NULL }
}; };
struct _ComponentData
{
gchar *name;
gchar *type;
gint priority;
gint flags;
WpSpaJson *deps;
};
typedef struct _ComponentData ComponentData;
static gint
component_cmp_func (const ComponentData *a, const ComponentData *b)
{
return b->priority - a->priority;
}
static gint
component_equal_func (const ComponentData *a, ComponentData * b)
{
return
g_str_equal (a->name, b->name) && g_str_equal (a->type, b->type) ? 0 : 1;
}
static void
component_data_free (ComponentData *self)
{
g_clear_pointer (&self->name, g_free);
g_clear_pointer (&self->type, g_free);
g_clear_pointer (&self->deps, wp_spa_json_unref);
g_slice_free (ComponentData, self);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ComponentData, component_data_free)
enum
{
NO_FAIL = 0x1,
IF_EXISTS = 0x2
};
static void
on_plugin_loaded (WpCore *core, GAsyncResult *res, gpointer user_data);
/*** WpInitTransition ***/ /*** WpInitTransition ***/
struct _WpInitTransition struct _WpInitTransition
{ {
WpTransition parent; WpTransition parent;
WpObjectManager *om; WpObjectManager *om;
GList *components;
GList *components_iter;
ComponentData *curr_component;
}; };
enum { enum {
STEP_CONNECT = WP_TRANSITION_STEP_CUSTOM_START, STEP_CONNECT = WP_TRANSITION_STEP_CUSTOM_START,
STEP_CHECK_MEDIA_SESSION, STEP_CHECK_MEDIA_SESSION,
STEP_PARSE_COMPONENTS, STEP_LOAD_COMPONENTS,
STEP_LOAD_ENABLE_COMPONENTS,
STEP_CLEANUP, STEP_CLEANUP,
}; };
@@ -126,9 +79,8 @@ wp_init_transition_get_next_step (WpTransition * transition, guint step)
return STEP_CONNECT; return STEP_CONNECT;
} }
} }
case STEP_CHECK_MEDIA_SESSION: return STEP_PARSE_COMPONENTS; case STEP_CHECK_MEDIA_SESSION: return STEP_LOAD_COMPONENTS;
case STEP_PARSE_COMPONENTS: return STEP_LOAD_ENABLE_COMPONENTS; case STEP_LOAD_COMPONENTS: return STEP_CLEANUP;
case STEP_LOAD_ENABLE_COMPONENTS: return STEP_CLEANUP;
case STEP_CLEANUP: return WP_TRANSITION_STEP_NONE; case STEP_CLEANUP: return WP_TRANSITION_STEP_NONE;
default: default:
@@ -136,99 +88,6 @@ wp_init_transition_get_next_step (WpTransition * transition, guint step)
} }
} }
static gboolean
component_meets_dependencies (WpCore *core, ComponentData *comp)
{
g_autoptr (WpConf) conf = NULL;
g_autoptr (WpIterator) it = NULL;
g_auto (GValue) item = G_VALUE_INIT;
if (!comp->deps)
return TRUE;
/* Note that we consider the dependency valid by default if it is not
* found in the settings configuration section */
conf = wp_conf_get_instance (core);
it = wp_spa_json_new_iterator (comp->deps);
for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
WpSpaJson *dep = g_value_get_boxed (&item);
g_autofree gchar *dep_str = wp_spa_json_parse_string (dep);
gboolean value = wp_conf_get_value_boolean (conf,
"wireplumber.settings", dep_str, TRUE);
if (!value)
return FALSE;
}
return TRUE;
}
static gboolean
load_enable_components (WpInitTransition *self)
{
WpCore *core = wp_transition_get_source_object (WP_TRANSITION (self));
while (self->components_iter) {
self->curr_component = (ComponentData *) self->components_iter->data;
/* Advance */
self->components_iter = g_list_next (self->components_iter);
/* Skip component if its dependencies are not met */
if (!component_meets_dependencies (core, self->curr_component)) {
wp_info_object (self, "... skipping component '%s' as its dependencies "
"are not met", self->curr_component->name);
continue;
}
/* Load the component */
wp_debug_object (self,
"... loading component '%s' ('%s') with priority '%d' and flags '%x'",
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,
(GAsyncReadyCallback) on_plugin_loaded, self);
return FALSE;
}
self->curr_component = NULL;
return TRUE;
}
static void
on_plugin_loaded (WpCore *core, GAsyncResult *res, gpointer data)
{
WpInitTransition *self = data;
g_autoptr (GError) error = NULL;
g_return_if_fail (self->curr_component);
if (!wp_core_load_component_finish (core, res, &error)) {
if (self->curr_component->flags & IF_EXISTS &&
error->domain == G_IO_ERROR &&
error->code == G_IO_ERROR_NOT_FOUND) {
wp_info_object (self, "skipping component '%s' with 'ifexists' flag "
"because the file does not exist", self->curr_component->name);
goto next;
} else if (self->curr_component->flags & NO_FAIL) {
wp_info_object (self, "skipping component '%s' with 'nofail' flag "
"due to error: %s", self->curr_component->name, error->message);
goto next;
}
wp_transition_return_error (WP_TRANSITION (self), g_error_new (
WP_DOMAIN_DAEMON, WP_EXIT_CONFIG,
"failed to activate component '%s': %s", self->curr_component->name,
error->message));
return;
}
next:
/* load and enable the rest of components */
if (load_enable_components (self))
wp_transition_advance (WP_TRANSITION (self));
}
static void static void
check_media_session (WpObjectManager * om, WpInitTransition *self) check_media_session (WpObjectManager * om, WpInitTransition *self)
{ {
@@ -242,100 +101,20 @@ check_media_session (WpObjectManager * om, WpInitTransition *self)
wp_transition_advance (WP_TRANSITION (self)); wp_transition_advance (WP_TRANSITION (self));
} }
static gint
pick_default_component_priority (const char *type)
{
if (g_str_equal (type, "module"))
/* regular module default priority */
return 110;
else if (g_str_equal (type, "script/lua"))
/* Lua Script default priority */
return 100;
return 100;
}
static void static void
append_json_components (GList **list, WpSpaJson *json) on_components_loaded (WpCore *core, GAsyncResult *res, gpointer data)
{ {
g_autoptr (WpIterator) it = NULL; WpTransition *self = data;
g_auto (GValue) item = G_VALUE_INIT; g_autoptr (GError) error = NULL;
if (!wp_spa_json_is_array (json)) { if (!wp_core_load_component_finish (core, res, &error)) {
wp_warning ("components section is not a JSON array, skipping..."); wp_transition_return_error (self, g_error_new (
WP_DOMAIN_DAEMON, WP_EXIT_CONFIG,
"failed to load components: %s", error->message));
return; return;
} }
it = wp_spa_json_new_iterator (json); wp_transition_advance (self);
for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
WpSpaJson *cjson = g_value_get_boxed (&item);
g_autoptr (ComponentData) comp = g_slice_new0 (ComponentData);
g_autoptr (WpSpaJson) deps = NULL;
g_autoptr (WpSpaJson) flags = NULL;
/* Parse name and type (mandatory) */
if (!wp_spa_json_is_object (cjson) ||
!wp_spa_json_object_get (cjson,
"name", "s", &comp->name,
"type", "s", &comp->type,
NULL)) {
wp_warning ("component must have both a 'name' and a 'type'");
continue;
}
/* Parse priority (optional) */
if (!wp_spa_json_object_get (cjson, "priority", "i", &comp->priority,
NULL))
comp->priority = pick_default_component_priority (comp->type);
/* Parse deps (optional) */
if (wp_spa_json_object_get (cjson, "deps", "J", &deps, NULL)) {
if (wp_spa_json_is_array (deps)) {
comp->deps = g_steal_pointer (&deps);
} else {
wp_warning ("skipping component %s as its 'deps' is not a JSON array",
comp->name);
continue;
}
}
/* Parse flags (optional) */
if (wp_spa_json_object_get (cjson, "flags", "J", &flags, NULL)) {
if (flags && wp_spa_json_is_array (flags)) {
g_autoptr (WpIterator) it = wp_spa_json_new_iterator (flags);
g_auto (GValue) item = G_VALUE_INIT;
for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
WpSpaJson *flag = g_value_get_boxed (&item);
g_autofree gchar *flag_str = wp_spa_json_parse_string (flag);
if (g_str_equal (flag_str, "ifexists"))
comp->flags |= IF_EXISTS;
else if (g_str_equal (flag_str, "nofail"))
comp->flags |= NO_FAIL;
else
wp_warning ("flag '%s' is not valid for component '%s'", flag_str,
comp->name);
}
} else {
wp_warning ("skipping component %s as its 'flags' is not a JSON array",
comp->name);
continue;
}
}
/* Insert component into the list if it does not exist */
if (!g_list_find_custom (*list, comp,
(GCompareFunc) component_equal_func)) {
wp_trace ("appended component '%s' of type '%s' with priority '%d'",
comp->name, comp->type, comp->priority);
*list = g_list_insert_sorted (*list, g_steal_pointer (&comp),
(GCompareFunc) component_cmp_func);
} else {
wp_debug ("ignoring component '%s' as it is already defined previously",
comp->name);
}
}
} }
static void static void
@@ -403,36 +182,24 @@ wp_init_transition_execute_step (WpTransition * transition, guint step)
break; break;
} }
case STEP_PARSE_COMPONENTS: { case STEP_LOAD_COMPONENTS: {
g_autoptr (WpConf) conf = wp_conf_get_instance (core); g_autoptr (WpConf) conf = wp_conf_get_instance (core);
g_autoptr (WpSpaJson) json_comps = NULL; g_autoptr (WpSpaJson) json_comps = NULL;
wp_info_object (self, "parsing components..."); wp_info_object (self, "parsing & loading components...");
/* Append components that are defined in the configuration section */ /* Load components that are defined in the configuration section */
json_comps = wp_conf_get_section (conf, "wireplumber.components", NULL); json_comps = wp_conf_get_section (conf, "wireplumber.components", NULL);
if (json_comps) wp_core_load_component (core, NULL, "array", json_comps, NULL,
append_json_components (&self->components, json_comps); (GAsyncReadyCallback) on_components_loaded, self);
self->components_iter = g_list_first (self->components);
wp_transition_advance (transition);
break; break;
} }
case STEP_LOAD_ENABLE_COMPONENTS:
wp_info_object (self, "loading and enabling components...");
if (load_enable_components (self))
wp_transition_advance (WP_TRANSITION (self));
break;
case STEP_CLEANUP: case STEP_CLEANUP:
wp_info_object (self, "WirePlumber initialized"); wp_info_object (self, "WirePlumber initialized");
G_GNUC_FALLTHROUGH; G_GNUC_FALLTHROUGH;
case WP_TRANSITION_STEP_ERROR: case WP_TRANSITION_STEP_ERROR:
g_clear_object (&self->om); g_clear_object (&self->om);
g_list_free_full (g_steal_pointer (&self->components),
(GDestroyNotify) component_data_free);
break; break;
default: default: