mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-17 07:00:03 -05:00
control: rework for spa_io_sequence
Put a pw_control object on all ports that support control messages. Allow linking of control objects (and thus ports). Make export-sink generate control messages to update the contrast property.
This commit is contained in:
parent
2631db14a8
commit
05d3502c84
7 changed files with 149 additions and 93 deletions
|
|
@ -24,7 +24,9 @@
|
|||
#include <spa/param/video/format-utils.h>
|
||||
#include <spa/param/props.h>
|
||||
#include <spa/node/io.h>
|
||||
#include <spa/control/control.h>
|
||||
#include <spa/debug/format.h>
|
||||
#include <spa/debug/pod.h>
|
||||
|
||||
#include <pipewire/pipewire.h>
|
||||
#include <pipewire/module.h>
|
||||
|
|
@ -74,7 +76,8 @@ struct data {
|
|||
const struct spa_node_callbacks *callbacks;
|
||||
void *callbacks_data;
|
||||
struct spa_io_buffers *io;
|
||||
struct spa_pod_double *ctrl_param;
|
||||
struct spa_io_sequence *io_notify;
|
||||
uint32_t io_notify_size;
|
||||
double param_accum;
|
||||
|
||||
uint8_t buffer[1024];
|
||||
|
|
@ -103,10 +106,17 @@ static void handle_events(struct data *data)
|
|||
|
||||
static void update_param(struct data *data)
|
||||
{
|
||||
if (data->ctrl_param == NULL)
|
||||
struct spa_pod_builder b = { 0, };
|
||||
|
||||
if (data->io_notify == NULL)
|
||||
return;
|
||||
|
||||
data->ctrl_param->value = (sin(data->param_accum) * 127.0) + 127.0;
|
||||
spa_pod_builder_init(&b, data->io_notify, data->io_notify_size);
|
||||
spa_pod_builder_sequence(&b, 0,
|
||||
".", 0, SPA_CONTROL_Properties,
|
||||
SPA_POD_OBJECT(SPA_TYPE_OBJECT_Props, 0,
|
||||
":", SPA_PROP_contrast, "f", (sin(data->param_accum) * 127.0) + 127.0));
|
||||
|
||||
data->param_accum += M_PI_M2 / 30.0;
|
||||
if (data->param_accum >= M_PI_M2)
|
||||
data->param_accum -= M_PI_M2;
|
||||
|
|
@ -154,19 +164,17 @@ static int impl_port_set_io(struct spa_node *node,
|
|||
{
|
||||
struct data *d = SPA_CONTAINER_OF(node, struct data, impl_node);
|
||||
|
||||
if (id == SPA_IO_Buffers)
|
||||
switch (id) {
|
||||
case SPA_IO_Buffers:
|
||||
d->io = data;
|
||||
#if 0
|
||||
else if (id == d->type.io_prop_param) {
|
||||
if (data && size >= sizeof(struct spa_pod_double))
|
||||
d->ctrl_param = data;
|
||||
else
|
||||
d->ctrl_param = NULL;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
break;
|
||||
case SPA_IO_Notify:
|
||||
d->io_notify = data;
|
||||
d->io_notify_size = size;
|
||||
break;
|
||||
default:
|
||||
return -ENOENT;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -273,25 +281,25 @@ static int impl_port_enum_params(struct spa_node *node,
|
|||
return 0;
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
else if (id == t->param_io.idPropsOut) {
|
||||
struct props *p = &d->props;
|
||||
|
||||
case SPA_PARAM_IO:
|
||||
switch (*index) {
|
||||
case 0:
|
||||
param = spa_pod_builder_object(builder,
|
||||
id, t->param_io.Prop,
|
||||
":", t->param_io.id, "I", d->type.io_prop_param,
|
||||
":", t->param_io.size, "i", sizeof(struct spa_pod_double),
|
||||
":", t->param.propId, "I", d->type.prop_param,
|
||||
":", t->param.propType, "dru", p->param,
|
||||
SPA_POD_PROP_MIN_MAX(0.0, 10.0));
|
||||
SPA_TYPE_OBJECT_ParamIO, id,
|
||||
":", SPA_PARAM_IO_id, "I", SPA_IO_Buffers,
|
||||
":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_buffers));
|
||||
break;
|
||||
case 1:
|
||||
param = spa_pod_builder_object(builder,
|
||||
SPA_TYPE_OBJECT_ParamIO, id,
|
||||
":", SPA_PARAM_IO_id, "I", SPA_IO_Notify,
|
||||
":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_sequence) + 1024);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -559,7 +559,7 @@ static void try_link_controls(struct impl *impl, struct pw_port *port, struct pw
|
|||
pw_log_debug("module %p: trying controls", impl);
|
||||
spa_list_for_each(cout, &port->control_list[SPA_DIRECTION_OUTPUT], port_link) {
|
||||
spa_list_for_each(cin, &target->control_list[SPA_DIRECTION_INPUT], port_link) {
|
||||
if (cin->prop_id == cout->prop_id) {
|
||||
if (cin->id != cout->id) {
|
||||
if ((res = pw_control_link(cout, cin)) < 0)
|
||||
pw_log_error("failed to link controls: %s", spa_strerror(res));
|
||||
}
|
||||
|
|
@ -567,7 +567,7 @@ static void try_link_controls(struct impl *impl, struct pw_port *port, struct pw
|
|||
}
|
||||
spa_list_for_each(cin, &port->control_list[SPA_DIRECTION_INPUT], port_link) {
|
||||
spa_list_for_each(cout, &target->control_list[SPA_DIRECTION_OUTPUT], port_link) {
|
||||
if (cin->prop_id == cout->prop_id) {
|
||||
if (cin->id != cout->id) {
|
||||
if ((res = pw_control_link(cout, cin)) < 0)
|
||||
pw_log_error("failed to link controls: %s", spa_strerror(res));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ static void try_link_controls(struct impl *impl, struct pw_port *port, struct pw
|
|||
pw_log_debug("module %p: trying controls", impl);
|
||||
spa_list_for_each(cout, &port->control_list[SPA_DIRECTION_OUTPUT], port_link) {
|
||||
spa_list_for_each(cin, &target->control_list[SPA_DIRECTION_INPUT], port_link) {
|
||||
if (cin->prop_id == cout->prop_id) {
|
||||
if (cin->id != cout->id) {
|
||||
if ((res = pw_control_link(cout, cin)) < 0)
|
||||
pw_log_error("failed to link controls: %s", spa_strerror(res));
|
||||
}
|
||||
|
|
@ -220,7 +220,7 @@ static void try_link_controls(struct impl *impl, struct pw_port *port, struct pw
|
|||
}
|
||||
spa_list_for_each(cin, &port->control_list[SPA_DIRECTION_INPUT], port_link) {
|
||||
spa_list_for_each(cout, &target->control_list[SPA_DIRECTION_OUTPUT], port_link) {
|
||||
if (cin->prop_id == cout->prop_id) {
|
||||
if (cin->id != cout->id) {
|
||||
if ((res = pw_control_link(cout, cin)) < 0)
|
||||
pw_log_error("failed to link controls: %s", spa_strerror(res));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,27 +38,34 @@ pw_control_new(struct pw_core *core,
|
|||
struct impl *impl;
|
||||
struct pw_control *this;
|
||||
enum spa_direction direction;
|
||||
uint32_t id, size;
|
||||
|
||||
if (spa_pod_object_parse(param,
|
||||
":", SPA_PARAM_IO_id, "I", &id,
|
||||
":", SPA_PARAM_IO_size, "i", &size) < 0)
|
||||
goto exit;
|
||||
|
||||
switch (id) {
|
||||
case SPA_IO_Control:
|
||||
direction = SPA_DIRECTION_INPUT;
|
||||
break;
|
||||
case SPA_IO_Notify:
|
||||
direction = SPA_DIRECTION_OUTPUT;
|
||||
break;
|
||||
default:
|
||||
goto exit;
|
||||
}
|
||||
|
||||
impl = calloc(1, sizeof(struct impl) + user_data_size);
|
||||
if (impl == NULL)
|
||||
goto exit;
|
||||
|
||||
this = &impl->this;
|
||||
|
||||
direction = SPA_DIRECTION_OUTPUT;
|
||||
#if 0
|
||||
direction = spa_pod_is_object_id(param, SPA_PARAM_PropsOut) ?
|
||||
SPA_DIRECTION_OUTPUT : SPA_DIRECTION_INPUT;
|
||||
|
||||
if (spa_pod_object_parse(param,
|
||||
":", t->param_io.id, "I", &this->id,
|
||||
":", t->param_io.size, "i", &this->size,
|
||||
":", t->param.propId, "I", &this->prop_id) < 0)
|
||||
goto exit_free;
|
||||
#endif
|
||||
this->id = id;
|
||||
this->size = size;
|
||||
|
||||
pw_log_debug("control %p: new %s %d", this,
|
||||
spa_debug_type_find_name(spa_debug_types, this->prop_id), direction);
|
||||
spa_debug_type_find_name(spa_types, this->id), direction);
|
||||
|
||||
this->core = core;
|
||||
this->port = port;
|
||||
|
|
@ -80,8 +87,6 @@ pw_control_new(struct pw_core *core,
|
|||
|
||||
return this;
|
||||
|
||||
// exit_free:
|
||||
// free(impl);
|
||||
exit:
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -141,6 +146,7 @@ int pw_control_link(struct pw_control *control, struct pw_control *other)
|
|||
{
|
||||
int res = 0;
|
||||
struct impl *impl;
|
||||
uint32_t size;
|
||||
|
||||
if (control->direction == SPA_DIRECTION_INPUT) {
|
||||
struct pw_control *tmp = control;
|
||||
|
|
@ -158,13 +164,15 @@ int pw_control_link(struct pw_control *control, struct pw_control *other)
|
|||
impl = SPA_CONTAINER_OF(control, struct impl, this);
|
||||
|
||||
pw_log_debug("control %p: link to %p %s", control, other,
|
||||
spa_debug_type_find_name(spa_debug_types, control->prop_id));
|
||||
spa_debug_type_find_name(spa_debug_types, control->id));
|
||||
|
||||
size = SPA_MAX(control->size, other->size);
|
||||
|
||||
if (impl->mem == NULL) {
|
||||
if ((res = pw_memblock_alloc(PW_MEMBLOCK_FLAG_WITH_FD |
|
||||
PW_MEMBLOCK_FLAG_SEAL |
|
||||
PW_MEMBLOCK_FLAG_MAP_READWRITE,
|
||||
control->size,
|
||||
size,
|
||||
&impl->mem)) < 0)
|
||||
goto exit;
|
||||
|
||||
|
|
@ -175,7 +183,7 @@ int pw_control_link(struct pw_control *control, struct pw_control *other)
|
|||
if ((res = spa_node_port_set_io(port->node->node,
|
||||
port->direction, port->port_id,
|
||||
other->id,
|
||||
impl->mem->ptr, control->size)) < 0) {
|
||||
impl->mem->ptr, size)) < 0) {
|
||||
pw_log_warn("control %p: set io failed %d %s", control,
|
||||
res, spa_strerror(res));
|
||||
goto exit;
|
||||
|
|
@ -188,7 +196,7 @@ int pw_control_link(struct pw_control *control, struct pw_control *other)
|
|||
if ((res = spa_node_port_set_io(port->node->node,
|
||||
port->direction, port->port_id,
|
||||
control->id,
|
||||
impl->mem->ptr, control->size)) < 0) {
|
||||
impl->mem->ptr, size)) < 0) {
|
||||
pw_log_warn("control %p: set io failed %d %s", control,
|
||||
res, spa_strerror(res));
|
||||
/* undo */
|
||||
|
|
|
|||
|
|
@ -341,7 +341,6 @@ static int do_add_port(struct spa_loop *loop,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int make_control(void *data, uint32_t id, uint32_t index, uint32_t next, struct spa_pod *param)
|
||||
{
|
||||
struct pw_port *port = data;
|
||||
|
|
@ -349,7 +348,6 @@ static int make_control(void *data, uint32_t id, uint32_t index, uint32_t next,
|
|||
pw_control_new(node->core, port, param, 0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void port_unbind_func(void *data)
|
||||
{
|
||||
|
|
@ -526,10 +524,7 @@ int pw_port_add(struct pw_port *port, struct pw_node *node)
|
|||
node->info.change_mask |= PW_NODE_CHANGE_MASK_OUTPUT_PORTS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
pw_port_for_each_param(port, SPA_PARAM_PropsOut, 0, 0, NULL, make_control, port);
|
||||
pw_port_for_each_param(port, SPA_PARAM_PropsIn, 0, 0, NULL, make_control, port);
|
||||
#endif
|
||||
pw_port_for_each_param(port, SPA_PARAM_IO, 0, 0, NULL, make_control, port);
|
||||
|
||||
pw_log_debug("port %p: setting node io", port);
|
||||
spa_node_port_set_io(node->node,
|
||||
|
|
|
|||
|
|
@ -627,7 +627,6 @@ struct pw_control {
|
|||
struct spa_list inputs_link; /**< link in linked input control */
|
||||
|
||||
uint32_t id;
|
||||
uint32_t prop_id;
|
||||
int32_t size;
|
||||
|
||||
struct spa_hook_list listener_list;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue