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
This commit is contained in:
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -77,11 +77,15 @@ context.modules = [
|
||||
{ name = libpipewire-module-spa-node-factory }
|
||||
]
|
||||
|
||||
wireplumber.features = {
|
||||
wireplumber.profiles = {
|
||||
## Syntax:
|
||||
## <profile> = {
|
||||
## # optional is the default
|
||||
## <feature name> = [ required | optional | disabled ]
|
||||
## optional is the default
|
||||
## ...
|
||||
## }
|
||||
|
||||
main = {
|
||||
check.no-media-session = required
|
||||
support.settings = required
|
||||
hardware.audio = required
|
||||
@@ -89,6 +93,7 @@ wireplumber.features = {
|
||||
hardware.video-capture = required
|
||||
policy.standard = required
|
||||
#policy.role-priority-system = optional
|
||||
}
|
||||
}
|
||||
|
||||
wireplumber.components = [
|
||||
|
@@ -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 */
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -2,8 +2,10 @@ context.modules = [
|
||||
{ name = libpipewire-module-protocol-native }
|
||||
]
|
||||
|
||||
wireplumber.features = {
|
||||
wireplumber.profiles = {
|
||||
test = {
|
||||
virtual.four = required
|
||||
}
|
||||
}
|
||||
|
||||
wireplumber.components = [
|
||||
|
Reference in New Issue
Block a user