mirror of
https://gitlab.freedesktop.org/pipewire/pipewire
synced 2024-10-14 20:02:38 +00:00
filter-chain: Support null inputs/outputs
Handle null inputs by ignoring the port Handle null output by clearing the buffer. Make sure we only have one input and output linked.
This commit is contained in:
parent
2017de6da8
commit
e94a977dcd
|
@ -136,6 +136,7 @@ struct port {
|
||||||
|
|
||||||
struct spa_list link_list;
|
struct spa_list link_list;
|
||||||
uint32_t n_links;
|
uint32_t n_links;
|
||||||
|
uint32_t external;
|
||||||
|
|
||||||
LADSPA_Data control_data;
|
LADSPA_Data control_data;
|
||||||
LADSPA_Data *audio_data[MAX_HNDL];
|
LADSPA_Data *audio_data[MAX_HNDL];
|
||||||
|
@ -278,7 +279,8 @@ static void capture_process(void *d)
|
||||||
for (i = 0; i < in->buffer->n_datas; i++) {
|
for (i = 0; i < in->buffer->n_datas; i++) {
|
||||||
struct spa_data *ds = &in->buffer->datas[i];
|
struct spa_data *ds = &in->buffer->datas[i];
|
||||||
struct graph_port *port = &graph->input[i];
|
struct graph_port *port = &graph->input[i];
|
||||||
port->desc->connect_port(port->hndl, port->port,
|
if (port->desc)
|
||||||
|
port->desc->connect_port(port->hndl, port->port,
|
||||||
SPA_MEMBER(ds->data, ds->chunk->offset, void));
|
SPA_MEMBER(ds->data, ds->chunk->offset, void));
|
||||||
size = SPA_MAX(size, ds->chunk->size);
|
size = SPA_MAX(size, ds->chunk->size);
|
||||||
stride = SPA_MAX(stride, ds->chunk->stride);
|
stride = SPA_MAX(stride, ds->chunk->stride);
|
||||||
|
@ -286,7 +288,10 @@ static void capture_process(void *d)
|
||||||
for (i = 0; i < out->buffer->n_datas; i++) {
|
for (i = 0; i < out->buffer->n_datas; i++) {
|
||||||
struct spa_data *dd = &out->buffer->datas[i];
|
struct spa_data *dd = &out->buffer->datas[i];
|
||||||
struct graph_port *port = &graph->output[i];
|
struct graph_port *port = &graph->output[i];
|
||||||
port->desc->connect_port(port->hndl, port->port, dd->data);
|
if (port->desc)
|
||||||
|
port->desc->connect_port(port->hndl, port->port, dd->data);
|
||||||
|
else
|
||||||
|
memset(dd->data, 0, size);
|
||||||
dd->chunk->offset = 0;
|
dd->chunk->offset = 0;
|
||||||
dd->chunk->size = size;
|
dd->chunk->size = size;
|
||||||
dd->chunk->stride = stride;
|
dd->chunk->stride = stride;
|
||||||
|
@ -862,8 +867,8 @@ static struct ladspa_descriptor *ladspa_descriptor_load(struct impl *impl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (desc->n_input == 0 || desc->n_output == 0) {
|
if (desc->n_input == 0 && desc->n_output == 0) {
|
||||||
pw_log_error("plugin has no input or no output ports");
|
pw_log_error("plugin has no input and no output ports");
|
||||||
res = -ENOTSUP;
|
res = -ENOTSUP;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -949,7 +954,16 @@ static int parse_link(struct graph *graph, struct spa_json *json)
|
||||||
pw_log_error("unknown input port %s", input);
|
pw_log_error("unknown input port %s", input);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
if (in_port->external != SPA_ID_INVALID) {
|
||||||
|
pw_log_info("%s already used as graph input %d, use mixer",
|
||||||
|
input, in_port->external);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (out_port->external != SPA_ID_INVALID) {
|
||||||
|
pw_log_info("%s already used as graph output %d, use copy",
|
||||||
|
output, out_port->external);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
if (in_port->n_links > 0) {
|
if (in_port->n_links > 0) {
|
||||||
pw_log_info("Can't have more than 1 link to %s, use a mixer", input);
|
pw_log_info("Can't have more than 1 link to %s, use a mixer", input);
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
|
@ -1062,6 +1076,7 @@ static int load_node(struct graph *graph, struct spa_json *json)
|
||||||
struct port *port = &node->input_port[i];
|
struct port *port = &node->input_port[i];
|
||||||
port->node = node;
|
port->node = node;
|
||||||
port->idx = i;
|
port->idx = i;
|
||||||
|
port->external = SPA_ID_INVALID;
|
||||||
port->p = desc->input[i];
|
port->p = desc->input[i];
|
||||||
spa_list_init(&port->link_list);
|
spa_list_init(&port->link_list);
|
||||||
}
|
}
|
||||||
|
@ -1069,6 +1084,7 @@ static int load_node(struct graph *graph, struct spa_json *json)
|
||||||
struct port *port = &node->output_port[i];
|
struct port *port = &node->output_port[i];
|
||||||
port->node = node;
|
port->node = node;
|
||||||
port->idx = i;
|
port->idx = i;
|
||||||
|
port->external = SPA_ID_INVALID;
|
||||||
port->p = desc->output[i];
|
port->p = desc->output[i];
|
||||||
spa_list_init(&port->link_list);
|
spa_list_init(&port->link_list);
|
||||||
}
|
}
|
||||||
|
@ -1076,6 +1092,7 @@ static int load_node(struct graph *graph, struct spa_json *json)
|
||||||
struct port *port = &node->control_port[i];
|
struct port *port = &node->control_port[i];
|
||||||
port->node = node;
|
port->node = node;
|
||||||
port->idx = i;
|
port->idx = i;
|
||||||
|
port->external = SPA_ID_INVALID;
|
||||||
port->p = desc->control[i];
|
port->p = desc->control[i];
|
||||||
spa_list_init(&port->link_list);
|
spa_list_init(&port->link_list);
|
||||||
port->control_data = desc->default_control[i];
|
port->control_data = desc->default_control[i];
|
||||||
|
@ -1084,6 +1101,7 @@ static int load_node(struct graph *graph, struct spa_json *json)
|
||||||
struct port *port = &node->notify_port[i];
|
struct port *port = &node->notify_port[i];
|
||||||
port->node = node;
|
port->node = node;
|
||||||
port->idx = i;
|
port->idx = i;
|
||||||
|
port->external = SPA_ID_INVALID;
|
||||||
port->p = desc->notify[i];
|
port->p = desc->notify[i];
|
||||||
spa_list_init(&port->link_list);
|
spa_list_init(&port->link_list);
|
||||||
}
|
}
|
||||||
|
@ -1104,8 +1122,10 @@ static void node_free(struct node *node)
|
||||||
for (i = 0; i < node->n_hndl; i++) {
|
for (i = 0; i < node->n_hndl; i++) {
|
||||||
for (j = 0; j < node->desc->n_output; j++)
|
for (j = 0; j < node->desc->n_output; j++)
|
||||||
free(node->output_port[j].audio_data[i]);
|
free(node->output_port[j].audio_data[i]);
|
||||||
if (d->activate)
|
if (node->hndl[i] == NULL)
|
||||||
d->activate(node->hndl[i]);
|
continue;
|
||||||
|
if (d->deactivate)
|
||||||
|
d->deactivate(node->hndl[i]);
|
||||||
d->cleanup(node->hndl[i]);
|
d->cleanup(node->hndl[i]);
|
||||||
}
|
}
|
||||||
ladspa_descriptor_unref(node->desc);
|
ladspa_descriptor_unref(node->desc);
|
||||||
|
@ -1285,19 +1305,36 @@ 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) {
|
||||||
if ((port = find_port(first, v, LADSPA_PORT_INPUT)) == NULL) {
|
gp = &graph->input[graph->n_input];
|
||||||
|
if (strcmp(v, "null") == 0) {
|
||||||
|
gp->desc = NULL;
|
||||||
|
pw_log_info("ignore input port %d", graph->n_input);
|
||||||
|
} else if ((port = find_port(first, v, LADSPA_PORT_INPUT)) == NULL) {
|
||||||
res = -ENOENT;
|
res = -ENOENT;
|
||||||
pw_log_error("input port %s not found", v);
|
pw_log_error("input port %s not found", v);
|
||||||
goto error;
|
goto error;
|
||||||
|
} else {
|
||||||
|
desc = port->node->desc;
|
||||||
|
d = desc->desc;
|
||||||
|
if (port->external != SPA_ID_INVALID) {
|
||||||
|
pw_log_error("input port %s[%d]:%s already used as input %d, use mixer",
|
||||||
|
port->node->name, i, d->PortNames[port->p],
|
||||||
|
graph->n_input);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (port->n_links > 0) {
|
||||||
|
pw_log_error("input port %s[%d]:%s already used by link, use mixer",
|
||||||
|
port->node->name, i, d->PortNames[port->p]);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
pw_log_info("input port %s[%d]:%s",
|
||||||
|
port->node->name, i, d->PortNames[port->p]);
|
||||||
|
port->external = graph->n_input;
|
||||||
|
gp->desc = d;
|
||||||
|
gp->hndl = port->node->hndl[i];
|
||||||
|
gp->port = port->p;
|
||||||
}
|
}
|
||||||
gp = &graph->input[graph->n_input++];
|
graph->n_input++;
|
||||||
desc = port->node->desc;
|
|
||||||
d = desc->desc;
|
|
||||||
pw_log_info("input port %s[%d]:%s",
|
|
||||||
port->node->name, i, d->PortNames[port->p]);
|
|
||||||
gp->desc = d;
|
|
||||||
gp->hndl = port->node->hndl[i];
|
|
||||||
gp->port = port->p;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (outputs == NULL) {
|
if (outputs == NULL) {
|
||||||
|
@ -1314,19 +1351,36 @@ 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) {
|
||||||
if ((port = find_port(last, v, LADSPA_PORT_OUTPUT)) == NULL) {
|
gp = &graph->output[graph->n_output];
|
||||||
|
if (strcmp(v, "null") == 0) {
|
||||||
|
gp->desc = NULL;
|
||||||
|
pw_log_info("silence output port %d", graph->n_output);
|
||||||
|
} else if ((port = find_port(last, v, LADSPA_PORT_OUTPUT)) == NULL) {
|
||||||
res = -ENOENT;
|
res = -ENOENT;
|
||||||
pw_log_error("output port %s not found", v);
|
pw_log_error("output port %s not found", v);
|
||||||
goto error;
|
goto error;
|
||||||
|
} else {
|
||||||
|
desc = port->node->desc;
|
||||||
|
d = desc->desc;
|
||||||
|
if (port->external != SPA_ID_INVALID) {
|
||||||
|
pw_log_error("output port %s[%d]:%s already used as output %d, use copy",
|
||||||
|
port->node->name, i, d->PortNames[port->p],
|
||||||
|
graph->n_output);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (port->n_links > 0) {
|
||||||
|
pw_log_error("output port %s[%d]:%s already used by link, use copy",
|
||||||
|
port->node->name, i, d->PortNames[port->p]);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
pw_log_info("output port %s[%d]:%s",
|
||||||
|
port->node->name, i, d->PortNames[port->p]);
|
||||||
|
port->external = graph->n_output;
|
||||||
|
gp->desc = d;
|
||||||
|
gp->hndl = port->node->hndl[i];
|
||||||
|
gp->port = port->p;
|
||||||
}
|
}
|
||||||
gp = &graph->output[graph->n_output++];
|
graph->n_output++;
|
||||||
desc = port->node->desc;
|
|
||||||
d = desc->desc;
|
|
||||||
pw_log_info("output port %s[%d]:%s",
|
|
||||||
port->node->name, i, d->PortNames[port->p]);
|
|
||||||
gp->desc = d;
|
|
||||||
gp->hndl = port->node->hndl[i];
|
|
||||||
gp->port = port->p;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1356,11 +1410,12 @@ static int setup_graph(struct graph *graph, struct spa_json *inputs, struct spa_
|
||||||
|
|
||||||
error:
|
error:
|
||||||
spa_list_for_each(node, &graph->node_list, link) {
|
spa_list_for_each(node, &graph->node_list, link) {
|
||||||
for (i = 0; i < n_hndl; i++) {
|
for (i = 0; i < node->n_hndl; i++) {
|
||||||
if (node->hndl[i] != NULL)
|
if (node->hndl[i] != NULL)
|
||||||
node->desc->desc->cleanup(node->hndl[i]);
|
node->desc->desc->cleanup(node->hndl[i]);
|
||||||
node->hndl[i] = NULL;
|
node->hndl[i] = NULL;
|
||||||
}
|
}
|
||||||
|
node->n_hndl = 0;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue