impl-node: add node.rules and device.rules

To be able to modify properties of nodes and devices. This is
interesting in the minimal config to give the nodes better defaults.
This commit is contained in:
Wim Taymans 2024-02-14 12:33:41 +01:00
parent fcea3eee01
commit 2807a1eafd
3 changed files with 92 additions and 12 deletions

View file

@ -191,10 +191,12 @@ context.objects = [
}
# This creates a ALSA udev device that will enumerate all
# ALSA devices. Because it is using ACP and has the audio-profile
# ALSA devices. Because it is using ACP and has the auto-profile
# property set, this will enable a profile and create associated
# nodes, which will be automatically configured to their best
# configuration.
# configuration with the auto-port-config settings.
# Extra node and device params can be given with node.param and
# device.param prefixes.
{ factory = spa-device-factory
args = {
factory.name = api.alsa.enum.udev
@ -411,3 +413,38 @@ context.exec = [
#
#@pulse_comment@{ path = "@pipewire_path@" args = "-c pipewire-pulse.conf" }
]
node.rules = [
{ matches = [
{
# all keys must match the value. ! negates. ~ starts regex.
#alsa.card_name = "ICUSBAUDIO7D"
#api.alsa.pcm.stream = "playback"
}
]
actions = {
update-props = {
#node.name = "alsa_playback.ICUSBAUDIO7D"
}
}
}
]
device.rules = [
{ matches = [
{
#alsa.card_name = "ICUSBAUDIO7D"
}
]
actions = {
update-props = {
#device.name = "alsa_card.ICUSBAUDIO7D"
#api.acp.auto-profile = false
#api.acp.auto-port = false
#device.param.Profile = {
# #idx = 0
# name = off
#}
}
}
}
]

View file

@ -117,9 +117,33 @@ static void object_register(struct object_data *od, uint32_t device_id)
}
}
struct match {
struct pw_impl_device *device;
int count;
};
#define MATCH_INIT(n) ((struct match){ .device = (n) })
static int execute_match(void *data, const char *location, const char *action,
const char *val, size_t len)
{
struct match *match = data;
struct pw_impl_device *this = match->device;
if (spa_streq(action, "update-props")) {
match->count += pw_properties_update_string(this->properties, val, len);
this->info.props = &this->properties->dict;
}
return 1;
}
static void check_properties(struct pw_impl_device *device)
{
struct pw_context *context = device->context;
const char *str;
struct match match;
match = MATCH_INIT(device);
pw_context_conf_section_match_rules(context, "device.rules",
&device->properties->dict, execute_match, &match);
if ((str = pw_properties_get(device->properties, PW_KEY_DEVICE_NAME)) &&
(device->name == NULL || !spa_streq(str, device->name))) {
@ -668,11 +692,10 @@ static int update_properties(struct pw_impl_device *device, const struct spa_dic
pw_log_debug("%p: updated %d properties", device, changed);
if (!changed)
return 0;
device->info.change_mask |= PW_DEVICE_CHANGE_MASK_PROPS;
if (changed) {
check_properties(device);
device->info.change_mask |= PW_DEVICE_CHANGE_MASK_PROPS;
}
return changed;
}
@ -961,6 +984,8 @@ int pw_impl_device_set_implementation(struct pw_impl_device *device, struct spa_
return -EEXIST;
}
device->device = spa_device;
res = spa_device_add_listener(device->device,
&device->listener, &device_events, device);
again:
spa_dict_for_each(it, &device->properties->dict) {
@ -971,8 +996,6 @@ again:
goto again;
}
}
res = spa_device_add_listener(device->device,
&device->listener, &device_events, device);
return res;
}

View file

@ -913,6 +913,24 @@ int pw_impl_node_set_driver(struct pw_impl_node *node, struct pw_impl_node *driv
return 0;
}
struct match {
struct pw_impl_node *node;
int count;
};
#define MATCH_INIT(n) ((struct match){ .node = (n) })
static int execute_match(void *data, const char *location, const char *action,
const char *val, size_t len)
{
struct match *match = data;
struct pw_impl_node *this = match->node;
if (spa_streq(action, "update-props")) {
match->count += pw_properties_update_string(this->properties, val, len);
this->info.props = &this->properties->dict;
}
return 1;
}
static void check_properties(struct pw_impl_node *node)
{
struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this);
@ -921,8 +939,11 @@ static void check_properties(struct pw_impl_node *node)
struct spa_fraction frac;
uint32_t value;
bool driver, trigger;
struct match match;
match = MATCH_INIT(node);
pw_context_conf_section_match_rules(context, "node.rules",
&node->properties->dict, execute_match, &match);
if ((str = pw_properties_get(node->properties, PW_KEY_PRIORITY_DRIVER))) {
value = pw_properties_parse_int(str);
@ -1980,6 +2001,7 @@ int pw_impl_node_set_implementation(struct pw_impl_node *node,
node->node = spa_node;
spa_node_set_callbacks(node->node, &node_callbacks, node);
res = spa_node_add_listener(node->node, &node->listener, &node_events, node);
again:
spa_dict_for_each(it, &node->properties->dict) {
@ -1991,8 +2013,6 @@ again:
}
}
res = spa_node_add_listener(node->node, &node->listener, &node_events, node);
if (node->registered)
update_io(node);