mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	audio-dsp: handle node remove
Handle dynamic samplerate and channels Improve node names Keep track of removed nodes
This commit is contained in:
		
							parent
							
								
									08484b92f5
								
							
						
					
					
						commit
						d2c545be8d
					
				
					 1 changed files with 54 additions and 22 deletions
				
			
		| 
						 | 
					@ -21,6 +21,7 @@
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -117,7 +118,9 @@ struct port {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct node {
 | 
					struct node {
 | 
				
			||||||
	struct spa_list link;
 | 
						struct spa_list link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct pw_node *node;
 | 
						struct pw_node *node;
 | 
				
			||||||
 | 
						struct spa_hook node_listener;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -394,8 +397,10 @@ static int port_enum_formats(struct spa_node *node,
 | 
				
			||||||
			"I", t->media_subtype.raw,
 | 
								"I", t->media_subtype.raw,
 | 
				
			||||||
                        ":", t->format_audio.format,   "I", t->audio_format.S16,
 | 
					                        ":", t->format_audio.format,   "I", t->audio_format.S16,
 | 
				
			||||||
                        ":", t->format_audio.layout,   "i", SPA_AUDIO_LAYOUT_INTERLEAVED,
 | 
					                        ":", t->format_audio.layout,   "i", SPA_AUDIO_LAYOUT_INTERLEAVED,
 | 
				
			||||||
                        ":", t->format_audio.rate,     "i", n->sample_rate,
 | 
					                        ":", t->format_audio.rate,     "iru", n->sample_rate,
 | 
				
			||||||
                        ":", t->format_audio.channels, "i", n->channels);
 | 
									SPA_POD_PROP_MIN_MAX(1, INT32_MAX),
 | 
				
			||||||
 | 
					                        ":", t->format_audio.channels, "iru", n->channels,
 | 
				
			||||||
 | 
									SPA_POD_PROP_MIN_MAX(1, MAX_PORTS));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
| 
						 | 
					@ -475,6 +480,8 @@ static int port_set_format(struct spa_node *node, struct port *p,
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_info(NAME " %p: set format on port %p", n, p);
 | 
						pw_log_info(NAME " %p: set format on port %p", n, p);
 | 
				
			||||||
 | 
						n->sample_rate = info.info.raw.rate;
 | 
				
			||||||
 | 
						n->channels = info.info.raw.channels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -729,36 +736,42 @@ static struct port *make_port(struct node *n, enum pw_direction direction,
 | 
				
			||||||
	return p;
 | 
						return p;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct pw_node *make_node(struct impl *impl, const struct pw_properties *props,
 | 
					static struct node *make_node(struct impl *impl, const struct pw_properties *props,
 | 
				
			||||||
		enum pw_direction direction)
 | 
							enum pw_direction direction)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pw_node *node;
 | 
						struct pw_node *node;
 | 
				
			||||||
	struct node *n;
 | 
						struct node *n;
 | 
				
			||||||
	struct port *p;
 | 
						struct port *p;
 | 
				
			||||||
	const char *alias;
 | 
						const char *api, *alias, *plugged;
 | 
				
			||||||
	char node_name[128];
 | 
						char node_name[128];
 | 
				
			||||||
 | 
						struct pw_properties *pr;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((alias = pw_properties_get(props, "alsa.device")) == NULL)
 | 
						if ((api = pw_properties_get(props, "device.api")) == NULL)
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((alias = pw_properties_get(props, "device.name")) == NULL)
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	snprintf(node_name, sizeof(node_name), "system_%s", alias);
 | 
						snprintf(node_name, sizeof(node_name), "system_%s", alias);
 | 
				
			||||||
	for (i = 0; node_name[i]; i++) {
 | 
						for (i = 0; node_name[i]; i++) {
 | 
				
			||||||
		if (node_name[i] == ':' || node_name[i] == ',')
 | 
							if (node_name[i] == ':' || node_name[i] == ',')
 | 
				
			||||||
			node_name[i] = '_';
 | 
								node_name[i] = '_';
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if ((alias = pw_properties_get(props, "alsa.card")) == NULL)
 | 
					 | 
				
			||||||
		goto error;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	node = pw_node_new(impl->core, node_name,
 | 
						pr = pw_properties_new(
 | 
				
			||||||
				pw_properties_new(
 | 
					 | 
				
			||||||
					"alsa.card", alias,
 | 
					 | 
				
			||||||
			"media.class",
 | 
								"media.class",
 | 
				
			||||||
			direction == PW_DIRECTION_OUTPUT ?
 | 
								direction == PW_DIRECTION_OUTPUT ?
 | 
				
			||||||
				"Audio/DSP/Playback" :
 | 
									"Audio/DSP/Playback" :
 | 
				
			||||||
				"Audio/DSP/Capture",
 | 
									"Audio/DSP/Capture",
 | 
				
			||||||
					NULL),
 | 
								"device.name", alias,
 | 
				
			||||||
				sizeof(struct node));
 | 
								NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((plugged = pw_properties_get(props, "node.plugged")) != NULL)
 | 
				
			||||||
 | 
							pw_properties_set(pr, "node.plugged", plugged);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						node = pw_node_new(impl->core, node_name, pr, sizeof(struct node));
 | 
				
			||||||
        if (node == NULL)
 | 
					        if (node == NULL)
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -784,7 +797,8 @@ static struct pw_node *make_node(struct impl *impl, const struct pw_properties *
 | 
				
			||||||
		snprintf(port_name, sizeof(port_name), "%s_%d",
 | 
							snprintf(port_name, sizeof(port_name), "%s_%d",
 | 
				
			||||||
				direction == PW_DIRECTION_INPUT ? "playback" : "capture",
 | 
									direction == PW_DIRECTION_INPUT ? "playback" : "capture",
 | 
				
			||||||
				n->port_count[direction]);
 | 
									n->port_count[direction]);
 | 
				
			||||||
		snprintf(alias_name, sizeof(alias_name), "alsa_pcm:%s:%s%d",
 | 
							snprintf(alias_name, sizeof(alias_name), "%s_pcm:%s:%s%d",
 | 
				
			||||||
 | 
									api,
 | 
				
			||||||
				alias,
 | 
									alias,
 | 
				
			||||||
				direction == PW_DIRECTION_INPUT ? "in" : "out",
 | 
									direction == PW_DIRECTION_INPUT ? "in" : "out",
 | 
				
			||||||
				n->port_count[direction]);
 | 
									n->port_count[direction]);
 | 
				
			||||||
| 
						 | 
					@ -805,7 +819,7 @@ static struct pw_node *make_node(struct impl *impl, const struct pw_properties *
 | 
				
			||||||
	pw_node_register(node, NULL, pw_module_get_global(impl->module), NULL);
 | 
						pw_node_register(node, NULL, pw_module_get_global(impl->module), NULL);
 | 
				
			||||||
	pw_node_set_active(node, true);
 | 
						pw_node_set_active(node, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return node;
 | 
						return n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     error_free_node:
 | 
					     error_free_node:
 | 
				
			||||||
	pw_node_destroy(node);
 | 
						pw_node_destroy(node);
 | 
				
			||||||
| 
						 | 
					@ -813,16 +827,31 @@ static struct pw_node *make_node(struct impl *impl, const struct pw_properties *
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void node_destroy(void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct node *node = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_list_remove(&node->link);
 | 
				
			||||||
 | 
						pw_node_destroy(node->node);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct pw_node_events node_events = {
 | 
				
			||||||
 | 
						PW_VERSION_NODE_EVENTS,
 | 
				
			||||||
 | 
						.destroy = node_destroy,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int on_global(void *data, struct pw_global *global)
 | 
					static int on_global(void *data, struct pw_global *global)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
	struct pw_node *n, *node;
 | 
						struct pw_node *n;
 | 
				
			||||||
 | 
						struct node *node;
 | 
				
			||||||
	const struct pw_properties *properties;
 | 
						const struct pw_properties *properties;
 | 
				
			||||||
	const char *str;
 | 
						const char *str;
 | 
				
			||||||
	char *error;
 | 
						char *error;
 | 
				
			||||||
	struct pw_port *ip, *op;
 | 
						struct pw_port *ip, *op;
 | 
				
			||||||
	struct pw_link *link;
 | 
						struct pw_link *link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pw_global_get_type(global) != impl->t->node)
 | 
						if (pw_global_get_type(global) != impl->t->node)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -832,12 +861,14 @@ static int on_global(void *data, struct pw_global *global)
 | 
				
			||||||
	if ((str = pw_properties_get(properties, "media.class")) == NULL)
 | 
						if ((str = pw_properties_get(properties, "media.class")) == NULL)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pw_log_debug("global added %s", str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (strcmp(str, "Audio/Sink") == 0) {
 | 
						if (strcmp(str, "Audio/Sink") == 0) {
 | 
				
			||||||
		if ((ip = pw_node_get_free_port(n, PW_DIRECTION_INPUT)) == NULL)
 | 
							if ((ip = pw_node_get_free_port(n, PW_DIRECTION_INPUT)) == NULL)
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		if ((node = make_node(impl, properties, PW_DIRECTION_OUTPUT)) == NULL)
 | 
							if ((node = make_node(impl, properties, PW_DIRECTION_OUTPUT)) == NULL)
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		if ((op = pw_node_get_free_port(node, PW_DIRECTION_OUTPUT)) == NULL)
 | 
							if ((op = pw_node_get_free_port(node->node, PW_DIRECTION_OUTPUT)) == NULL)
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else if (strcmp(str, "Audio/Source") == 0) {
 | 
						else if (strcmp(str, "Audio/Source") == 0) {
 | 
				
			||||||
| 
						 | 
					@ -845,7 +876,7 @@ static int on_global(void *data, struct pw_global *global)
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		if ((node = make_node(impl, properties, PW_DIRECTION_INPUT)) == NULL)
 | 
							if ((node = make_node(impl, properties, PW_DIRECTION_INPUT)) == NULL)
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		if ((ip = pw_node_get_free_port(node, PW_DIRECTION_INPUT)) == NULL)
 | 
							if ((ip = pw_node_get_free_port(node->node, PW_DIRECTION_INPUT)) == NULL)
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
| 
						 | 
					@ -862,9 +893,10 @@ static int on_global(void *data, struct pw_global *global)
 | 
				
			||||||
		free(error);
 | 
							free(error);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	pw_link_register(link, NULL, pw_module_get_global(impl->module), NULL);
 | 
						pw_link_register(link, NULL, pw_module_get_global(impl->module), NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pw_node_add_listener(n, &node->node_listener, &node_events, node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue