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;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g_autoptr (WpConf) conf = wp_conf_get_instance (self);
|
const gchar *profile = wp_properties_get (props, "wireplumber.profile");
|
||||||
g_autoptr (WpSpaJson) json_comps = NULL;
|
|
||||||
|
|
||||||
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 */
|
/* Load components that are defined in the configuration section */
|
||||||
json_comps = wp_conf_get_section (conf, "wireplumber.components", NULL);
|
wp_core_load_component (self, profile, "profile", NULL, NULL, NULL,
|
||||||
wp_core_load_component (self, NULL, "array", json_comps, NULL, NULL,
|
|
||||||
(GAsyncReadyCallback) on_components_loaded, transition);
|
(GAsyncReadyCallback) on_components_loaded, transition);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -169,6 +169,8 @@ struct _WpComponentArrayLoadTask
|
|||||||
WpTransition parent;
|
WpTransition parent;
|
||||||
/* the input json object */
|
/* the input json object */
|
||||||
WpSpaJson *json;
|
WpSpaJson *json;
|
||||||
|
/* the features profile */
|
||||||
|
WpProperties *profile;
|
||||||
/* all components that provide a feature; key: comp->provides, value: comp */
|
/* all components that provide a feature; key: comp->provides, value: comp */
|
||||||
GHashTable *feat_components;
|
GHashTable *feat_components;
|
||||||
/* the final sorted list of components to load */
|
/* the final sorted list of components to load */
|
||||||
@@ -286,25 +288,11 @@ add_component (ComponentData * comp, gboolean strongly_required,
|
|||||||
return TRUE;
|
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
|
static gboolean
|
||||||
parse_components (WpComponentArrayLoadTask * self, GError ** error)
|
parse_components (WpComponentArrayLoadTask * self, GError ** error)
|
||||||
{
|
{
|
||||||
/* all the parsed components that are explicitly required */
|
/* all the parsed components that are explicitly required */
|
||||||
g_autoptr (GPtrArray) required_components = NULL;
|
g_autoptr (GPtrArray) required_components = NULL;
|
||||||
g_autoptr (WpProperties) conf = conf_get_features_section (self);
|
|
||||||
g_autoptr (WpIterator) it = NULL;
|
g_autoptr (WpIterator) it = NULL;
|
||||||
g_auto (GValue) item = G_VALUE_INIT;
|
g_auto (GValue) item = G_VALUE_INIT;
|
||||||
|
|
||||||
@@ -329,7 +317,7 @@ parse_components (WpComponentArrayLoadTask * self, GError ** error)
|
|||||||
GError *e = NULL;
|
GError *e = NULL;
|
||||||
g_autoptr (ComponentData) comp = 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);
|
g_propagate_error (error, e);
|
||||||
return FALSE;
|
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->feat_components, g_hash_table_unref);
|
||||||
g_clear_pointer (&self->components, g_ptr_array_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_clear_pointer (&self->json, wp_spa_json_unref);
|
||||||
|
|
||||||
G_OBJECT_CLASS (wp_component_array_load_task_parent_class)->finalize (object);
|
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 *
|
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,
|
gpointer source_object, GCancellable * cancellable,
|
||||||
GAsyncReadyCallback callback, gpointer callback_data)
|
GAsyncReadyCallback callback, gpointer callback_data)
|
||||||
{
|
{
|
||||||
@@ -496,6 +485,7 @@ wp_component_array_load_task_new (WpSpaJson *json,
|
|||||||
source_object, cancellable, callback, callback_data);
|
source_object, cancellable, callback, callback_data);
|
||||||
WpComponentArrayLoadTask *task = WP_COMPONENT_ARRAY_LOAD_TASK (t);
|
WpComponentArrayLoadTask *task = WP_COMPONENT_ARRAY_LOAD_TASK (t);
|
||||||
task->json = wp_spa_json_ref (json);
|
task->json = wp_spa_json_ref (json);
|
||||||
|
task->profile = wp_properties_ref (profile);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,9 +627,10 @@ 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") ||
|
|
||||||
g_str_equal (type, "virtual") ||
|
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
|
static void
|
||||||
@@ -647,8 +638,26 @@ 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)
|
||||||
{
|
{
|
||||||
if (g_str_equal (type, "array")) {
|
if (g_str_equal (type, "profile") || g_str_equal (type, "array")) {
|
||||||
WpTransition *task = wp_component_array_load_task_new (args, self,
|
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);
|
cancellable, callback, data);
|
||||||
wp_transition_set_data (task, g_object_ref (core), g_object_unref);
|
wp_transition_set_data (task, g_object_ref (core), g_object_unref);
|
||||||
wp_transition_set_source_tag (task, wp_internal_comp_loader_load);
|
wp_transition_set_source_tag (task, wp_internal_comp_loader_load);
|
||||||
|
@@ -77,11 +77,15 @@ context.modules = [
|
|||||||
{ name = libpipewire-module-spa-node-factory }
|
{ name = libpipewire-module-spa-node-factory }
|
||||||
]
|
]
|
||||||
|
|
||||||
wireplumber.features = {
|
wireplumber.profiles = {
|
||||||
## Syntax:
|
## Syntax:
|
||||||
|
## <profile> = {
|
||||||
|
## # optional is the default
|
||||||
## <feature name> = [ required | optional | disabled ]
|
## <feature name> = [ required | optional | disabled ]
|
||||||
## optional is the default
|
## ...
|
||||||
|
## }
|
||||||
|
|
||||||
|
main = {
|
||||||
check.no-media-session = required
|
check.no-media-session = required
|
||||||
support.settings = required
|
support.settings = required
|
||||||
hardware.audio = required
|
hardware.audio = required
|
||||||
@@ -89,6 +93,7 @@ wireplumber.features = {
|
|||||||
hardware.video-capture = required
|
hardware.video-capture = required
|
||||||
policy.standard = required
|
policy.standard = required
|
||||||
#policy.role-priority-system = optional
|
#policy.role-priority-system = optional
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wireplumber.components = [
|
wireplumber.components = [
|
||||||
|
@@ -161,6 +161,7 @@ main (gint argc, gchar **argv)
|
|||||||
PW_KEY_CONFIG_NAME, config_file,
|
PW_KEY_CONFIG_NAME, config_file,
|
||||||
PW_KEY_APP_NAME, "WirePlumber",
|
PW_KEY_APP_NAME, "WirePlumber",
|
||||||
"wireplumber.daemon", "true",
|
"wireplumber.daemon", "true",
|
||||||
|
"wireplumber.profile", "main",
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
/* init wireplumber daemon */
|
/* init wireplumber daemon */
|
||||||
|
@@ -200,14 +200,7 @@ test_dependencies_setup (TestFixture *f, gconstpointer data)
|
|||||||
static void
|
static void
|
||||||
test_dependencies (TestFixture *f, gconstpointer data)
|
test_dependencies (TestFixture *f, gconstpointer data)
|
||||||
{
|
{
|
||||||
g_autoptr (WpConf) conf = wp_conf_get_instance (f->base.core);
|
wp_core_load_component (f->base.core, "test", "profile", NULL,
|
||||||
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,
|
|
||||||
NULL, NULL, (GAsyncReadyCallback) on_component_loaded, f);
|
NULL, NULL, (GAsyncReadyCallback) on_component_loaded, f);
|
||||||
g_main_loop_run (f->base.loop);
|
g_main_loop_run (f->base.loop);
|
||||||
|
|
||||||
|
@@ -2,8 +2,10 @@ context.modules = [
|
|||||||
{ name = libpipewire-module-protocol-native }
|
{ name = libpipewire-module-protocol-native }
|
||||||
]
|
]
|
||||||
|
|
||||||
wireplumber.features = {
|
wireplumber.profiles = {
|
||||||
|
test = {
|
||||||
virtual.four = required
|
virtual.four = required
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wireplumber.components = [
|
wireplumber.components = [
|
||||||
|
Reference in New Issue
Block a user