Implement param filtering

Make a new pod filter function and use it in the plugins to filter
in enum_params.
Small tweaks to the pod_builder
This commit is contained in:
Wim Taymans 2017-11-09 17:07:04 +01:00
parent cc47fb7e3a
commit 58451d626c
35 changed files with 1150 additions and 917 deletions

View file

@ -29,7 +29,7 @@
#include <sys/eventfd.h>
#include "spa/node.h"
#include "spa/lib/format.h"
#include "spa/lib/pod.h"
#include "pipewire/pipewire.h"
#include "pipewire/interfaces.h"
@ -57,6 +57,10 @@
#define CHECK_OUT_PORT(this,d,p) (CHECK_OUT_PORT_ID(this,d,p) && (this)->out_ports[p].valid)
#define CHECK_PORT(this,d,p) (CHECK_IN_PORT (this,d,p) || CHECK_OUT_PORT (this,d,p))
#define GET_IN_PORT(this,p) (&this->in_ports[p])
#define GET_OUT_PORT(this,p) (&this->out_ports[p])
#define GET_PORT(this,d,p) (d == SPA_DIRECTION_INPUT ? GET_IN_PORT(this,p) : GET_OUT_PORT(this,p))
#define CHECK_PORT_BUFFER(this,b,p) (b < p->n_buffers)
struct proxy_buffer {
@ -152,6 +156,7 @@ static int spa_proxy_node_enum_params(struct spa_node *node,
struct spa_pod_builder *builder)
{
struct proxy *this;
uint32_t offset;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
@ -159,6 +164,8 @@ static int spa_proxy_node_enum_params(struct spa_node *node,
this = SPA_CONTAINER_OF(node, struct proxy, node);
offset = builder->offset;
while (true) {
struct spa_pod_object *param;
@ -167,10 +174,13 @@ static int spa_proxy_node_enum_params(struct spa_node *node,
param = this->params[(*index)++];
if (param->body.id == id) {
spa_pod_builder_primitive(builder, &param->pod);
if (param->body.id != id)
continue;
if (spa_pod_filter(builder, &param->pod, &filter->pod) == SPA_RESULT_OK)
break;
}
spa_pod_builder_reset(builder, offset);
}
return SPA_RESULT_OK;
}
@ -312,11 +322,7 @@ do_update_port(struct proxy *this,
struct proxy_port *port;
struct pw_type *t = this->impl->t;
if (direction == SPA_DIRECTION_INPUT) {
port = &this->in_ports[port_id];
} else {
port = &this->out_ports[port_id];
}
port = GET_PORT(this, direction, port_id);
if (change_mask & PW_CLIENT_NODE_PORT_UPDATE_PARAMS) {
int i;
@ -369,11 +375,12 @@ static void do_uninit_port(struct proxy *this, enum spa_direction direction, uin
struct proxy_port *port;
spa_log_info(this->log, "proxy %p: removing port %d", this, port_id);
if (direction == SPA_DIRECTION_INPUT) {
port = &this->in_ports[port_id];
port = GET_IN_PORT(this, port_id);
this->n_inputs--;
} else {
port = &this->out_ports[port_id];
port = GET_OUT_PORT(this, port_id);
this->n_outputs--;
}
clear_port(this, port, direction, port_id);
@ -394,8 +401,7 @@ spa_proxy_node_add_port(struct spa_node *node, enum spa_direction direction, uin
if (!CHECK_FREE_PORT(this, direction, port_id))
return SPA_RESULT_INVALID_PORT;
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
port = GET_PORT(this, direction, port_id);
clear_port(this, port, direction, port_id);
return SPA_RESULT_OK;
@ -435,9 +441,7 @@ spa_proxy_node_port_get_info(struct spa_node *node,
if (!CHECK_PORT(this, direction, port_id))
return SPA_RESULT_INVALID_PORT;
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
port = GET_PORT(this, direction, port_id);
*info = &port->info;
return SPA_RESULT_OK;
@ -452,6 +456,7 @@ spa_proxy_node_port_enum_params(struct spa_node *node,
{
struct proxy *this;
struct proxy_port *port;
uint32_t offset;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
@ -461,9 +466,9 @@ spa_proxy_node_port_enum_params(struct spa_node *node,
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
port = GET_PORT(this, direction, port_id);
offset = builder->offset;
while (true) {
struct spa_pod_object *param;
@ -472,10 +477,13 @@ spa_proxy_node_port_enum_params(struct spa_node *node,
param = port->params[(*index)++];
if (param->body.id == id) {
spa_pod_builder_primitive(builder, &param->pod);
if (param->body.id != id)
continue;
if (spa_pod_filter(builder, &param->pod, &filter->pod) == SPA_RESULT_OK)
break;
}
spa_pod_builder_reset(builder, offset);
}
return SPA_RESULT_OK;
}
@ -523,8 +531,7 @@ spa_proxy_node_port_set_io(struct spa_node *node,
if (!CHECK_PORT(this, direction, port_id))
return SPA_RESULT_INVALID_PORT;
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
port = GET_PORT(this, direction, port_id);
port->io = io;
return SPA_RESULT_OK;
@ -555,8 +562,7 @@ spa_proxy_node_port_use_buffers(struct spa_node *node,
if (!CHECK_PORT(this, direction, port_id))
return SPA_RESULT_INVALID_PORT;
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
port = GET_PORT(this, direction, port_id);
if (!port->have_format)
return SPA_RESULT_NO_FORMAT;
@ -661,8 +667,7 @@ spa_proxy_node_port_alloc_buffers(struct spa_node *node,
if (!CHECK_PORT(this, direction, port_id))
return SPA_RESULT_INVALID_PORT;
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
port = GET_PORT(this, direction, port_id);
if (!port->have_format)
return SPA_RESULT_NO_FORMAT;

View file

@ -30,9 +30,10 @@
#include <spa/node.h>
#include <spa/hook.h>
#include <spa/lib/format.h>
#include <spa/audio/format-utils.h>
#include <spa/lib/pod.h>
#include "pipewire/pipewire.h"
#include "pipewire/core.h"
#include "pipewire/private.h"
@ -374,61 +375,6 @@ static int port_set_io(struct spa_node *node, enum spa_direction direction, uint
return SPA_RESULT_OK;
}
static int port_enum_formats(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl);
struct port_data *pd = nd->port_data[direction][port_id];
struct type *t = &pd->node->type;
struct spa_pod_builder b = { NULL, };
struct spa_pod_object *fmt;
uint8_t buffer[4096];
int res;
struct jack_engine_control *ctrl = pd->node->node.server->engine_control;
if (index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_init(&b, buffer, sizeof(buffer));
if (pd->port.jack_port) {
if (pd->port.jack_port->type_id == 0) {
fmt = spa_pod_builder_object(&b,
t->param.idEnumFormat, t->format,
"I", t->media_type.audio,
"I", t->media_subtype.raw,
":", t->format_audio.format, "I", t->audio_format.F32,
":", t->format_audio.rate, "i", ctrl->sample_rate,
":", t->format_audio.channels, "i", 1);
}
else if (pd->port.jack_port->type_id == 1) {
fmt = spa_pod_builder_object(&b,
t->param.idEnumFormat, t->format,
"I", t->media_type.audio,
"I", t->media_subtype_audio.midi);
}
else
return SPA_RESULT_ENUM_END;
}
else {
fmt = spa_pod_builder_object(&b,
t->param.idEnumFormat, t->format,
"I", t->media_type.audio,
"I", t->media_subtype.raw,
":", t->format_audio.format, "I", t->audio_format.S16,
":", t->format_audio.rate, "i", ctrl->sample_rate,
":", t->format_audio.channels, "i", 2);
}
if ((res = spa_pod_object_filter(fmt, filter, builder)) < 0)
return res;
return SPA_RESULT_OK;
}
static int port_get_info(struct spa_node *node, enum spa_direction direction, uint32_t port_id,
const struct spa_port_info **info)
{
@ -446,6 +392,52 @@ static int port_get_info(struct spa_node *node, enum spa_direction direction, ui
return SPA_RESULT_OK;
}
static int port_enum_formats(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder,
struct spa_pod **param)
{
struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl);
struct port_data *pd = nd->port_data[direction][port_id];
struct type *t = &pd->node->type;
struct jack_engine_control *ctrl = pd->node->node.server->engine_control;
if (index > 0)
return SPA_RESULT_ENUM_END;
if (pd->port.jack_port) {
if (pd->port.jack_port->type_id == 0) {
*param = spa_pod_builder_object(builder,
t->param.idEnumFormat, t->format,
"I", t->media_type.audio,
"I", t->media_subtype.raw,
":", t->format_audio.format, "I", t->audio_format.F32,
":", t->format_audio.rate, "i", ctrl->sample_rate,
":", t->format_audio.channels, "i", 1);
}
else if (pd->port.jack_port->type_id == 1) {
*param = spa_pod_builder_object(builder,
t->param.idEnumFormat, t->format,
"I", t->media_type.audio,
"I", t->media_subtype_audio.midi);
}
else
return SPA_RESULT_ENUM_END;
}
else {
*param = spa_pod_builder_object(builder,
t->param.idEnumFormat, t->format,
"I", t->media_type.audio,
"I", t->media_subtype.raw,
":", t->format_audio.format, "I", t->audio_format.S16,
":", t->format_audio.rate, "i", ctrl->sample_rate,
":", t->format_audio.channels, "i", 2);
}
return SPA_RESULT_OK;
}
static int port_enum_params(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t *index,
@ -454,16 +446,30 @@ static int port_enum_params(struct spa_node *node,
{
struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl);
struct type *t = &nd->type;
struct spa_pod *param;
uint32_t offset;
int res;
offset = builder->offset;
next:
if (id == t->param.idEnumFormat) {
return port_enum_formats(node, direction, port_id, index, filter, builder);
if ((res = port_enum_formats(node, direction, port_id, index, filter, builder, &param)) < 0)
return res;
}
else if (id == t->param.idFormat) {
return port_enum_formats(node, direction, port_id, index, filter, builder);
if ((res = port_enum_formats(node, direction, port_id, index, filter, builder, &param)) < 0)
return res;
}
else
return SPA_RESULT_UNKNOWN_PARAM;
(*index)++;
spa_pod_builder_reset(builder, offset);
if ((res = spa_pod_filter(builder, param, (struct spa_pod*)filter)) < 0)
goto next;
return SPA_RESULT_ENUM_END;
}

View file

@ -338,12 +338,12 @@ static inline void *begin_write(struct pw_protocol_native_connection *conn, uint
return p + 2;
}
static uint32_t write_pod(struct spa_pod_builder *b, uint32_t ref, const void *data, uint32_t size)
static uint32_t write_pod(struct spa_pod_builder *b, const void *data, uint32_t size)
{
struct impl *impl = SPA_CONTAINER_OF(b, struct impl, builder);
uint32_t ref = b->offset;
if (ref == -1)
ref = b->offset;
ref = b->offset;
if (b->size <= b->offset) {
b->size = SPA_ROUND_UP_N(b->offset + size, 4096);

View file

@ -25,8 +25,6 @@
#include <getopt.h>
#include <limits.h>
#include <spa/lib/props.h>
#include <pipewire/utils.h>
#include <pipewire/log.h>
#include <pipewire/core.h>

View file

@ -25,8 +25,6 @@
#include <getopt.h>
#include <limits.h>
#include <spa/lib/props.h>
#include <pipewire/core.h>
#include <pipewire/log.h>
#include <pipewire/module.h>