From 84d33822922171f7c01bf1ab7579588157299a8c Mon Sep 17 00:00:00 2001 From: George Kiagiadakis Date: Fri, 23 Jun 2023 20:15:26 +0300 Subject: [PATCH] config: make it possible to have feature profiles A profile is a list of features set to required/optional/disabled which governs which components are getting loaded, given a static components list with well-defined dependencies --- lib/wp/core.c | 9 +++-- lib/wp/private/internal-comp-loader.c | 49 ++++++++++++++++----------- src/config/wireplumber.conf | 25 ++++++++------ src/main.c | 1 + tests/wp/component-loader.c | 9 +---- tests/wp/component-loader.conf | 6 ++-- 6 files changed, 54 insertions(+), 45 deletions(-) diff --git a/lib/wp/core.c b/lib/wp/core.c index bc72a388..06edca57 100644 --- a/lib/wp/core.c +++ b/lib/wp/core.c @@ -476,14 +476,13 @@ wp_core_activate_execute_step (WpObject * object, return; } else { - g_autoptr (WpConf) conf = wp_conf_get_instance (self); - g_autoptr (WpSpaJson) json_comps = NULL; + const gchar *profile = wp_properties_get (props, "wireplumber.profile"); - wp_info_object (self, "parsing & loading components..."); + wp_info_object (self, + "parsing & loading components for profile [%s]...", profile); /* Load components that are defined in the configuration section */ - json_comps = wp_conf_get_section (conf, "wireplumber.components", NULL); - wp_core_load_component (self, NULL, "array", json_comps, NULL, NULL, + wp_core_load_component (self, profile, "profile", NULL, NULL, NULL, (GAsyncReadyCallback) on_components_loaded, transition); } break; diff --git a/lib/wp/private/internal-comp-loader.c b/lib/wp/private/internal-comp-loader.c index fbcf9d84..dc711f59 100644 --- a/lib/wp/private/internal-comp-loader.c +++ b/lib/wp/private/internal-comp-loader.c @@ -169,6 +169,8 @@ struct _WpComponentArrayLoadTask WpTransition parent; /* the input json object */ WpSpaJson *json; + /* the features profile */ + WpProperties *profile; /* all components that provide a feature; key: comp->provides, value: comp */ GHashTable *feat_components; /* the final sorted list of components to load */ @@ -286,25 +288,11 @@ add_component (ComponentData * comp, gboolean strongly_required, return TRUE; } -static WpProperties * -conf_get_features_section (WpComponentArrayLoadTask * self) -{ - WpProperties *props = wp_properties_new_empty (); - WpCore *core = wp_transition_get_data (WP_TRANSITION (self)); - g_autoptr (WpConf) conf = wp_conf_get_instance (core); - g_autoptr (WpSpaJson) json = - wp_conf_get_section (conf, "wireplumber.features", NULL); - if (json) - wp_properties_update_from_json (props, json); - return props; -} - static gboolean parse_components (WpComponentArrayLoadTask * self, GError ** error) { /* all the parsed components that are explicitly required */ g_autoptr (GPtrArray) required_components = NULL; - g_autoptr (WpProperties) conf = conf_get_features_section (self); g_autoptr (WpIterator) it = NULL; g_auto (GValue) item = G_VALUE_INIT; @@ -329,7 +317,7 @@ parse_components (WpComponentArrayLoadTask * self, GError ** error) GError *e = NULL; g_autoptr (ComponentData) comp = NULL; - if (!(comp = component_data_new_from_json (cjson, conf, &e))) { + if (!(comp = component_data_new_from_json (cjson, self->profile, &e))) { g_propagate_error (error, e); return FALSE; } @@ -470,6 +458,7 @@ wp_component_array_load_task_finalize (GObject * object) g_clear_pointer (&self->feat_components, g_hash_table_unref); g_clear_pointer (&self->components, g_ptr_array_unref); + g_clear_pointer (&self->profile, wp_properties_unref); g_clear_pointer (&self->json, wp_spa_json_unref); G_OBJECT_CLASS (wp_component_array_load_task_parent_class)->finalize (object); @@ -488,7 +477,7 @@ wp_component_array_load_task_class_init (WpComponentArrayLoadTaskClass * klass) } static WpTransition * -wp_component_array_load_task_new (WpSpaJson *json, +wp_component_array_load_task_new (WpSpaJson * json, WpProperties * profile, gpointer source_object, GCancellable * cancellable, GAsyncReadyCallback callback, gpointer callback_data) { @@ -496,6 +485,7 @@ wp_component_array_load_task_new (WpSpaJson *json, source_object, cancellable, callback, callback_data); WpComponentArrayLoadTask *task = WP_COMPONENT_ARRAY_LOAD_TASK (t); task->json = wp_spa_json_ref (json); + task->profile = wp_properties_ref (profile); return t; } @@ -637,9 +627,10 @@ wp_internal_comp_loader_supports_type (WpComponentLoader * cl, const gchar * type) { return g_str_equal (type, "module") || - g_str_equal (type, "array") || g_str_equal (type, "virtual") || - g_str_equal (type, "built-in"); + g_str_equal (type, "built-in") || + g_str_equal (type, "profile") || + g_str_equal (type, "array"); } static void @@ -647,8 +638,26 @@ wp_internal_comp_loader_load (WpComponentLoader * self, WpCore * core, const gchar * component, const gchar * type, WpSpaJson * args, GCancellable * cancellable, GAsyncReadyCallback callback, gpointer data) { - if (g_str_equal (type, "array")) { - WpTransition *task = wp_component_array_load_task_new (args, self, + if (g_str_equal (type, "profile") || g_str_equal (type, "array")) { + WpTransition *task = NULL; + g_autoptr (WpSpaJson) components = NULL; + g_autoptr (WpProperties) profile = wp_properties_new_empty (); + + if (g_str_equal (type, "profile")) { + /* component name is the profile name; + component list and profile features are loaded from config */ + g_autoptr (WpConf) conf = wp_conf_get_instance (core); + g_autoptr (WpSpaJson) profile_json = + wp_conf_get_value (conf, "wireplumber.profiles", component, NULL); + if (profile_json) + wp_properties_update_from_json (profile, profile_json); + components = wp_conf_get_section (conf, "wireplumber.components", NULL); + } else { + /* component list is retrieved from args; profile features are empty */ + components = wp_spa_json_ref (args); + } + + task = wp_component_array_load_task_new (components, profile, self, cancellable, callback, data); wp_transition_set_data (task, g_object_ref (core), g_object_unref); wp_transition_set_source_tag (task, wp_internal_comp_loader_load); diff --git a/src/config/wireplumber.conf b/src/config/wireplumber.conf index c0289923..38bc6675 100644 --- a/src/config/wireplumber.conf +++ b/src/config/wireplumber.conf @@ -77,18 +77,23 @@ context.modules = [ { name = libpipewire-module-spa-node-factory } ] -wireplumber.features = { +wireplumber.profiles = { ## Syntax: - ## = [ required | optional | disabled ] - ## optional is the default + ## = { + ## # optional is the default + ## = [ required | optional | disabled ] + ## ... + ## } - check.no-media-session = required - support.settings = required - hardware.audio = required - hardware.bluetooth = required - hardware.video-capture = required - policy.standard = required - #policy.role-priority-system = optional + main = { + check.no-media-session = required + support.settings = required + hardware.audio = required + hardware.bluetooth = required + hardware.video-capture = required + policy.standard = required + #policy.role-priority-system = optional + } } wireplumber.components = [ diff --git a/src/main.c b/src/main.c index 5b6f5409..fc44612c 100644 --- a/src/main.c +++ b/src/main.c @@ -161,6 +161,7 @@ main (gint argc, gchar **argv) PW_KEY_CONFIG_NAME, config_file, PW_KEY_APP_NAME, "WirePlumber", "wireplumber.daemon", "true", + "wireplumber.profile", "main", NULL); /* init wireplumber daemon */ diff --git a/tests/wp/component-loader.c b/tests/wp/component-loader.c index 388c7b7b..8223c07b 100644 --- a/tests/wp/component-loader.c +++ b/tests/wp/component-loader.c @@ -200,14 +200,7 @@ test_dependencies_setup (TestFixture *f, gconstpointer data) static void test_dependencies (TestFixture *f, gconstpointer data) { - g_autoptr (WpConf) conf = wp_conf_get_instance (f->base.core); - g_assert_nonnull (conf); - - g_autoptr (WpSpaJson) components = wp_conf_get_section (conf, - "wireplumber.components", NULL); - g_assert_nonnull (components); - - wp_core_load_component (f->base.core, NULL, "array", components, + wp_core_load_component (f->base.core, "test", "profile", NULL, NULL, NULL, (GAsyncReadyCallback) on_component_loaded, f); g_main_loop_run (f->base.loop); diff --git a/tests/wp/component-loader.conf b/tests/wp/component-loader.conf index 2af7c31c..f642e2ab 100644 --- a/tests/wp/component-loader.conf +++ b/tests/wp/component-loader.conf @@ -2,8 +2,10 @@ context.modules = [ { name = libpipewire-module-protocol-native } ] -wireplumber.features = { - virtual.four = required +wireplumber.profiles = { + test = { + virtual.four = required + } } wireplumber.components = [