spa: give meaning to port_enum_params with SPA_ID_INVALID port_id

This is to iterate params that are common to all ports, such as
EnumFormat or the supported IO areas. Mostly interesting for mixer and
splitter nodes so that we don't have to create a new port just to query
things.
This commit is contained in:
Wim Taymans 2024-04-12 17:23:24 +02:00
parent bf273690fd
commit 77ed5ccb31
5 changed files with 32 additions and 22 deletions

View file

@ -450,6 +450,9 @@ struct spa_node_methods {
* Enumerate all possible parameters of \a id on \a port_id of \a node
* that are compatible with \a filter.
*
* When SPA_ID_INVALID is given as the port_id, the node will reply with
* the params that would be returned for a new port in the given direction.
*
* The result parameters can be queried and modified and ultimately be used
* to call port_set_param.
*
@ -464,7 +467,7 @@ struct spa_node_methods {
* \param seq a sequence number to pass to the result event when
* this method is executed synchronously.
* \param direction an spa_direction
* \param port_id the port to query
* \param port_id the port to query or SPA_ID_INVALID
* \param id the parameter id to query
* \param start the first index to query, 0 to get the first item
* \param max the maximum number of params to query

View file

@ -120,13 +120,16 @@ struct impl {
};
#define PORT_VALID(p) ((p) != NULL && (p)->valid)
#define CHECK_ANY_IN(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) == SPA_ID_INVALID)
#define CHECK_FREE_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && !PORT_VALID(this->in_ports[(p)]))
#define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && PORT_VALID(this->in_ports[(p)]))
#define CHECK_OUT_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) == 0)
#define CHECK_PORT(this,d,p) (CHECK_OUT_PORT(this,d,p) || CHECK_IN_PORT (this,d,p))
#define CHECK_PORT_ANY(this,d,p) (CHECK_ANY_IN(this,d,p) || CHECK_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 GET_PORT_ANY(this,d,p) (CHECK_ANY_IN(this,d,p) ? NULL : GET_PORT(this,d,p))
static int impl_node_enum_params(void *object, int seq,
uint32_t id, uint32_t start, uint32_t num,
@ -307,8 +310,7 @@ impl_node_remove_port(void *object, enum spa_direction direction, uint32_t port_
return 0;
}
static int port_enum_formats(void *object,
enum spa_direction direction, uint32_t port_id,
static int port_enum_formats(void *object, struct port *port,
uint32_t index,
struct spa_pod **param,
struct spa_pod_builder *builder)
@ -372,9 +374,9 @@ impl_node_port_enum_params(void *object, int seq,
spa_return_val_if_fail(this != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
spa_return_val_if_fail(CHECK_PORT_ANY(this, direction, port_id), -EINVAL);
port = GET_PORT(this, direction, port_id);
port = GET_PORT_ANY(this, direction, port_id);
result.id = id;
result.next = start;
@ -385,12 +387,12 @@ impl_node_port_enum_params(void *object, int seq,
switch (id) {
case SPA_PARAM_EnumFormat:
if ((res = port_enum_formats(this, direction, port_id, result.index, &param, &b)) <= 0)
if ((res = port_enum_formats(this, port, result.index, &param, &b)) <= 0)
return res;
break;
case SPA_PARAM_Format:
if (!port->have_format)
if (port == NULL || !port->have_format)
return -EIO;
if (result.index > 0)
return 0;
@ -399,7 +401,7 @@ impl_node_port_enum_params(void *object, int seq,
break;
case SPA_PARAM_Buffers:
if (!port->have_format)
if (port == NULL || !port->have_format)
return -EIO;
if (result.index > 0)
return 0;

View file

@ -115,13 +115,16 @@ struct impl {
};
#define PORT_VALID(p) ((p) != NULL && (p)->valid)
#define CHECK_ANY_IN(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) == SPA_ID_INVALID)
#define CHECK_FREE_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && !PORT_VALID(this->in_ports[(p)]))
#define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && PORT_VALID(this->in_ports[(p)]))
#define CHECK_OUT_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) == 0)
#define CHECK_PORT(this,d,p) (CHECK_OUT_PORT(this,d,p) || CHECK_IN_PORT (this,d,p))
#define CHECK_PORT_ANY(this,d,p) (CHECK_ANY_IN(this,d,p) || CHECK_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 GET_PORT_ANY(this,d,p) (CHECK_ANY_IN(this,d,p) ? NULL : GET_PORT(this,d,p))
static int impl_node_enum_params(void *object, int seq,
uint32_t id, uint32_t start, uint32_t num,
@ -303,8 +306,7 @@ impl_node_remove_port(void *object, enum spa_direction direction, uint32_t port_
return 0;
}
static int port_enum_formats(void *object,
enum spa_direction direction, uint32_t port_id,
static int port_enum_formats(void *object, struct port *port,
uint32_t index,
struct spa_pod **param,
struct spa_pod_builder *builder)
@ -347,9 +349,9 @@ impl_node_port_enum_params(void *object, int seq,
spa_return_val_if_fail(this != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
spa_return_val_if_fail(CHECK_PORT_ANY(this, direction, port_id), -EINVAL);
port = GET_PORT(this, direction, port_id);
port = GET_PORT_ANY(this, direction, port_id);
result.id = id;
result.next = start;
@ -360,12 +362,12 @@ next:
switch (id) {
case SPA_PARAM_EnumFormat:
if ((res = port_enum_formats(this, direction, port_id, result.index, &param, &b)) <= 0)
if ((res = port_enum_formats(this, port, result.index, &param, &b)) <= 0)
return res;
break;
case SPA_PARAM_Format:
if (!port->have_format)
if (port == NULL || !port->have_format)
return -EIO;
if (result.index > 0)
return 0;
@ -374,7 +376,7 @@ next:
break;
case SPA_PARAM_Buffers:
if (!port->have_format)
if (port == NULL || !port->have_format)
return -EIO;
if (result.index > 0)
return 0;

View file

@ -85,13 +85,16 @@ struct impl {
};
#define PORT_VALID(p) ((p) != NULL && (p)->valid)
#define CHECK_ANY_IN(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) == SPA_ID_INVALID)
#define CHECK_FREE_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && !PORT_VALID(this->in_ports[(p)]))
#define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && PORT_VALID(this->in_ports[(p)]))
#define CHECK_OUT_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) == 0)
#define CHECK_PORT(this,d,p) (CHECK_OUT_PORT(this,d,p) || CHECK_IN_PORT (this,d,p))
#define CHECK_PORT_ANY(this,d,p) (CHECK_ANY_IN(this,d,p) || CHECK_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 GET_PORT_ANY(this,d,p) (CHECK_ANY_IN(this,d,p) ? NULL : GET_PORT(this,d,p))
static int impl_node_enum_params(void *object, int seq,
uint32_t id, uint32_t start, uint32_t num,
@ -269,8 +272,7 @@ impl_node_remove_port(void *object, enum spa_direction direction, uint32_t port_
return 0;
}
static int port_enum_formats(void *object,
enum spa_direction direction, uint32_t port_id,
static int port_enum_formats(void *object, struct port *port,
uint32_t index,
struct spa_pod **param,
struct spa_pod_builder *builder)
@ -318,19 +320,19 @@ next:
switch (id) {
case SPA_PARAM_EnumFormat:
if ((res = port_enum_formats(this, direction, port_id, result.index, &param, &b)) <= 0)
if ((res = port_enum_formats(this, port, result.index, &param, &b)) <= 0)
return res;
break;
case SPA_PARAM_Format:
if (!port->have_format)
if (port == NULL || !port->have_format)
return -EIO;
if ((res = port_enum_formats(this, direction, port_id, result.index, &param, &b)) <= 0)
if ((res = port_enum_formats(this, port, result.index, &param, &b)) <= 0)
return res;
break;
case SPA_PARAM_Buffers:
if (!port->have_format)
if (port == NULL || !port->have_format)
return -EIO;
if (result.index > 0)
return 0;

View file

@ -827,7 +827,8 @@ static int setup_mixer(struct pw_impl_port *port, const struct spa_pod *param)
return res;
}
pw_log_debug("mix node handle:%p iface:%p", handle, iface);
pw_log_debug("mix node %s (%s) handle:%p iface:%p", factory_name, fallback_lib,
handle, iface);
pw_impl_port_set_mix(port, (struct spa_node*)iface,
PW_IMPL_PORT_MIX_FLAG_MULTI |
PW_IMPL_PORT_MIX_FLAG_NEGOTIATE);