mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
control: keep track of linked controls
Keep track of what controls are linked together. Clean up links on destroy. Implement unlink, reset io area. Add events for control link/unlink
This commit is contained in:
parent
8e89474c7e
commit
f9237eb0db
4 changed files with 93 additions and 11 deletions
|
|
@ -60,6 +60,8 @@ pw_control_new(struct pw_core *core,
|
|||
this->param = pw_spa_pod_copy(param);
|
||||
this->direction = direction;
|
||||
|
||||
spa_list_init(&this->inputs);
|
||||
|
||||
if (user_data_size > 0)
|
||||
this->user_data = SPA_MEMBER(impl, sizeof(struct impl), void);
|
||||
|
||||
|
|
@ -83,11 +85,21 @@ pw_control_new(struct pw_core *core,
|
|||
void pw_control_destroy(struct pw_control *control)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF(control, struct impl, this);
|
||||
struct pw_control *other;
|
||||
|
||||
pw_log_debug("control %p: destroy", control);
|
||||
|
||||
spa_hook_list_call(&control->listener_list, struct pw_control_events, destroy);
|
||||
|
||||
if (control->direction == SPA_DIRECTION_OUTPUT) {
|
||||
spa_list_for_each(other, &control->inputs, inputs_link)
|
||||
pw_control_unlink(control, other);
|
||||
}
|
||||
else {
|
||||
if (control->output)
|
||||
pw_control_unlink(control->output, control);
|
||||
}
|
||||
|
||||
spa_list_remove(&control->link);
|
||||
|
||||
if (control->port) {
|
||||
|
|
@ -99,9 +111,10 @@ void pw_control_destroy(struct pw_control *control)
|
|||
pw_log_debug("control %p: free", control);
|
||||
spa_hook_list_call(&control->listener_list, struct pw_control_events, free);
|
||||
|
||||
if (control->direction == SPA_DIRECTION_OUTPUT)
|
||||
if (control->direction == SPA_DIRECTION_OUTPUT) {
|
||||
if (impl->mem)
|
||||
pw_memblock_free(impl->mem);
|
||||
}
|
||||
|
||||
free(control->param);
|
||||
|
||||
|
|
@ -135,6 +148,10 @@ int pw_control_link(struct pw_control *control, struct pw_control *other)
|
|||
other->direction != SPA_DIRECTION_INPUT)
|
||||
return -EINVAL;
|
||||
|
||||
/* input control already has a linked output control */
|
||||
if (other->output != NULL)
|
||||
return -EEXIST;
|
||||
|
||||
impl = SPA_CONTAINER_OF(control, struct impl, this);
|
||||
|
||||
pw_log_debug("control %p: link to %p", control, other);
|
||||
|
|
@ -147,15 +164,6 @@ int pw_control_link(struct pw_control *control, struct pw_control *other)
|
|||
&impl->mem)) < 0)
|
||||
goto exit;
|
||||
|
||||
if (control->port) {
|
||||
struct pw_port *port = control->port;
|
||||
if ((res = spa_node_port_set_io(port->node->node,
|
||||
port->direction, port->port_id,
|
||||
control->id,
|
||||
impl->mem->ptr, control->size)) < 0) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (other->port) {
|
||||
|
|
@ -168,11 +176,68 @@ int pw_control_link(struct pw_control *control, struct pw_control *other)
|
|||
}
|
||||
}
|
||||
|
||||
if (spa_list_is_empty(&control->inputs)) {
|
||||
if (control->port) {
|
||||
struct pw_port *port = control->port;
|
||||
if ((res = spa_node_port_set_io(port->node->node,
|
||||
port->direction, port->port_id,
|
||||
control->id,
|
||||
impl->mem->ptr, control->size)) < 0) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
other->output = control;
|
||||
spa_list_append(&control->inputs, &other->inputs_link);
|
||||
|
||||
spa_hook_list_call(&control->listener_list, struct pw_control_events, linked, other);
|
||||
|
||||
exit:
|
||||
return res;
|
||||
}
|
||||
|
||||
int pw_control_unlink(struct pw_control *control, struct pw_control *other)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
int res = 0;
|
||||
|
||||
if (control->direction == SPA_DIRECTION_INPUT) {
|
||||
struct pw_control *tmp = control;
|
||||
control = other;
|
||||
other = tmp;
|
||||
}
|
||||
if (control->direction != SPA_DIRECTION_OUTPUT ||
|
||||
other->direction != SPA_DIRECTION_INPUT)
|
||||
return -EINVAL;
|
||||
|
||||
if (other->output != control)
|
||||
return -EINVAL;
|
||||
|
||||
pw_log_debug("control %p: unlink from %p", control, other);
|
||||
|
||||
other->output = NULL;
|
||||
spa_list_remove(&other->inputs_link);
|
||||
|
||||
if (spa_list_is_empty(&control->inputs)) {
|
||||
struct pw_port *port = control->port;
|
||||
if ((res = spa_node_port_set_io(port->node->node,
|
||||
port->direction, port->port_id,
|
||||
control->id, NULL, 0)) < 0) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (other->port) {
|
||||
struct pw_port *port = other->port;
|
||||
if ((res = spa_node_port_set_io(port->node->node,
|
||||
port->direction, port->port_id,
|
||||
other->id, NULL, 0)) < 0) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
spa_hook_list_call(&control->listener_list, struct pw_control_events, unlinked, other);
|
||||
|
||||
exit:
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,12 @@ struct pw_control_events {
|
|||
|
||||
/** The control is freed */
|
||||
void (*free) (void *data);
|
||||
|
||||
/** control is linked to another control */
|
||||
void (*linked) (void *data, struct pw_control *other);
|
||||
/** control is unlinked from another control */
|
||||
void (*unlinked) (void *data, struct pw_control *other);
|
||||
|
||||
};
|
||||
|
||||
/** Get the control parent port or NULL when not set */
|
||||
|
|
|
|||
|
|
@ -352,6 +352,7 @@ static int do_remove_port(struct spa_loop *loop,
|
|||
void pw_port_destroy(struct pw_port *port)
|
||||
{
|
||||
struct pw_node *node = port->node;
|
||||
struct pw_control *control, *ctemp;
|
||||
|
||||
pw_log_debug("port %p: destroy", port);
|
||||
|
||||
|
|
@ -374,6 +375,11 @@ void pw_port_destroy(struct pw_port *port)
|
|||
spa_hook_list_call(&node->listener_list, struct pw_node_events, port_removed, port);
|
||||
}
|
||||
|
||||
spa_list_for_each_safe(control, ctemp, &port->control_list[0], port_link)
|
||||
pw_control_destroy(control);
|
||||
spa_list_for_each_safe(control, ctemp, &port->control_list[1], port_link)
|
||||
pw_control_destroy(control);
|
||||
|
||||
pw_log_debug("port %p: free", port);
|
||||
spa_hook_list_call(&port->listener_list, struct pw_port_events, free);
|
||||
|
||||
|
|
|
|||
|
|
@ -418,6 +418,11 @@ struct pw_control {
|
|||
enum spa_direction direction; /**< the direction */
|
||||
struct spa_pod *param; /**< control params */
|
||||
|
||||
struct pw_control *output; /**< pointer to linked output control */
|
||||
|
||||
struct spa_list inputs; /**< list of linked input controls */
|
||||
struct spa_list inputs_link; /**< link in linked input control */
|
||||
|
||||
uint32_t id;
|
||||
int32_t size;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue