control: add control objects

Add control objects for all controllable properties on ports.
Try to link compatible control properties in autolink.
Allocate shared memory for the output property memory and configure
the io area on the ports when the controls are linked.
Send the shared memfd to clients when the io area is configured.
Add port_set_io support in remote.c, mmap the control io area and
set on the port.
Add some param helpers
Add volume control to export-source update the volume before
sending each buffer.
This commit is contained in:
Wim Taymans 2017-11-30 16:36:29 +01:00
parent 91a3670610
commit 541553be1c
19 changed files with 577 additions and 34 deletions

View file

@ -113,7 +113,7 @@ struct proxy {
uint32_t n_params;
struct spa_pod **params;
uint8_t format_buffer[1024];
uint32_t membase;
uint32_t seq;
};
@ -337,7 +337,6 @@ do_update_port(struct proxy *this,
if (spa_pod_is_object_id(port->params[i], t->param.idFormat))
port->have_format = true;
}
}
if (change_mask & PW_CLIENT_NODE_PORT_UPDATE_INFO && info)
@ -534,9 +533,27 @@ spa_proxy_node_port_set_io(struct spa_node *node,
if (id == t->io.Buffers)
port->io = data;
else
return -ENOENT;
else {
struct pw_memblock *mem;
uint32_t memid = this->membase++;
if ((mem = pw_memblock_find(data)) == NULL)
return -EINVAL;
pw_client_node_resource_port_add_mem(this->resource,
direction, port_id,
memid,
t->data.MemFd,
mem->fd, mem->flags,
0, mem->offset + mem->size);
pw_client_node_resource_port_set_io(this->resource,
this->seq,
direction, port_id,
id,
memid,
mem->offset, mem->size);
}
return 0;
}
@ -582,7 +599,7 @@ spa_proxy_node_port_use_buffers(struct spa_node *node,
if (this->resource == NULL)
return 0;
n_mem = 0;
n_mem = this->membase;
for (i = 0; i < n_buffers; i++) {
struct buffer *b = &port->buffers[i];
struct pw_memblock *m;
@ -1109,10 +1126,13 @@ static void node_initialized(void *data)
impl->other_fds[1] = impl->fds[0];
spa_loop_add_source(impl->proxy.data_loop, &impl->proxy.data_source);
pw_log_debug("client-node %p: add data fd %d", node, impl->proxy.data_source.fd);
pw_log_debug("client-node %p: transport fd %d %d", node, impl->fds[0], impl->fds[1]);
pw_client_node_resource_transport(this->resource, pw_global_get_id(pw_node_get_global(node)),
impl->other_fds[0], impl->other_fds[1], impl->transport);
pw_client_node_resource_transport(this->resource,
pw_global_get_id(pw_node_get_global(node)),
impl->other_fds[0],
impl->other_fds[1],
impl->transport);
}
static void node_free(void *data)

View file

@ -408,6 +408,32 @@ static bool client_node_demarshal_port_command(void *object, void *data, size_t
return true;
}
static bool client_node_demarshal_port_set_io(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_parser prs;
uint32_t seq, direction, port_id, id, memid, off, sz;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
"i", &seq,
"i", &direction,
"i", &port_id,
"I", &id,
"i", &memid,
"i", &off,
"i", &sz, NULL) < 0)
return false;
pw_proxy_notify(proxy, struct pw_client_node_proxy_events, port_set_io,
seq,
direction, port_id,
id, memid,
off, sz);
return true;
}
static void client_node_marshal_transport(void *object, uint32_t node_id, int readfd, int writefd,
struct pw_client_node_transport *transport)
{
@ -629,6 +655,33 @@ client_node_marshal_port_command(void *object,
pw_protocol_native_end_resource(resource, b);
}
static void
client_node_marshal_port_set_io(void *object,
uint32_t seq,
uint32_t direction,
uint32_t port_id,
uint32_t id,
uint32_t memid,
uint32_t offset,
uint32_t size)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_PROXY_EVENT_PORT_SET_IO);
spa_pod_builder_struct(b,
"i", seq,
"i", direction,
"i", port_id,
"I", id,
"i", memid,
"i", offset,
"i", size);
pw_protocol_native_end_resource(resource, b);
}
static bool client_node_demarshal_done(void *object, void *data, size_t size)
{
@ -683,7 +736,7 @@ static bool client_node_demarshal_port_update(void *object, void *data, size_t s
struct spa_pod_parser prs;
uint32_t i, direction, port_id, change_mask, n_params;
const struct spa_pod **params = NULL;
struct spa_port_info info, *infop = NULL;
struct spa_port_info info = { 0 }, *infop = NULL;
struct spa_pod *ipod;
spa_pod_parser_init(&prs, data, size, 0);
@ -799,6 +852,7 @@ static const struct pw_client_node_proxy_events pw_protocol_native_client_node_e
&client_node_marshal_port_add_mem,
&client_node_marshal_port_use_buffers,
&client_node_marshal_port_command,
&client_node_marshal_port_set_io,
};
static const struct pw_protocol_native_demarshal pw_protocol_native_client_node_event_demarshal[] = {
@ -812,6 +866,7 @@ static const struct pw_protocol_native_demarshal pw_protocol_native_client_node_
{ &client_node_demarshal_port_add_mem, PW_PROTOCOL_NATIVE_REMAP },
{ &client_node_demarshal_port_use_buffers, PW_PROTOCOL_NATIVE_REMAP },
{ &client_node_demarshal_port_command, PW_PROTOCOL_NATIVE_REMAP },
{ &client_node_demarshal_port_set_io, PW_PROTOCOL_NATIVE_REMAP },
};
const struct pw_protocol_marshal pw_protocol_native_client_node_marshal = {

View file

@ -195,12 +195,15 @@ pw_client_node_transport_new(uint32_t max_input_ports, uint32_t max_output_ports
if (impl == NULL)
return NULL;
pw_log_debug("transport %p: new %d %d", impl, max_input_ports, max_output_ports);
trans = &impl->trans;
impl->offset = 0;
if (pw_memblock_alloc(PW_MEMBLOCK_FLAG_WITH_FD |
PW_MEMBLOCK_FLAG_MAP_READWRITE |
PW_MEMBLOCK_FLAG_SEAL, area_get_size(&area),
PW_MEMBLOCK_FLAG_SEAL,
area_get_size(&area),
&impl->mem) < 0)
return NULL;
@ -229,6 +232,7 @@ pw_client_node_transport_new_from_info(struct pw_client_node_transport_info *inf
return NULL;
trans = &impl->trans;
pw_log_debug("transport %p: new from info", impl);
if ((res = pw_memblock_import(PW_MEMBLOCK_FLAG_MAP_READWRITE |
PW_MEMBLOCK_FLAG_WITH_FD,