mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	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:
		
							parent
							
								
									fcea3eee01
								
							
						
					
					
						commit
						2807a1eafd
					
				
					 3 changed files with 92 additions and 12 deletions
				
			
		| 
						 | 
					@ -191,10 +191,12 @@ context.objects = [
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # This creates a ALSA udev device that will enumerate all
 | 
					    # 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
 | 
					    # property set, this will enable a profile and create associated
 | 
				
			||||||
    # nodes, which will be automatically configured to their best
 | 
					    # 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
 | 
					    { factory = spa-device-factory
 | 
				
			||||||
        args = {
 | 
					        args = {
 | 
				
			||||||
            factory.name           = api.alsa.enum.udev
 | 
					            factory.name           = api.alsa.enum.udev
 | 
				
			||||||
| 
						 | 
					@ -411,3 +413,38 @@ context.exec = [
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    #@pulse_comment@{ path = "@pipewire_path@" args = "-c pipewire-pulse.conf" }
 | 
					    #@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
 | 
				
			||||||
 | 
					                #}
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
					static void check_properties(struct pw_impl_device *device)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct pw_context *context = device->context;
 | 
				
			||||||
	const char *str;
 | 
						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)) &&
 | 
						if ((str = pw_properties_get(device->properties, PW_KEY_DEVICE_NAME)) &&
 | 
				
			||||||
	    (device->name == NULL || !spa_streq(str, 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);
 | 
						pw_log_debug("%p: updated %d properties", device, changed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!changed)
 | 
						if (changed) {
 | 
				
			||||||
		return 0;
 | 
							check_properties(device);
 | 
				
			||||||
 | 
							device->info.change_mask |= PW_DEVICE_CHANGE_MASK_PROPS;
 | 
				
			||||||
	device->info.change_mask |= PW_DEVICE_CHANGE_MASK_PROPS;
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return changed;
 | 
						return changed;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -961,6 +984,8 @@ int pw_impl_device_set_implementation(struct pw_impl_device *device, struct spa_
 | 
				
			||||||
		return -EEXIST;
 | 
							return -EEXIST;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	device->device = spa_device;
 | 
						device->device = spa_device;
 | 
				
			||||||
 | 
						res = spa_device_add_listener(device->device,
 | 
				
			||||||
 | 
								&device->listener, &device_events, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
again:
 | 
					again:
 | 
				
			||||||
	spa_dict_for_each(it, &device->properties->dict) {
 | 
						spa_dict_for_each(it, &device->properties->dict) {
 | 
				
			||||||
| 
						 | 
					@ -971,8 +996,6 @@ again:
 | 
				
			||||||
			goto again;
 | 
								goto again;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	res = spa_device_add_listener(device->device,
 | 
					 | 
				
			||||||
			&device->listener, &device_events, device);
 | 
					 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -913,6 +913,24 @@ int pw_impl_node_set_driver(struct pw_impl_node *node, struct pw_impl_node *driv
 | 
				
			||||||
	return 0;
 | 
						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)
 | 
					static void check_properties(struct pw_impl_node *node)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this);
 | 
						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;
 | 
						struct spa_fraction frac;
 | 
				
			||||||
	uint32_t value;
 | 
						uint32_t value;
 | 
				
			||||||
	bool driver, trigger;
 | 
						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))) {
 | 
						if ((str = pw_properties_get(node->properties, PW_KEY_PRIORITY_DRIVER))) {
 | 
				
			||||||
		value = pw_properties_parse_int(str);
 | 
							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;
 | 
						node->node = spa_node;
 | 
				
			||||||
	spa_node_set_callbacks(node->node, &node_callbacks, node);
 | 
						spa_node_set_callbacks(node->node, &node_callbacks, node);
 | 
				
			||||||
 | 
						res = spa_node_add_listener(node->node, &node->listener, &node_events, node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
again:
 | 
					again:
 | 
				
			||||||
	spa_dict_for_each(it, &node->properties->dict) {
 | 
						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)
 | 
						if (node->registered)
 | 
				
			||||||
		update_io(node);
 | 
							update_io(node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue