diff --git a/src/daemon/minimal.conf.in b/src/daemon/minimal.conf.in index 673424d41..21ea5b518 100644 --- a/src/daemon/minimal.conf.in +++ b/src/daemon/minimal.conf.in @@ -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 + #} + } + } + } +] diff --git a/src/pipewire/impl-device.c b/src/pipewire/impl-device.c index ff243f7cd..184bed38d 100644 --- a/src/pipewire/impl-device.c +++ b/src/pipewire/impl-device.c @@ -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; } diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c index d36ac60a5..06a571407 100644 --- a/src/pipewire/impl-node.c +++ b/src/pipewire/impl-node.c @@ -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);