mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	filter-chain: parse and handle links
This commit is contained in:
		
							parent
							
								
									4d680a816f
								
							
						
					
					
						commit
						8ec0f1eb4b
					
				
					 1 changed files with 137 additions and 51 deletions
				
			
		| 
						 | 
					@ -181,6 +181,9 @@ struct graph {
 | 
				
			||||||
	uint32_t n_control;
 | 
						uint32_t n_control;
 | 
				
			||||||
	struct node *control_node[MAX_CONTROLS];
 | 
						struct node *control_node[MAX_CONTROLS];
 | 
				
			||||||
	uint32_t control_index[MAX_CONTROLS];
 | 
						uint32_t control_index[MAX_CONTROLS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LADSPA_Data silence_data[MAX_SAMPLES];
 | 
				
			||||||
 | 
						LADSPA_Data discard_data[MAX_SAMPLES];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct impl {
 | 
					struct impl {
 | 
				
			||||||
| 
						 | 
					@ -605,6 +608,36 @@ static uint32_t find_port(struct node *node, const char *name, int mask)
 | 
				
			||||||
	return SPA_ID_INVALID;
 | 
						return SPA_ID_INVALID;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct node_port {
 | 
				
			||||||
 | 
						struct node *node;
 | 
				
			||||||
 | 
						uint32_t port;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int find_node_port(struct graph *graph, char *name, int mask, struct node_port *result)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char *col, *node_name, *port_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						col = strchr(name, ':');
 | 
				
			||||||
 | 
						if (col != NULL) {
 | 
				
			||||||
 | 
							node_name = name;
 | 
				
			||||||
 | 
							port_name = col + 1;
 | 
				
			||||||
 | 
							*col = '\0';
 | 
				
			||||||
 | 
							result->node = find_node(graph, node_name);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							result->node = (mask & LADSPA_PORT_INPUT) ?
 | 
				
			||||||
 | 
								spa_list_first(&graph->node_list, struct node, link) :
 | 
				
			||||||
 | 
								spa_list_last(&graph->node_list, struct node, link);
 | 
				
			||||||
 | 
							node_name = result->node->name;
 | 
				
			||||||
 | 
							port_name = name;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (result->node == NULL)
 | 
				
			||||||
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
						result->port = find_port(result->node, port_name, mask);
 | 
				
			||||||
 | 
						if (result->port == SPA_ID_INVALID)
 | 
				
			||||||
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint32_t count_array(struct spa_json *json)
 | 
					static uint32_t count_array(struct spa_json *json)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct spa_json it = *json;
 | 
						struct spa_json it = *json;
 | 
				
			||||||
| 
						 | 
					@ -789,6 +822,64 @@ static int parse_control(struct node *node, struct spa_json *control)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * output = [name:][portname]
 | 
				
			||||||
 | 
					 * input = [name:][portname]
 | 
				
			||||||
 | 
					 * ...
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int parse_link(struct graph *graph, struct spa_json *json)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int res;
 | 
				
			||||||
 | 
						char key[256];
 | 
				
			||||||
 | 
						char output[256] = "";
 | 
				
			||||||
 | 
						char input[256] = "";
 | 
				
			||||||
 | 
						const char *val;
 | 
				
			||||||
 | 
						struct node_port np_in, np_out;
 | 
				
			||||||
 | 
						struct link *link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (spa_json_get_string(json, key, sizeof(key)) > 0) {
 | 
				
			||||||
 | 
							if (strcmp(key, "output") == 0) {
 | 
				
			||||||
 | 
								if (spa_json_get_string(json, output, sizeof(output)) <= 0) {
 | 
				
			||||||
 | 
									pw_log_error("output expects a string");
 | 
				
			||||||
 | 
									return -EINVAL;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (strcmp(key, "input") == 0) {
 | 
				
			||||||
 | 
								if (spa_json_get_string(json, input, sizeof(input)) <= 0) {
 | 
				
			||||||
 | 
									pw_log_error("input expects a string");
 | 
				
			||||||
 | 
									return -EINVAL;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (spa_json_next(json, &val) < 0)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if ((res = find_node_port(graph, output, LADSPA_PORT_OUTPUT, &np_out)) < 0)
 | 
				
			||||||
 | 
							return res;
 | 
				
			||||||
 | 
						if ((res = find_node_port(graph, input, LADSPA_PORT_INPUT, &np_in)) < 0)
 | 
				
			||||||
 | 
							return res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((link = calloc(1, sizeof(*link))) == NULL)
 | 
				
			||||||
 | 
							return -errno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						link->output = np_out.node;
 | 
				
			||||||
 | 
						link->output_port = np_out.port;
 | 
				
			||||||
 | 
						link->input = np_in.node;
 | 
				
			||||||
 | 
						link->input_port = np_in.port;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pw_log_info("linking %s:%s -> %s:%s",
 | 
				
			||||||
 | 
								link->output->name,
 | 
				
			||||||
 | 
								link->output->desc->desc->PortNames[link->output_port],
 | 
				
			||||||
 | 
								link->input->name,
 | 
				
			||||||
 | 
								link->input->desc->desc->PortNames[link->input_port]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_list_append(&link->output->output_link_list, &link->output_link);
 | 
				
			||||||
 | 
						link->input->n_input_links++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_list_append(&graph->link_list, &link->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * type = ladspa
 | 
					 * type = ladspa
 | 
				
			||||||
 * name = rev
 | 
					 * name = rev
 | 
				
			||||||
| 
						 | 
					@ -887,7 +978,7 @@ static int setup_graph(struct graph *graph, struct spa_json *inputs, struct spa_
 | 
				
			||||||
	unsigned long p;
 | 
						unsigned long p;
 | 
				
			||||||
	struct ladspa_descriptor *desc;
 | 
						struct ladspa_descriptor *desc;
 | 
				
			||||||
	const LADSPA_Descriptor *d;
 | 
						const LADSPA_Descriptor *d;
 | 
				
			||||||
	char v[256], *col, *node_name, *port_name;
 | 
						char v[256];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	graph->n_input = 0;
 | 
						graph->n_input = 0;
 | 
				
			||||||
	graph->n_output = 0;
 | 
						graph->n_output = 0;
 | 
				
			||||||
| 
						 | 
					@ -937,8 +1028,18 @@ static int setup_graph(struct graph *graph, struct spa_json *inputs, struct spa_
 | 
				
			||||||
				res = -ENOMEM;
 | 
									res = -ENOMEM;
 | 
				
			||||||
				goto error;
 | 
									goto error;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			node->n_hndl = i;
 | 
								node->n_hndl = i + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for (j = 0; j < desc->n_input; j++) {
 | 
				
			||||||
 | 
									p = desc->input[j];
 | 
				
			||||||
 | 
									d->connect_port(node->hndl[i], p, graph->silence_data);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								for (j = 0; j < desc->n_output; j++) {
 | 
				
			||||||
 | 
									p = desc->output[j];
 | 
				
			||||||
 | 
									pw_log_info("out %d %lu %s %p %p %p", i, p,
 | 
				
			||||||
 | 
											node->name, node->hndl[i], d, *d->connect_port);
 | 
				
			||||||
 | 
									d->connect_port(node->hndl[i], p, graph->discard_data);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			for (j = 0; j < desc->n_control; j++) {
 | 
								for (j = 0; j < desc->n_control; j++) {
 | 
				
			||||||
				p = desc->control[j];
 | 
									p = desc->control[j];
 | 
				
			||||||
				d->connect_port(node->hndl[i], p, &node->control_data[j]);
 | 
									d->connect_port(node->hndl[i], p, &node->control_data[j]);
 | 
				
			||||||
| 
						 | 
					@ -949,6 +1050,7 @@ static int setup_graph(struct graph *graph, struct spa_json *inputs, struct spa_
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (d->activate)
 | 
								if (d->activate)
 | 
				
			||||||
				d->activate(node->hndl[i]);
 | 
									d->activate(node->hndl[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		/* collect all control ports on the graph */
 | 
							/* collect all control ports on the graph */
 | 
				
			||||||
		for (j = 0; j < desc->n_control; j++) {
 | 
							for (j = 0; j < desc->n_control; j++) {
 | 
				
			||||||
| 
						 | 
					@ -957,6 +1059,22 @@ static int setup_graph(struct graph *graph, struct spa_json *inputs, struct spa_
 | 
				
			||||||
			graph->n_control++;
 | 
								graph->n_control++;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						/* set data on all ports */
 | 
				
			||||||
 | 
						spa_list_for_each(node, &graph->node_list, link) {
 | 
				
			||||||
 | 
							struct link *link;
 | 
				
			||||||
 | 
							desc = node->desc;
 | 
				
			||||||
 | 
							d = desc->desc;
 | 
				
			||||||
 | 
							spa_list_for_each(link, &node->output_link_list, output_link) {
 | 
				
			||||||
 | 
								for (i = 0; i < n_hndl; i++) {
 | 
				
			||||||
 | 
									pw_log_info("link %d  %s:%d %s:%d %p", i,
 | 
				
			||||||
 | 
											node->name, link->output_port,
 | 
				
			||||||
 | 
											link->input->name, link->input_port,
 | 
				
			||||||
 | 
											link->audio_data);
 | 
				
			||||||
 | 
									d->connect_port(node->hndl[i], link->output_port, link->audio_data);
 | 
				
			||||||
 | 
									d->connect_port(link->input->hndl[i], link->input_port, link->audio_data);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	/* now collect all input and output ports for all the handles. */
 | 
						/* now collect all input and output ports for all the handles. */
 | 
				
			||||||
	for (i = 0; i < n_hndl; i++) {
 | 
						for (i = 0; i < n_hndl; i++) {
 | 
				
			||||||
		if (inputs == NULL) {
 | 
							if (inputs == NULL) {
 | 
				
			||||||
| 
						 | 
					@ -972,39 +1090,22 @@ static int setup_graph(struct graph *graph, struct spa_json *inputs, struct spa_
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			struct spa_json it = *inputs;
 | 
								struct spa_json it = *inputs;
 | 
				
			||||||
			while (spa_json_get_string(&it, v, sizeof(v)) > 0) {
 | 
								while (spa_json_get_string(&it, v, sizeof(v)) > 0) {
 | 
				
			||||||
				col = strchr(v, ':');
 | 
									struct node_port np;
 | 
				
			||||||
				if (col != NULL) {
 | 
									if ((res = find_node_port(graph, v, LADSPA_PORT_INPUT, &np)) < 0) {
 | 
				
			||||||
					node_name = v;
 | 
										pw_log_error("input port %s not found", v);
 | 
				
			||||||
					port_name = col + 1;
 | 
					 | 
				
			||||||
					*col = '\0';
 | 
					 | 
				
			||||||
					node = find_node(graph, node_name);
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					node = first;
 | 
					 | 
				
			||||||
					node_name = first->name;
 | 
					 | 
				
			||||||
					port_name = v;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if (node == NULL) {
 | 
					 | 
				
			||||||
					pw_log_error("input node %s not found", node_name);
 | 
					 | 
				
			||||||
					res = -EINVAL;
 | 
					 | 
				
			||||||
					goto error;
 | 
										goto error;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				p = find_port(node, port_name, LADSPA_PORT_INPUT);
 | 
									desc = np.node->desc;
 | 
				
			||||||
				if (p == SPA_ID_INVALID) {
 | 
					 | 
				
			||||||
					pw_log_error("input port %s:%s not found", node_name, port_name);
 | 
					 | 
				
			||||||
					res = -EINVAL;
 | 
					 | 
				
			||||||
					goto error;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				desc = node->desc;
 | 
					 | 
				
			||||||
				d = desc->desc;
 | 
									d = desc->desc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				graph->in_desc[graph->n_input] = d;
 | 
									graph->in_desc[graph->n_input] = d;
 | 
				
			||||||
				graph->in_hndl[graph->n_input] = node->hndl[i];
 | 
									graph->in_hndl[graph->n_input] = np.node->hndl[i];
 | 
				
			||||||
				graph->in_port[graph->n_input] = p;
 | 
									graph->in_port[graph->n_input] = np.port;
 | 
				
			||||||
				graph->n_input++;
 | 
									graph->n_input++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (outputs == NULL) {
 | 
							if (outputs == NULL) {
 | 
				
			||||||
			desc = first->desc;
 | 
								desc = last->desc;
 | 
				
			||||||
			d = desc->desc;
 | 
								d = desc->desc;
 | 
				
			||||||
			for (j = 0; j < desc->n_output; j++) {
 | 
								for (j = 0; j < desc->n_output; j++) {
 | 
				
			||||||
				p = desc->output[j];
 | 
									p = desc->output[j];
 | 
				
			||||||
| 
						 | 
					@ -1016,35 +1117,19 @@ static int setup_graph(struct graph *graph, struct spa_json *inputs, struct spa_
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			struct spa_json it = *outputs;
 | 
								struct spa_json it = *outputs;
 | 
				
			||||||
			while (spa_json_get_string(&it, v, sizeof(v)) > 0) {
 | 
								while (spa_json_get_string(&it, v, sizeof(v)) > 0) {
 | 
				
			||||||
				col = strchr(v, ':');
 | 
									struct node_port np;
 | 
				
			||||||
				if (col != NULL) {
 | 
									if ((res = find_node_port(graph, v, LADSPA_PORT_OUTPUT, &np)) < 0) {
 | 
				
			||||||
					node_name = v;
 | 
										pw_log_error("output port %s not found", v);
 | 
				
			||||||
					port_name = col + 1;
 | 
					 | 
				
			||||||
					*col = '\0';
 | 
					 | 
				
			||||||
					node = find_node(graph, node_name);
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					node = first;
 | 
					 | 
				
			||||||
					node_name = first->name;
 | 
					 | 
				
			||||||
					port_name = v;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if (node == NULL) {
 | 
					 | 
				
			||||||
					pw_log_error("output node %s not found", node_name);
 | 
					 | 
				
			||||||
					res = -EINVAL;
 | 
					 | 
				
			||||||
					goto error;
 | 
										goto error;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				p = find_port(node, port_name, LADSPA_PORT_OUTPUT);
 | 
									desc = np.node->desc;
 | 
				
			||||||
				if (p == SPA_ID_INVALID) {
 | 
					 | 
				
			||||||
					pw_log_error("output port %s:%s not found", node_name, port_name);
 | 
					 | 
				
			||||||
					res = -EINVAL;
 | 
					 | 
				
			||||||
					goto error;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				desc = node->desc;
 | 
					 | 
				
			||||||
				d = desc->desc;
 | 
									d = desc->desc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				graph->out_desc[graph->n_output] = d;
 | 
									graph->out_desc[graph->n_output] = d;
 | 
				
			||||||
				graph->out_hndl[graph->n_output] = node->hndl[i];
 | 
									graph->out_hndl[graph->n_output] = np.node->hndl[i];
 | 
				
			||||||
				graph->out_port[graph->n_output] = p;
 | 
									graph->out_port[graph->n_output] = np.port;
 | 
				
			||||||
				graph->n_output++;
 | 
									graph->n_output++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1115,7 +1200,7 @@ static int load_graph(struct graph *graph, struct pw_properties *props)
 | 
				
			||||||
	while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
 | 
						while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
 | 
				
			||||||
		if (strcmp("nodes", key) == 0) {
 | 
							if (strcmp("nodes", key) == 0) {
 | 
				
			||||||
			if (spa_json_enter_array(&it[1], &it[2]) <= 0) {
 | 
								if (spa_json_enter_array(&it[1], &it[2]) <= 0) {
 | 
				
			||||||
				pw_log_error("nodes expect and array");
 | 
									pw_log_error("nodes expect an array");
 | 
				
			||||||
				return -EINVAL;
 | 
									return -EINVAL;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1129,7 +1214,8 @@ static int load_graph(struct graph *graph, struct pw_properties *props)
 | 
				
			||||||
				return -EINVAL;
 | 
									return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			while (spa_json_enter_object(&it[2], &it[3]) > 0) {
 | 
								while (spa_json_enter_object(&it[2], &it[3]) > 0) {
 | 
				
			||||||
				return -ENOTSUP;
 | 
									if ((res = parse_link(graph, &it[3])) < 0)
 | 
				
			||||||
 | 
										return res;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if (strcmp("inputs", key) == 0) {
 | 
							else if (strcmp("inputs", key) == 0) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue