comp-loader: add support for wireplumber.components.rules

This is a new rules section that allows defining rules to modify
component definitions. This is useful to add repetitive dependencies,
for example, as in the case of "type = script/lua" that always requires
the "support.lua-scripting" feature. This can also be useful to modify
other component properties, such as the arguments, in overriding
configuration files, without needing to redefine the whole components
section.
This commit is contained in:
George Kiagiadakis
2023-11-14 12:42:32 +02:00
parent 42b64bfc28
commit 4593245fbb
3 changed files with 208 additions and 75 deletions

View File

@@ -83,12 +83,83 @@ get_feature_state (WpProperties * dict, const gchar * feature)
} }
} }
static ComponentData * static gboolean
component_data_new_from_json (WpSpaJson * json, WpProperties * features, component_rule_match_cb (gpointer data, const gchar * action, WpSpaJson * value,
GError ** error) GError ** error)
{
WpProperties *props = data;
g_autoptr (WpIterator) it = NULL;
g_auto (GValue) item = G_VALUE_INIT;
gboolean merge;
if (!wp_spa_json_is_object (value)) {
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
"expected JSON object instead of: %.*s", (int) wp_spa_json_get_size (value),
wp_spa_json_get_data (value));
return FALSE;
}
if (g_str_equal (action, "merge")) {
merge = TRUE;
} else if (g_str_equal (action, "override")) {
merge = FALSE;
} else {
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
"invalid action '%s' in component rules", action);
return FALSE;
}
it = wp_spa_json_new_iterator (value);
do {
g_autofree gchar *key = NULL;
g_autofree gchar *val = NULL;
const gchar *old_val = NULL;
/* extract key */
if (!wp_iterator_next (it, &item))
break;
key = wp_spa_json_to_string (g_value_get_boxed (&item));
g_value_unset (&item);
/* extract value */
if (!wp_iterator_next (it, &item)) {
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
"expected value for key '%s' in component rules", key);
return FALSE;
}
val = wp_spa_json_to_string (g_value_get_boxed (&item));
g_value_unset (&item);
old_val = wp_properties_get (props, key);
/* override if not merging or if the value is not a container */
if (!merge || !old_val || (*old_val != '[' && *old_val != '{')) {
wp_properties_set (props, key, val);
}
else {
g_autoptr (WpSpaJson) old_json = NULL;
g_autoptr (WpSpaJson) new_json = NULL;
g_autoptr (WpSpaJson) merged_json = NULL;
old_json = wp_spa_json_new_wrap_string (old_val);
new_json = wp_spa_json_new_wrap_string (val);
merged_json = wp_json_utils_merge_containers (old_json, new_json);
wp_properties_set (props, key,
merged_json ? wp_spa_json_get_data (merged_json) : val);
}
} while (TRUE);
return TRUE;
}
static ComponentData *
component_data_new_from_json (WpSpaJson * json, WpProperties * features,
WpSpaJson * rules, GError ** error)
{ {
g_autoptr (ComponentData) comp = NULL; g_autoptr (ComponentData) comp = NULL;
g_autoptr (WpSpaJson) comp_reqs = NULL, comp_wants = NULL; g_autoptr (WpProperties) props = NULL;
const gchar *str;
if (!wp_spa_json_is_object (json)) { if (!wp_spa_json_is_object (json)) {
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT, g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
@@ -102,17 +173,24 @@ component_data_new_from_json (WpSpaJson * json, WpProperties * features,
comp->requires = g_ptr_array_new_with_free_func (g_free); comp->requires = g_ptr_array_new_with_free_func (g_free);
comp->wants = g_ptr_array_new_with_free_func (g_free); comp->wants = g_ptr_array_new_with_free_func (g_free);
if (!wp_spa_json_object_get (json, "type", "s", &comp->type, NULL)) { props = wp_properties_new_json (json);
if (rules && !wp_json_utils_match_rules (rules, props, component_rule_match_cb,
props, error))
return NULL;
if (!(comp->type = g_strdup (wp_properties_get (props, "type")))) {
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT, g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
"component 'type' is required at: %.*s", (int) wp_spa_json_get_size (json), "component 'type' is required at: %.*s", (int) wp_spa_json_get_size (json),
wp_spa_json_get_data (json)); wp_spa_json_get_data (json));
return NULL; return NULL;
} }
wp_spa_json_object_get (json, "name", "s", &comp->name, NULL); comp->name = g_strdup (wp_properties_get (props, "name"));
wp_spa_json_object_get (json, "arguments", "J", &comp->arguments, NULL); str = wp_properties_get (props, "arguments");
comp->arguments = str ? wp_spa_json_new_from_string (str) : NULL;
if (wp_spa_json_object_get (json, "provides", "s", &comp->provides, NULL)) { if ((str = wp_properties_get (props, "provides"))) {
comp->provides = g_strdup (str);
comp->state = get_feature_state (features, comp->provides); comp->state = get_feature_state (features, comp->provides);
if (comp->name) { if (comp->name) {
comp->printable_id = comp->printable_id =
@@ -126,7 +204,8 @@ component_data_new_from_json (WpSpaJson * json, WpProperties * features,
comp->printable_id = g_strdup_printf ("[%s: %s]", comp->type, comp->name); comp->printable_id = g_strdup_printf ("[%s: %s]", comp->type, comp->name);
} }
if (wp_spa_json_object_get (json, "requires", "J", &comp_reqs, NULL)) { if ((str = wp_properties_get (props, "requires"))) {
g_autoptr (WpSpaJson) comp_reqs = wp_spa_json_new_wrap_string (str);
g_autoptr (WpIterator) it = wp_spa_json_new_iterator (comp_reqs); g_autoptr (WpIterator) it = wp_spa_json_new_iterator (comp_reqs);
g_auto (GValue) item = G_VALUE_INIT; g_auto (GValue) item = G_VALUE_INIT;
@@ -136,7 +215,8 @@ component_data_new_from_json (WpSpaJson * json, WpProperties * features,
} }
} }
if (wp_spa_json_object_get (json, "wants", "J", &comp_wants, NULL)) { if ((str = wp_properties_get (props, "wants"))) {
g_autoptr (WpSpaJson) comp_wants = wp_spa_json_new_wrap_string (str);
g_autoptr (WpIterator) it = wp_spa_json_new_iterator (comp_wants); g_autoptr (WpIterator) it = wp_spa_json_new_iterator (comp_wants);
g_auto (GValue) item = G_VALUE_INIT; g_auto (GValue) item = G_VALUE_INIT;
@@ -171,6 +251,8 @@ struct _WpComponentArrayLoadTask
WpSpaJson *json; WpSpaJson *json;
/* the features profile */ /* the features profile */
WpProperties *profile; WpProperties *profile;
/* the rules to apply on each component description */
WpSpaJson *rules;
/* 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 */
@@ -317,7 +399,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, self->profile, &e))) { if (!(comp = component_data_new_from_json (cjson, self->profile, self->rules, &e))) {
g_propagate_error (error, e); g_propagate_error (error, e);
return FALSE; return FALSE;
} }
@@ -459,6 +541,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->profile, wp_properties_unref);
g_clear_pointer (&self->rules, wp_spa_json_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);
@@ -478,7 +561,7 @@ wp_component_array_load_task_class_init (WpComponentArrayLoadTaskClass * klass)
static WpTransition * static WpTransition *
wp_component_array_load_task_new (WpSpaJson * json, WpProperties * profile, wp_component_array_load_task_new (WpSpaJson * json, WpProperties * profile,
gpointer source_object, GCancellable * cancellable, WpSpaJson * rules, gpointer source_object, GCancellable * cancellable,
GAsyncReadyCallback callback, gpointer callback_data) GAsyncReadyCallback callback, gpointer callback_data)
{ {
WpTransition *t = wp_transition_new (wp_component_array_load_task_get_type (), WpTransition *t = wp_transition_new (wp_component_array_load_task_get_type (),
@@ -486,6 +569,7 @@ wp_component_array_load_task_new (WpSpaJson * json, WpProperties * profile,
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); task->profile = wp_properties_ref (profile);
task->rules = rules ? wp_spa_json_ref (rules) : NULL;
return t; return t;
} }
@@ -641,23 +725,30 @@ wp_internal_comp_loader_load (WpComponentLoader * self, WpCore * core,
if (g_str_equal (type, "profile") || g_str_equal (type, "array")) { if (g_str_equal (type, "profile") || g_str_equal (type, "array")) {
WpTransition *task = NULL; WpTransition *task = NULL;
g_autoptr (WpSpaJson) components = NULL; g_autoptr (WpSpaJson) components = NULL;
g_autoptr (WpSpaJson) rules = NULL;
g_autoptr (WpProperties) profile = wp_properties_new_empty (); g_autoptr (WpProperties) profile = wp_properties_new_empty ();
if (g_str_equal (type, "profile")) { if (g_str_equal (type, "profile")) {
/* component name is the profile name; /* component name is the profile name;
component list and profile features are loaded from config */ component list and profile features are loaded from config */
g_autoptr (WpConf) conf = wp_conf_get_instance (core); g_autoptr (WpConf) conf = wp_conf_get_instance (core);
g_autoptr (WpSpaJson) profile_json = g_autoptr (WpSpaJson) profile_json = NULL;
profile_json =
wp_conf_get_value (conf, "wireplumber.profiles", component, NULL); wp_conf_get_value (conf, "wireplumber.profiles", component, NULL);
if (profile_json) if (profile_json)
wp_properties_update_from_json (profile, profile_json); wp_properties_update_from_json (profile, profile_json);
components = wp_conf_get_section (conf, "wireplumber.components", NULL); components = wp_conf_get_section (conf, "wireplumber.components", NULL);
} else {
rules = wp_conf_get_section (conf, "wireplumber.components.rules", NULL);
}
else {
/* component list is retrieved from args; profile features are empty */ /* component list is retrieved from args; profile features are empty */
components = wp_spa_json_ref (args); components = wp_spa_json_ref (args);
} }
task = wp_component_array_load_task_new (components, profile, self, task = wp_component_array_load_task_new (components, profile, rules, 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);

View File

@@ -214,7 +214,6 @@ wireplumber.components = [
name = metadata.lua, type = script/lua name = metadata.lua, type = script/lua
arguments = { metadata.name = default } arguments = { metadata.name = default }
provides = metadata.default provides = metadata.default
requires = [ support.lua-scripting ]
} }
## Provide the "filters" pw_metadata ## Provide the "filters" pw_metadata
@@ -222,7 +221,6 @@ wireplumber.components = [
name = metadata.lua, type = script/lua name = metadata.lua, type = script/lua
arguments = { metadata.name = filters } arguments = { metadata.name = filters }
provides = metadata.filters provides = metadata.filters
requires = [ support.lua-scripting ]
} }
## Device monitors' optional features ## Device monitors' optional features
@@ -243,54 +241,49 @@ wireplumber.components = [
{ {
name = monitors/alsa.lua, type = script/lua name = monitors/alsa.lua, type = script/lua
provides = monitor.alsa provides = monitor.alsa
requires = [ support.lua-scripting, support.export-core ] requires = [ support.export-core ]
wants = [ monitor.alsa.reserve-device ] wants = [ monitor.alsa.reserve-device ]
} }
{ {
name = monitors/bluez.lua, type = script/lua name = monitors/bluez.lua, type = script/lua
provides = monitor.bluez provides = monitor.bluez
requires = [ support.lua-scripting, support.export-core ] requires = [ support.export-core ]
wants = [ monitor.bluetooth.seat-monitoring ] wants = [ monitor.bluetooth.seat-monitoring ]
} }
{ {
name = monitors/bluez-midi.lua, type = script/lua name = monitors/bluez-midi.lua, type = script/lua
provides = monitor.bluez-midi provides = monitor.bluez-midi
requires = [ support.lua-scripting, support.export-core ] requires = [ support.export-core ]
wants = [ monitor.bluetooth.seat-monitoring ] wants = [ monitor.bluetooth.seat-monitoring ]
} }
{ {
name = monitors/alsa-midi.lua, type = script/lua name = monitors/alsa-midi.lua, type = script/lua
provides = monitor.alsa-midi provides = monitor.alsa-midi
requires = [ support.lua-scripting ]
wants = [ monitor.alsa-midi.monitoring ] wants = [ monitor.alsa-midi.monitoring ]
} }
## v4l2 monitor hooks ## v4l2 monitor hooks
{ {
name = monitors/v4l2/name-device.lua, type = script/lua name = monitors/v4l2/name-device.lua, type = script/lua
provides = hooks.monitor.v4l2-name-device provides = hooks.monitor.v4l2-name-device
requires = [ support.lua-scripting, requires = [ support.export-core,
support.export-core,
support.standard-event-source ] support.standard-event-source ]
} }
{ {
name = monitors/v4l2/create-device.lua, type = script/lua name = monitors/v4l2/create-device.lua, type = script/lua
provides = hooks.monitor.v4l2-create-device provides = hooks.monitor.v4l2-create-device
requires = [ support.lua-scripting, requires = [ support.export-core,
support.export-core,
support.standard-event-source ] support.standard-event-source ]
} }
{ {
name = monitors/v4l2/name-node.lua, type = script/lua name = monitors/v4l2/name-node.lua, type = script/lua
provides = hooks.monitor.v4l2-name-node provides = hooks.monitor.v4l2-name-node
requires = [ support.lua-scripting, requires = [ support.export-core,
support.export-core,
support.standard-event-source ] support.standard-event-source ]
} }
{ {
name = monitors/v4l2/create-node.lua, type = script/lua name = monitors/v4l2/create-node.lua, type = script/lua
provides = hooks.monitor.v4l2-create-node provides = hooks.monitor.v4l2-create-node
requires = [ support.lua-scripting, requires = [ support.export-core,
support.export-core,
support.standard-event-source ] support.standard-event-source ]
} }
{ {
@@ -304,8 +297,7 @@ wireplumber.components = [
{ {
name = monitors/v4l2/enumerate-device.lua, type = script/lua name = monitors/v4l2/enumerate-device.lua, type = script/lua
provides = hooks.monitor.v4l2-enumerate-device provides = hooks.monitor.v4l2-enumerate-device
requires = [ support.lua-scripting, requires = [ support.export-core,
support.export-core,
support.standard-event-source, support.standard-event-source,
monitor.v4l2.hooks ] monitor.v4l2.hooks ]
} }
@@ -319,29 +311,25 @@ wireplumber.components = [
{ {
name = monitors/libcamera/name-device.lua, type = script/lua name = monitors/libcamera/name-device.lua, type = script/lua
provides = hooks.monitor.libcamera-name-device provides = hooks.monitor.libcamera-name-device
requires = [ support.lua-scripting, requires = [ support.export-core,
support.export-core,
support.standard-event-source ] support.standard-event-source ]
} }
{ {
name = monitors/libcamera/create-device.lua, type = script/lua name = monitors/libcamera/create-device.lua, type = script/lua
provides = hooks.monitor.libcamera-create-device provides = hooks.monitor.libcamera-create-device
requires = [ support.lua-scripting, requires = [ support.export-core,
support.export-core,
support.standard-event-source ] support.standard-event-source ]
} }
{ {
name = monitors/libcamera/name-node.lua, type = script/lua name = monitors/libcamera/name-node.lua, type = script/lua
provides = hooks.monitor.libcamera-name-node provides = hooks.monitor.libcamera-name-node
requires = [ support.lua-scripting, requires = [ support.export-core,
support.export-core,
support.standard-event-source ] support.standard-event-source ]
} }
{ {
name = monitors/libcamera/create-node.lua, type = script/lua name = monitors/libcamera/create-node.lua, type = script/lua
provides = hooks.monitor.libcamera-create-node provides = hooks.monitor.libcamera-create-node
requires = [ support.lua-scripting, requires = [ support.export-core,
support.export-core,
support.standard-event-source ] support.standard-event-source ]
} }
{ {
@@ -355,8 +343,7 @@ wireplumber.components = [
{ {
name = monitors/libcamera/enumerate-device.lua, type = script/lua name = monitors/libcamera/enumerate-device.lua, type = script/lua
provides = hooks.monitor.libcamera-enumerate-device provides = hooks.monitor.libcamera-enumerate-device
requires = [ support.lua-scripting, requires = [ support.export-core,
support.export-core,
support.standard-event-source, support.standard-event-source,
monitor.libcamera.hooks ] monitor.libcamera.hooks ]
} }
@@ -370,12 +357,11 @@ wireplumber.components = [
{ {
name = client/access-default.lua, type = script/lua name = client/access-default.lua, type = script/lua
provides = script.client.access-default provides = script.client.access-default
requires = [ support.lua-scripting ]
} }
{ {
name = client/access-portal.lua, type = script/lua name = client/access-portal.lua, type = script/lua
provides = script.client.access-portal provides = script.client.access-portal
requires = [ support.lua-scripting, support.portal-permissionstore ] requires = [ support.portal-permissionstore ]
} }
{ {
type = virtual, provides = policy.client.access type = virtual, provides = policy.client.access
@@ -387,27 +373,22 @@ wireplumber.components = [
{ {
name = device/select-profile.lua, type = script/lua name = device/select-profile.lua, type = script/lua
provides = hooks.device.profile.select provides = hooks.device.profile.select
requires = [ support.lua-scripting ]
} }
{ {
name = device/find-best-profile.lua, type = script/lua name = device/find-best-profile.lua, type = script/lua
provides = hooks.device.profile.find-best provides = hooks.device.profile.find-best
requires = [ support.lua-scripting ]
} }
{ {
name = device/state-profile.lua, type = script/lua name = device/state-profile.lua, type = script/lua
provides = hooks.device.profile.state provides = hooks.device.profile.state
requires = [ support.lua-scripting ]
} }
{ {
name = device/apply-profile.lua, type = script/lua name = device/apply-profile.lua, type = script/lua
provides = hooks.device.profile.apply provides = hooks.device.profile.apply
requires = [ support.lua-scripting ]
} }
{ {
name = device/autoswitch-bluetooth-profile.lua, type = script/lua name = device/autoswitch-bluetooth-profile.lua, type = script/lua
provides = hooks.device.profile.autoswitch-bluetooth provides = hooks.device.profile.autoswitch-bluetooth
requires = [ support.lua-scripting ]
} }
{ {
type = virtual, provides = policy.device.profile type = virtual, provides = policy.device.profile
@@ -422,22 +403,18 @@ wireplumber.components = [
{ {
name = device/select-routes.lua, type = script/lua name = device/select-routes.lua, type = script/lua
provides = hooks.device.routes.select provides = hooks.device.routes.select
requires = [ support.lua-scripting ]
} }
{ {
name = device/find-best-routes.lua, type = script/lua name = device/find-best-routes.lua, type = script/lua
provides = hooks.device.routes.find-best provides = hooks.device.routes.find-best
requires = [ support.lua-scripting ]
} }
{ {
name = device/state-routes.lua, type = script/lua name = device/state-routes.lua, type = script/lua
provides = hooks.device.routes.state provides = hooks.device.routes.state
requires = [ support.lua-scripting ]
} }
{ {
name = device/apply-routes.lua, type = script/lua name = device/apply-routes.lua, type = script/lua
provides = hooks.device.routes.apply provides = hooks.device.routes.apply
requires = [ support.lua-scripting ]
} }
{ {
type = virtual, provides = policy.device.routes type = virtual, provides = policy.device.routes
@@ -451,27 +428,25 @@ wireplumber.components = [
{ {
name = default-nodes/rescan.lua, type = script/lua name = default-nodes/rescan.lua, type = script/lua
provides = hooks.default-nodes.rescan provides = hooks.default-nodes.rescan
requires = [ support.lua-scripting ]
} }
{ {
name = default-nodes/find-selected-default-node.lua, type = script/lua name = default-nodes/find-selected-default-node.lua, type = script/lua
provides = hooks.default-nodes.find-selected provides = hooks.default-nodes.find-selected
requires = [ support.lua-scripting, metadata.default ] requires = [ metadata.default ]
} }
{ {
name = default-nodes/find-best-default-node.lua, type = script/lua name = default-nodes/find-best-default-node.lua, type = script/lua
provides = hooks.default-nodes.find-best provides = hooks.default-nodes.find-best
requires = [ support.lua-scripting ]
} }
{ {
name = default-nodes/state-default-nodes.lua, type = script/lua name = default-nodes/state-default-nodes.lua, type = script/lua
provides = hooks.default-nodes.state provides = hooks.default-nodes.state
requires = [ support.lua-scripting, metadata.default ] requires = [ metadata.default ]
} }
{ {
name = default-nodes/apply-default-node.lua, type = script/lua, name = default-nodes/apply-default-node.lua, type = script/lua,
provides = hooks.default-nodes.apply provides = hooks.default-nodes.apply
requires = [ support.lua-scripting, metadata.default ] requires = [ metadata.default ]
} }
{ {
type = virtual, provides = policy.default-nodes type = virtual, provides = policy.default-nodes
@@ -486,74 +461,67 @@ wireplumber.components = [
{ {
name = node/create-item.lua, type = script/lua name = node/create-item.lua, type = script/lua
provides = hooks.node.create-session-item provides = hooks.node.create-session-item
requires = [ support.lua-scripting, si.audio-adapter, si.node ] requires = [ si.audio-adapter, si.node ]
} }
{ {
name = node/suspend-node.lua, type = script/lua name = node/suspend-node.lua, type = script/lua
provides = hooks.node.suspend provides = hooks.node.suspend
requires = [ support.lua-scripting ]
} }
{ {
name = node/state-stream.lua, type = script/lua name = node/state-stream.lua, type = script/lua
provides = hooks.stream.state provides = hooks.stream.state
requires = [ support.lua-scripting ]
} }
{ {
name = linking/filter-forward-format.lua, type = script/lua name = linking/filter-forward-format.lua, type = script/lua
provides = hooks.loopback.forward-format provides = hooks.loopback.forward-format
requires = [ support.lua-scripting ]
} }
{ {
name = node/create-virtual-item.lua, type = script/lua name = node/create-virtual-item.lua, type = script/lua
provides = script.create-role-items provides = script.create-role-items
requires = [ support.lua-scripting, si.audio-virtual ] requires = [ si.audio-virtual ]
} }
## Linking hooks ## Linking hooks
{ {
name = linking/rescan.lua, type = script/lua name = linking/rescan.lua, type = script/lua
provides = hooks.linking.rescan provides = hooks.linking.rescan
requires = [ support.lua-scripting ]
} }
{ {
name = linking/move-follow.lua, type = script/lua name = linking/move-follow.lua, type = script/lua
provides = hooks.linking.move-follow provides = hooks.linking.move-follow
requires = [ support.lua-scripting ]
} }
{ {
name = linking/find-defined-target.lua, type = script/lua name = linking/find-defined-target.lua, type = script/lua
provides = hooks.linking.target.find-defined provides = hooks.linking.target.find-defined
requires = [ support.lua-scripting ]
} }
{ {
name = linking/find-filter-target.lua, type = script/lua name = linking/find-filter-target.lua, type = script/lua
provides = hooks.linking.target.find-filter provides = hooks.linking.target.find-filter
requires = [ support.lua-scripting, metadata.filters ] requires = [ metadata.filters ]
} }
{ {
name = linking/find-default-target.lua, type = script/lua name = linking/find-default-target.lua, type = script/lua
provides = hooks.linking.target.find-default provides = hooks.linking.target.find-default
requires = [ support.lua-scripting, api.default-nodes ] requires = [ api.default-nodes ]
} }
{ {
name = linking/find-best-target.lua, type = script/lua name = linking/find-best-target.lua, type = script/lua
provides = hooks.linking.target.find-best provides = hooks.linking.target.find-best
requires = [ support.lua-scripting ]
} }
{ {
name = linking/get-filter-from-target.lua, type = script/lua name = linking/get-filter-from-target.lua, type = script/lua
provides = hooks.linking.target.get-filter-from provides = hooks.linking.target.get-filter-from
requires = [ support.lua-scripting, metadata.filters ] requires = [ metadata.filters ]
} }
{ {
name = linking/prepare-link.lua, type = script/lua name = linking/prepare-link.lua, type = script/lua
provides = hooks.linking.target.prepare-link provides = hooks.linking.target.prepare-link
requires = [ support.lua-scripting, api.default-nodes ] requires = [ api.default-nodes ]
} }
{ {
name = linking/link-target.lua, type = script/lua name = linking/link-target.lua, type = script/lua
provides = hooks.linking.target.link provides = hooks.linking.target.link
requires = [ support.lua-scripting, si.standard-link ] requires = [ si.standard-link ]
} }
{ {
type = virtual, provides = policy.linking.standard type = virtual, provides = policy.linking.standard
@@ -572,12 +540,11 @@ wireplumber.components = [
{ {
name = linking/rescan-virtual-links.lua, type = script/lua name = linking/rescan-virtual-links.lua, type = script/lua
provides = hooks.linking.role-priority-system.links.rescan provides = hooks.linking.role-priority-system.links.rescan
requires = [ support.lua-scripting, api.mixer ] requires = [ api.mixer ]
} }
{ {
name = linking/find-virtual-target.lua, type = script/lua name = linking/find-virtual-target.lua, type = script/lua
provides = hooks.linking.role-priority-system.target.find provides = hooks.linking.role-priority-system.target.find
requires = [ support.lua-scripting ]
} }
{ {
type = virtual, provides = policy.linking.role-priority-system type = virtual, provides = policy.linking.role-priority-system
@@ -619,6 +586,38 @@ wireplumber.components = [
} }
] ]
wireplumber.components.rules = [
## Rules to apply on top of wireplumber.components
## Syntax:
## {
## matches = [
## {
## [ <key> = <value> ... ]
## }
## ...
## ]
## actions = {
## <override|merge> = {
## [ <key> = <value> ... ]
## }
## ...
## }
## }
{
matches = [
{
type = "script/lua"
}
]
actions = {
merge = {
requires = [ support.lua-scripting ]
}
}
}
]
wireplumber.settings = { wireplumber.settings = {
## This main config file is only supposed to contain the common settings and ## This main config file is only supposed to contain the common settings and
## rules. rest of the settings and rules are distributed across ## rules. rest of the settings and rules are distributed across

View File

@@ -21,17 +21,17 @@ wireplumber.components = [
name = two name = two
type = test type = test
provides = support.two provides = support.two
requires = [ support.one support.six ] requires = [ support.one ]
} }
{ {
type = virtual type = virtual
provides = virtual.four provides = virtual.four
requires = [ support.four ] requires = [ INVALID ]
} }
{ {
name = three name = three
type = test type = test
provides = support.three provides = INVALID
wants = [ support.two ] wants = [ support.two ]
} }
{ {
@@ -64,3 +64,46 @@ wireplumber.components = [
requires = [ support.four ] requires = [ support.four ]
} }
] ]
wireplumber.components.rules = [
{
matches = [
{
name = two
}
]
actions = {
merge = {
# final array should be [ support.one, support.six ]
# if this fails, support.six will not be loaded
requires = [ support.six ]
}
}
}
{
matches = [
{
name = three
}
]
actions = {
merge = {
provides = support.three
}
}
}
{
matches = [
{
provides = virtual.four
}
]
actions = {
override = {
requires = [ support.four ]
}
}
}
]