mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
Port: Add tag param
The tag param has a list of arbitrary key/value pairs. Like the Latency param, it travels up and downstream. Mixers will append the info dictionaries or do some more fancy merging. The purpose is to transport arbirary metadata, out-of-band, through the graph and it's used for stream metadata and other stream properties.
This commit is contained in:
parent
6bf42e9bcd
commit
41dcac0ecd
20 changed files with 566 additions and 24 deletions
|
|
@ -40,6 +40,7 @@ static const struct spa_type_info spa_type_param[] = {
|
|||
{ SPA_PARAM_Control, SPA_TYPE_Sequence, SPA_TYPE_INFO_PARAM_ID_BASE "Control", NULL },
|
||||
{ SPA_PARAM_Latency, SPA_TYPE_OBJECT_ParamLatency, SPA_TYPE_INFO_PARAM_ID_BASE "Latency", NULL },
|
||||
{ SPA_PARAM_ProcessLatency, SPA_TYPE_OBJECT_ParamProcessLatency, SPA_TYPE_INFO_PARAM_ID_BASE "ProcessLatency", NULL },
|
||||
{ SPA_PARAM_Tag, SPA_TYPE_OBJECT_ParamTag, SPA_TYPE_INFO_PARAM_ID_BASE "Tag", NULL },
|
||||
{ 0, 0, NULL, NULL },
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ enum spa_param_type {
|
|||
SPA_PARAM_Control, /**< Control parameter, a SPA_TYPE_Sequence */
|
||||
SPA_PARAM_Latency, /**< latency reporting, a SPA_TYPE_OBJECT_ParamLatency */
|
||||
SPA_PARAM_ProcessLatency, /**< processing latency, a SPA_TYPE_OBJECT_ParamProcessLatency */
|
||||
SPA_PARAM_Tag, /**< tag reporting, a SPA_TYPE_OBJECT_ParamTag. Since 0.3.79 */
|
||||
};
|
||||
|
||||
/** information about a parameter */
|
||||
|
|
|
|||
39
spa/include/spa/param/tag-types.h
Normal file
39
spa/include/spa/param/tag-types.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* Simple Plugin API */
|
||||
/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef SPA_PARAM_TAG_TYPES_H
|
||||
#define SPA_PARAM_TAG_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \addtogroup spa_param
|
||||
* \{
|
||||
*/
|
||||
|
||||
#include <spa/utils/enum-types.h>
|
||||
#include <spa/param/param-types.h>
|
||||
#include <spa/param/tag.h>
|
||||
|
||||
#define SPA_TYPE_INFO_PARAM_Tag SPA_TYPE_INFO_PARAM_BASE "Tag"
|
||||
#define SPA_TYPE_INFO_PARAM_TAG_BASE SPA_TYPE_INFO_PARAM_Tag ":"
|
||||
|
||||
static const struct spa_type_info spa_type_param_tag[] = {
|
||||
{ SPA_PARAM_TAG_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_TAG_BASE, spa_type_param, },
|
||||
{ SPA_PARAM_TAG_direction, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_TAG_BASE "direction", spa_type_direction, },
|
||||
{ SPA_PARAM_TAG_info, SPA_TYPE_Struct, SPA_TYPE_INFO_PARAM_TAG_BASE "info", NULL, },
|
||||
{ 0, 0, NULL, NULL },
|
||||
};
|
||||
|
||||
/**
|
||||
* \}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* SPA_PARAM_TAG_TYPES_H */
|
||||
143
spa/include/spa/param/tag-utils.h
Normal file
143
spa/include/spa/param/tag-utils.h
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/* Simple Plugin API */
|
||||
/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef SPA_PARAM_TAG_UTILS_H
|
||||
#define SPA_PARAM_TAG_UTILS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \addtogroup spa_param
|
||||
* \{
|
||||
*/
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include <spa/utils/dict.h>
|
||||
#include <spa/pod/builder.h>
|
||||
#include <spa/pod/parser.h>
|
||||
#include <spa/param/tag.h>
|
||||
|
||||
static inline int
|
||||
spa_tag_compare(const struct spa_pod *a, const struct spa_pod *b)
|
||||
{
|
||||
return ((a == b) || (a && b && SPA_POD_SIZE(a) == SPA_POD_SIZE(b) &&
|
||||
memcmp(a, b, SPA_POD_SIZE(b)) == 0)) ? 0 : 1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
spa_tag_parse(const struct spa_pod *tag, struct spa_tag_info *info, void **state)
|
||||
{
|
||||
int res;
|
||||
const struct spa_pod_object *obj = (const struct spa_pod_object*)tag;
|
||||
const struct spa_pod_prop *first, *start, *cur;
|
||||
|
||||
spa_zero(*info);
|
||||
|
||||
if ((res = spa_pod_parse_object(tag,
|
||||
SPA_TYPE_OBJECT_ParamTag, NULL,
|
||||
SPA_PARAM_TAG_direction, SPA_POD_Id(&info->direction))) < 0)
|
||||
return res;
|
||||
|
||||
first = spa_pod_prop_first(&obj->body);
|
||||
start = *state ? spa_pod_prop_next((struct spa_pod_prop*)*state) : first;
|
||||
|
||||
res = 0;
|
||||
for (cur = start; spa_pod_prop_is_inside(&obj->body, obj->pod.size, cur);
|
||||
cur = spa_pod_prop_next(cur)) {
|
||||
if (cur->key == SPA_PARAM_TAG_info) {
|
||||
info->info = &cur->value;
|
||||
*state = (void*)cur;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
spa_tag_info_parse(const struct spa_tag_info *info, struct spa_dict *dict, struct spa_dict_item *items)
|
||||
{
|
||||
struct spa_pod_parser prs;
|
||||
uint32_t n, n_items;
|
||||
const char *key, *value;
|
||||
struct spa_pod_frame f[1];
|
||||
|
||||
spa_pod_parser_pod(&prs, info->info);
|
||||
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
|
||||
spa_pod_parser_get_int(&prs, (int32_t*)&n_items) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (items == NULL) {
|
||||
dict->n_items = n_items;
|
||||
return 0;
|
||||
}
|
||||
n_items = SPA_MIN(dict->n_items, n_items);
|
||||
|
||||
for (n = 0; n < n_items; n++) {
|
||||
if (spa_pod_parser_get(&prs,
|
||||
SPA_POD_String(&key),
|
||||
SPA_POD_String(&value),
|
||||
NULL) < 0)
|
||||
break;
|
||||
items[n].key = key;
|
||||
items[n].value = value;
|
||||
}
|
||||
dict->items = items;
|
||||
spa_pod_parser_pop(&prs, &f[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_tag_build_start(struct spa_pod_builder *builder, struct spa_pod_frame *f,
|
||||
uint32_t id, enum spa_direction direction)
|
||||
{
|
||||
spa_pod_builder_push_object(builder, f, SPA_TYPE_OBJECT_ParamTag, id);
|
||||
spa_pod_builder_add(builder,
|
||||
SPA_PARAM_TAG_direction, SPA_POD_Id(direction),
|
||||
0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_tag_build_add_info(struct spa_pod_builder *builder, const struct spa_pod *info)
|
||||
{
|
||||
spa_pod_builder_add(builder,
|
||||
SPA_PARAM_TAG_info, SPA_POD_Pod(info),
|
||||
0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_tag_build_add_dict(struct spa_pod_builder *builder, const struct spa_dict *dict)
|
||||
{
|
||||
uint32_t i, n_items;
|
||||
struct spa_pod_frame f;
|
||||
|
||||
n_items = dict ? dict->n_items : 0;
|
||||
|
||||
spa_pod_builder_prop(builder, SPA_PARAM_TAG_info, SPA_POD_PROP_FLAG_HINT_DICT);
|
||||
spa_pod_builder_push_struct(builder, &f);
|
||||
spa_pod_builder_int(builder, n_items);
|
||||
for (i = 0; i < n_items; i++) {
|
||||
spa_pod_builder_string(builder, dict->items[i].key);
|
||||
spa_pod_builder_string(builder, dict->items[i].value);
|
||||
}
|
||||
spa_pod_builder_pop(builder, &f);
|
||||
}
|
||||
|
||||
static inline struct spa_pod *
|
||||
spa_tag_build_end(struct spa_pod_builder *builder, struct spa_pod_frame *f)
|
||||
{
|
||||
return (struct spa_pod*)spa_pod_builder_pop(builder, f);
|
||||
}
|
||||
|
||||
/**
|
||||
* \}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* SPA_PARAM_TAG_UTILS_H */
|
||||
46
spa/include/spa/param/tag.h
Normal file
46
spa/include/spa/param/tag.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/* Simple Plugin API */
|
||||
/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef SPA_PARAM_TAG_H
|
||||
#define SPA_PARAM_TAG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \addtogroup spa_param
|
||||
* \{
|
||||
*/
|
||||
|
||||
#include <spa/param/param.h>
|
||||
|
||||
/** properties for SPA_TYPE_OBJECT_ParamTag */
|
||||
enum spa_param_tag {
|
||||
SPA_PARAM_TAG_START,
|
||||
SPA_PARAM_TAG_direction, /**< direction, input/output (Id enum spa_direction) */
|
||||
SPA_PARAM_TAG_info, /**< Struct(
|
||||
* Int: n_items
|
||||
* (String: key
|
||||
* String: value)*
|
||||
* ) */
|
||||
};
|
||||
|
||||
/** helper structure for managing tag objects */
|
||||
struct spa_tag_info {
|
||||
enum spa_direction direction;
|
||||
const struct spa_pod *info;
|
||||
};
|
||||
|
||||
#define SPA_TAG_INFO(dir,...) ((struct spa_tag_info) { .direction = (dir), ## __VA_ARGS__ })
|
||||
|
||||
/**
|
||||
* \}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* SPA_PARAM_TAG_H */
|
||||
|
|
@ -14,5 +14,6 @@
|
|||
#include <spa/param/profiler-types.h>
|
||||
#include <spa/param/profile-types.h>
|
||||
#include <spa/param/route-types.h>
|
||||
#include <spa/param/tag-types.h>
|
||||
|
||||
#endif /* SPA_PARAM_TYPE_INFO_H */
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ static const struct spa_type_info spa_types[] = {
|
|||
{ SPA_TYPE_OBJECT_Profiler, SPA_TYPE_Object, SPA_TYPE_INFO_Profiler, spa_type_profiler },
|
||||
{ SPA_TYPE_OBJECT_ParamLatency, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Latency, spa_type_param_latency },
|
||||
{ SPA_TYPE_OBJECT_ParamProcessLatency, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_ProcessLatency, spa_type_param_process_latency },
|
||||
{ SPA_TYPE_OBJECT_ParamTag, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Tag, spa_type_param_tag },
|
||||
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ enum {
|
|||
SPA_TYPE_OBJECT_Profiler,
|
||||
SPA_TYPE_OBJECT_ParamLatency,
|
||||
SPA_TYPE_OBJECT_ParamProcessLatency,
|
||||
SPA_TYPE_OBJECT_ParamTag,
|
||||
_SPA_TYPE_OBJECT_LAST, /**< not part of ABI */
|
||||
|
||||
/* vendor extensions */
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
#include <spa/utils/string.h>
|
||||
#include <spa/param/audio/format.h>
|
||||
#include <spa/pod/filter.h>
|
||||
#include <spa/debug/log.h>
|
||||
#include <spa/debug/pod.h>
|
||||
|
||||
#include "alsa-pcm.h"
|
||||
|
||||
|
|
@ -669,7 +671,7 @@ impl_node_port_set_param(void *object,
|
|||
const struct spa_pod *param)
|
||||
{
|
||||
struct state *this = object;
|
||||
int res;
|
||||
int res = 0;
|
||||
|
||||
spa_return_val_if_fail(this != NULL, -EINVAL);
|
||||
|
||||
|
|
@ -693,9 +695,12 @@ impl_node_port_set_param(void *object,
|
|||
this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
|
||||
this->port_params[PORT_Latency].user++;
|
||||
emit_port_info(this, false);
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
case SPA_PARAM_Tag:
|
||||
if (param != NULL)
|
||||
spa_debug_log_pod(this->log, SPA_LOG_LEVEL_DEBUG, 0, NULL, param);
|
||||
break;
|
||||
default:
|
||||
res = -ENOENT;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <spa/param/param.h>
|
||||
#include <spa/param/audio/format-utils.h>
|
||||
#include <spa/param/latency-utils.h>
|
||||
#include <spa/param/tag-utils.h>
|
||||
#include <spa/debug/format.h>
|
||||
#include <spa/debug/pod.h>
|
||||
#include <spa/debug/log.h>
|
||||
|
|
@ -75,7 +76,8 @@ struct impl {
|
|||
#define IDX_PortConfig 5
|
||||
#define IDX_Latency 6
|
||||
#define IDX_ProcessLatency 7
|
||||
#define N_NODE_PARAMS 8
|
||||
#define IDX_Tag 8
|
||||
#define N_NODE_PARAMS 9
|
||||
struct spa_param_info params[N_NODE_PARAMS];
|
||||
uint32_t convert_params_flags[N_NODE_PARAMS];
|
||||
uint32_t follower_params_flags[N_NODE_PARAMS];
|
||||
|
|
@ -204,6 +206,7 @@ next:
|
|||
case SPA_PARAM_EnumFormat:
|
||||
case SPA_PARAM_Format:
|
||||
case SPA_PARAM_Latency:
|
||||
case SPA_PARAM_Tag:
|
||||
res = spa_node_port_enum_params_sync(this->follower,
|
||||
this->direction, 0,
|
||||
id, &result.next, filter, &result.param, &b.b);
|
||||
|
|
@ -1093,8 +1096,10 @@ static int recalc_latency(struct impl *this, enum spa_direction direction, uint3
|
|||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||
if ((res = spa_node_port_enum_params_sync(this->follower,
|
||||
direction, port_id, SPA_PARAM_Latency,
|
||||
&index, NULL, ¶m, &b)) != 1)
|
||||
return res;
|
||||
&index, NULL, ¶m, &b)) != 1) {
|
||||
param = NULL;
|
||||
break;
|
||||
}
|
||||
if ((res = spa_latency_parse(param, &latency)) < 0)
|
||||
return res;
|
||||
if (latency.direction == direction)
|
||||
|
|
@ -1108,6 +1113,42 @@ static int recalc_latency(struct impl *this, enum spa_direction direction, uint3
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int recalc_tag(struct impl *this, enum spa_direction direction, uint32_t port_id)
|
||||
{
|
||||
struct spa_pod_builder b = { 0 };
|
||||
uint8_t buffer[1024];
|
||||
struct spa_pod *param;
|
||||
uint32_t index = 0;
|
||||
struct spa_tag_info info;
|
||||
int res;
|
||||
|
||||
spa_log_debug(this->log, "%p: ", this);
|
||||
|
||||
if (this->target == this->follower)
|
||||
return 0;
|
||||
|
||||
while (true) {
|
||||
void *state = NULL;
|
||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||
if ((res = spa_node_port_enum_params_sync(this->follower,
|
||||
direction, port_id, SPA_PARAM_Tag,
|
||||
&index, NULL, ¶m, &b)) != 1) {
|
||||
param = NULL;
|
||||
break;
|
||||
}
|
||||
if ((res = spa_tag_parse(param, &info, &state)) < 0)
|
||||
return res;
|
||||
if (info.direction == direction)
|
||||
break;
|
||||
}
|
||||
if ((res = spa_node_port_set_param(this->target,
|
||||
SPA_DIRECTION_REVERSE(direction), 0,
|
||||
SPA_PARAM_Tag, 0, param)) < 0)
|
||||
return res;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void follower_port_info(void *data,
|
||||
enum spa_direction direction, uint32_t port_id,
|
||||
const struct spa_port_info *info)
|
||||
|
|
@ -1144,6 +1185,9 @@ static void follower_port_info(void *data,
|
|||
case SPA_PARAM_Latency:
|
||||
idx = IDX_Latency;
|
||||
break;
|
||||
case SPA_PARAM_Tag:
|
||||
idx = IDX_Tag;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1166,6 +1210,11 @@ static void follower_port_info(void *data,
|
|||
spa_log_debug(this->log, "latency: %d (%s)", res,
|
||||
spa_strerror(res));
|
||||
}
|
||||
if (idx == IDX_Tag) {
|
||||
res = recalc_tag(this, direction, port_id);
|
||||
spa_log_debug(this->log, "tag: %d (%s)", res,
|
||||
spa_strerror(res));
|
||||
}
|
||||
if (idx == IDX_EnumFormat) {
|
||||
spa_log_debug(this->log, "new formats");
|
||||
configure_format(this, 0, NULL);
|
||||
|
|
@ -1403,7 +1452,7 @@ impl_node_port_set_param(void *object,
|
|||
flags, param)) < 0)
|
||||
return res;
|
||||
|
||||
if ((id == SPA_PARAM_Latency) &&
|
||||
if ((id == SPA_PARAM_Latency || id == SPA_PARAM_Tag) &&
|
||||
direction == this->direction) {
|
||||
if ((res = spa_node_port_set_param(this->follower, direction, 0, id,
|
||||
flags, param)) < 0)
|
||||
|
|
@ -1707,6 +1756,7 @@ impl_init(const struct spa_handle_factory *factory,
|
|||
this->params[IDX_PortConfig] = SPA_PARAM_INFO(SPA_PARAM_PortConfig, SPA_PARAM_INFO_READWRITE);
|
||||
this->params[IDX_Latency] = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_READWRITE);
|
||||
this->params[IDX_ProcessLatency] = SPA_PARAM_INFO(SPA_PARAM_ProcessLatency, SPA_PARAM_INFO_READWRITE);
|
||||
this->params[IDX_Tag] = SPA_PARAM_INFO(SPA_PARAM_Tag, SPA_PARAM_INFO_READWRITE);
|
||||
this->info.params = this->params;
|
||||
this->info.n_params = N_NODE_PARAMS;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include <spa/param/audio/format-utils.h>
|
||||
#include <spa/param/param.h>
|
||||
#include <spa/param/latency-utils.h>
|
||||
#include <spa/param/tag-utils.h>
|
||||
#include <spa/pod/filter.h>
|
||||
#include <spa/pod/dynamic.h>
|
||||
#include <spa/debug/types.h>
|
||||
|
|
@ -138,7 +139,8 @@ struct port {
|
|||
#define IDX_Format 3
|
||||
#define IDX_Buffers 4
|
||||
#define IDX_Latency 5
|
||||
#define N_PORT_PARAMS 6
|
||||
#define IDX_Tag 6
|
||||
#define N_PORT_PARAMS 7
|
||||
struct spa_param_info params[N_PORT_PARAMS];
|
||||
char position[16];
|
||||
|
||||
|
|
@ -171,6 +173,7 @@ struct dir {
|
|||
unsigned int have_format:1;
|
||||
unsigned int have_profile:1;
|
||||
struct spa_latency_info latency;
|
||||
struct spa_pod *tag;
|
||||
|
||||
uint32_t remap[MAX_PORTS];
|
||||
|
||||
|
|
@ -339,6 +342,7 @@ static int init_port(struct impl *this, enum spa_direction direction, uint32_t p
|
|||
port->params[IDX_Format] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
|
||||
port->params[IDX_Buffers] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
|
||||
port->params[IDX_Latency] = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_READWRITE);
|
||||
port->params[IDX_Tag] = SPA_PARAM_INFO(SPA_PARAM_Tag, SPA_PARAM_INFO_READWRITE);
|
||||
port->info.params = port->params;
|
||||
port->info.n_params = N_PORT_PARAMS;
|
||||
|
||||
|
|
@ -2108,6 +2112,22 @@ impl_node_port_enum_params(void *object, int seq,
|
|||
return 0;
|
||||
}
|
||||
break;
|
||||
case SPA_PARAM_Tag:
|
||||
switch (result.index) {
|
||||
case 0: case 1:
|
||||
{
|
||||
uint32_t idx = result.index;
|
||||
if (port->is_monitor)
|
||||
idx = idx ^ 1;
|
||||
param = this->dir[idx].tag;
|
||||
if (param == NULL)
|
||||
goto next;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
|
|
@ -2173,6 +2193,48 @@ static int port_set_latency(void *object,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int port_set_tag(void *object,
|
||||
enum spa_direction direction,
|
||||
uint32_t port_id,
|
||||
uint32_t flags,
|
||||
const struct spa_pod *tag)
|
||||
{
|
||||
struct impl *this = object;
|
||||
struct port *port, *oport;
|
||||
enum spa_direction other = SPA_DIRECTION_REVERSE(direction);
|
||||
uint32_t i;
|
||||
|
||||
spa_log_debug(this->log, "%p: set tag direction:%d id:%d %p",
|
||||
this, direction, port_id, tag);
|
||||
|
||||
port = GET_PORT(this, direction, port_id);
|
||||
if (port->is_monitor)
|
||||
return 0;
|
||||
|
||||
free(this->dir[other].tag);
|
||||
this->dir[other].tag = NULL;
|
||||
|
||||
if (tag != NULL) {
|
||||
struct spa_tag_info info;
|
||||
void *state = NULL;
|
||||
if (spa_tag_parse(tag, &info, &state) < 0 ||
|
||||
info.direction != other)
|
||||
return -EINVAL;
|
||||
this->dir[other].tag = spa_pod_copy(tag);
|
||||
}
|
||||
|
||||
for (i = 0; i < this->dir[other].n_ports; i++) {
|
||||
oport = GET_PORT(this, other, i);
|
||||
oport->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
|
||||
oport->params[IDX_Tag].user++;
|
||||
emit_port_info(this, oport, false);
|
||||
}
|
||||
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
|
||||
port->params[IDX_Tag].user++;
|
||||
emit_port_info(this, port, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int port_set_format(void *object,
|
||||
enum spa_direction direction,
|
||||
uint32_t port_id,
|
||||
|
|
@ -2296,6 +2358,8 @@ impl_node_port_set_param(void *object,
|
|||
switch (id) {
|
||||
case SPA_PARAM_Latency:
|
||||
return port_set_latency(this, direction, port_id, flags, param);
|
||||
case SPA_PARAM_Tag:
|
||||
return port_set_tag(this, direction, port_id, flags, param);
|
||||
case SPA_PARAM_Format:
|
||||
return port_set_format(this, direction, port_id, flags, param);
|
||||
default:
|
||||
|
|
@ -3123,19 +3187,27 @@ static int impl_get_interface(struct spa_handle *handle, const char *type, void
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void free_dir(struct dir *dir)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < MAX_PORTS; i++)
|
||||
free(dir->ports[i]);
|
||||
if (dir->conv.free)
|
||||
convert_free(&dir->conv);
|
||||
free(dir->tag);
|
||||
}
|
||||
|
||||
static int impl_clear(struct spa_handle *handle)
|
||||
{
|
||||
struct impl *this;
|
||||
uint32_t i;
|
||||
|
||||
spa_return_val_if_fail(handle != NULL, -EINVAL);
|
||||
|
||||
this = (struct impl *) handle;
|
||||
|
||||
for (i = 0; i < MAX_PORTS; i++)
|
||||
free(this->dir[SPA_DIRECTION_INPUT].ports[i]);
|
||||
for (i = 0; i < MAX_PORTS; i++)
|
||||
free(this->dir[SPA_DIRECTION_OUTPUT].ports[i]);
|
||||
free_dir(&this->dir[SPA_DIRECTION_INPUT]);
|
||||
free_dir(&this->dir[SPA_DIRECTION_OUTPUT]);
|
||||
|
||||
free(this->empty);
|
||||
free(this->scratch);
|
||||
free(this->tmp[0]);
|
||||
|
|
@ -3143,10 +3215,6 @@ static int impl_clear(struct spa_handle *handle)
|
|||
|
||||
if (this->resample.free)
|
||||
resample_free(&this->resample);
|
||||
if (this->dir[0].conv.free)
|
||||
convert_free(&this->dir[0].conv);
|
||||
if (this->dir[1].conv.free)
|
||||
convert_free(&this->dir[1].conv);
|
||||
if (this->wav_file != NULL)
|
||||
wav_file_close(this->wav_file);
|
||||
free (this->vol_ramp_sequence);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue