pod: improve parser and builder

Remove the spa_pod_iter helpers
Remove builder/parser vararg recurse option, you have to
manually recurse into structures when needed. This simplifies
things a lot.
Pass spa_pod_frames to builder and parser explicitly, we don't
have to keep an internal stack anymore.
The parser is now almost a mirror image of the builder.
Make the parser safer when iterating over objects, add functions
to check and get pod contents in a safe way.
Make the builder return errno style results on errors
Improve performance of object properties when they are stored and
retrieved in the same order.
Add many more tests for the builder and parser
Add some benchmarks
This commit is contained in:
Wim Taymans 2019-01-22 17:38:23 +01:00
parent 878ae769ef
commit 351fb9ce29
36 changed files with 1605 additions and 973 deletions

View File

@ -25,6 +25,9 @@ valgrind:
test: all
ninja -C build test
benchmark: all
ninja -C build benchmark
monitor: all
SPA_PLUGIN_DIR=build/spa/plugins \
PIPEWIRE_MODULE_DIR=build/src/modules/ \

@ -1 +1 @@
Subproject commit 4bdaa083d13771e37d7d2c1e20953c7b617dfa2b
Subproject commit c404942e9d15bd3340c57121753fed8d38b247c6

View File

@ -198,27 +198,28 @@ static void update_props(struct data *data)
{
struct spa_pod_builder b;
struct spa_pod *pod;
struct spa_pod_frame f[2];
spa_pod_builder_init(&b, data->ctrl, sizeof(data->ctrl));
#if 0
spa_pod_builder_push_sequence(&b, 0);
spa_pod_builder_push_sequence(&b, &f[0], 0);
spa_pod_builder_control(&b, 0, SPA_CONTROL_Properties);
spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_Props, 0);
spa_pod_builder_push_object(&b, &f[1], SPA_TYPE_OBJECT_Props, 0);
spa_pod_builder_prop(&b, SPA_PROP_frequency, 0);
spa_pod_builder_float(&b, ((sin(data->freq_accum) + 1.0) * 200.0) + 440.0);
spa_pod_builder_prop(&b, SPA_PROP_volume, 0);
spa_pod_builder_float(&b, (sin(data->volume_accum) / 2.0) + 0.5);
spa_pod_builder_pop(&b);
pod = spa_pod_builder_pop(&b);
spa_pod_builder_pop(&b, &f[1]);
pod = spa_pod_builder_pop(&b, &f[0]);
#else
spa_pod_builder_push_sequence(&b, 0);
spa_pod_builder_push_sequence(&b, &f[0], 0);
spa_pod_builder_control(&b, 0, SPA_CONTROL_Properties);
spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Props, 0,
SPA_PROP_frequency, SPA_POD_Float(((sin(data->freq_accum) + 1.0) * 200.0) + 440.0),
SPA_PROP_volume, SPA_POD_Float((sin(data->volume_accum) / 2.0) + 0.5));
pod = spa_pod_builder_pop(&b);
pod = spa_pod_builder_pop(&b, &f[0]);
#endif
spa_debug_pod(0, NULL, pod);
@ -386,9 +387,10 @@ static int negotiate_formats(struct data *data)
filter, &format, &b)) <= 0)
return -EBADF;
spa_debug_pod(0, NULL, format);
spa_log_debug(&default_log.log, "sink set_param");
spa_debug_pod(0, NULL, format);
spa_pod_fixate(format);
if ((res = spa_node_port_set_param(data->sink,
SPA_DIRECTION_INPUT, 0,
SPA_PARAM_Format, 0, format)) < 0)
@ -527,11 +529,11 @@ int main(int argc, char *argv[])
data.n_support = 3;
if ((res = make_nodes(&data, argc > 1 ? argv[1] : NULL)) < 0) {
printf("can't make nodes: %d\n", res);
printf("can't make nodes: %d (%s)\n", res, spa_strerror(res));
return -1;
}
if ((res = negotiate_formats(&data)) < 0) {
printf("can't negotiate nodes: %d\n", res);
printf("can't negotiate nodes: %d (%s)\n", res, spa_strerror(res));
return -1;
}

View File

@ -39,15 +39,13 @@ static inline int
spa_format_audio_raw_parse(const struct spa_pod *format, struct spa_audio_info_raw *info)
{
struct spa_pod *position = NULL;
struct spa_pod_parser prs;
int res;
spa_pod_parser_pod(&prs, format);
res = spa_pod_parser_get_object(&prs,
info->flags = 0;
res = spa_pod_parse_object(format,
SPA_TYPE_OBJECT_Format, NULL,
SPA_FORMAT_AUDIO_format, SPA_POD_Id(&info->format),
SPA_FORMAT_AUDIO_rate, SPA_POD_Int(&info->rate),
SPA_FORMAT_AUDIO_channels, SPA_POD_Int(&info->channels),
SPA_FORMAT_AUDIO_flags, SPA_POD_OPT_Int(&info->flags),
SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position));
if (position && spa_pod_is_array(position) &&
SPA_POD_ARRAY_VALUE_TYPE(position) == SPA_TYPE_Id) {
@ -64,7 +62,8 @@ spa_format_audio_raw_parse(const struct spa_pod *format, struct spa_audio_info_r
static inline struct spa_pod *
spa_format_audio_raw_build(struct spa_pod_builder *builder, uint32_t id, struct spa_audio_info_raw *info)
{
spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_Format, id);
struct spa_pod_frame f;
spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id);
spa_pod_builder_add(builder,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
@ -78,7 +77,7 @@ spa_format_audio_raw_build(struct spa_pod_builder *builder, uint32_t id, struct
spa_pod_builder_array(builder, sizeof(uint32_t), SPA_TYPE_Id,
info->channels, info->position);
}
return (struct spa_pod*)spa_pod_builder_pop(builder);
return (struct spa_pod*)spa_pod_builder_pop(builder, &f);
}

View File

@ -31,37 +31,31 @@ extern "C" {
#include <stdarg.h>
#include <spa/pod/pod.h>
struct spa_pod_frame {
struct spa_pod pod;
uint32_t ref;
uint32_t _padding;
};
#include <spa/pod/iter.h>
struct spa_pod_builder_state {
uint32_t offset;
#define SPA_POD_BUILDER_FLAG_BODY (1<<0)
#define SPA_POD_BUILDER_FLAG_FIRST (1<<1)
#define SPA_POD_BUILDER_FLAG_OBJECT (1<<2)
#define SPA_POD_BUILDER_FLAG_SEQUENCE (1<<3)
#define SPA_POD_BUILDER_FLAG_HEADER (1<<4)
uint32_t flags;
uint32_t depth;
uint32_t _padding;
struct spa_pod_frame *frame;
};
struct spa_pod_builder;
struct spa_pod_builder_callbacks {
#define SPA_VERSION_POD_BUILDER_CALLBACKS 0
uint32_t version;
int (*overflow) (void *callbacks_data, uint32_t size);
};
struct spa_pod_builder {
void *data;
uint32_t size;
uint32_t _padding;
uint32_t (*write) (struct spa_pod_builder *builder, const void *data, uint32_t size);
void * (*deref) (struct spa_pod_builder *builder, uint32_t ref, bool safe);
void (*reset) (struct spa_pod_builder *builder, struct spa_pod_builder_state *state);
struct spa_pod_builder_state state;
struct spa_pod_frame frame[SPA_POD_MAX_DEPTH];
const struct spa_pod_builder_callbacks *callbacks;
void *callbacks_data;
};
#define SPA_POD_BUILDER_INIT(buffer,size) (struct spa_pod_builder){ buffer, size, }
@ -75,10 +69,7 @@ spa_pod_builder_get_state(struct spa_pod_builder *builder, struct spa_pod_builde
static inline void
spa_pod_builder_reset(struct spa_pod_builder *builder, struct spa_pod_builder_state *state)
{
if (builder->reset)
builder->reset(builder, state);
else
builder->state = *state;
builder->state = *state;
}
static inline void spa_pod_builder_init(struct spa_pod_builder *builder, void *data, uint32_t size)
@ -86,128 +77,97 @@ static inline void spa_pod_builder_init(struct spa_pod_builder *builder, void *d
*builder = SPA_POD_BUILDER_INIT(data, size);
}
static inline struct spa_pod_frame *
spa_pod_builder_top(struct spa_pod_builder *builder)
static inline struct spa_pod *
spa_pod_builder_deref(struct spa_pod_builder *builder, uint32_t offset, uint32_t size)
{
return builder->state.depth > 0 ? &builder->frame[builder->state.depth-1] : NULL;
}
static inline void *
spa_pod_builder_deref_checked(struct spa_pod_builder *builder, uint32_t ref, bool safe)
{
if (ref == SPA_ID_INVALID)
return NULL;
else if (builder->deref)
return builder->deref(builder, ref, safe);
else if (ref + 8 <= builder->size) {
struct spa_pod *pod = SPA_MEMBER(builder->data, ref, struct spa_pod);
if (!safe || SPA_POD_SIZE(pod) <= builder->size)
return (void *) pod;
if (offset + 8 <= size) {
struct spa_pod *pod = SPA_MEMBER(builder->data, offset, struct spa_pod);
if (offset + SPA_POD_SIZE(pod) <= size)
return pod;
}
return NULL;
}
static inline void *
spa_pod_builder_deref(struct spa_pod_builder *builder, uint32_t ref)
static inline struct spa_pod *
spa_pod_builder_frame(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
{
return spa_pod_builder_deref_checked(builder, ref, false);
return spa_pod_builder_deref(builder, frame->offset, builder->size);
}
static inline void
spa_pod_builder_update_frame(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
{
switch (frame->pod.type) {
case SPA_TYPE_Array:
case SPA_TYPE_Choice:
builder->state.flags = SPA_POD_BUILDER_FLAG_BODY;
break;
case SPA_TYPE_Object:
builder->state.flags = SPA_POD_BUILDER_FLAG_OBJECT;
break;
case SPA_TYPE_Sequence:
builder->state.flags = SPA_POD_BUILDER_FLAG_SEQUENCE;
break;
}
}
static inline uint32_t
spa_pod_builder_push(struct spa_pod_builder *builder,
struct spa_pod_frame *frame,
const struct spa_pod *pod,
uint32_t ref)
uint32_t offset)
{
struct spa_pod_frame *frame = &builder->frame[builder->state.depth++];
frame->pod = *pod;
frame->ref = ref;
spa_pod_builder_update_frame(builder, frame);
if (builder->state.flags & SPA_POD_BUILDER_FLAG_BODY)
SPA_FLAG_SET(builder->state.flags, SPA_POD_BUILDER_FLAG_FIRST);
return ref;
frame->offset = offset;
frame->parent = builder->state.frame;
frame->flags = builder->state.flags;
builder->state.frame = frame;
if (frame->pod.type == SPA_TYPE_Array || frame->pod.type == SPA_TYPE_Choice)
builder->state.flags = SPA_POD_BUILDER_FLAG_FIRST | SPA_POD_BUILDER_FLAG_BODY;
}
static inline uint32_t
spa_pod_builder_raw(struct spa_pod_builder *builder, const void *data, uint32_t size)
static inline int spa_pod_builder_raw(struct spa_pod_builder *builder, const void *data, uint32_t size)
{
uint32_t i, ref;
int res = 0;
struct spa_pod_frame *f;
uint32_t offset = builder->state.offset;
if (builder->write) {
ref = builder->write(builder, data, size);
} else {
ref = builder->state.offset;
if (ref + size > builder->size)
ref = SPA_ID_INVALID;
if (offset + size > builder->size) {
if (builder->callbacks && builder->callbacks->overflow)
res = builder->callbacks->overflow(builder->callbacks_data, offset + size);
else
memcpy(SPA_MEMBER(builder->data, ref, void), data, size);
res = -ENOSPC;
}
if (res == 0)
memcpy(SPA_MEMBER(builder->data, offset, void), data, size);
builder->state.offset += size;
for (i = 0; i < builder->state.depth; i++)
builder->frame[i].pod.size += size;
for (f = builder->state.frame; f ; f = f->parent)
f->pod.size += size;
return ref;
return res;
}
static inline void spa_pod_builder_pad(struct spa_pod_builder *builder, uint32_t size)
static inline int spa_pod_builder_pad(struct spa_pod_builder *builder, uint32_t size)
{
uint64_t zeroes = 0;
size = SPA_ROUND_UP_N(size, 8) - size;
if (size)
spa_pod_builder_raw(builder, &zeroes, size);
SPA_FLAG_UNSET(builder->state.flags, SPA_POD_BUILDER_FLAG_HEADER);
return size ? spa_pod_builder_raw(builder, &zeroes, size) : 0;
}
static inline uint32_t
static inline int
spa_pod_builder_raw_padded(struct spa_pod_builder *builder, const void *data, uint32_t size)
{
uint32_t ref = size ? spa_pod_builder_raw(builder, data, size) : SPA_ID_INVALID;
spa_pod_builder_pad(builder, size);
return ref;
int r, res = spa_pod_builder_raw(builder, data, size);
if ((r = spa_pod_builder_pad(builder, size)) < 0)
res = r;
return res;
}
static inline void *spa_pod_builder_pop(struct spa_pod_builder *builder)
static inline void *spa_pod_builder_pop(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
{
struct spa_pod_frame *frame;
struct spa_pod *pod;
frame = &builder->frame[--builder->state.depth];
if ((pod = (struct spa_pod *) spa_pod_builder_deref_checked(builder, frame->ref, true)) != NULL)
if ((pod = (struct spa_pod *) spa_pod_builder_frame(builder, frame)) != NULL)
*pod = frame->pod;
if ((frame = spa_pod_builder_top(builder)) != NULL)
spa_pod_builder_update_frame(builder, frame);
else
builder->state.flags = 0;
builder->state.frame = frame->parent;
builder->state.flags = frame->flags;
spa_pod_builder_pad(builder, builder->state.offset);
return pod;
}
static inline uint32_t
static inline int
spa_pod_builder_primitive(struct spa_pod_builder *builder, const struct spa_pod *p)
{
const void *data;
uint32_t size, ref;
uint32_t size;
int r, res;
if (builder->state.flags == SPA_POD_BUILDER_FLAG_BODY) {
data = SPA_POD_BODY_CONST(p);
@ -217,18 +177,18 @@ spa_pod_builder_primitive(struct spa_pod_builder *builder, const struct spa_pod
size = SPA_POD_SIZE(p);
SPA_FLAG_UNSET(builder->state.flags, SPA_POD_BUILDER_FLAG_FIRST);
}
ref = spa_pod_builder_raw(builder, data, size);
res = spa_pod_builder_raw(builder, data, size);
if (builder->state.flags != SPA_POD_BUILDER_FLAG_BODY)
spa_pod_builder_pad(builder, size);
return ref;
if ((r = spa_pod_builder_pad(builder, size)) < 0)
res = r;
return res;
}
#define SPA_POD_INIT(size,type) (struct spa_pod) { size, type }
#define SPA_POD_INIT_None() SPA_POD_INIT(0, SPA_TYPE_None)
static inline uint32_t spa_pod_builder_none(struct spa_pod_builder *builder)
static inline int spa_pod_builder_none(struct spa_pod_builder *builder)
{
const struct spa_pod p = SPA_POD_INIT_None();
return spa_pod_builder_primitive(builder, &p);
@ -236,7 +196,7 @@ static inline uint32_t spa_pod_builder_none(struct spa_pod_builder *builder)
#define SPA_POD_INIT_Bool(val) (struct spa_pod_bool){ { sizeof(uint32_t), SPA_TYPE_Bool }, val ? 1 : 0, 0 }
static inline uint32_t spa_pod_builder_bool(struct spa_pod_builder *builder, bool val)
static inline int spa_pod_builder_bool(struct spa_pod_builder *builder, bool val)
{
const struct spa_pod_bool p = SPA_POD_INIT_Bool(val);
return spa_pod_builder_primitive(builder, &p.pod);
@ -244,7 +204,7 @@ static inline uint32_t spa_pod_builder_bool(struct spa_pod_builder *builder, boo
#define SPA_POD_INIT_Id(val) (struct spa_pod_id){ { sizeof(uint32_t), SPA_TYPE_Id }, (uint32_t)val, 0 }
static inline uint32_t spa_pod_builder_id(struct spa_pod_builder *builder, uint32_t val)
static inline int spa_pod_builder_id(struct spa_pod_builder *builder, uint32_t val)
{
const struct spa_pod_id p = SPA_POD_INIT_Id(val);
return spa_pod_builder_primitive(builder, &p.pod);
@ -252,7 +212,7 @@ static inline uint32_t spa_pod_builder_id(struct spa_pod_builder *builder, uint3
#define SPA_POD_INIT_Int(val) (struct spa_pod_int){ { sizeof(int32_t), SPA_TYPE_Int }, (int32_t)val, 0 }
static inline uint32_t spa_pod_builder_int(struct spa_pod_builder *builder, int32_t val)
static inline int spa_pod_builder_int(struct spa_pod_builder *builder, int32_t val)
{
const struct spa_pod_int p = SPA_POD_INIT_Int(val);
return spa_pod_builder_primitive(builder, &p.pod);
@ -260,7 +220,7 @@ static inline uint32_t spa_pod_builder_int(struct spa_pod_builder *builder, int3
#define SPA_POD_INIT_Long(val) (struct spa_pod_long){ { sizeof(int64_t), SPA_TYPE_Long }, (int64_t)val }
static inline uint32_t spa_pod_builder_long(struct spa_pod_builder *builder, int64_t val)
static inline int spa_pod_builder_long(struct spa_pod_builder *builder, int64_t val)
{
const struct spa_pod_long p = SPA_POD_INIT_Long(val);
return spa_pod_builder_primitive(builder, &p.pod);
@ -268,7 +228,7 @@ static inline uint32_t spa_pod_builder_long(struct spa_pod_builder *builder, int
#define SPA_POD_INIT_Float(val) (struct spa_pod_float){ { sizeof(float), SPA_TYPE_Float }, val }
static inline uint32_t spa_pod_builder_float(struct spa_pod_builder *builder, float val)
static inline int spa_pod_builder_float(struct spa_pod_builder *builder, float val)
{
const struct spa_pod_float p = SPA_POD_INIT_Float(val);
return spa_pod_builder_primitive(builder, &p.pod);
@ -276,7 +236,7 @@ static inline uint32_t spa_pod_builder_float(struct spa_pod_builder *builder, fl
#define SPA_POD_INIT_Double(val) (struct spa_pod_double){ { sizeof(double), SPA_TYPE_Double }, val }
static inline uint32_t spa_pod_builder_double(struct spa_pod_builder *builder, double val)
static inline int spa_pod_builder_double(struct spa_pod_builder *builder, double val)
{
const struct spa_pod_double p = SPA_POD_INIT_Double(val);
return spa_pod_builder_primitive(builder, &p.pod);
@ -284,29 +244,29 @@ static inline uint32_t spa_pod_builder_double(struct spa_pod_builder *builder, d
#define SPA_POD_INIT_String(len) (struct spa_pod_string){ { len, SPA_TYPE_String } }
static inline uint32_t
static inline int
spa_pod_builder_write_string(struct spa_pod_builder *builder, const char *str, uint32_t len)
{
uint32_t ref = 0;
if (spa_pod_builder_raw(builder, str, len) == SPA_ID_INVALID)
ref = SPA_ID_INVALID;
if (spa_pod_builder_raw(builder, "", 1) == SPA_ID_INVALID)
ref = SPA_ID_INVALID;
spa_pod_builder_pad(builder, builder->state.offset);
return ref;
int r, res;
res = spa_pod_builder_raw(builder, str, len);
if ((r = spa_pod_builder_raw(builder, "", 1)) < 0)
res = r;
if ((r = spa_pod_builder_pad(builder, builder->state.offset)) < 0)
res = r;
return res;
}
static inline uint32_t
static inline int
spa_pod_builder_string_len(struct spa_pod_builder *builder, const char *str, uint32_t len)
{
const struct spa_pod_string p = SPA_POD_INIT_String(len+1);
uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p));
if (spa_pod_builder_write_string(builder, str, len) == SPA_ID_INVALID)
ref = SPA_ID_INVALID;
return ref;
int r, res = spa_pod_builder_raw(builder, &p, sizeof(p));
if ((r = spa_pod_builder_write_string(builder, str, len)) < 0)
res = r;
return res;
}
static inline uint32_t spa_pod_builder_string(struct spa_pod_builder *builder, const char *str)
static inline int spa_pod_builder_string(struct spa_pod_builder *builder, const char *str)
{
uint32_t len = str ? strlen(str) : 0;
return spa_pod_builder_string_len(builder, str ? str : "", len);
@ -314,19 +274,19 @@ static inline uint32_t spa_pod_builder_string(struct spa_pod_builder *builder, c
#define SPA_POD_INIT_Bytes(len) (struct spa_pod_bytes){ { len, SPA_TYPE_Bytes } }
static inline uint32_t
static inline int
spa_pod_builder_bytes(struct spa_pod_builder *builder, const void *bytes, uint32_t len)
{
const struct spa_pod_bytes p = SPA_POD_INIT_Bytes(len);
uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p));
if (spa_pod_builder_raw_padded(builder, bytes, len) == SPA_ID_INVALID)
ref = SPA_ID_INVALID;
return ref;
int r, res = spa_pod_builder_raw(builder, &p, sizeof(p));
if ((r = spa_pod_builder_raw_padded(builder, bytes, len)) < 0)
res = r;
return res;
}
#define SPA_POD_INIT_Pointer(type,value) (struct spa_pod_pointer){ { sizeof(struct spa_pod_pointer_body), SPA_TYPE_Pointer }, { type, 0, value } }
static inline uint32_t
static inline int
spa_pod_builder_pointer(struct spa_pod_builder *builder, uint32_t type, const void *val)
{
const struct spa_pod_pointer p = SPA_POD_INIT_Pointer(type, val);
@ -335,7 +295,7 @@ spa_pod_builder_pointer(struct spa_pod_builder *builder, uint32_t type, const vo
#define SPA_POD_INIT_Fd(fd) (struct spa_pod_fd){ { sizeof(int64_t), SPA_TYPE_Fd }, fd }
static inline uint32_t spa_pod_builder_fd(struct spa_pod_builder *builder, int64_t fd)
static inline int spa_pod_builder_fd(struct spa_pod_builder *builder, int64_t fd)
{
const struct spa_pod_fd p = SPA_POD_INIT_Fd(fd);
return spa_pod_builder_primitive(builder, &p.pod);
@ -343,7 +303,7 @@ static inline uint32_t spa_pod_builder_fd(struct spa_pod_builder *builder, int64
#define SPA_POD_INIT_Rectangle(val) (struct spa_pod_rectangle){ { sizeof(struct spa_rectangle), SPA_TYPE_Rectangle }, val }
static inline uint32_t
static inline int
spa_pod_builder_rectangle(struct spa_pod_builder *builder, uint32_t width, uint32_t height)
{
const struct spa_pod_rectangle p = SPA_POD_INIT_Rectangle(SPA_RECTANGLE(width, height));
@ -352,25 +312,26 @@ spa_pod_builder_rectangle(struct spa_pod_builder *builder, uint32_t width, uint3
#define SPA_POD_INIT_Fraction(val) (struct spa_pod_fraction){ { sizeof(struct spa_fraction), SPA_TYPE_Fraction }, val }
static inline uint32_t
static inline int
spa_pod_builder_fraction(struct spa_pod_builder *builder, uint32_t num, uint32_t denom)
{
const struct spa_pod_fraction p = SPA_POD_INIT_Fraction(SPA_FRACTION(num, denom));
return spa_pod_builder_primitive(builder, &p.pod);
}
static inline uint32_t
spa_pod_builder_push_array(struct spa_pod_builder *builder)
static inline int
spa_pod_builder_push_array(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
{
const struct spa_pod_array p =
{ {sizeof(struct spa_pod_array_body) - sizeof(struct spa_pod), SPA_TYPE_Array},
{{0, 0}} };
return spa_pod_builder_push(builder, &p.pod,
spa_pod_builder_raw(builder, &p,
sizeof(p) - sizeof(struct spa_pod)));
uint32_t offset = builder->state.offset;
int res = spa_pod_builder_raw(builder, &p, sizeof(p) - sizeof(struct spa_pod));
spa_pod_builder_push(builder, frame, &p.pod, offset);
return res;
}
static inline uint32_t
static inline int
spa_pod_builder_array(struct spa_pod_builder *builder,
uint32_t child_size, uint32_t child_type, uint32_t n_elems, const void *elems)
{
@ -378,10 +339,10 @@ spa_pod_builder_array(struct spa_pod_builder *builder,
{(uint32_t)(sizeof(struct spa_pod_array_body) + n_elems * child_size), SPA_TYPE_Array},
{{child_size, child_type}}
};
uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p));
if (spa_pod_builder_raw_padded(builder, elems, child_size * n_elems) == SPA_ID_INVALID)
ref = SPA_ID_INVALID;
return ref;
int r, res = spa_pod_builder_raw(builder, &p, sizeof(p));
if ((r = spa_pod_builder_raw_padded(builder, elems, child_size * n_elems)) < 0)
res = r;
return res;
}
#define SPA_POD_INIT_CHOICE_BODY(type, flags, child_size, child_type) \
@ -392,69 +353,74 @@ spa_pod_builder_array(struct spa_pod_builder *builder,
{ { { n_vals * sizeof(ctype) + sizeof(struct spa_pod_choice_body), SPA_TYPE_Choice }, \
{ type, 0, { sizeof(ctype), child_type } } }, { __VA_ARGS__ } }
static inline uint32_t
spa_pod_builder_push_choice(struct spa_pod_builder *builder, uint32_t type, uint32_t flags)
static inline int
spa_pod_builder_push_choice(struct spa_pod_builder *builder, struct spa_pod_frame *frame,
uint32_t type, uint32_t flags)
{
const struct spa_pod_choice p =
{ {sizeof(struct spa_pod_choice_body) - sizeof(struct spa_pod), SPA_TYPE_Choice},
{ type, flags, {0, 0}} };
return spa_pod_builder_push(builder, &p.pod,
spa_pod_builder_raw(builder, &p,
sizeof(p) - sizeof(struct spa_pod)));
uint32_t offset = builder->state.offset;
int res = spa_pod_builder_raw(builder, &p, sizeof(p) - sizeof(struct spa_pod));
spa_pod_builder_push(builder, frame, &p.pod, offset);
return res;
}
#define SPA_POD_INIT_Struct(size) (struct spa_pod_struct){ { size, SPA_TYPE_Struct } }
static inline uint32_t
spa_pod_builder_push_struct(struct spa_pod_builder *builder)
static inline int
spa_pod_builder_push_struct(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
{
const struct spa_pod_struct p = SPA_POD_INIT_Struct(0);
return spa_pod_builder_push(builder, &p.pod,
spa_pod_builder_raw(builder, &p, sizeof(p)));
uint32_t offset = builder->state.offset;
int res = spa_pod_builder_raw(builder, &p, sizeof(p));
spa_pod_builder_push(builder, frame, &p.pod, offset);
return res;
}
#define SPA_POD_INIT_Object(size,type,id,...) (struct spa_pod_object){ { size, SPA_TYPE_Object }, { type, id }, ##__VA_ARGS__ }
static inline uint32_t
spa_pod_builder_push_object(struct spa_pod_builder *builder, uint32_t type, uint32_t id)
static inline int
spa_pod_builder_push_object(struct spa_pod_builder *builder, struct spa_pod_frame *frame,
uint32_t type, uint32_t id)
{
const struct spa_pod_object p =
SPA_POD_INIT_Object(sizeof(struct spa_pod_object_body), type, id);
return spa_pod_builder_push(builder, &p.pod,
spa_pod_builder_raw(builder, &p, sizeof(p)));
uint32_t offset = builder->state.offset;
int res = spa_pod_builder_raw(builder, &p, sizeof(p));
spa_pod_builder_push(builder, frame, &p.pod, offset);
return res;
}
#define SPA_POD_INIT_Prop(key,flags,size,type) \
(struct spa_pod_prop){ key, flags, { size, type } }
static inline uint32_t
static inline int
spa_pod_builder_prop(struct spa_pod_builder *builder, uint32_t key, uint32_t flags)
{
const struct { uint32_t key; uint32_t flags; } p = { key, flags };
uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p));
SPA_FLAG_SET(builder->state.flags, SPA_POD_BUILDER_FLAG_HEADER);
return ref;
return spa_pod_builder_raw(builder, &p, sizeof(p));
}
#define SPA_POD_INIT_Sequence(size,unit) \
(struct spa_pod_sequence){ { size, SPA_TYPE_Sequence}, {unit, 0 } }
static inline uint32_t
spa_pod_builder_push_sequence(struct spa_pod_builder *builder, uint32_t unit)
static inline int
spa_pod_builder_push_sequence(struct spa_pod_builder *builder, struct spa_pod_frame *frame, uint32_t unit)
{
const struct spa_pod_sequence p =
SPA_POD_INIT_Sequence(sizeof(struct spa_pod_sequence_body), unit);
return spa_pod_builder_push(builder, &p.pod,
spa_pod_builder_raw(builder, &p, sizeof(p)));
uint32_t offset = builder->state.offset;
int res = spa_pod_builder_raw(builder, &p, sizeof(p));
spa_pod_builder_push(builder, frame, &p.pod, offset);
return res;
}
static inline uint32_t
spa_pod_builder_control(struct spa_pod_builder *builder, uint32_t offset, uint32_t type)
{
const struct { uint32_t offset; uint32_t type; } p = { offset, type };
uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p));
SPA_FLAG_SET(builder->state.flags, SPA_POD_BUILDER_FLAG_HEADER);
return ref;
return spa_pod_builder_raw(builder, &p, sizeof(p));
}
static inline uint32_t spa_choice_from_id(char id)
@ -513,7 +479,7 @@ do { \
spa_pod_builder_string_len(builder, strval, len); \
break; \
} \
case 'z': \
case 'y': \
{ \
void *ptr = va_arg(args, void *); \
int len = va_arg(args, int); \
@ -569,94 +535,66 @@ do { \
} \
} while(false)
static inline void *
static inline int
spa_pod_builder_addv(struct spa_pod_builder *builder, va_list args)
{
const char *format = "";
void *top = NULL;
do {
int n_values = 1;
bool do_pop = false;
int res = 0;
struct spa_pod_frame *f = builder->state.frame;
uint32_t ftype = f ? f->pod.type : SPA_TYPE_None;
if (builder->state.flags == SPA_POD_BUILDER_FLAG_OBJECT) {
do {
const char *format;
int n_values = 1;
struct spa_pod_frame f;
bool choice;
switch (ftype) {
case SPA_TYPE_Object:
{
uint32_t key = va_arg(args, uint32_t);
if (key == 0)
break;
if (key != SPA_ID_INVALID)
spa_pod_builder_prop(builder, key, 0);
goto exit;
spa_pod_builder_prop(builder, key, 0);
break;
}
else if (builder->state.flags == SPA_POD_BUILDER_FLAG_SEQUENCE) {
case SPA_TYPE_Sequence:
{
uint32_t offset = va_arg(args, uint32_t);
uint32_t type = va_arg(args, uint32_t);
if (type == 0)
break;
if (type != SPA_ID_INVALID)
spa_pod_builder_control(builder, offset, type);
goto exit;
spa_pod_builder_control(builder, offset, type);
}
default:
break;
}
if ((format = va_arg(args, const char *)) == NULL)
break;
again:
switch (*format) {
case '{':
{
uint32_t type = va_arg(args, uint32_t);
uint32_t id = va_arg(args, uint32_t);
spa_pod_builder_push_object(builder, type, id);
break;
}
case '[':
spa_pod_builder_push_struct(builder);
break;
case '(':
spa_pod_builder_push_array(builder);
break;
case '<':
{
uint32_t unit = va_arg(args, uint32_t);
spa_pod_builder_push_sequence(builder, unit);
break;
}
case '?':
{
uint32_t choice, flags = 0;
format++;
choice = spa_choice_from_id(*format);
choice = *format == '?';
if (choice) {
uint32_t type = spa_choice_from_id(*++format);
if (*format != '\0')
format++;
spa_pod_builder_push_choice(builder, choice, flags);
spa_pod_builder_push_choice(builder, &f, type, 0);
n_values = va_arg(args, int);
do_pop = true;
goto do_collect;
}
case ']': case ')': case '>': case '}':
top = spa_pod_builder_pop(builder);
break;
case ' ': case '\n': case '\t': case '\r':
break;
case '\0':
if ((format = va_arg(args, const char *)) != NULL)
goto again;
continue;
default:
do_collect:
while (n_values-- > 0)
SPA_POD_BUILDER_COLLECT(builder, *format, args);
if (do_pop)
top = spa_pod_builder_pop(builder);
break;
}
if (*format != '\0')
format++;
} while (format != NULL);
while (n_values-- > 0)
SPA_POD_BUILDER_COLLECT(builder, *format, args);
return top;
if (choice)
spa_pod_builder_pop(builder, &f);
} while (true);
exit:
return res;
}
static inline void *spa_pod_builder_add(struct spa_pod_builder *builder, ...)
static inline int spa_pod_builder_add(struct spa_pod_builder *builder, ...)
{
void *res;
int res;
va_list args;
va_start(args, builder);
@ -666,29 +604,35 @@ static inline void *spa_pod_builder_add(struct spa_pod_builder *builder, ...)
return res;
}
#define SPA_POD_Object(type,id,...) \
"{", type, id, ##__VA_ARGS__, SPA_ID_INVALID, "}"
#define SPA_POD_Prop(key,...) \
key, ##__VA_ARGS__
#define SPA_POD_Struct(...) \
"[", ##__VA_ARGS__, "]"
#define SPA_POD_Sequence(unit,...) \
"<", unit, ##__VA_ARGS__, 0, SPA_ID_INVALID, ">"
#define SPA_POD_Control(offset,type,...) \
offset, type, ##__VA_ARGS__
#define spa_pod_builder_add_object(b,type,id,...) \
spa_pod_builder_add(b, SPA_POD_Object(type,id,##__VA_ARGS__), NULL, NULL, NULL)
({ \
struct spa_pod_frame f; \
spa_pod_builder_push_object(b, &f, type, id); \
spa_pod_builder_add(b, ##__VA_ARGS__, 0); \
spa_pod_builder_pop(b, &f); \
})
#define spa_pod_builder_add_struct(b,...) \
spa_pod_builder_add(b, SPA_POD_Struct(__VA_ARGS__), NULL, NULL, NULL)
({ \
struct spa_pod_frame f; \
spa_pod_builder_push_struct(b, &f); \
spa_pod_builder_add(b, ##__VA_ARGS__, NULL); \
spa_pod_builder_pop(b, &f); \
})
#define spa_pod_builder_add_sequence(b,unit,...) \
spa_pod_builder_add(b, SPA_POD_Sequence(unit,__VA_ARGS__), NULL, NULL, NULL)
({ \
struct spa_pod_frame f; \
spa_pod_builder_push_sequence(b, &f, unit); \
spa_pod_builder_add(b, ##__VA_ARGS__, 0, 0); \
spa_pod_builder_pop(b, &f); \
})
#define SPA_CHOICE_RANGE(def,min,max) 3,(def),(min),(max)
#define SPA_CHOICE_STEP(def,min,max,step) 4,(def),(min),(max),(step)
@ -724,7 +668,7 @@ static inline void *spa_pod_builder_add(struct spa_pod_builder *builder, ...)
#define SPA_POD_String(val) "s",val
#define SPA_POD_Stringn(val,len) "S",val,len
#define SPA_POD_Bytes(val,len) "z",val,len
#define SPA_POD_Bytes(val,len) "y",val,len
#define SPA_POD_Rectangle(val) "R", val
#define SPA_POD_CHOICE_ENUM_Rectangle(n_vals,...) "?eR", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__)

View File

@ -142,14 +142,16 @@ static inline int spa_pod_compare(const struct spa_pod *pod1,
o1 = (const struct spa_pod_object*)pod1;
o2 = (const struct spa_pod_object*)pod2;
p2 = NULL;
SPA_POD_OBJECT_FOREACH(o1, p1) {
if ((p2 = spa_pod_object_find_prop(o2, p1->key)) == NULL)
if ((p2 = spa_pod_object_find_prop(o2, p2, p1->key)) == NULL)
return 1;
if ((res = spa_pod_compare(&p1->value, &p2->value)) != 0)
return res;
}
p1 = NULL;
SPA_POD_OBJECT_FOREACH(o2, p2) {
if ((p1 = spa_pod_object_find_prop(o1, p2->key)) == NULL)
if ((p1 = spa_pod_object_find_prop(o1, p1, p2->key)) == NULL)
return -1;
}
break;

View File

@ -96,6 +96,7 @@ spa_pod_filter_prop(struct spa_pod_builder *b,
uint32_t j, k, nalt1, nalt2;
void *alt1, *alt2, *a1, *a2;
uint32_t type, size, p1c, p2c;
struct spa_pod_frame f;
v1 = spa_pod_get_values(&p1->value, &nalt1, &p1c);
alt1 = SPA_POD_BODY(v1);
@ -125,7 +126,8 @@ spa_pod_filter_prop(struct spa_pod_builder *b,
/* start with copying the property */
spa_pod_builder_prop(b, p1->key, 0);
nc = (struct spa_pod_choice*)spa_pod_builder_deref(b, spa_pod_builder_push_choice(b, 0, 0));
spa_pod_builder_push_choice(b, &f, 0, 0);
nc = (struct spa_pod_choice*)spa_pod_builder_frame(b, &f);
/* default value */
spa_pod_builder_primitive(b, v1);
@ -241,7 +243,7 @@ spa_pod_filter_prop(struct spa_pod_builder *b,
if (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_Flags)
return -ENOTSUP;
spa_pod_builder_pop(b);
spa_pod_builder_pop(b, &f);
spa_pod_choice_fix_default(nc);
return 0;
@ -259,20 +261,22 @@ static inline int spa_pod_filter_part(struct spa_pod_builder *b,
SPA_POD_FOREACH(pod, pod_size, pp) {
bool do_copy = false, do_advance = false;
uint32_t filter_offset = 0;
struct spa_pod_frame f;
switch (SPA_POD_TYPE(pp)) {
case SPA_TYPE_Object:
if (pf != NULL) {
struct spa_pod_object *op = (struct spa_pod_object *) pp;
struct spa_pod_object *of = (struct spa_pod_object *) pf;
struct spa_pod_prop *p1, *p2;
const struct spa_pod_prop *p1, *p2;
if (SPA_POD_TYPE(pf) != SPA_POD_TYPE(pp))
return -EINVAL;
spa_pod_builder_push_object(b, op->body.type, op->body.id);
spa_pod_builder_push_object(b, &f, op->body.type, op->body.id);
p2 = NULL;
SPA_POD_OBJECT_FOREACH(op, p1) {
p2 = spa_pod_object_find_prop(of, p1->key);
p2 = spa_pod_object_find_prop(of, p2, p1->key);
if (p2 != NULL)
res = spa_pod_filter_prop(b, p1, p2);
else
@ -281,15 +285,16 @@ static inline int spa_pod_filter_part(struct spa_pod_builder *b,
break;
}
if (res >= 0) {
p1 = NULL;
SPA_POD_OBJECT_FOREACH(of, p2) {
p1 = spa_pod_object_find_prop(op, p2->key);
p1 = spa_pod_object_find_prop(op, p1, p2->key);
if (p1 != NULL)
continue;
spa_pod_builder_raw_padded(b, p2, SPA_POD_PROP_SIZE(p2));
}
}
spa_pod_builder_pop(b);
spa_pod_builder_pop(b, &f);
do_advance = true;
}
else
@ -302,13 +307,13 @@ static inline int spa_pod_filter_part(struct spa_pod_builder *b,
return -EINVAL;
filter_offset = sizeof(struct spa_pod_struct);
spa_pod_builder_push_struct(b);
spa_pod_builder_push_struct(b, &f);
res = spa_pod_filter_part(b,
SPA_MEMBER(pp,filter_offset,const struct spa_pod),
SPA_POD_SIZE(pp) - filter_offset,
SPA_MEMBER(pf,filter_offset,const struct spa_pod),
SPA_POD_SIZE(pf) - filter_offset);
spa_pod_builder_pop(b);
spa_pod_builder_pop(b, &f);
do_advance = true;
}
else
@ -352,16 +357,17 @@ spa_pod_filter(struct spa_pod_builder *b,
spa_return_val_if_fail(b != NULL, -EINVAL);
if (filter == NULL) {
*result = (struct spa_pod*)spa_pod_builder_deref(b,
spa_pod_builder_raw_padded(b, pod, SPA_POD_SIZE(pod)));
spa_pod_builder_raw_padded(b, pod, SPA_POD_SIZE(pod));
*result = (struct spa_pod*)b->data;
return 0;
}
spa_pod_builder_get_state(b, &state);
if ((res = spa_pod_filter_part(b, pod, SPA_POD_SIZE(pod), filter, SPA_POD_SIZE(filter))) < 0)
if ((res = spa_pod_filter_part(b, pod, SPA_POD_SIZE(pod), filter, SPA_POD_SIZE(filter))) < 0) {
spa_pod_builder_reset(b, &state);
}
else
*result = (struct spa_pod*)spa_pod_builder_deref(b, state.offset);
*result = (struct spa_pod*)spa_pod_builder_deref(b, state.offset, b->size);
return res;
}

View File

@ -30,40 +30,16 @@ extern "C" {
#endif
#include <errno.h>
#include <stdarg.h>
#include <spa/pod/pod.h>
struct spa_pod_iter {
const void *data;
uint32_t size;
struct spa_pod_frame {
struct spa_pod pod;
struct spa_pod_frame *parent;
uint32_t offset;
uint32_t flags;
};
static inline void spa_pod_iter_init(struct spa_pod_iter *iter,
const void *data, uint32_t size, uint32_t offset)
{
iter->data = data;
iter->size = size;
iter->offset = offset;
}
static inline struct spa_pod *spa_pod_iter_current(struct spa_pod_iter *iter)
{
if (iter->offset + 8 <= iter->size) {
struct spa_pod *pod = SPA_MEMBER(iter->data, iter->offset, struct spa_pod);
if (SPA_POD_SIZE(pod) <= iter->size)
return pod;
}
return NULL;
}
static inline void spa_pod_iter_advance(struct spa_pod_iter *iter, struct spa_pod *current)
{
if (current)
iter->offset += SPA_ROUND_UP_N(SPA_POD_SIZE(current), 8);
}
static inline bool spa_pod_is_inside(const void *pod, uint32_t size, const void *iter)
{
return SPA_POD_BODY(iter) <= SPA_MEMBER(pod, size, void) &&
@ -80,10 +56,11 @@ static inline struct spa_pod_prop *spa_pod_prop_first(const struct spa_pod_objec
return SPA_MEMBER(body, sizeof(struct spa_pod_object_body), struct spa_pod_prop);
}
static inline bool spa_pod_prop_is_inside(const void *pod, uint32_t size, const struct spa_pod_prop *iter)
static inline bool spa_pod_prop_is_inside(const struct spa_pod_object_body *body,
uint32_t size, const struct spa_pod_prop *iter)
{
return SPA_POD_CONTENTS(struct spa_pod_prop, iter) <= SPA_MEMBER(pod, size, void) &&
SPA_MEMBER(iter, SPA_POD_PROP_SIZE(iter), void) <= SPA_MEMBER(pod, size, void);
return SPA_POD_CONTENTS(struct spa_pod_prop, iter) <= SPA_MEMBER(body, size, void) &&
SPA_MEMBER(iter, SPA_POD_PROP_SIZE(iter), void) <= SPA_MEMBER(body, size, void);
}
static inline struct spa_pod_prop *spa_pod_prop_next(const struct spa_pod_prop *iter)
@ -96,10 +73,11 @@ static inline struct spa_pod_control *spa_pod_control_first(const struct spa_pod
return SPA_MEMBER(body, sizeof(struct spa_pod_sequence_body), struct spa_pod_control);
}
static inline bool spa_pod_control_is_inside(const void *pod, uint32_t size, const struct spa_pod_control *iter)
static inline bool spa_pod_control_is_inside(const struct spa_pod_sequence_body *body,
uint32_t size, const struct spa_pod_control *iter)
{
return SPA_POD_CONTENTS(struct spa_pod_control, iter) <= SPA_MEMBER(pod, size, void) &&
SPA_MEMBER(iter, SPA_POD_CONTROL_SIZE(iter), void) <= SPA_MEMBER(pod, size, void);
return SPA_POD_CONTENTS(struct spa_pod_control, iter) <= SPA_MEMBER(body, size, void) &&
SPA_MEMBER(iter, SPA_POD_CONTROL_SIZE(iter), void) <= SPA_MEMBER(body, size, void);
}
static inline struct spa_pod_control *spa_pod_control_next(const struct spa_pod_control *iter)
@ -327,6 +305,12 @@ static inline int spa_pod_get_fraction(const struct spa_pod *pod, struct spa_fra
return 0;
}
static inline int spa_pod_is_bitmap(const struct spa_pod *pod)
{
return (SPA_POD_TYPE(pod) == SPA_TYPE_Bitmap &&
SPA_POD_BODY_SIZE(pod) >= sizeof(uint8_t));
}
static inline int spa_pod_is_array(const struct spa_pod *pod)
{
return (SPA_POD_TYPE(pod) == SPA_TYPE_Array &&
@ -381,21 +365,32 @@ static inline int spa_pod_is_sequence(const struct spa_pod *pod)
SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_sequence_body));
}
static inline struct spa_pod_prop *spa_pod_object_find_prop(const struct spa_pod_object *pod, uint32_t key)
static inline const struct spa_pod_prop *spa_pod_object_find_prop(const struct spa_pod_object *pod,
const struct spa_pod_prop *start, uint32_t key)
{
struct spa_pod_prop *res;
SPA_POD_OBJECT_FOREACH(pod, res) {
const struct spa_pod_prop *first, *res;
first = spa_pod_prop_first(&pod->body);
start = start ? spa_pod_prop_next(start) : first;
for (res = start; spa_pod_prop_is_inside(&pod->body, pod->pod.size, res);
res = spa_pod_prop_next(res)) {
if (res->key == key)
return res;
}
for (res = first; res != start; res = spa_pod_prop_next(res)) {
if (res->key == key)
return res;
}
return NULL;
}
static inline struct spa_pod_prop *spa_pod_find_prop(const struct spa_pod *pod, uint32_t key)
static inline const struct spa_pod_prop *spa_pod_find_prop(const struct spa_pod *pod,
const struct spa_pod_prop *start, uint32_t key)
{
if (!spa_pod_is_object(pod))
return NULL;
return spa_pod_object_find_prop((const struct spa_pod_object *)pod, key);
return spa_pod_object_find_prop((const struct spa_pod_object *)pod, start, key);
}
static inline int spa_pod_object_fixate(struct spa_pod_object *pod)

View File

@ -34,74 +34,295 @@ extern "C" {
#include <spa/pod/iter.h>
struct spa_pod_parser {
uint32_t depth;
#define SPA_POD_PARSER_FLAG_OBJECT (1<<0)
#define SPA_POD_PARSER_FLAG_STRUCT (1<<1)
struct spa_pod_parser_state {
uint32_t offset;
uint32_t flags;
struct spa_pod_iter iter[SPA_POD_MAX_DEPTH];
struct spa_pod_frame *frame;
};
struct spa_pod_parser {
const void *data;
uint32_t size;
uint32_t _padding;
struct spa_pod_parser_state state;
};
#define SPA_POD_PARSER_INIT(buffer,size) (struct spa_pod_parser){ buffer, size, }
static inline void spa_pod_parser_init(struct spa_pod_parser *parser,
const void *data, uint32_t size, uint32_t offset)
const void *data, uint32_t size)
{
parser->depth = 0;
parser->flags = 0;
spa_pod_iter_init(&parser->iter[0], data, size, offset);
*parser = SPA_POD_PARSER_INIT(data, size);
}
static inline void spa_pod_parser_pod(struct spa_pod_parser *parser,
const struct spa_pod *pod)
{
spa_pod_parser_init(parser, pod, SPA_POD_SIZE(pod), 0);
spa_pod_parser_init(parser, pod, SPA_POD_SIZE(pod));
}
static inline bool spa_pod_parser_can_collect(struct spa_pod *pod, char type)
static inline void
spa_pod_parser_get_state(struct spa_pod_parser *parser, struct spa_pod_parser_state *state)
{
*state = parser->state;
}
static inline void
spa_pod_parser_reset(struct spa_pod_parser *parser, struct spa_pod_parser_state *state)
{
parser->state = *state;
}
static inline struct spa_pod *
spa_pod_parser_deref(struct spa_pod_parser *parser, uint32_t offset, uint32_t size)
{
if (offset + 8 <= size) {
struct spa_pod *pod = SPA_MEMBER(parser->data, offset, struct spa_pod);
if (offset + SPA_POD_SIZE(pod) <= size)
return pod;
}
return NULL;
}
static inline struct spa_pod *spa_pod_parser_frame(struct spa_pod_parser *parser, struct spa_pod_frame *frame)
{
return SPA_MEMBER(parser->data, frame->offset, struct spa_pod);
}
static inline void spa_pod_parser_push(struct spa_pod_parser *parser,
struct spa_pod_frame *frame, const struct spa_pod *pod, uint32_t offset)
{
frame->pod = *pod;
frame->offset = offset;
frame->parent = parser->state.frame;
frame->flags = parser->state.flags;
parser->state.frame = frame;
}
static inline struct spa_pod *spa_pod_parser_current(struct spa_pod_parser *parser)
{
struct spa_pod_frame *f = parser->state.frame;
uint32_t size = f ? f->offset + SPA_POD_SIZE(&f->pod) : parser->size;
return spa_pod_parser_deref(parser, parser->state.offset, size);
}
static inline void spa_pod_parser_advance(struct spa_pod_parser *parser, const struct spa_pod *pod)
{
parser->state.offset += SPA_ROUND_UP_N(SPA_POD_SIZE(pod), 8);
}
static inline struct spa_pod *spa_pod_parser_next(struct spa_pod_parser *parser)
{
struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod)
spa_pod_parser_advance(parser, pod);
return pod;
}
static inline int spa_pod_parser_pop(struct spa_pod_parser *parser,
struct spa_pod_frame *frame)
{
parser->state.frame = frame->parent;
parser->state.offset = frame->offset + SPA_ROUND_UP_N(SPA_POD_SIZE(&frame->pod), 8);
return 0;
}
static inline int spa_pod_parser_get_bool(struct spa_pod_parser *parser, bool *value)
{
int res = -EPIPE;
const struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod != NULL && (res = spa_pod_get_bool(pod, value)) >= 0)
spa_pod_parser_advance(parser, pod);
return res;
}
static inline int spa_pod_parser_get_id(struct spa_pod_parser *parser, uint32_t *value)
{
int res = -EPIPE;
const struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod != NULL && (res = spa_pod_get_id(pod, value)) >= 0)
spa_pod_parser_advance(parser, pod);
return res;
}
static inline int spa_pod_parser_get_int(struct spa_pod_parser *parser, int32_t *value)
{
int res = -EPIPE;
const struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod != NULL && (res = spa_pod_get_int(pod, value)) >= 0)
spa_pod_parser_advance(parser, pod);
return res;
}
static inline int spa_pod_parser_get_long(struct spa_pod_parser *parser, int64_t *value)
{
int res = -EPIPE;
const struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod != NULL && (res = spa_pod_get_long(pod, value)) >= 0)
spa_pod_parser_advance(parser, pod);
return res;
}
static inline int spa_pod_parser_get_float(struct spa_pod_parser *parser, float *value)
{
int res = -EPIPE;
const struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod != NULL && (res = spa_pod_get_float(pod, value)) >= 0)
spa_pod_parser_advance(parser, pod);
return res;
}
static inline int spa_pod_parser_get_double(struct spa_pod_parser *parser, double *value)
{
int res = -EPIPE;
const struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod != NULL && (res = spa_pod_get_double(pod, value)) >= 0)
spa_pod_parser_advance(parser, pod);
return res;
}
static inline int spa_pod_parser_get_string(struct spa_pod_parser *parser, const char **value)
{
int res = -EPIPE;
const struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod != NULL && (res = spa_pod_get_string(pod, value)) >= 0)
spa_pod_parser_advance(parser, pod);
return res;
}
static inline int spa_pod_parser_get_bytes(struct spa_pod_parser *parser, const void **value, uint32_t *len)
{
int res = -EPIPE;
const struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod != NULL && (res = spa_pod_get_bytes(pod, value, len)) >= 0)
spa_pod_parser_advance(parser, pod);
return res;
}
static inline int spa_pod_parser_get_pointer(struct spa_pod_parser *parser, uint32_t *type, const void **value)
{
int res = -EPIPE;
const struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod != NULL && (res = spa_pod_get_pointer(pod, type, value)) >= 0)
spa_pod_parser_advance(parser, pod);
return res;
}
static inline int spa_pod_parser_get_fd(struct spa_pod_parser *parser, int64_t *value)
{
int res = -EPIPE;
const struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod != NULL && (res = spa_pod_get_fd(pod, value)) >= 0)
spa_pod_parser_advance(parser, pod);
return res;
}
static inline int spa_pod_parser_get_rectangle(struct spa_pod_parser *parser, struct spa_rectangle *value)
{
int res = -EPIPE;
const struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod != NULL && (res = spa_pod_get_rectangle(pod, value)) >= 0)
spa_pod_parser_advance(parser, pod);
return res;
}
static inline int spa_pod_parser_get_fraction(struct spa_pod_parser *parser, struct spa_fraction *value)
{
int res = -EPIPE;
const struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod != NULL && (res = spa_pod_get_fraction(pod, value)) >= 0)
spa_pod_parser_advance(parser, pod);
return res;
}
static inline int spa_pod_parser_get_pod(struct spa_pod_parser *parser, struct spa_pod **value)
{
struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod == NULL)
return -EPIPE;
*value = pod;
spa_pod_parser_advance(parser, pod);
return 0;
}
static inline int spa_pod_parser_push_struct(struct spa_pod_parser *parser,
struct spa_pod_frame *frame)
{
const struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod == NULL)
return -EPIPE;
if (!spa_pod_is_struct(pod))
return -EINVAL;
spa_pod_parser_push(parser, frame, pod, parser->state.offset);
parser->state.offset += sizeof(struct spa_pod_struct);
return 0;
}
static inline int spa_pod_parser_push_object(struct spa_pod_parser *parser,
struct spa_pod_frame *frame, uint32_t type, uint32_t *id)
{
const struct spa_pod *pod = spa_pod_parser_current(parser);
if (pod == NULL)
return -EPIPE;
if (!spa_pod_is_object(pod))
return -EINVAL;
if (type != SPA_POD_OBJECT_TYPE(pod))
return -EPROTO;
if (id != NULL)
*id = SPA_POD_OBJECT_ID(pod);
spa_pod_parser_push(parser, frame, pod, parser->state.offset);
parser->state.offset = parser->size;
return 0;
}
static inline bool spa_pod_parser_can_collect(const struct spa_pod *pod, char type)
{
if (pod == NULL)
return false;
if (type == 'P')
if (spa_pod_is_choice(pod) &&
SPA_POD_CHOICE_TYPE(pod) == SPA_CHOICE_None &&
spa_pod_parser_can_collect(SPA_POD_CHOICE_CHILD(pod), type))
return true;
switch (SPA_POD_TYPE(pod)) {
case SPA_TYPE_None:
return type == 'T' || type == 'O' || type == 'V' || type == 's';
case SPA_TYPE_Bool:
return type == 'b';
case SPA_TYPE_Id:
return type == 'I';
case SPA_TYPE_Int:
return type == 'i';
case SPA_TYPE_Long:
return type == 'l';
case SPA_TYPE_Float:
return type == 'f';
case SPA_TYPE_Double:
return type == 'd';
case SPA_TYPE_String:
return type == 's' || type == 'S';
case SPA_TYPE_Bytes:
return type == 'z';
case SPA_TYPE_Rectangle:
return type == 'R';
case SPA_TYPE_Fraction:
return type == 'F';
case SPA_TYPE_Bitmap:
return type == 'B';
case SPA_TYPE_Array:
return type == 'a';
case SPA_TYPE_Struct:
return type == 'T';
case SPA_TYPE_Object:
return type == 'O';
case SPA_TYPE_Pointer:
return type == 'p';
case SPA_TYPE_Fd:
return type == 'h';
case SPA_TYPE_Choice:
return type == 'V' ||
(SPA_POD_CHOICE_TYPE(pod) == SPA_CHOICE_None &&
spa_pod_parser_can_collect(SPA_POD_CHOICE_CHILD(pod), type));
switch (type) {
case 'P':
return true;
case 'b':
return spa_pod_is_bool(pod);
case 'I':
return spa_pod_is_id(pod);
case 'i':
return spa_pod_is_int(pod);
case 'l':
return spa_pod_is_long(pod);
case 'f':
return spa_pod_is_float(pod);
case 'd':
return spa_pod_is_double(pod);
case 's':
return spa_pod_is_string(pod) || spa_pod_is_none(pod);
case 'S':
return spa_pod_is_string(pod);
case 'y':
return spa_pod_is_bytes(pod);
case 'R':
return spa_pod_is_rectangle(pod);
case 'F':
return spa_pod_is_fraction(pod);
case 'B':
return spa_pod_is_bitmap(pod);
case 'a':
return spa_pod_is_array(pod);
case 'p':
return spa_pod_is_pointer(pod);
case 'h':
return spa_pod_is_fd(pod);
case 'T':
return spa_pod_is_struct(pod) || spa_pod_is_none(pod);
case 'O':
return spa_pod_is_object(pod) || spa_pod_is_none(pod);
case 'V':
return spa_pod_is_choice(pod);
default:
return false;
}
@ -139,7 +360,7 @@ do { \
strncpy(dest, (char *)SPA_POD_CONTENTS(struct spa_pod_string, pod), maxlen-1); \
break; \
} \
case 'z': \
case 'y': \
*(va_arg(args, void **)) = SPA_POD_CONTENTS(struct spa_pod_bytes, pod); \
*(va_arg(args, uint32_t *)) = SPA_POD_BODY_SIZE(pod); \
break; \
@ -155,6 +376,12 @@ do { \
*va_arg(args, uint32_t **) = \
(uint32_t *) SPA_POD_CONTENTS(struct spa_pod_bitmap, pod); \
break; \
case 'a': \
*va_arg(args, uint32_t*) = SPA_POD_ARRAY_VALUE_SIZE(pod); \
*va_arg(args, uint32_t*) = SPA_POD_ARRAY_VALUE_TYPE(pod); \
*va_arg(args, uint32_t*) = SPA_POD_ARRAY_N_VALUES(pod); \
*va_arg(args, void**) = SPA_POD_ARRAY_VALUES(pod); \
break; \
case 'p': \
{ \
struct spa_pod_pointer_body *b = \
@ -166,17 +393,11 @@ do { \
case 'h': \
*va_arg(args, int64_t*) = SPA_POD_VALUE(struct spa_pod_fd, pod); \
break; \
case 'a': \
*va_arg(args, uint32_t*) = SPA_POD_ARRAY_VALUE_SIZE(pod); \
*va_arg(args, uint32_t*) = SPA_POD_ARRAY_VALUE_TYPE(pod); \
*va_arg(args, uint32_t*) = SPA_POD_ARRAY_N_VALUES(pod); \
*va_arg(args, void**) = SPA_POD_ARRAY_VALUES(pod); \
break; \
case 'V': \
case 'P': \
case 'O': \
case 'T': \
*va_arg(args, struct spa_pod**) = \
case 'O': \
case 'V': \
*va_arg(args, const struct spa_pod**) = \
(pod == NULL || (SPA_POD_TYPE(pod) == SPA_TYPE_None) \
? NULL : pod); \
break; \
@ -197,7 +418,7 @@ do { \
va_arg(args, void*); \
/* fallthrough */ \
case 'p': \
case 'z': \
case 'y': \
va_arg(args, void*); \
/* fallthrough */ \
case 'b': \
@ -222,108 +443,53 @@ do { \
static inline int spa_pod_parser_getv(struct spa_pod_parser *parser, va_list args)
{
struct spa_pod *pod = NULL, *current;
struct spa_pod_prop *prop = NULL;
bool required = true;
struct spa_pod_iter *it = &parser->iter[parser->depth];
const char *format = "";
uint32_t *idp;
struct spa_pod_frame *f = parser->state.frame;
uint32_t ftype = f ? f->pod.type : SPA_TYPE_Struct;
const struct spa_pod_prop *prop = NULL;
int count = 0;
current = pod = spa_pod_iter_current(it);
do {
again:
switch (*format) {
case '{':
if (pod == NULL || SPA_POD_TYPE(pod) != SPA_TYPE_Object)
return -EINVAL;
if (va_arg(args, uint32_t) != SPA_POD_OBJECT_TYPE(pod))
return -EPROTO;
if ((idp = va_arg(args, uint32_t*)) != NULL)
*idp = SPA_POD_OBJECT_ID(pod);
parser->flags = SPA_POD_PARSER_FLAG_OBJECT;
goto enter;
case '[':
if (pod == NULL || SPA_POD_TYPE(pod) != SPA_TYPE_Struct)
return -EINVAL;
parser->flags = SPA_POD_PARSER_FLAG_STRUCT;
bool optional;
const struct spa_pod *pod = NULL;
const char *format;
enter:
if (++parser->depth >= SPA_POD_MAX_DEPTH)
return -ENOSPC;
it = &parser->iter[parser->depth];
spa_pod_iter_init(it, pod, SPA_POD_SIZE(pod), sizeof(struct spa_pod_struct));
goto read_pod;
case ']':
case '}':
if (current != NULL)
return -EINVAL;
if (--parser->depth < 0)
return -EINVAL;
it = &parser->iter[parser->depth];
if (ftype == SPA_TYPE_Object) {
uint32_t key = va_arg(args, uint32_t);
const struct spa_pod_object *object;
if (SPA_POD_TYPE(it->data) == SPA_TYPE_Object)
parser->flags = SPA_POD_PARSER_FLAG_OBJECT;
else if (SPA_POD_TYPE(it->data) == SPA_TYPE_Struct)
parser->flags = SPA_POD_PARSER_FLAG_STRUCT;
else
parser->flags = 0;
if (key == 0)
break;
current = spa_pod_iter_current(it);
spa_pod_iter_advance(it, current);
goto read_pod;
case '\0':
if (parser->flags & SPA_POD_PARSER_FLAG_OBJECT) {
uint32_t key = va_arg(args, uint32_t);
if (key == 0) {
format = NULL;
continue;
}
if (key != SPA_ID_INVALID) {
prop = spa_pod_object_find_prop(
(const struct spa_pod_object *) it->data, key);
if (prop != NULL)
pod = &prop->value;
else
pod = NULL;
it->offset = it->size;
current = NULL;
}
}
if ((format = va_arg(args, char *)) != NULL)
goto again;
continue;
case ' ': case '\n': case '\t': case '\r':
break;
case '?':
required = false;
break;
default:
if (!spa_pod_parser_can_collect(pod, *format)) {
if (required) {
if (prop == NULL || pod == NULL)
return -ESRCH;
else
return -EPROTO;
}
SPA_POD_PARSER_SKIP(*format, args);
} else {
if (pod->type == SPA_TYPE_Choice && *format != 'V')
pod = SPA_POD_CHOICE_CHILD(pod);
SPA_POD_PARSER_COLLECT(pod, *format, args);
count++;
}
spa_pod_iter_advance(it, current);
read_pod:
pod = current = spa_pod_iter_current(it);
prop = NULL;
required = true;
break;
object = (const struct spa_pod_object *)spa_pod_parser_frame(parser, f);
prop = spa_pod_object_find_prop(object, prop, key);
pod = prop ? &prop->value : NULL;
}
format++;
} while (format != NULL);
if ((format = va_arg(args, char *)) == NULL)
break;
if (ftype == SPA_TYPE_Struct)
pod = spa_pod_parser_next(parser);
if ((optional = (*format == '?')))
format++;
if (!spa_pod_parser_can_collect(pod, *format)) {
if (!optional) {
if (pod == NULL)
return -ESRCH;
else
return -EPROTO;
}
SPA_POD_PARSER_SKIP(*format, args);
} else {
if (pod->type == SPA_TYPE_Choice && *format != 'V')
pod = SPA_POD_CHOICE_CHILD(pod);
SPA_POD_PARSER_COLLECT(pod, *format, args);
count++;
}
} while (true);
return count;
}
@ -359,11 +525,27 @@ static inline int spa_pod_parser_get(struct spa_pod_parser *parser, ...)
#define SPA_POD_OPT_PodStruct(val) "?" SPA_POD_PodStruct(val)
#define SPA_POD_OPT_PodChoice(val) "?" SPA_POD_PodChoice(val)
#define spa_pod_parser_get_object(p,type,id,...) \
spa_pod_parser_get(p, SPA_POD_Object(type,id,##__VA_ARGS__), NULL)
#define spa_pod_parser_get_object(p,type,id,...) \
({ \
struct spa_pod_frame _f; \
int _res; \
if ((_res = spa_pod_parser_push_object(p, &_f, type, id)) == 0) { \
_res = spa_pod_parser_get(p,##__VA_ARGS__, 0); \
spa_pod_parser_pop(p, &_f); \
} \
_res; \
})
#define spa_pod_parser_get_struct(p,...) \
spa_pod_parser_get(p, SPA_POD_Struct(__VA_ARGS__), NULL)
#define spa_pod_parser_get_struct(p,...) \
({ \
struct spa_pod_frame _f; \
int _res; \
if ((_res = spa_pod_parser_push_struct(p, &_f)) == 0) { \
_res = spa_pod_parser_get(p,##__VA_ARGS__, NULL); \
spa_pod_parser_pop(p, &_f); \
} \
_res; \
})
#define spa_pod_parse_object(pod,type,id,...) \
({ \

View File

@ -29,8 +29,6 @@
extern "C" {
#endif
#include <stdarg.h>
#include <spa/utils/defs.h>
#include <spa/utils/type.h>

View File

@ -114,6 +114,7 @@ static int fill_item(struct impl *this, struct udev_device *dev,
struct spa_pod **result, struct spa_pod_builder *builder)
{
const char *str, *name;
struct spa_pod_frame f[2];
name = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE");
if (!(name && *name)) {
@ -125,7 +126,7 @@ static int fill_item(struct impl *this, struct udev_device *dev,
if (!(name && *name))
name = "Unknown";
spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_MonitorItem, 0);
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_MonitorItem, 0);
spa_pod_builder_add(builder,
SPA_MONITOR_ITEM_id, SPA_POD_String(udev_device_get_syspath(dev)),
SPA_MONITOR_ITEM_flags, SPA_POD_Id(SPA_MONITOR_ITEM_FLAG_NONE),
@ -140,7 +141,7 @@ static int fill_item(struct impl *this, struct udev_device *dev,
return 0;
spa_pod_builder_prop(builder, SPA_MONITOR_ITEM_info, 0);
spa_pod_builder_push_struct(builder),
spa_pod_builder_push_struct(builder, &f[1]),
add_dict(builder,
"udev-probed", "1",
"device.path", udev_device_get_devnode(dev),
@ -195,8 +196,8 @@ static int fill_item(struct impl *this, struct udev_device *dev,
if ((str = udev_device_get_property_value(dev, "SOUND_FORM_FACTOR")) && *str) {
add_dict(builder, "device.form_factor", str, 0);
}
spa_pod_builder_pop(builder);
*result = spa_pod_builder_pop(builder);
spa_pod_builder_pop(builder, &f[1]);
*result = spa_pod_builder_pop(builder, &f[0]);
return 1;
}

View File

@ -29,6 +29,7 @@
#include <spa/node/node.h>
#include <spa/param/audio/format.h>
#include <spa/pod/filter.h>
#include <spa/debug/pod.h>
#define NAME "alsa-sink"
@ -486,6 +487,8 @@ static int port_set_format(struct spa_node *node,
info.media_subtype != SPA_MEDIA_SUBTYPE_raw)
return -EINVAL;
spa_debug_pod(0, NULL, format);
if (spa_format_audio_raw_parse(format, &info.info.raw) < 0)
return -EINVAL;

View File

@ -236,6 +236,7 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
struct spa_pod *fmt;
int res;
bool opened;
struct spa_pod_frame f[2];
opened = state->opened;
if ((err = spa_alsa_open(state)) < 0)
@ -248,7 +249,7 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
snd_pcm_hw_params_alloca(&params);
CHECK(snd_pcm_hw_params_any(hndl, params), "Broken configuration: no configurations available");
spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
spa_pod_builder_add(&b,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
@ -262,8 +263,8 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_format, 0);
choice = spa_pod_builder_deref(&b,
spa_pod_builder_push_choice(&b, SPA_CHOICE_None, 0));
spa_pod_builder_push_choice(&b, &f[1], SPA_CHOICE_None, 0);
choice = (struct spa_pod_choice*)spa_pod_builder_frame(&b, &f[1]);
for (i = 1, j = 0; i < SPA_N_ELEMENTS(format_info); i++) {
const struct format_info *fi = &format_info[i];
@ -284,7 +285,7 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
}
if (j > 1)
choice->body.type = SPA_CHOICE_Enum;
spa_pod_builder_pop(&b);
spa_pod_builder_pop(&b, &f[1]);
CHECK(snd_pcm_hw_params_get_rate_min(params, &min, &dir), "get_rate_min");
@ -292,8 +293,8 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_rate, 0);
choice = spa_pod_builder_deref(&b,
spa_pod_builder_push_choice(&b, SPA_CHOICE_None, 0));
spa_pod_builder_push_choice(&b, &f[1], SPA_CHOICE_None, 0);
choice = (struct spa_pod_choice*)spa_pod_builder_frame(&b, &f[1]);
spa_pod_builder_int(&b, SPA_CLAMP(DEFAULT_RATE, min, max));
if (min != max) {
@ -301,7 +302,7 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
spa_pod_builder_int(&b, max);
choice->body.type = SPA_CHOICE_Range;
}
spa_pod_builder_pop(&b);
spa_pod_builder_pop(&b, &f[1]);
CHECK(snd_pcm_hw_params_get_channels_min(params, &min), "get_channels_min");
CHECK(snd_pcm_hw_params_get_channels_max(params, &max), "get_channels_max");
@ -323,13 +324,13 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
spa_pod_builder_int(&b, map->channels);
spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_position, 0);
spa_pod_builder_push_array(&b);
spa_pod_builder_push_array(&b, &f[1]);
for (j = 0; j < map->channels; j++) {
spa_log_debug(state->log, "position %zd %d", j, map->pos[j]);
channel = chmap_position_to_channel(map->pos[j]);
spa_pod_builder_id(&b, channel);
}
spa_pod_builder_pop(&b);
spa_pod_builder_pop(&b, &f[1]);
snd_pcm_free_chmaps(maps);
}
@ -339,18 +340,18 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
goto exit;
}
choice = spa_pod_builder_deref(&b,
spa_pod_builder_push_choice(&b, SPA_CHOICE_None, 0));
spa_pod_builder_push_choice(&b, &f[1], SPA_CHOICE_None, 0);
choice = (struct spa_pod_choice*)spa_pod_builder_frame(&b, &f[1]);
spa_pod_builder_int(&b, SPA_CLAMP(DEFAULT_CHANNELS, min, max));
if (min != max) {
spa_pod_builder_int(&b, min);
spa_pod_builder_int(&b, max);
choice->body.type = SPA_CHOICE_Range;
}
spa_pod_builder_pop(&b);
spa_pod_builder_pop(&b, &f[1]);
}
fmt = spa_pod_builder_pop(&b);
fmt = spa_pod_builder_pop(&b, &f[0]);
(*index)++;
@ -395,8 +396,10 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
/* set the sample format */
format = spa_format_to_alsa(info->format);
if (format == SND_PCM_FORMAT_UNKNOWN)
if (format == SND_PCM_FORMAT_UNKNOWN) {
spa_log_warn(state->log, "unknown format %u", info->format);
return -EINVAL;
}
spa_log_info(state->log, "Stream parameters are %iHz, %s, %i channels", info->rate, snd_pcm_format_name(format),
info->channels);

View File

@ -344,12 +344,13 @@ static int port_enum_formats(struct spa_node *node,
}
else if (other->have_format) {
struct spa_audio_info info;
struct spa_pod_frame f;
info = other->format;
qsort(info.info.raw.position, info.info.raw.channels, sizeof(uint32_t), int32_cmp);
spa_pod_builder_push_object(builder,
spa_pod_builder_push_object(builder, &f,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
spa_pod_builder_add(builder,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio),
@ -367,7 +368,7 @@ static int port_enum_formats(struct spa_node *node,
spa_pod_builder_array(builder, sizeof(uint32_t), SPA_TYPE_Id,
info.info.raw.channels, info.info.raw.position);
}
*param = spa_pod_builder_pop(builder);
*param = spa_pod_builder_pop(builder, &f);
} else {
*param = spa_pod_builder_add_object(builder,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,

View File

@ -327,13 +327,14 @@ static int port_enum_formats(struct spa_node *node,
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct port *other;
struct spa_pod_frame f;
other = GET_PORT(this, SPA_DIRECTION_REVERSE(direction), 0);
switch (*index) {
case 0:
if (other->have_format) {
spa_pod_builder_push_object(builder,
spa_pod_builder_push_object(builder, &f,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
spa_pod_builder_add(builder,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio),
@ -346,7 +347,7 @@ static int port_enum_formats(struct spa_node *node,
spa_pod_builder_prop(builder, SPA_FORMAT_AUDIO_position, 0);
spa_pod_builder_array(builder, sizeof(uint32_t), SPA_TYPE_Id,
other->format.info.raw.channels, other->format.info.raw.position);
*param = spa_pod_builder_pop(builder);
*param = spa_pod_builder_pop(builder, &f);
} else {
*param = spa_pod_builder_add_object(builder,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,

View File

@ -162,6 +162,7 @@ static int impl_node_enum_params(struct spa_node *node,
case SPA_PARAM_PropInfo:
{
struct props *p = &this->props;
struct spa_pod_frame f[2];
switch (*index) {
case 0:
@ -172,20 +173,20 @@ static int impl_node_enum_params(struct spa_node *node,
SPA_PROP_INFO_type, SPA_POD_Bool(p->live));
break;
case 1:
spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_PropInfo, id);
spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_PropInfo, id);
spa_pod_builder_add(&b,
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_waveType),
SPA_PROP_INFO_name, SPA_POD_String("Select the waveform"),
SPA_PROP_INFO_type, SPA_POD_Int(p->wave),
0);
spa_pod_builder_prop(&b, SPA_PROP_INFO_labels, 0);
spa_pod_builder_push_struct(&b);
spa_pod_builder_push_struct(&b, &f[1]);
spa_pod_builder_int(&b, WAVE_SINE);
spa_pod_builder_string(&b, "Sine wave");
spa_pod_builder_int(&b, WAVE_SQUARE);
spa_pod_builder_string(&b, "Square wave");
spa_pod_builder_pop(&b);
param = spa_pod_builder_pop(&b);
spa_pod_builder_pop(&b, &f[1]);
param = spa_pod_builder_pop(&b, &f[0]);
break;
case 2:
param = spa_pod_builder_add_object(&b,

View File

@ -89,8 +89,9 @@ static void fill_item(struct spa_bt_monitor *this, struct spa_bt_device *device,
struct spa_pod **result, struct spa_pod_builder *builder)
{
char dev[16];
struct spa_pod_frame f[2];
spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_MonitorItem, 0);
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_MonitorItem, 0);
spa_pod_builder_add(builder,
SPA_MONITOR_ITEM_id, SPA_POD_String(device->path),
SPA_MONITOR_ITEM_flags, SPA_POD_Id(SPA_MONITOR_ITEM_FLAG_NONE),
@ -103,7 +104,7 @@ static void fill_item(struct spa_bt_monitor *this, struct spa_bt_device *device,
0);
spa_pod_builder_prop(builder, SPA_MONITOR_ITEM_info, 0);
spa_pod_builder_push_struct(builder);
spa_pod_builder_push_struct(builder, &f[1]);
snprintf(dev, sizeof(dev), "%p", device);
add_dict(builder, "device.api", "bluez5");
@ -113,8 +114,8 @@ static void fill_item(struct spa_bt_monitor *this, struct spa_bt_device *device,
add_dict(builder, "device.bluez5.address", device->address);
add_dict(builder, "bluez5.device", dev);
spa_pod_builder_pop(builder);
*result = spa_pod_builder_pop(builder);
spa_pod_builder_pop(builder, &f[1]);
*result = spa_pod_builder_pop(builder, &f[0]);
}
static uint8_t a2dp_default_bitpool(struct spa_bt_monitor *monitor, uint8_t freq, uint8_t mode) {

View File

@ -84,6 +84,7 @@ static void fill_item(struct impl *this, struct udev_device *dev,
struct spa_pod **result, struct spa_pod_builder *builder)
{
const char *str, *name;
struct spa_pod_frame f[2];
name = udev_device_get_property_value(dev, "ID_V4L_PRODUCT");
if (!(name && *name)) {
@ -98,7 +99,7 @@ static void fill_item(struct impl *this, struct udev_device *dev,
if (!(name && *name))
name = "Unknown";
spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_MonitorItem, 0);
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_MonitorItem, 0);
spa_pod_builder_add(builder,
SPA_MONITOR_ITEM_id, SPA_POD_String(udev_device_get_syspath(dev)),
SPA_MONITOR_ITEM_flags, SPA_POD_Id(SPA_MONITOR_ITEM_FLAG_NONE),
@ -110,7 +111,7 @@ static void fill_item(struct impl *this, struct udev_device *dev,
0);
spa_pod_builder_prop(builder, SPA_MONITOR_ITEM_info, 0);
spa_pod_builder_push_struct(builder);
spa_pod_builder_push_struct(builder, &f[1]);
add_dict(builder, "udev-probed", "1");
add_dict(builder, "device.path", udev_device_get_devnode(dev));
@ -159,8 +160,8 @@ static void fill_item(struct impl *this, struct udev_device *dev,
add_dict(builder, "device.capabilities", str);
}
spa_pod_builder_pop(builder);
*result = spa_pod_builder_pop(builder);
spa_pod_builder_pop(builder, &f[1]);
*result = spa_pod_builder_pop(builder, &f[0]);
}
static int emit_device(struct impl *this, uint32_t id, struct udev_device *dev)

View File

@ -430,13 +430,14 @@ static int port_get_format(struct spa_node *node,
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct port *port = GET_PORT(this, direction, port_id);
struct spa_pod_frame f;
if (!port->have_format)
return -EIO;
if (*index > 0)
return 0;
spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_Format, SPA_PARAM_Format);
spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, SPA_PARAM_Format);
spa_pod_builder_add(builder,
SPA_FORMAT_mediaType, SPA_POD_Id(port->current_format.media_type),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(port->current_format.media_subtype),
@ -467,7 +468,7 @@ static int port_get_format(struct spa_node *node,
return -EIO;
}
*param = spa_pod_builder_pop(builder);
*param = spa_pod_builder_pop(builder, &f);
return 1;
}

View File

@ -402,12 +402,12 @@ enum_filter_format(uint32_t media_type, int32_t media_subtype,
case SPA_MEDIA_TYPE_video:
case SPA_MEDIA_TYPE_image:
if (media_subtype == SPA_MEDIA_SUBTYPE_raw) {
struct spa_pod_prop *p;
const struct spa_pod_prop *p;
const struct spa_pod *val;
uint32_t n_values, choice;
const uint32_t *values;
if (!(p = spa_pod_find_prop(filter, SPA_FORMAT_VIDEO_format)))
if (!(p = spa_pod_find_prop(filter, NULL, SPA_FORMAT_VIDEO_format)))
return SPA_VIDEO_FORMAT_UNKNOWN;
val = spa_pod_get_values(&p->value, &n_values, &choice);
@ -532,6 +532,7 @@ spa_v4l2_enum_format(struct impl *this,
struct spa_pod_choice *choice;
uint32_t filter_media_type, filter_media_subtype, video_format;
struct spa_v4l2_device *dev = &port->dev;
struct spa_pod_frame f[2];
if ((res = spa_v4l2_open(dev, this->props.device)) < 0)
return res;
@ -592,12 +593,12 @@ spa_v4l2_enum_format(struct impl *this,
next_frmsize:
while (port->next_frmsize) {
if (filter) {
struct spa_pod_prop *p;
const struct spa_pod_prop *p;
struct spa_pod *val;
uint32_t n_vals, choice;
/* check if we have a fixed frame size */
if (!(p = spa_pod_find_prop(filter, SPA_FORMAT_VIDEO_size)))
if (!(p = spa_pod_find_prop(filter, NULL, SPA_FORMAT_VIDEO_size)))
goto do_frmsize;
val = spa_pod_get_values(&p->value, &n_vals, &choice);
@ -626,13 +627,13 @@ spa_v4l2_enum_format(struct impl *this,
goto exit;
}
if (filter) {
struct spa_pod_prop *p;
const struct spa_pod_prop *p;
struct spa_pod *val;
const struct spa_rectangle step = { 1, 1 }, *values;
uint32_t choice, i, n_values;
/* check if we have a fixed frame size */
if (!(p = spa_pod_find_prop(filter, SPA_FORMAT_VIDEO_size)))
if (!(p = spa_pod_find_prop(filter, NULL, SPA_FORMAT_VIDEO_size)))
goto have_size;
val = spa_pod_get_values(&p->value, &n_values, &choice);
@ -680,7 +681,7 @@ spa_v4l2_enum_format(struct impl *this,
}
}
spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
spa_pod_builder_add(builder,
SPA_FORMAT_mediaType, SPA_POD_Id(info->media_type),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(info->media_subtype),
@ -697,8 +698,8 @@ spa_v4l2_enum_format(struct impl *this,
n_fractions = 0;
choice = spa_pod_builder_deref(builder,
spa_pod_builder_push_choice(builder, SPA_CHOICE_None, 0));
spa_pod_builder_push_choice(builder, &f[1], SPA_CHOICE_None, 0);
choice = (struct spa_pod_choice*)spa_pod_builder_frame(builder, &f[1]);
port->frmival.index = 0;
while (true) {
@ -715,12 +716,12 @@ spa_v4l2_enum_format(struct impl *this,
goto exit;
}
if (filter) {
struct spa_pod_prop *p;
const struct spa_pod_prop *p;
struct spa_pod *val;
uint32_t i, n_values, choice;
const struct spa_fraction step = { 1, 1 }, *values;
if (!(p = spa_pod_find_prop(filter, SPA_FORMAT_VIDEO_framerate)))
if (!(p = spa_pod_find_prop(filter, NULL, SPA_FORMAT_VIDEO_framerate)))
goto have_framerate;
val = spa_pod_get_values(&p->value, &n_values, &choice);
@ -800,8 +801,8 @@ spa_v4l2_enum_format(struct impl *this,
if (n_fractions <= 1)
choice->body.type = SPA_CHOICE_None;
spa_pod_builder_pop(builder);
*result = spa_pod_builder_pop(builder);
spa_pod_builder_pop(builder, &f[1]);
*result = spa_pod_builder_pop(builder, &f[0]);
(*index)++;
@ -1009,6 +1010,7 @@ spa_v4l2_enum_controls(struct impl *this,
uint8_t buffer[1024];
int res;
const unsigned next_fl = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
struct spa_pod_frame f[2];
if ((res = spa_v4l2_open(dev, this->props.device)) < 0)
return res;
@ -1091,7 +1093,7 @@ spa_v4l2_enum_controls(struct impl *this,
{
struct v4l2_querymenu querymenu;
spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo);
spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo);
spa_pod_builder_add(&b,
SPA_PROP_INFO_id, SPA_POD_Id(prop_id),
SPA_PROP_INFO_type, SPA_POD_CHOICE_ENUM_Int(1, queryctrl.default_value),
@ -1102,7 +1104,7 @@ spa_v4l2_enum_controls(struct impl *this,
querymenu.id = queryctrl.id;
spa_pod_builder_prop(&b, SPA_PROP_INFO_labels, 0);
spa_pod_builder_push_struct(&b);
spa_pod_builder_push_struct(&b, &f[1]);
for (querymenu.index = queryctrl.minimum;
querymenu.index <= queryctrl.maximum;
querymenu.index++) {
@ -1111,8 +1113,8 @@ spa_v4l2_enum_controls(struct impl *this,
spa_pod_builder_string(&b, (const char *)querymenu.name);
}
}
spa_pod_builder_pop(&b);
param = spa_pod_builder_pop(&b);
spa_pod_builder_pop(&b, &f[1]);
param = spa_pod_builder_pop(&b, &f[0]);
break;
}
case V4L2_CTRL_TYPE_INTEGER_MENU:

View File

@ -146,6 +146,7 @@ static int impl_node_enum_params(struct spa_node *node,
case SPA_PARAM_PropInfo:
{
struct props *p = &this->props;
struct spa_pod_frame f[2];
switch (*index) {
case 0:
@ -156,20 +157,20 @@ static int impl_node_enum_params(struct spa_node *node,
SPA_PROP_INFO_type, SPA_POD_Bool(p->live));
break;
case 1:
spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_PropInfo, id);
spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_PropInfo, id);
spa_pod_builder_add(&b,
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_patternType),
SPA_PROP_INFO_name, SPA_POD_String("The pattern"),
SPA_PROP_INFO_type, SPA_POD_Int(p->pattern),
0);
spa_pod_builder_prop(&b, SPA_PROP_INFO_labels, 0),
spa_pod_builder_push_struct(&b);
spa_pod_builder_push_struct(&b, &f[1]);
spa_pod_builder_int(&b, PATTERN_SMPTE_SNOW);
spa_pod_builder_string(&b, "SMPTE snow");
spa_pod_builder_int(&b, PATTERN_SNOW);
spa_pod_builder_string(&b, "Snow");
spa_pod_builder_pop(&b);
param = spa_pod_builder_pop(&b);
spa_pod_builder_pop(&b, &f[1]);
param = spa_pod_builder_pop(&b, &f[0]);
break;
default:
return 0;

View File

@ -2,7 +2,6 @@ test_apps = [
'test-buffer',
'test-pod',
'test-utils',
'stress-ringbuffer',
]
foreach a : test_apps
@ -24,3 +23,20 @@ test_cpp = executable('test-cpp', 'test-cpp.cpp',
install : false)
test('test-cpp', test_cpp)
endif
benchmark_apps = [
'stress-ringbuffer',
'benchmark-pod',
]
foreach a : benchmark_apps
benchmark(a,
executable(a, a + '.c',
dependencies : [dl_lib, pthread_lib],
include_directories : [spa_inc ],
c_args : [ '-D_GNU_SOURCE' ],
install : false),
env : [
'SPA_PLUGIN_DIR=@0@/spa/plugins/'.format(meson.build_root()),
])
endforeach

View File

@ -2,6 +2,8 @@
#include <pthread.h>
#include <stdio.h>
#include <sched.h>
#include <errno.h>
#include <semaphore.h>
#include <spa/utils/ringbuffer.h>
@ -9,9 +11,10 @@
#define ARRAY_SIZE 63
#define MAX_VALUE 0x10000
struct spa_ringbuffer rb;
int32_t size;
uint8_t *data;
static struct spa_ringbuffer rb;
static uint32_t size;
static void *data;
static sem_t sem;
static int fill_int_array(int *array, int start, int count)
{
@ -53,10 +56,14 @@ static void *reader_start(void *arg)
spa_ringbuffer_read_data(&rb, data, size, index % size, b, sizeof(b));
spa_ringbuffer_read_update(&rb, index + sizeof(b));
if (index >= INT32_MAX - sizeof(a))
break;
spa_assert(cmp_array(a, b, ARRAY_SIZE));
i = fill_int_array(a, i, ARRAY_SIZE);
}
}
sem_post(&sem);
return NULL;
}
@ -78,15 +85,26 @@ static void *writer_start(void *arg)
spa_ringbuffer_write_data(&rb, data, size, index % size, a, sizeof(a));
spa_ringbuffer_write_update(&rb, index + sizeof(a));
if (index >= INT32_MAX - sizeof(a))
break;
i = fill_int_array(a, i, ARRAY_SIZE);
}
}
sem_post(&sem);
return NULL;
}
#define exit_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[])
{
pthread_t reader_thread, writer_thread;
struct timespec ts;
int s;
printf("starting ringbuffer stress test\n");
if (argc > 1)
@ -100,11 +118,21 @@ int main(int argc, char *argv[])
spa_ringbuffer_init(&rb);
data = malloc(size);
pthread_t reader_thread, writer_thread;
if (sem_init(&sem, 0, 0) != 0)
exit_error("init_sem");
pthread_create(&reader_thread, NULL, reader_start, NULL);
pthread_create(&writer_thread, NULL, writer_start, NULL);
sleep(5);
if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
exit_error("clock_gettime");
ts.tv_sec += 2;
while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR)
continue;
while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR)
continue;
printf("read %u, written %u\n", rb.readindex, rb.writeindex);

View File

@ -69,9 +69,9 @@ static void test_abi(void)
spa_assert(sizeof(struct spa_pod_sequence) == 16);
/* builder */
spa_assert(sizeof(struct spa_pod_frame) == 16);
spa_assert(sizeof(struct spa_pod_frame) == 24);
spa_assert(sizeof(struct spa_pod_builder_state) == 16);
spa_assert(sizeof(struct spa_pod_builder) == 312);
spa_assert(sizeof(struct spa_pod_builder) == 48);
/* command */
spa_assert(sizeof(struct spa_command_body) == 8);
@ -81,11 +81,9 @@ static void test_abi(void)
spa_assert(sizeof(struct spa_event_body) == 8);
spa_assert(sizeof(struct spa_event) == 16);
/* iter */
spa_assert(sizeof(struct spa_pod_iter) == 16);
/* parser */
spa_assert(sizeof(struct spa_pod_parser) == 264);
spa_assert(sizeof(struct spa_pod_parser_state) == 16);
spa_assert(sizeof(struct spa_pod_parser) == 32);
}
@ -339,10 +337,10 @@ static void test_build(void)
uint8_t buffer[4096];
struct spa_pod_builder b;
struct spa_pod *array, *choice, *head, *pod, *it;
struct spa_pod_prop *prop;
const struct spa_pod_prop *prop;
struct spa_pod_control *control;
int64_t longs[] = { 5, 7, 11, 13, 17 }, *al;
uint32_t i, len, zl, *ai;
uint32_t i, len, yl, *ai;
union {
bool b;
uint32_t I;
@ -351,103 +349,131 @@ static void test_build(void)
float f;
double d;
const char *s;
const void *z;
const void *y;
const void *p;
int64_t h;
struct spa_rectangle R;
struct spa_fraction F;
} val;
struct spa_pod_frame f;
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_assert(b.data == buffer);
spa_assert(b.size == sizeof(buffer));
spa_assert(b.state.offset == 0);
spa_assert(b.state.flags == 0);
spa_assert(b.state.depth == 0);
spa_assert(spa_pod_builder_none(&b) == 0);
spa_assert(spa_pod_builder_bool(&b, true) == 8);
spa_assert(spa_pod_builder_id(&b, SPA_TYPE_Object) == 24);
spa_assert(spa_pod_builder_int(&b, 21) == 40);
spa_assert(spa_pod_builder_float(&b, 0.8f) == 56);
spa_assert(spa_pod_builder_double(&b, -1.56) == 72);
spa_assert(spa_pod_builder_string(&b, "test") == 88);
spa_assert(spa_pod_builder_bytes(&b, "PipeWire", 8) == 104);
spa_assert(spa_pod_builder_pointer(&b, SPA_TYPE_Object, &b) == 120);
spa_assert(spa_pod_builder_fd(&b, 4) == 144);
spa_assert(spa_pod_builder_rectangle(&b, 320, 240) == 160);
spa_assert(spa_pod_builder_fraction(&b, 25, 1) == 176);
spa_assert(b.state.offset == 8);
spa_assert(spa_pod_builder_bool(&b, true) == 0);
spa_assert(b.state.offset == 24);
spa_assert(spa_pod_builder_id(&b, SPA_TYPE_Object) == 0);
spa_assert(b.state.offset == 40);
spa_assert(spa_pod_builder_int(&b, 21) == 0);
spa_assert(b.state.offset == 56);
spa_assert(spa_pod_builder_float(&b, 0.8f) == 0);
spa_assert(b.state.offset == 72);
spa_assert(spa_pod_builder_double(&b, -1.56) == 0);
spa_assert(b.state.offset == 88);
spa_assert(spa_pod_builder_string(&b, "test") == 0);
spa_assert(b.state.offset == 104);
spa_assert(spa_pod_builder_bytes(&b, "PipeWire", 8) == 0);
spa_assert(b.state.offset == 120);
spa_assert(spa_pod_builder_pointer(&b, SPA_TYPE_Object, &b) == 0);
spa_assert(b.state.offset == 144);
spa_assert(spa_pod_builder_fd(&b, 4) == 0);
spa_assert(b.state.offset == 160);
spa_assert(spa_pod_builder_rectangle(&b, 320, 240) == 0);
spa_assert(b.state.offset == 176);
spa_assert(spa_pod_builder_fraction(&b, 25, 1) == 0);
spa_assert(spa_pod_builder_push_array(&b) == 192);
spa_assert(b.state.offset == 192);
spa_assert(spa_pod_builder_push_array(&b, &f) == 0);
spa_assert(f.offset == 192);
spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_BODY | SPA_POD_BUILDER_FLAG_FIRST));
spa_assert(b.state.depth == 1);
spa_assert(spa_pod_builder_int(&b, 1) == 200);
spa_assert(b.state.offset == 200);
spa_assert(spa_pod_builder_int(&b, 1) == 0);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_BODY);
spa_assert(spa_pod_builder_int(&b, 2) == 212);
spa_assert(spa_pod_builder_int(&b, 3) == 216);
array = spa_pod_builder_pop(&b);
spa_assert(b.state.offset == 212);
spa_assert(spa_pod_builder_int(&b, 2) == 0);
spa_assert(b.state.offset == 216);
spa_assert(spa_pod_builder_int(&b, 3) == 0);
array = spa_pod_builder_pop(&b, &f);
spa_assert(f.pod.size == 20);
spa_assert(array != NULL);
spa_assert(SPA_POD_BODY_SIZE(array) == 8 + 12);
spa_assert(b.state.flags == 0);
spa_assert(b.state.depth == 0);
spa_assert(b.state.offset == 224);
spa_assert(spa_pod_builder_array(&b,
sizeof(int64_t), SPA_TYPE_Long,
SPA_N_ELEMENTS(longs), longs) == 224);
SPA_N_ELEMENTS(longs), longs) == 0);
spa_assert(b.state.flags == 0);
spa_assert(b.state.depth == 0);
spa_assert(spa_pod_builder_push_choice(&b, SPA_CHOICE_Enum, 0) == 280);
spa_assert(b.state.offset == 280);
spa_assert(spa_pod_builder_push_choice(&b, &f, SPA_CHOICE_Enum, 0) == 0);
spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_BODY | SPA_POD_BUILDER_FLAG_FIRST));
spa_assert(b.state.depth == 1);
spa_assert(spa_pod_builder_long(&b, 1) == 296);
spa_assert(b.state.offset == 296);
spa_assert(spa_pod_builder_long(&b, 1) == 0);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_BODY);
spa_assert(spa_pod_builder_long(&b, 2) == 312);
spa_assert(spa_pod_builder_long(&b, 3) == 320);
choice = spa_pod_builder_pop(&b);
spa_assert(b.state.offset == 312);
spa_assert(spa_pod_builder_long(&b, 2) == 0);
spa_assert(b.state.offset == 320);
spa_assert(spa_pod_builder_long(&b, 3) == 0);
choice = spa_pod_builder_pop(&b, &f);
spa_assert(choice != NULL);
spa_assert(b.state.flags == 0);
spa_assert(b.state.depth == 0);
spa_assert(spa_pod_builder_push_struct(&b) == 328);
spa_assert(b.state.offset == 328);
spa_assert(spa_pod_builder_push_struct(&b, &f) == 0);
spa_assert(b.state.flags == 0);
spa_assert(b.state.depth == 1);
spa_assert(spa_pod_builder_int(&b, 21) == 336);
spa_assert(spa_pod_builder_float(&b, 0.8f) == 352);
spa_assert(spa_pod_builder_double(&b, -1.56) == 368);
spa_assert(spa_pod_builder_pop(&b) != NULL);
spa_assert(b.state.depth == 0);
spa_assert(b.state.offset == 336);
spa_assert(spa_pod_builder_int(&b, 21) == 0);
spa_assert(b.state.offset == 352);
spa_assert(spa_pod_builder_float(&b, 0.8f) == 0);
spa_assert(b.state.offset == 368);
spa_assert(spa_pod_builder_double(&b, -1.56) == 0);
spa_assert(spa_pod_builder_pop(&b, &f) != NULL);
spa_assert(spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_Props, 0) == 384);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_OBJECT);
spa_assert(b.state.depth == 1);
spa_assert(spa_pod_builder_prop(&b, 1, 0) == 400);
spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_OBJECT | SPA_POD_BUILDER_FLAG_HEADER));
spa_assert(spa_pod_builder_int(&b, 21) == 408);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_OBJECT);
spa_assert(spa_pod_builder_prop(&b, 2, 0) == 424);
spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_OBJECT | SPA_POD_BUILDER_FLAG_HEADER));
spa_assert(spa_pod_builder_long(&b, 42) == 432);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_OBJECT);
spa_assert(spa_pod_builder_prop(&b, 3, 0) == 448);
spa_assert(spa_pod_builder_string(&b, "test123") == 456);
spa_assert(spa_pod_builder_pop(&b) != NULL);
spa_assert(b.state.offset == 384);
spa_assert(spa_pod_builder_push_object(&b, &f, SPA_TYPE_OBJECT_Props, 0) == 0);
spa_assert(b.state.flags == 0);
spa_assert(b.state.offset == 400);
spa_assert(spa_pod_builder_prop(&b, 1, 0) == 0);
spa_assert(b.state.flags == 0);
spa_assert(b.state.offset == 408);
spa_assert(spa_pod_builder_int(&b, 21) == 0);
spa_assert(b.state.flags == 0);
spa_assert(b.state.offset == 424);
spa_assert(spa_pod_builder_prop(&b, 2, 0) == 0);
spa_assert(b.state.flags == 0);
spa_assert(b.state.offset == 432);
spa_assert(spa_pod_builder_long(&b, 42) == 0);
spa_assert(b.state.flags == 0);
spa_assert(b.state.offset == 448);
spa_assert(spa_pod_builder_prop(&b, 3, 0) == 0);
spa_assert(b.state.offset == 456);
spa_assert(spa_pod_builder_string(&b, "test123") == 0);
spa_assert(spa_pod_builder_pop(&b, &f) != NULL);
spa_assert(b.state.flags == 0);
spa_assert(b.state.depth == 0);
spa_assert(spa_pod_builder_push_sequence(&b, 0) == 472);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_SEQUENCE);
spa_assert(b.state.depth == 1);
spa_assert(spa_pod_builder_control(&b, 0, 0) == 488);
spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_SEQUENCE | SPA_POD_BUILDER_FLAG_HEADER));
spa_assert(spa_pod_builder_float(&b, 0.667f) == 496);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_SEQUENCE);
spa_assert(spa_pod_builder_control(&b, 12, 0) == 512);
spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_SEQUENCE | SPA_POD_BUILDER_FLAG_HEADER));
spa_assert(spa_pod_builder_double(&b, 1.22) == 520);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_SEQUENCE);
spa_assert(spa_pod_builder_pop(&b) != NULL);
spa_assert(b.state.offset == 472);
spa_assert(spa_pod_builder_push_sequence(&b, &f, 0) == 0);
spa_assert(b.state.flags == 0);
spa_assert(b.state.offset == 488);
spa_assert(spa_pod_builder_control(&b, 0, 0) == 0);
spa_assert(b.state.flags == 0);
spa_assert(b.state.offset == 496);
spa_assert(spa_pod_builder_float(&b, 0.667f) == 0);
spa_assert(b.state.flags == 0);
spa_assert(b.state.offset == 512);
spa_assert(spa_pod_builder_control(&b, 12, 0) == 0);
spa_assert(b.state.flags == 0);
spa_assert(b.state.offset == 520);
spa_assert(spa_pod_builder_double(&b, 1.22) == 0);
spa_assert(b.state.flags == 0);
spa_assert(spa_pod_builder_pop(&b, &f) != NULL);
spa_assert(b.state.flags == 0);
spa_assert(b.state.depth == 0);
spa_assert(b.state.offset == 536);
@ -482,13 +508,13 @@ static void test_build(void)
spa_assert(strcmp(val.s, "test") == 0);
spa_assert((pod = spa_pod_next(pod)) != NULL && spa_pod_is_inside(head, len, pod));
spa_assert(spa_pod_is_bytes(pod));
spa_assert(spa_pod_get_bytes(pod, &val.z, &zl) == 0);
spa_assert(zl == 8);
spa_assert(memcmp(val.z, "PipeWire", zl) == 0);
spa_assert(spa_pod_get_bytes(pod, &val.y, &yl) == 0);
spa_assert(yl == 8);
spa_assert(memcmp(val.y, "PipeWire", yl) == 0);
spa_assert((pod = spa_pod_next(pod)) != NULL && spa_pod_is_inside(head, len, pod));
spa_assert(spa_pod_is_pointer(pod));
spa_assert(spa_pod_get_pointer(pod, &zl, &val.p) == 0);
spa_assert(zl == SPA_TYPE_Object);
spa_assert(spa_pod_get_pointer(pod, &yl, &val.p) == 0);
spa_assert(yl == SPA_TYPE_Object);
spa_assert(val.p == &b);
spa_assert((pod = spa_pod_next(pod)) != NULL && spa_pod_is_inside(head, len, pod));
spa_assert(spa_pod_is_fd(pod));
@ -605,17 +631,22 @@ static void test_build(void)
break;
}
}
spa_assert((prop = spa_pod_find_prop(pod, 3)) != NULL);
spa_assert((prop = spa_pod_find_prop(pod, NULL, 3)) != NULL);
spa_assert(prop->key == 3);
spa_assert(spa_pod_get_string(&prop->value, &val.s) == 0 &&
strcmp(val.s, "test123") == 0);
spa_assert((prop = spa_pod_find_prop(pod, 1)) != NULL);
spa_assert((prop = spa_pod_find_prop(pod, prop, 1)) != NULL);
spa_assert(prop->key == 1);
spa_assert(spa_pod_get_int(&prop->value, &val.i) == 0 && val.i == 21);
spa_assert((prop = spa_pod_find_prop(pod, 2)) != NULL);
spa_assert((prop = spa_pod_find_prop(pod, prop, 2)) != NULL);
spa_assert(prop->key == 2);
spa_assert(spa_pod_get_long(&prop->value, &val.l) == 0 && val.l == 42);
spa_assert((prop = spa_pod_find_prop(pod, 5)) == NULL);
spa_assert((prop = spa_pod_find_prop(pod, prop, 5)) == NULL);
spa_assert((prop = spa_pod_find_prop(pod, NULL, 3)) != NULL);
spa_assert(prop->key == 3);
spa_assert(spa_pod_get_string(&prop->value, &val.s) == 0 &&
strcmp(val.s, "test123") == 0);
spa_assert((pod = spa_pod_next(pod)) != NULL && spa_pod_is_inside(head, len, pod));
spa_assert(spa_pod_is_sequence(pod));
@ -655,7 +686,7 @@ static void test_varargs(void)
float f;
double d;
const char *s;
const void *z;
const void *y;
const void *p;
int64_t h;
struct spa_rectangle R;
@ -826,8 +857,8 @@ static void test_varargs2(void)
float f;
double d;
const char *s;
uint32_t zl;
const void *z;
uint32_t yl;
const void *y;
uint32_t ptype;
const void *p;
uint32_t asize, atype, anvals;
@ -903,9 +934,9 @@ static void test_varargs2(void)
case 7:
spa_assert(prop->key == 8);
spa_assert(SPA_POD_PROP_SIZE(prop) == 21);
spa_assert(spa_pod_get_bytes(&prop->value, &val.z, &val.zl) == 0);
spa_assert(val.zl == sizeof(bytes));
spa_assert(memcmp(val.z, bytes, val.zl) == 0);
spa_assert(spa_pod_get_bytes(&prop->value, &val.y, &val.yl) == 0);
spa_assert(val.yl == sizeof(bytes));
spa_assert(memcmp(val.y, bytes, val.yl) == 0);
break;
case 8:
spa_assert(prop->key == 9);
@ -969,7 +1000,7 @@ static void test_varargs2(void)
5, SPA_POD_Float(&val.f),
6, SPA_POD_Double(&val.d),
7, SPA_POD_String(&val.s),
8, SPA_POD_Bytes(&val.z, &val.zl),
8, SPA_POD_Bytes(&val.y, &val.yl),
9, SPA_POD_Rectangle(&val.R),
10, SPA_POD_Fraction(&val.F),
11, SPA_POD_Array(&val.asize, &val.atype, &val.anvals, &val.a),
@ -984,8 +1015,8 @@ static void test_varargs2(void)
spa_assert(val.f == 0.453f);
spa_assert(val.d == 0.871);
spa_assert(strcmp(val.s, "test") == 0);
spa_assert(val.zl == sizeof(bytes));
spa_assert(memcmp(val.z, bytes, sizeof(bytes)) == 0);
spa_assert(val.yl == sizeof(bytes));
spa_assert(memcmp(val.y, bytes, sizeof(bytes)) == 0);
spa_assert(memcmp(&val.R, &SPA_RECTANGLE(3, 4), sizeof(struct spa_rectangle)) == 0);
spa_assert(memcmp(&val.F, &SPA_FRACTION(24, 1), sizeof(struct spa_fraction)) == 0);
spa_assert(val.asize == sizeof(int64_t));
@ -1007,7 +1038,7 @@ static void test_varargs2(void)
0, SPA_POD_OPT_Float(&val.f),
0, SPA_POD_OPT_Double(&val.d),
0, SPA_POD_OPT_String(&val.s),
0, SPA_POD_OPT_Bytes(&val.z, &val.zl),
0, SPA_POD_OPT_Bytes(&val.y, &val.yl),
0, SPA_POD_OPT_Rectangle(&val.R),
0, SPA_POD_OPT_Fraction(&val.F),
0, SPA_POD_OPT_Array(&val.asize, &val.atype, &val.anvals, &val.a),
@ -1026,7 +1057,7 @@ static void test_varargs2(void)
i, SPA_POD_OPT_Float(&val.f),
i, SPA_POD_OPT_Double(&val.d),
i, SPA_POD_OPT_String(&val.s),
i, SPA_POD_OPT_Bytes(&val.z, &val.zl),
i, SPA_POD_OPT_Bytes(&val.y, &val.yl),
i, SPA_POD_OPT_Rectangle(&val.R),
i, SPA_POD_OPT_Fraction(&val.F),
i, SPA_POD_OPT_Array(&val.asize, &val.atype, &val.anvals, &val.a),
@ -1036,6 +1067,392 @@ static void test_varargs2(void)
}
}
static void test_parser(void)
{
uint8_t buffer[4096];
struct spa_pod_builder b;
struct spa_pod_parser p;
struct spa_pod_frame f;
struct spa_pod *pod;
struct {
bool b;
uint32_t I;
int32_t i;
int64_t l;
float f;
double d;
const char *s;
uint32_t yl;
const void *y;
uint32_t ptype;
const void *p;
uint32_t asize, atype, anvals;
const void *a;
int64_t h;
struct spa_rectangle R;
struct spa_fraction F;
struct spa_pod *P;
} val;
uint8_t bytes[] = { 0x56, 0x00, 0x12, 0xf3, 0xba };
int64_t longs[] = { 1002, 5383, 28944, 1237748 };
struct spa_pod_int pi = SPA_POD_INIT_Int(77);
spa_pod_builder_init(&b, buffer, sizeof(buffer));
pod = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Props, 0,
1, SPA_POD_Bool(true),
2, SPA_POD_Id(SPA_TYPE_Id),
3, SPA_POD_Int(3),
4, SPA_POD_Long(4),
5, SPA_POD_Float(0.453f),
6, SPA_POD_Double(0.871),
7, SPA_POD_String("test"),
8, SPA_POD_Bytes(bytes, sizeof(bytes)),
9, SPA_POD_Rectangle(&SPA_RECTANGLE(3,4)),
10, SPA_POD_Fraction(&SPA_FRACTION(24,1)),
11, SPA_POD_Array(sizeof(int64_t), SPA_TYPE_Long, SPA_N_ELEMENTS(longs), longs),
12, SPA_POD_Pointer(SPA_TYPE_Object, &b),
13, SPA_POD_Fd(3),
14, SPA_POD_Pod(&pi));
spa_debug_pod(0, NULL, pod);
spa_pod_parser_pod(&p, pod);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_bool(&p, &val.b) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_id(&p, &val.I) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_int(&p, &val.i) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_long(&p, &val.l) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_float(&p, &val.f) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_double(&p, &val.d) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_string(&p, &val.s) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_bytes(&p, &val.y, &val.yl) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_rectangle(&p, &val.R) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_fraction(&p, &val.F) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_pointer(&p, &val.ptype, &val.p) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_fd(&p, &val.h) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_pod(&p, &val.P) == 0);
spa_assert(p.state.offset == 392);
spa_assert(spa_pod_is_object(val.P));
spa_pod_parser_pod(&p, val.P);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_push_struct(&p, &f) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_push_object(&p, &f, SPA_TYPE_OBJECT_Format, NULL) == -EPROTO);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_push_object(&p, &f, SPA_TYPE_OBJECT_Props, NULL) == 0);
spa_assert(p.state.offset == 392);
spa_assert(spa_pod_parser_frame(&p, &f) == val.P);
spa_zero(val);
spa_assert(spa_pod_parser_get(&p,
1, SPA_POD_OPT_Bool(&val.b),
2, SPA_POD_OPT_Id(&val.I),
3, SPA_POD_OPT_Int(&val.i),
4, SPA_POD_OPT_Long(&val.l),
5, SPA_POD_OPT_Float(&val.f),
6, SPA_POD_OPT_Double(&val.d),
7, SPA_POD_OPT_String(&val.s),
8, SPA_POD_OPT_Bytes(&val.y, &val.yl),
9, SPA_POD_OPT_Rectangle(&val.R),
10, SPA_POD_OPT_Fraction(&val.F),
11, SPA_POD_OPT_Array(&val.asize, &val.atype, &val.anvals, &val.a),
12, SPA_POD_OPT_Pointer(&val.ptype, &val.p),
13, SPA_POD_OPT_Fd(&val.h),
14, SPA_POD_OPT_Pod(&val.P), 0) == 14);
spa_pod_parser_pop(&p, &f);
spa_assert(val.b == true);
spa_assert(val.I == SPA_TYPE_Id);
spa_assert(val.i == 3);
spa_assert(val.l == 4);
spa_assert(val.f == 0.453f);
spa_assert(val.d == 0.871);
spa_assert(strcmp(val.s, "test") == 0);
spa_assert(val.yl == sizeof(bytes));
spa_assert(memcmp(val.y, bytes, sizeof(bytes)) == 0);
spa_assert(memcmp(&val.R, &SPA_RECTANGLE(3, 4), sizeof(struct spa_rectangle)) == 0);
spa_assert(memcmp(&val.F, &SPA_FRACTION(24, 1), sizeof(struct spa_fraction)) == 0);
spa_assert(val.asize == sizeof(int64_t));
spa_assert(val.atype == SPA_TYPE_Long);
spa_assert(val.anvals == SPA_N_ELEMENTS(longs));
spa_assert(memcmp(val.a, longs, val.anvals * val.asize) == 0);
spa_assert(val.ptype == SPA_TYPE_Object);
spa_assert(val.p == &b);
spa_assert(val.h == 3);
spa_assert(memcmp(val.P, &pi, sizeof(pi)) == 0);
spa_assert(p.state.offset == 392);
}
static void test_parser2(void)
{
uint8_t buffer[4096];
struct spa_pod_builder b;
struct spa_pod_parser p;
struct spa_pod_frame f;
struct spa_pod *pod;
struct {
bool b;
uint32_t I;
int32_t i;
int64_t l;
float f;
double d;
const char *s;
uint32_t yl;
const void *y;
uint32_t ptype;
const void *p;
uint32_t asize, atype, anvals;
const void *a;
int64_t h;
struct spa_rectangle R;
struct spa_fraction F;
struct spa_pod *P;
} val;
uint8_t bytes[] = { 0x56, 0x00, 0x12, 0xf3, 0xba };
int64_t longs[] = { 1002, 5383, 28944, 1237748 };
struct spa_pod_int pi = SPA_POD_INIT_Int(77);
spa_pod_builder_init(&b, buffer, sizeof(buffer));
pod = spa_pod_builder_add_struct(&b,
SPA_POD_Bool(true),
SPA_POD_Id(SPA_TYPE_Id),
SPA_POD_Int(3),
SPA_POD_Long(4),
SPA_POD_Float(0.453f),
SPA_POD_Double(0.871),
SPA_POD_String("test"),
SPA_POD_Bytes(bytes, sizeof(bytes)),
SPA_POD_Rectangle(&SPA_RECTANGLE(3,4)),
SPA_POD_Fraction(&SPA_FRACTION(24,1)),
SPA_POD_Array(sizeof(int64_t), SPA_TYPE_Long, SPA_N_ELEMENTS(longs), longs),
SPA_POD_Pointer(SPA_TYPE_Object, &b),
SPA_POD_Fd(3),
SPA_POD_Pod(&pi));
spa_debug_pod(0, NULL, pod);
spa_pod_parser_pod(&p, pod);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_bool(&p, &val.b) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_id(&p, &val.I) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_int(&p, &val.i) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_long(&p, &val.l) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_float(&p, &val.f) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_double(&p, &val.d) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_string(&p, &val.s) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_bytes(&p, &val.y, &val.yl) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_rectangle(&p, &val.R) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_fraction(&p, &val.F) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_pointer(&p, &val.ptype, &val.p) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_fd(&p, &val.h) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_get_pod(&p, &val.P) == 0);
spa_assert(p.state.offset == 272);
spa_assert(spa_pod_is_struct(val.P));
spa_pod_parser_pod(&p, val.P);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_push_object(&p, &f, SPA_TYPE_OBJECT_Format, NULL) == -EINVAL);
spa_assert(p.state.offset == 0);
spa_assert(spa_pod_parser_push_struct(&p, &f) == 0);
spa_assert(f.pod.type == SPA_TYPE_Struct);
spa_assert(f.pod.size == 264);
spa_assert(f.offset == 0);
spa_assert(p.state.frame == &f);
spa_assert(spa_pod_parser_frame(&p, &f) == val.P);
spa_assert(p.state.offset == 8);
spa_assert(spa_pod_parser_get_bool(&p, &val.b) == 0 && val.b == true);
spa_assert(p.state.offset == 24);
spa_assert(spa_pod_parser_get_id(&p, &val.I) == 0 && val.I == SPA_TYPE_Id);
spa_assert(p.state.offset == 40);
spa_assert(spa_pod_parser_get_int(&p, &val.i) == 0 && val.i == 3);
spa_assert(p.state.offset == 56);
spa_assert(spa_pod_parser_get_long(&p, &val.l) == 0 && val.l == 4);
spa_assert(p.state.offset == 72);
spa_assert(spa_pod_parser_get_float(&p, &val.f) == 0 && val.f == 0.453f);
spa_assert(p.state.offset == 88);
spa_assert(spa_pod_parser_get_double(&p, &val.d) == 0 && val.d == 0.871);
spa_assert(p.state.offset == 104);
spa_assert(spa_pod_parser_get_string(&p, &val.s) == 0 && strcmp(val.s, "test") == 0);
spa_assert(p.state.offset == 120);
spa_assert(spa_pod_parser_get_bytes(&p, &val.y, &val.yl) == 0);
spa_assert(val.yl == sizeof(bytes));
spa_assert(memcmp(bytes, val.y, sizeof(bytes)) == 0);
spa_assert(p.state.offset == 136);
spa_assert(spa_pod_parser_get_rectangle(&p, &val.R) == 0);
spa_assert(memcmp(&val.R, &SPA_RECTANGLE(3,4), sizeof(struct spa_rectangle)) == 0);
spa_assert(p.state.offset == 152);
spa_assert(spa_pod_parser_get_fraction(&p, &val.F) == 0);
spa_assert(memcmp(&val.F, &SPA_FRACTION(24,1), sizeof(struct spa_fraction)) == 0);
spa_assert(p.state.offset == 168);
spa_assert((val.P = spa_pod_parser_next(&p)) != NULL);
spa_assert(spa_pod_is_array(val.P));
spa_assert(p.state.offset == 216);
spa_assert(SPA_POD_ARRAY_VALUE_TYPE(val.P) == SPA_TYPE_Long);
spa_assert(SPA_POD_ARRAY_VALUE_SIZE(val.P) == sizeof(int64_t));
spa_assert(SPA_POD_ARRAY_N_VALUES(val.P) == SPA_N_ELEMENTS(longs));
spa_assert(spa_pod_parser_get_pointer(&p, &val.ptype, &val.p) == 0);
spa_assert(val.ptype == SPA_TYPE_Object);
spa_assert(val.p == &b);
spa_assert(p.state.offset == 240);
spa_assert(spa_pod_parser_get_fd(&p, &val.h) == 0);
spa_assert(val.h == 3);
spa_assert(p.state.offset == 256);
spa_assert(spa_pod_parser_get_pod(&p, &val.P) == 0);
spa_assert(p.state.offset == 272);
spa_assert(spa_pod_is_int(val.P));
spa_pod_parser_pop(&p, &f);
spa_assert(p.state.offset == 272);
spa_assert(p.state.frame == NULL);
}
static void test_static(void)
{
struct _test_format {
struct spa_pod_object fmt;
struct {
struct spa_pod_prop prop_media_type SPA_ALIGNED(8);
uint32_t media_type;
struct spa_pod_prop prop_media_subtype SPA_ALIGNED(8);
uint32_t media_subtype;
struct spa_pod_prop prop_format SPA_ALIGNED(8);
struct {
struct spa_pod_choice_body choice;
uint32_t def_format;
uint32_t enum_format[2];
} format_vals;
struct spa_pod_prop prop_size SPA_ALIGNED(8);
struct {
struct spa_pod_choice_body choice;
struct spa_rectangle def_size;
struct spa_rectangle min_size;
struct spa_rectangle max_size;
} size_vals;
struct spa_pod_prop prop_framerate SPA_ALIGNED(8);
struct {
struct spa_pod_choice_body choice;
struct spa_fraction def_framerate;
struct spa_fraction min_framerate;
struct spa_fraction max_framerate;
} framerate_vals;
} props;
} test_format = {
SPA_POD_INIT_Object(sizeof(test_format.props) + sizeof(struct spa_pod_object_body),
SPA_TYPE_OBJECT_Format, 0),
{
SPA_POD_INIT_Prop(SPA_FORMAT_mediaType, 0,
sizeof(test_format.props.media_type), SPA_TYPE_Id),
SPA_MEDIA_TYPE_video,
SPA_POD_INIT_Prop(SPA_FORMAT_mediaSubtype, 0,
sizeof(test_format.props.media_subtype), SPA_TYPE_Id),
SPA_MEDIA_SUBTYPE_raw,
SPA_POD_INIT_Prop(SPA_FORMAT_VIDEO_format, 0,
sizeof(test_format.props.format_vals), SPA_TYPE_Choice),
{
SPA_POD_INIT_CHOICE_BODY(SPA_CHOICE_Enum, 0,
sizeof(uint32_t), SPA_TYPE_Id),
SPA_VIDEO_FORMAT_I420,
{ SPA_VIDEO_FORMAT_I420, SPA_VIDEO_FORMAT_YUY2 }
},
SPA_POD_INIT_Prop(SPA_FORMAT_VIDEO_size, 0,
sizeof(test_format.props.size_vals), SPA_TYPE_Choice),
{
SPA_POD_INIT_CHOICE_BODY(SPA_CHOICE_Range, 0,
sizeof(struct spa_rectangle), SPA_TYPE_Rectangle),
SPA_RECTANGLE(320,243),
SPA_RECTANGLE(1,1), SPA_RECTANGLE(INT32_MAX, INT32_MAX)
},
SPA_POD_INIT_Prop(SPA_FORMAT_VIDEO_framerate, 0,
sizeof(test_format.props.framerate_vals), SPA_TYPE_Choice),
{
SPA_POD_INIT_CHOICE_BODY(SPA_CHOICE_Range, 0,
sizeof(struct spa_fraction), SPA_TYPE_Fraction),
SPA_FRACTION(25,1),
SPA_FRACTION(0,1), SPA_FRACTION(INT32_MAX,1)
}
}
};
struct {
uint32_t media_type;
uint32_t media_subtype;
uint32_t format;
struct spa_rectangle size;
struct spa_fraction framerate;
} vals;
int res;
spa_debug_pod(0, NULL, &test_format.fmt.pod);
spa_zero(vals);
res = spa_pod_parse_object(&test_format.fmt.pod,
SPA_TYPE_OBJECT_Format, NULL,
SPA_FORMAT_mediaType, SPA_POD_Id(&vals.media_type),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(&vals.media_subtype),
SPA_FORMAT_VIDEO_format, SPA_POD_Id(&vals.format),
SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&vals.size),
SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&vals.framerate));
spa_assert(res == -EPROTO);
spa_assert(vals.media_type == SPA_MEDIA_TYPE_video);
spa_assert(vals.media_subtype == SPA_MEDIA_SUBTYPE_raw);
spa_assert(vals.format == 0);
spa_assert(vals.size.width == 0 && vals.size.height == 0);
spa_assert(vals.framerate.num == 0 && vals.framerate.denom == 0);
spa_pod_fixate(&test_format.fmt.pod);
spa_zero(vals);
res = spa_pod_parse_object(&test_format.fmt.pod,
SPA_TYPE_OBJECT_Format, NULL,
SPA_FORMAT_mediaType, SPA_POD_Id(&vals.media_type),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(&vals.media_subtype),
SPA_FORMAT_VIDEO_format, SPA_POD_Id(&vals.format),
SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&vals.size),
SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&vals.framerate));
spa_assert(res == 5);
spa_assert(vals.media_type == SPA_MEDIA_TYPE_video);
spa_assert(vals.media_subtype == SPA_MEDIA_SUBTYPE_raw);
spa_assert(vals.format == SPA_VIDEO_FORMAT_I420);
spa_assert(vals.size.width == 320 && vals.size.height == 243);
spa_assert(vals.framerate.num == 25 && vals.framerate.denom == 1);
}
int main(int argc, char *argv[])
{
test_abi();
@ -1043,5 +1460,8 @@ int main(int argc, char *argv[])
test_build();
test_varargs();
test_varargs2();
test_parser();
test_parser2();
test_static();
return 0;
}

View File

@ -110,18 +110,19 @@ static void handle_events(struct data *data)
static void update_param(struct data *data)
{
struct spa_pod_builder b = { 0, };
struct spa_pod_frame f[2];
if (data->io_notify == NULL)
return;
spa_pod_builder_init(&b, data->io_notify, data->io_notify_size);
spa_pod_builder_push_sequence(&b, 0);
spa_pod_builder_push_sequence(&b, &f[0], 0);
spa_pod_builder_control(&b, 0, SPA_CONTROL_Properties);
spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_Props, 0);
spa_pod_builder_push_object(&b, &f[1], SPA_TYPE_OBJECT_Props, 0);
spa_pod_builder_prop(&b, SPA_PROP_contrast, 0);
spa_pod_builder_float(&b, (sin(data->param_accum) * 127.0) + 127.0);
spa_pod_builder_pop(&b);
spa_pod_builder_pop(&b);
spa_pod_builder_pop(&b, &f[1]);
spa_pod_builder_pop(&b, &f[0]);
data->param_accum += M_PI_M2 / 30.0;
if (data->param_accum >= M_PI_M2)

View File

@ -81,18 +81,19 @@ struct data {
static void update_volume(struct data *data)
{
struct spa_pod_builder b = { 0, };
struct spa_pod_frame f[2];
if (data->io_notify == NULL)
return;
spa_pod_builder_init(&b, data->io_notify, data->io_notify_size);
spa_pod_builder_push_sequence(&b, 0);
spa_pod_builder_push_sequence(&b, &f[0], 0);
spa_pod_builder_control(&b, 0, SPA_CONTROL_Properties);
spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_Props, 0);
spa_pod_builder_push_object(&b, &f[1], SPA_TYPE_OBJECT_Props, 0);
spa_pod_builder_prop(&b, SPA_PROP_volume, 0);
spa_pod_builder_float(&b, (sin(data->volume_accum) / 2.0) + 0.5);
spa_pod_builder_pop(&b);
spa_pod_builder_pop(&b);
spa_pod_builder_pop(&b, &f[1]);
spa_pod_builder_pop(&b, &f[0]);
data->volume_accum += M_PI_M2 / 1000.0;
if (data->volume_accum >= M_PI_M2)

View File

@ -101,15 +101,16 @@ static Uint32 id_to_sdl_format(uint32_t id)
static struct spa_pod *sdl_build_formats(SDL_RendererInfo *info, struct spa_pod_builder *b)
{
uint32_t i, c;
struct spa_pod_frame f[2];
spa_pod_builder_push_object(b, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
spa_pod_builder_push_object(b, &f[0], SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
spa_pod_builder_prop(b, SPA_FORMAT_mediaType, 0);
spa_pod_builder_id(b, SPA_MEDIA_TYPE_video);
spa_pod_builder_prop(b, SPA_FORMAT_mediaSubtype, 0);
spa_pod_builder_id(b, SPA_MEDIA_SUBTYPE_raw);
spa_pod_builder_prop(b, SPA_FORMAT_VIDEO_format, 0);
spa_pod_builder_push_choice(b, SPA_CHOICE_Enum, 0);
spa_pod_builder_push_choice(b, &f[1], SPA_CHOICE_Enum, 0);
for (i = 0, c = 0; i < info->num_texture_formats; i++) {
uint32_t id = sdl_format_to_id(info->texture_formats[i]);
if (id == 0)
@ -123,7 +124,7 @@ static struct spa_pod *sdl_build_formats(SDL_RendererInfo *info, struct spa_pod_
if (id != SPA_VIDEO_FORMAT_UNKNOWN)
spa_pod_builder_id(b, id);
}
spa_pod_builder_pop(b);
spa_pod_builder_pop(b, &f[1]);
spa_pod_builder_add(b,
SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle(
&SPA_RECTANGLE(WIDTH, HEIGHT),
@ -135,5 +136,5 @@ static struct spa_pod *sdl_build_formats(SDL_RendererInfo *info, struct spa_pod_
&SPA_FRACTION(0,1),
&SPA_FRACTION(30,1)),
0);
return spa_pod_builder_pop(b);
return spa_pod_builder_pop(b, &f[0]);
}

View File

@ -362,6 +362,7 @@ handle_video_fields (ConvertData *d)
const GValue *value, *value2;
int i;
struct spa_pod_choice *choice;
struct spa_pod_frame f;
value = gst_structure_get_value (d->cs, "format");
if (value) {
@ -370,14 +371,14 @@ handle_video_fields (ConvertData *d)
for (i = 0; (v = get_nth_string (value, i)); i++) {
if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_format, 0);
spa_pod_builder_push_choice(&d->b, get_range_type (value), 0);
spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0);
}
idx = gst_video_format_from_string (v);
if (idx < (int)SPA_N_ELEMENTS (video_format_map))
spa_pod_builder_id (&d->b, video_format_map[idx]);
}
choice = spa_pod_builder_pop(&d->b);
choice = spa_pod_builder_pop(&d->b, &f);
if (i <= 1)
choice->body.type = SPA_CHOICE_None;
}
@ -388,12 +389,12 @@ handle_video_fields (ConvertData *d)
for (i = 0; get_nth_rectangle (value, value2, i, &v); i++) {
if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_size, 0);
spa_pod_builder_push_choice(&d->b, get_range_type2 (value, value2), 0);
spa_pod_builder_push_choice(&d->b, &f, get_range_type2 (value, value2), 0);
}
spa_pod_builder_rectangle (&d->b, v.width, v.height);
}
choice = spa_pod_builder_pop(&d->b);
choice = spa_pod_builder_pop(&d->b, &f);
if (i <= 1)
choice->body.type = SPA_CHOICE_None;
}
@ -404,12 +405,12 @@ handle_video_fields (ConvertData *d)
for (i = 0; get_nth_fraction (value, i, &v); i++) {
if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_framerate, 0);
spa_pod_builder_push_choice(&d->b, get_range_type (value), 0);
spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0);
}
spa_pod_builder_fraction (&d->b, v.num, v.denom);
}
choice = spa_pod_builder_pop(&d->b);
choice = spa_pod_builder_pop(&d->b, &f);
if (i <= 1)
choice->body.type = SPA_CHOICE_None;
}
@ -420,12 +421,12 @@ handle_video_fields (ConvertData *d)
for (i = 0; get_nth_fraction (value, i, &v); i++) {
if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_maxFramerate, 0);
spa_pod_builder_push_choice(&d->b, get_range_type (value), 0);
spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0);
}
spa_pod_builder_fraction (&d->b, v.num, v.denom);
}
choice = spa_pod_builder_pop(&d->b);
choice = spa_pod_builder_pop(&d->b, &f);
if (i <= 1)
choice->body.type = SPA_CHOICE_None;
}
@ -437,6 +438,7 @@ handle_audio_fields (ConvertData *d)
{
const GValue *value;
struct spa_pod_choice *choice;
struct spa_pod_frame f;
int i = 0;
value = gst_structure_get_value (d->cs, "format");
@ -446,14 +448,14 @@ handle_audio_fields (ConvertData *d)
for (i = 0; (v = get_nth_string (value, i)); i++) {
if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_format, 0);
spa_pod_builder_push_choice(&d->b, get_range_type (value), 0);
spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0);
}
idx = gst_audio_format_from_string (v);
if (idx < (int)SPA_N_ELEMENTS (audio_format_map))
spa_pod_builder_id (&d->b, audio_format_map[idx]);
}
choice = spa_pod_builder_pop(&d->b);
choice = spa_pod_builder_pop(&d->b, &f);
if (i <= 1)
choice->body.type = SPA_CHOICE_None;
}
@ -474,12 +476,12 @@ handle_audio_fields (ConvertData *d)
if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_layout, 0);
spa_pod_builder_push_choice(&d->b, get_range_type (value), 0);
spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0);
}
spa_pod_builder_id (&d->b, layout);
}
choice = spa_pod_builder_pop(&d->b);
choice = spa_pod_builder_pop(&d->b, &f);
if (i <= 1)
choice->body.type = SPA_CHOICE_None;
}
@ -490,12 +492,12 @@ handle_audio_fields (ConvertData *d)
for (i = 0; get_nth_int (value, i, &v); i++) {
if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_rate, 0);
spa_pod_builder_push_choice(&d->b, get_range_type (value), 0);
spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0);
}
spa_pod_builder_int (&d->b, v);
}
choice = spa_pod_builder_pop(&d->b);
choice = spa_pod_builder_pop(&d->b, &f);
if (i <= 1)
choice->body.type = SPA_CHOICE_None;
}
@ -505,42 +507,46 @@ handle_audio_fields (ConvertData *d)
for (i = 0; get_nth_int (value, i, &v); i++) {
if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_channels, 0);
spa_pod_builder_push_choice(&d->b, get_range_type (value), 0);
spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0);
}
spa_pod_builder_int (&d->b, v);
}
choice = spa_pod_builder_pop(&d->b);
choice = spa_pod_builder_pop(&d->b, &f);
if (i <= 1)
choice->body.type = SPA_CHOICE_None;
}
return TRUE;
}
static uint32_t
write_pod (struct spa_pod_builder *b, const void *data, uint32_t size)
static int
builder_overflow (void *event_data, uint32_t size)
{
uint32_t ref = b->state.offset;
if (b->size <= ref) {
b->size = SPA_ROUND_UP_N (ref + size, 512);
b->data = realloc (b->data, b->size);
if (b->data == NULL)
return -1;
}
memcpy (SPA_MEMBER(b->data, ref, void), data, size);
return ref;
struct spa_pod_builder *b = event_data;
b->size = SPA_ROUND_UP_N (size, 512);
b->data = realloc (b->data, b->size);
if (b->data == NULL)
return -ENOMEM;
return 0;
}
static const struct spa_pod_builder_callbacks builder_callbacks = {
SPA_VERSION_POD_BUILDER_CALLBACKS,
.overflow = builder_overflow
};
static struct spa_pod *
convert_1 (ConvertData *d)
{
struct spa_pod_frame f;
if (!(d->type = find_media_types (gst_structure_get_name (d->cs))))
return NULL;
d->b.write = write_pod;
d->b.callbacks = &builder_callbacks;
d->b.callbacks_data = &d->b;
spa_pod_builder_push_object (&d->b, SPA_TYPE_OBJECT_Format, d->id);
spa_pod_builder_push_object (&d->b, &f, SPA_TYPE_OBJECT_Format, d->id);
spa_pod_builder_prop (&d->b, SPA_FORMAT_mediaType, 0);
spa_pod_builder_id(&d->b, d->type->media_type);
@ -553,7 +559,7 @@ convert_1 (ConvertData *d)
else if (d->type->media_type == SPA_MEDIA_TYPE_audio)
handle_audio_fields (d);
spa_pod_builder_pop (&d->b);
spa_pod_builder_pop (&d->b, &f);
return SPA_MEMBER (d->b.data, 0, struct spa_pod);
}
@ -628,7 +634,7 @@ static const char *audio_id_to_string(uint32_t id)
}
static void
handle_id_prop (struct spa_pod_prop *prop, const char *key, id_to_string_func func, GstCaps *res)
handle_id_prop (const struct spa_pod_prop *prop, const char *key, id_to_string_func func, GstCaps *res)
{
const char * str;
struct spa_pod *val;
@ -670,7 +676,7 @@ handle_id_prop (struct spa_pod_prop *prop, const char *key, id_to_string_func fu
}
static void
handle_int_prop (struct spa_pod_prop *prop, const char *key, GstCaps *res)
handle_int_prop (const struct spa_pod_prop *prop, const char *key, GstCaps *res)
{
struct spa_pod *val;
uint32_t *ints;
@ -714,7 +720,7 @@ handle_int_prop (struct spa_pod_prop *prop, const char *key, GstCaps *res)
}
static void
handle_rect_prop (struct spa_pod_prop *prop, const char *width, const char *height, GstCaps *res)
handle_rect_prop (const struct spa_pod_prop *prop, const char *width, const char *height, GstCaps *res)
{
struct spa_pod *val;
struct spa_rectangle *rect;
@ -767,7 +773,7 @@ handle_rect_prop (struct spa_pod_prop *prop, const char *width, const char *heig
}
static void
handle_fraction_prop (struct spa_pod_prop *prop, const char *key, GstCaps *res)
handle_fraction_prop (const struct spa_pod_prop *prop, const char *key, GstCaps *res)
{
struct spa_pod *val;
struct spa_fraction *fract;
@ -815,7 +821,7 @@ gst_caps_from_format (const struct spa_pod *format)
{
GstCaps *res = NULL;
uint32_t media_type, media_subtype;
struct spa_pod_prop *prop;
const struct spa_pod_prop *prop = NULL;
const struct spa_pod_object *obj = (const struct spa_pod_object *) format;
if (spa_format_parse(format, &media_type, &media_subtype) < 0)
@ -824,7 +830,7 @@ gst_caps_from_format (const struct spa_pod *format)
if (media_type == SPA_MEDIA_TYPE_video) {
if (media_subtype == SPA_MEDIA_SUBTYPE_raw) {
res = gst_caps_new_empty_simple ("video/x-raw");
if ((prop = spa_pod_object_find_prop (obj, SPA_FORMAT_VIDEO_format))) {
if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_VIDEO_format))) {
handle_id_prop (prop, "format", video_id_to_string, res);
}
}
@ -837,13 +843,13 @@ gst_caps_from_format (const struct spa_pod *format)
"alignment", G_TYPE_STRING, "au",
NULL);
}
if ((prop = spa_pod_object_find_prop (obj, SPA_FORMAT_VIDEO_size))) {
if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_VIDEO_size))) {
handle_rect_prop (prop, "width", "height", res);
}
if ((prop = spa_pod_object_find_prop (obj, SPA_FORMAT_VIDEO_framerate))) {
if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_VIDEO_framerate))) {
handle_fraction_prop (prop, "framerate", res);
}
if ((prop = spa_pod_object_find_prop (obj, SPA_FORMAT_VIDEO_maxFramerate))) {
if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_VIDEO_maxFramerate))) {
handle_fraction_prop (prop, "max-framerate", res);
}
} else if (media_type == SPA_MEDIA_TYPE_audio) {
@ -851,13 +857,13 @@ gst_caps_from_format (const struct spa_pod *format)
res = gst_caps_new_simple ("audio/x-raw",
"layout", G_TYPE_STRING, "interleaved",
NULL);
if ((prop = spa_pod_object_find_prop (obj, SPA_FORMAT_AUDIO_format))) {
if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_AUDIO_format))) {
handle_id_prop (prop, "format", audio_id_to_string, res);
}
if ((prop = spa_pod_object_find_prop (obj, SPA_FORMAT_AUDIO_rate))) {
if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_AUDIO_rate))) {
handle_int_prop (prop, "rate", res);
}
if ((prop = spa_pod_object_find_prop (obj, SPA_FORMAT_AUDIO_channels))) {
if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_AUDIO_channels))) {
handle_int_prop (prop, "channels", res);
}
}

View File

@ -230,12 +230,13 @@ pool_activated (GstPipeWirePool *pool, GstPipeWireSink *sink)
const struct spa_pod *port_params[2];
struct spa_pod_builder b = { NULL };
uint8_t buffer[1024];
struct spa_pod_frame f;
config = gst_buffer_pool_get_config (GST_BUFFER_POOL (pool));
gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers);
spa_pod_builder_init (&b, buffer, sizeof (buffer));
spa_pod_builder_push_object (&b, SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers);
spa_pod_builder_push_object (&b, &f, SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers);
if (size == 0)
spa_pod_builder_add (&b,
SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int(0, 0, INT32_MAX),
@ -251,7 +252,7 @@ pool_activated (GstPipeWirePool *pool, GstPipeWireSink *sink)
max_buffers ? max_buffers : INT32_MAX),
SPA_PARAM_BUFFERS_align, SPA_POD_Int(16),
0);
port_params[0] = spa_pod_builder_pop (&b);
port_params[0] = spa_pod_builder_pop (&b, &f);
port_params[1] = spa_pod_builder_add_object (&b,
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,

View File

@ -58,12 +58,13 @@ client_node_marshal_update(void *object,
{
struct pw_proxy *proxy = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
uint32_t i, n_items;
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_NODE_PROXY_METHOD_UPDATE);
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
"[",
SPA_POD_Int(change_mask),
SPA_POD_Int(max_input_ports),
SPA_POD_Int(max_output_ports),
@ -80,7 +81,7 @@ client_node_marshal_update(void *object,
SPA_POD_String(props->items[i].key),
SPA_POD_String(props->items[i].value), NULL);
}
spa_pod_builder_add(b, "]", NULL);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_proxy(proxy, b);
}
@ -96,12 +97,13 @@ client_node_marshal_port_update(void *object,
{
struct pw_proxy *proxy = object;
struct spa_pod_builder *b;
struct spa_pod_frame f[2];
uint32_t i, n_items;
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_NODE_PROXY_METHOD_PORT_UPDATE);
spa_pod_builder_push_struct(b, &f[0]);
spa_pod_builder_add(b,
"[",
SPA_POD_Int(direction),
SPA_POD_Int(port_id),
SPA_POD_Int(change_mask),
@ -114,8 +116,8 @@ client_node_marshal_port_update(void *object,
if (info) {
n_items = info->props ? info->props->n_items : 0;
spa_pod_builder_push_struct(b, &f[1]);
spa_pod_builder_add(b,
"[",
SPA_POD_Int(info->flags),
SPA_POD_Int(info->rate),
SPA_POD_Int(n_items), NULL);
@ -124,13 +126,12 @@ client_node_marshal_port_update(void *object,
SPA_POD_String(info->props->items[i].key),
SPA_POD_String(info->props->items[i].value), NULL);
}
spa_pod_builder_add(b,
"]", NULL);
spa_pod_builder_pop(b, &f[1]);
} else {
spa_pod_builder_add(b,
SPA_POD_Pod(NULL), NULL);
}
spa_pod_builder_add(b, "]", NULL);
spa_pod_builder_pop(b, &f[0]);
pw_protocol_native_end_proxy(proxy, b);
}
@ -168,7 +169,7 @@ static int client_node_demarshal_add_mem(void *object, void *data, size_t size)
uint32_t mem_id, type, memfd_idx, flags;
int memfd;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&mem_id),
SPA_POD_Id(&type),
@ -192,7 +193,7 @@ static int client_node_demarshal_transport(void *object, void *data, size_t size
uint32_t node_id, ridx, widx;
int readfd, writefd;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&node_id),
SPA_POD_Int(&ridx),
@ -217,7 +218,7 @@ static int client_node_demarshal_set_param(void *object, void *data, size_t size
uint32_t seq, id, flags;
const struct spa_pod *param = NULL;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq),
SPA_POD_Id(&id),
@ -235,7 +236,7 @@ static int client_node_demarshal_event_event(void *object, void *data, size_t si
struct spa_pod_parser prs;
const struct spa_event *event;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_PodObject(&event)) < 0)
return -EINVAL;
@ -251,7 +252,7 @@ static int client_node_demarshal_command(void *object, void *data, size_t size)
const struct spa_command *command;
uint32_t seq;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq),
SPA_POD_PodObject(&command)) < 0)
@ -267,7 +268,7 @@ static int client_node_demarshal_add_port(void *object, void *data, size_t size)
struct spa_pod_parser prs;
int32_t seq, direction, port_id;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq),
SPA_POD_Int(&direction),
@ -284,7 +285,7 @@ static int client_node_demarshal_remove_port(void *object, void *data, size_t si
struct spa_pod_parser prs;
int32_t seq, direction, port_id;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq),
SPA_POD_Int(&direction),
@ -302,7 +303,7 @@ static int client_node_demarshal_port_set_param(void *object, void *data, size_t
uint32_t seq, direction, port_id, id, flags;
const struct spa_pod *param = NULL;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq),
SPA_POD_Int(&direction),
@ -321,13 +322,14 @@ static int client_node_demarshal_port_use_buffers(void *object, void *data, size
{
struct pw_proxy *proxy = object;
struct spa_pod_parser prs;
struct spa_pod_frame f;
uint32_t seq, direction, port_id, mix_id, n_buffers, data_id;
struct pw_client_node_buffer *buffers;
uint32_t i, j;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&seq),
SPA_POD_Int(&direction),
SPA_POD_Int(&port_id),
@ -389,7 +391,7 @@ static int client_node_demarshal_port_command(void *object, void *data, size_t s
const struct spa_command *command;
uint32_t direction, port_id;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&direction),
SPA_POD_Int(&port_id),
@ -408,7 +410,7 @@ static int client_node_demarshal_port_set_io(void *object, void *data, size_t si
struct spa_pod_parser prs;
uint32_t seq, direction, port_id, mix_id, id, memid, off, sz;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq),
SPA_POD_Int(&direction),
@ -434,7 +436,7 @@ static int client_node_demarshal_set_io(void *object, void *data, size_t size)
struct spa_pod_parser prs;
uint32_t id, memid, off, sz;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id),
SPA_POD_Int(&memid),
@ -597,12 +599,13 @@ client_node_marshal_port_use_buffers(void *object,
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
uint32_t i, j;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_PROXY_EVENT_PORT_USE_BUFFERS);
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
"[",
SPA_POD_Int(seq),
SPA_POD_Int(direction),
SPA_POD_Int(port_id),
@ -636,7 +639,7 @@ client_node_marshal_port_use_buffers(void *object,
SPA_POD_Int(d->maxsize), NULL);
}
}
spa_pod_builder_add(b, "]", NULL);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_resource(resource, b);
}
@ -714,7 +717,7 @@ static int client_node_demarshal_done(void *object, void *data, size_t size)
struct spa_pod_parser prs;
uint32_t seq, res;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq),
SPA_POD_Int(&res)) < 0)
@ -728,14 +731,15 @@ static int client_node_demarshal_update(void *object, void *data, size_t size)
{
struct pw_resource *resource = object;
struct spa_pod_parser prs;
struct spa_pod_frame f;
uint32_t change_mask, max_input_ports, max_output_ports, n_params;
const struct spa_pod **params;
struct spa_dict props;
uint32_t i;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&change_mask),
SPA_POD_Int(&max_input_ports),
SPA_POD_Int(&max_output_ports),
@ -774,15 +778,16 @@ static int client_node_demarshal_port_update(void *object, void *data, size_t si
{
struct pw_resource *resource = object;
struct spa_pod_parser prs;
struct spa_pod_frame f;
uint32_t i, direction, port_id, change_mask, n_params;
const struct spa_pod **params = NULL;
struct spa_port_info info = { 0 }, *infop = NULL;
struct spa_pod *ipod;
struct spa_dict props;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&direction),
SPA_POD_Int(&port_id),
SPA_POD_Int(&change_mask),
@ -801,11 +806,12 @@ static int client_node_demarshal_port_update(void *object, void *data, size_t si
if (ipod) {
struct spa_pod_parser p2;
struct spa_pod_frame f2;
infop = &info;
spa_pod_parser_pod(&p2, ipod);
if (spa_pod_parser_get(&p2,
"["
if (spa_pod_parser_push_struct(&p2, &f2) < 0 ||
spa_pod_parser_get(&p2,
SPA_POD_Int(&info.flags),
SPA_POD_Int(&info.rate),
SPA_POD_Int(&props.n_items), NULL) < 0)
@ -838,7 +844,7 @@ static int client_node_demarshal_set_active(void *object, void *data, size_t siz
struct spa_pod_parser prs;
int active;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Bool(&active)) < 0)
return -EINVAL;
@ -853,7 +859,7 @@ static int client_node_demarshal_event_method(void *object, void *data, size_t s
struct spa_pod_parser prs;
struct spa_event *event;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_PodObject(&event)) < 0)
return -EINVAL;

View File

@ -352,20 +352,22 @@ 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, const void *data, uint32_t size)
static int builder_overflow(void *callbacks_data, uint32_t size)
{
struct impl *impl = SPA_CONTAINER_OF(b, struct impl, builder);
uint32_t ref = b->state.offset;
struct impl *impl = callbacks_data;
struct spa_pod_builder *b = &impl->builder;
if (b->size <= ref) {
b->size = SPA_ROUND_UP_N(ref + size, 4096);
b->data = begin_write(&impl->this, b->size);
}
memcpy(SPA_MEMBER(b->data, ref, void), data, size);
return ref;
b->size = SPA_ROUND_UP_N(size, 4096);
if ((b->data = begin_write(&impl->this, b->size)) == NULL)
return -ENOMEM;
return 0;
}
static const struct spa_pod_builder_callbacks builder_callbacks = {
SPA_VERSION_POD_BUILDER_CALLBACKS,
.overflow = builder_overflow
};
struct spa_pod_builder *
pw_protocol_native_connection_begin_resource(struct pw_protocol_native_connection *conn,
struct pw_resource *resource,
@ -375,8 +377,9 @@ pw_protocol_native_connection_begin_resource(struct pw_protocol_native_connectio
impl->dest_id = resource->id;
impl->opcode = opcode;
impl->builder = (struct spa_pod_builder) { NULL, 0, 0, write_pod };
impl->builder = SPA_POD_BUILDER_INIT(NULL, 0);
impl->builder.callbacks = &builder_callbacks;
impl->builder.callbacks_data = impl;
return &impl->builder;
}
@ -389,8 +392,9 @@ pw_protocol_native_connection_begin_proxy(struct pw_protocol_native_connection *
impl->dest_id = proxy->id;
impl->opcode = opcode;
impl->builder = (struct spa_pod_builder) { NULL, 0, 0, write_pod, };
impl->builder = SPA_POD_BUILDER_INIT(NULL, 0);
impl->builder.callbacks = &builder_callbacks;
impl->builder.callbacks_data = impl;
return &impl->builder;
}

View File

@ -72,6 +72,22 @@ static void core_marshal_get_registry(void *object, uint32_t version, uint32_t n
pw_protocol_native_end_proxy(proxy, b);
}
static void push_dict(struct spa_pod_builder *b, 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_push_struct(b, &f);
spa_pod_builder_int(b, n_items);
for (i = 0; i < n_items; i++) {
spa_pod_builder_string(b, dict->items[i].key);
spa_pod_builder_string(b, dict->items[i].value);
}
spa_pod_builder_pop(b, &f);
}
static void
core_marshal_create_object(void *object,
const char *factory_name,
@ -80,29 +96,19 @@ core_marshal_create_object(void *object,
{
struct pw_proxy *proxy = object;
struct spa_pod_builder *b;
uint32_t i, n_items;
struct spa_pod_frame f;
b = pw_protocol_native_begin_proxy(proxy, PW_CORE_PROXY_METHOD_CREATE_OBJECT);
n_items = props ? props->n_items : 0;
spa_pod_builder_add(b, "["
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
SPA_POD_String(factory_name),
SPA_POD_Id(type),
SPA_POD_Int(version),
SPA_POD_Int(n_items),
NULL);
for (i = 0; i < n_items; i++) {
spa_pod_builder_add(b,
SPA_POD_String(props->items[i].key),
SPA_POD_String(props->items[i].value),
NULL);
}
spa_pod_builder_add(b,
SPA_POD_Int(new_id),
"]",
NULL);
push_dict(b, props);
spa_pod_builder_int(b, new_id);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_proxy(proxy, b);
}
@ -125,20 +131,27 @@ static int core_demarshal_info(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_dict props;
struct spa_pod_frame f[2];
struct pw_core_info info;
struct spa_pod_parser prs;
uint32_t i;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0)
return -EINVAL;
if (spa_pod_parser_get(&prs,
"["
SPA_POD_Int(&info.id),
SPA_POD_Long(&info.change_mask),
SPA_POD_String(&info.user_name),
SPA_POD_String(&info.host_name),
SPA_POD_String(&info.version),
SPA_POD_String(&info.name),
SPA_POD_Int(&info.cookie),
SPA_POD_Int(&info.cookie), NULL) < 0)
return -EINVAL;
if (spa_pod_parser_push_struct(&prs, &f[1]) < 0)
return -EINVAL;
if (spa_pod_parser_get(&prs,
SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL;
@ -161,7 +174,7 @@ static int core_demarshal_done(void *object, void *data, size_t size)
struct spa_pod_parser prs;
uint32_t seq;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq)) < 0)
return -EINVAL;
@ -177,7 +190,7 @@ static int core_demarshal_error(void *object, void *data, size_t size)
uint32_t id, res;
const char *error;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&id),
SPA_POD_Int(&res),
@ -194,7 +207,7 @@ static int core_demarshal_remove_id(void *object, void *data, size_t size)
struct spa_pod_parser prs;
uint32_t id;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&id)) < 0)
return -EINVAL;
@ -206,14 +219,12 @@ static void core_marshal_info(void *object, const struct pw_core_info *info)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
uint32_t i, n_items;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_CORE_PROXY_EVENT_INFO);
n_items = info->props ? info->props->n_items : 0;
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
"[",
SPA_POD_Int(info->id),
SPA_POD_Long(info->change_mask),
SPA_POD_String(info->user_name),
@ -221,16 +232,9 @@ static void core_marshal_info(void *object, const struct pw_core_info *info)
SPA_POD_String(info->version),
SPA_POD_String(info->name),
SPA_POD_Int(info->cookie),
SPA_POD_Int(n_items),
NULL);
for (i = 0; i < n_items; i++) {
spa_pod_builder_add(b,
SPA_POD_String(info->props->items[i].key),
SPA_POD_String(info->props->items[i].value),
NULL);
}
spa_pod_builder_add(b, "]", NULL);
push_dict(b, info->props);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_resource(resource, b);
}
@ -288,7 +292,7 @@ static int core_demarshal_hello(void *object, void *data, size_t size)
struct spa_pod_parser prs;
uint32_t version;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&version)) < 0)
return -EINVAL;
@ -303,7 +307,7 @@ static int core_demarshal_sync(void *object, void *data, size_t size)
struct spa_pod_parser prs;
uint32_t seq;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq)) < 0)
return -EINVAL;
@ -318,7 +322,7 @@ static int core_demarshal_get_registry(void *object, void *data, size_t size)
struct spa_pod_parser prs;
int32_t version, new_id;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&version),
SPA_POD_Int(&new_id)) < 0)
@ -332,16 +336,22 @@ static int core_demarshal_create_object(void *object, void *data, size_t size)
{
struct pw_resource *resource = object;
struct spa_pod_parser prs;
struct spa_pod_frame f[2];
uint32_t version, type, new_id, i;
const char *factory_name;
struct spa_dict props;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_String(&factory_name),
SPA_POD_Id(&type),
SPA_POD_Int(&version),
NULL) < 0)
return -EINVAL;
if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL;
@ -352,6 +362,8 @@ static int core_demarshal_create_object(void *object, void *data, size_t size)
SPA_POD_String(&props.items[i].value), NULL) < 0)
return -EINVAL;
}
spa_pod_parser_pop(&prs, &f[1]);
if (spa_pod_parser_get(&prs,
SPA_POD_Int(&new_id), NULL) < 0)
return -EINVAL;
@ -368,7 +380,7 @@ static int core_demarshal_destroy(void *object, void *data, size_t size)
struct spa_pod_parser prs;
uint32_t id;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&id)) < 0)
return -EINVAL;
@ -382,27 +394,20 @@ static void registry_marshal_global(void *object, uint32_t id, uint32_t parent_i
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
uint32_t i, n_items;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_REGISTRY_PROXY_EVENT_GLOBAL);
n_items = props ? props->n_items : 0;
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
"[",
SPA_POD_Int(id),
SPA_POD_Int(parent_id),
SPA_POD_Int(permissions),
SPA_POD_Id(type),
SPA_POD_Int(version),
SPA_POD_Int(n_items), NULL);
for (i = 0; i < n_items; i++) {
spa_pod_builder_add(b,
SPA_POD_String(props->items[i].key),
SPA_POD_String(props->items[i].value), NULL);
}
spa_pod_builder_add(b, "]", NULL);
NULL);
push_dict(b, props);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_resource(resource, b);
}
@ -425,7 +430,7 @@ static int registry_demarshal_bind(void *object, void *data, size_t size)
struct spa_pod_parser prs;
uint32_t id, version, type, new_id;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&id),
SPA_POD_Id(&type),
@ -443,7 +448,7 @@ static int registry_demarshal_destroy(void *object, void *data, size_t size)
struct spa_pod_parser prs;
uint32_t id;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&id)) < 0)
return -EINVAL;
@ -456,27 +461,20 @@ static void module_marshal_info(void *object, const struct pw_module_info *info)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
uint32_t i, n_items;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_MODULE_PROXY_EVENT_INFO);
n_items = info->props ? info->props->n_items : 0;
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
"[",
SPA_POD_Int(info->id),
SPA_POD_Long(info->change_mask),
SPA_POD_String(info->name),
SPA_POD_String(info->filename),
SPA_POD_String(info->args),
SPA_POD_Int(n_items), NULL);
for (i = 0; i < n_items; i++) {
spa_pod_builder_add(b,
SPA_POD_String(info->props->items[i].key),
SPA_POD_String(info->props->items[i].value), NULL);
}
spa_pod_builder_add(b, "]", NULL);
NULL);
push_dict(b, info->props);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_resource(resource, b);
}
@ -485,18 +483,23 @@ static int module_demarshal_info(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_parser prs;
struct spa_pod_frame f[2];
struct spa_dict props;
struct pw_module_info info;
uint32_t i;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&info.id),
SPA_POD_Long(&info.change_mask),
SPA_POD_String(&info.name),
SPA_POD_String(&info.filename),
SPA_POD_String(&info.args),
SPA_POD_String(&info.args), NULL) < 0)
return -EINVAL;
if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL;
@ -516,25 +519,18 @@ static void device_marshal_info(void *object, const struct pw_device_info *info)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
uint32_t i, n_items;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_DEVICE_PROXY_EVENT_INFO);
n_items = info->props ? info->props->n_items : 0;
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
"[",
SPA_POD_Int(info->id),
SPA_POD_String(info->name),
SPA_POD_Long(info->change_mask),
SPA_POD_Int(n_items), NULL);
for (i = 0; i < n_items; i++) {
spa_pod_builder_add(b,
SPA_POD_String(info->props->items[i].key),
SPA_POD_String(info->props->items[i].value), NULL);
}
spa_pod_builder_add(b, "]", NULL);
NULL);
push_dict(b, info->props);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_resource(resource, b);
}
@ -543,16 +539,21 @@ static int device_demarshal_info(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_parser prs;
struct spa_pod_frame f[2];
struct spa_dict props;
struct pw_device_info info;
uint32_t i;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&info.id),
SPA_POD_String(&info.name),
SPA_POD_Long(&info.change_mask),
SPA_POD_Long(&info.change_mask), NULL) < 0)
return -EINVAL;
if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL;
@ -592,7 +593,7 @@ static int device_demarshal_param(void *object, void *data, size_t size)
uint32_t id, index, next;
struct spa_pod *param;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id),
SPA_POD_Int(&index),
@ -628,7 +629,7 @@ static int device_demarshal_enum_params(void *object, void *data, size_t size)
uint32_t id, index, num;
struct spa_pod *filter;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id),
SPA_POD_Int(&index),
@ -662,7 +663,7 @@ static int device_demarshal_set_param(void *object, void *data, size_t size)
uint32_t id, flags;
struct spa_pod *param;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id),
SPA_POD_Int(&flags),
@ -677,27 +678,20 @@ static void factory_marshal_info(void *object, const struct pw_factory_info *inf
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
uint32_t i, n_items;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_FACTORY_PROXY_EVENT_INFO);
n_items = info->props ? info->props->n_items : 0;
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
"[",
SPA_POD_Int(info->id),
SPA_POD_Long(info->change_mask),
SPA_POD_String(info->name),
SPA_POD_Id(info->type),
SPA_POD_Int(info->version),
SPA_POD_Int(n_items), NULL);
for (i = 0; i < n_items; i++) {
spa_pod_builder_add(b,
SPA_POD_String(info->props->items[i].key),
SPA_POD_String(info->props->items[i].value), NULL);
}
spa_pod_builder_add(b, "]", NULL);
NULL);
push_dict(b, info->props);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_resource(resource, b);
}
@ -706,18 +700,23 @@ static int factory_demarshal_info(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_parser prs;
struct spa_pod_frame f[2];
struct spa_dict props;
struct pw_factory_info info;
uint32_t i;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&info.id),
SPA_POD_Long(&info.change_mask),
SPA_POD_String(&info.name),
SPA_POD_Id(&info.type),
SPA_POD_Int(&info.version),
SPA_POD_Int(&info.version), NULL) < 0)
return -EINVAL;
if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL;
@ -737,14 +736,12 @@ static void node_marshal_info(void *object, const struct pw_node_info *info)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
uint32_t i, n_items;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_NODE_PROXY_EVENT_INFO);
n_items = info->props ? info->props->n_items : 0;
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
"[",
SPA_POD_Int(info->id),
SPA_POD_Long(info->change_mask),
SPA_POD_String(info->name),
@ -754,14 +751,9 @@ static void node_marshal_info(void *object, const struct pw_node_info *info)
SPA_POD_Int(info->n_output_ports),
SPA_POD_Id(info->state),
SPA_POD_String(info->error),
SPA_POD_Int(n_items), NULL);
for (i = 0; i < n_items; i++) {
spa_pod_builder_add(b,
SPA_POD_String(info->props->items[i].key),
SPA_POD_String(info->props->items[i].value), NULL);
}
spa_pod_builder_add(b, "]", NULL);
NULL);
push_dict(b, info->props);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_resource(resource, b);
}
@ -770,13 +762,14 @@ static int node_demarshal_info(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_parser prs;
struct spa_pod_frame f[2];
struct spa_dict props;
struct pw_node_info info;
uint32_t i;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&info.id),
SPA_POD_Long(&info.change_mask),
SPA_POD_String(&info.name),
@ -785,7 +778,11 @@ static int node_demarshal_info(void *object, void *data, size_t size)
SPA_POD_Int(&info.max_output_ports),
SPA_POD_Int(&info.n_output_ports),
SPA_POD_Id(&info.state),
SPA_POD_String(&info.error),
SPA_POD_String(&info.error), NULL) < 0)
return -EINVAL;
if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL;
@ -825,7 +822,7 @@ static int node_demarshal_param(void *object, void *data, size_t size)
uint32_t id, index, next;
struct spa_pod *param;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id),
SPA_POD_Int(&index),
@ -861,7 +858,7 @@ static int node_demarshal_enum_params(void *object, void *data, size_t size)
uint32_t id, index, num;
struct spa_pod *filter;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id),
SPA_POD_Int(&index),
@ -895,7 +892,7 @@ static int node_demarshal_set_param(void *object, void *data, size_t size)
uint32_t id, flags;
struct spa_pod *param;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id),
SPA_POD_Int(&flags),
@ -923,7 +920,7 @@ static int node_demarshal_send_command(void *object, void *data, size_t size)
struct spa_pod_parser prs;
struct spa_command *command;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Pod(&command)) < 0)
return -EINVAL;
@ -936,25 +933,18 @@ static void port_marshal_info(void *object, const struct pw_port_info *info)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
uint32_t i, n_items;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_PORT_PROXY_EVENT_INFO);
n_items = info->props ? info->props->n_items : 0;
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
"[",
SPA_POD_Int(info->id),
SPA_POD_Int(info->direction),
SPA_POD_Long(info->change_mask),
SPA_POD_Int(n_items), NULL);
for (i = 0; i < n_items; i++) {
spa_pod_builder_add(b,
SPA_POD_String(info->props->items[i].key),
SPA_POD_String(info->props->items[i].value), NULL);
}
spa_pod_builder_add(b, "]", NULL);
NULL);
push_dict(b, info->props);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_resource(resource, b);
}
@ -963,16 +953,21 @@ static int port_demarshal_info(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_parser prs;
struct spa_pod_frame f[2];
struct spa_dict props;
struct pw_port_info info;
uint32_t i;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&info.id),
SPA_POD_Int(&info.direction),
SPA_POD_Long(&info.change_mask),
SPA_POD_Long(&info.change_mask), NULL) < 0)
return -EINVAL;
if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL;
@ -1012,7 +1007,7 @@ static int port_demarshal_param(void *object, void *data, size_t size)
uint32_t id, index, next;
struct spa_pod *param;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id),
SPA_POD_Int(&index),
@ -1048,7 +1043,7 @@ static int port_demarshal_enum_params(void *object, void *data, size_t size)
uint32_t id, index, num;
struct spa_pod *filter;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id),
SPA_POD_Int(&index),
@ -1064,24 +1059,17 @@ static void client_marshal_info(void *object, const struct pw_client_info *info)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
uint32_t i, n_items;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_PROXY_EVENT_INFO);
n_items = info->props ? info->props->n_items : 0;
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
"[",
SPA_POD_Int(info->id),
SPA_POD_Long(info->change_mask),
SPA_POD_Int(n_items), NULL);
for (i = 0; i < n_items; i++) {
spa_pod_builder_add(b,
SPA_POD_String(info->props->items[i].key),
SPA_POD_String(info->props->items[i].value), NULL);
}
spa_pod_builder_add(b, "]", NULL);
NULL);
push_dict(b, info->props);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_resource(resource, b);
}
@ -1090,15 +1078,20 @@ static int client_demarshal_info(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_parser prs;
struct spa_pod_frame f[2];
struct spa_dict props;
struct pw_client_info info;
uint32_t i;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&info.id),
SPA_POD_Long(&info.change_mask),
SPA_POD_Long(&info.change_mask), NULL) < 0)
return -EINVAL;
if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL;
@ -1119,6 +1112,7 @@ static void client_marshal_permissions(void *object, uint32_t index, uint32_t n_
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
struct spa_pod_frame f[2];
uint32_t i, n = 0;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_PROXY_EVENT_PERMISSIONS);
@ -1128,19 +1122,19 @@ static void client_marshal_permissions(void *object, uint32_t index, uint32_t n_
n++;
}
spa_pod_builder_add(b,
"[",
SPA_POD_Int(index),
SPA_POD_Int(n), NULL);
spa_pod_builder_push_struct(b, &f[0]);
spa_pod_builder_int(b, index);
spa_pod_builder_push_struct(b, &f[1]);
spa_pod_builder_int(b, n);
for (i = 0; i < n_permissions; i++) {
if (permissions[i].permissions == SPA_ID_INVALID)
continue;
spa_pod_builder_add(b,
SPA_POD_Int(permissions[i].id),
SPA_POD_Int(permissions[i].permissions), NULL);
spa_pod_builder_int(b, permissions[i].id);
spa_pod_builder_int(b, permissions[i].permissions);
}
spa_pod_builder_add(b, "]", NULL);
spa_pod_builder_pop(b, &f[1]);
spa_pod_builder_pop(b, &f[0]);
pw_protocol_native_end_resource(resource, b);
}
@ -1150,12 +1144,18 @@ static int client_demarshal_permissions(void *object, void *data, size_t size)
struct pw_proxy *proxy = object;
struct pw_permission *permissions;
struct spa_pod_parser prs;
struct spa_pod_frame f[2];
uint32_t i, index, n_permissions;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs, "[",
SPA_POD_Int(&index),
SPA_POD_Int(&n_permissions), NULL) < 0)
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&index), NULL) < 0)
return -EINVAL;
if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&n_permissions), NULL) < 0)
return -EINVAL;
permissions = alloca(n_permissions * sizeof(struct pw_permission));
@ -1189,7 +1189,7 @@ static int client_demarshal_error(void *object, void *data, size_t size)
uint32_t id, res;
const char *error;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&id),
SPA_POD_Int(&res),
@ -1218,21 +1218,13 @@ static void client_marshal_update_properties(void *object, const struct spa_dict
{
struct pw_proxy *proxy = object;
struct spa_pod_builder *b;
uint32_t i, n_items;
struct spa_pod_frame f;
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_PROXY_METHOD_UPDATE_PROPERTIES);
n_items = props ? props->n_items : 0;
spa_pod_builder_add(b, "[",
SPA_POD_Int(n_items), NULL);
for (i = 0; i < n_items; i++) {
spa_pod_builder_add(b,
SPA_POD_String(props->items[i].key),
SPA_POD_String(props->items[i].value), NULL);
}
spa_pod_builder_add(b, "]", NULL);
spa_pod_builder_push_struct(b, &f);
push_dict(b, props);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_proxy(proxy, b);
}
@ -1242,12 +1234,14 @@ static int client_demarshal_update_properties(void *object, void *data, size_t s
struct pw_resource *resource = object;
struct spa_dict props;
struct spa_pod_parser prs;
struct spa_pod_frame f[2];
uint32_t i;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"[",
SPA_POD_Int(&props.n_items), NULL) < 0)
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL;
props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
@ -1268,7 +1262,7 @@ static int client_demarshal_get_permissions(void *object, void *data, size_t siz
struct spa_pod_parser prs;
uint32_t index, num;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&index),
SPA_POD_Int(&num)) < 0)
@ -1283,19 +1277,18 @@ static void client_marshal_update_permissions(void *object, uint32_t n_permissio
{
struct pw_proxy *proxy = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
uint32_t i;
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_PROXY_METHOD_UPDATE_PERMISSIONS);
spa_pod_builder_add(b, "[",
SPA_POD_Int(n_permissions), NULL);
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_int(b, n_permissions);
for (i = 0; i < n_permissions; i++) {
spa_pod_builder_add(b,
SPA_POD_Int(permissions[i].id),
SPA_POD_Int(permissions[i].permissions), NULL);
spa_pod_builder_int(b, permissions[i].id);
spa_pod_builder_int(b, permissions[i].permissions);
}
spa_pod_builder_add(b, "]", NULL);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_proxy(proxy, b);
}
@ -1305,11 +1298,12 @@ static int client_demarshal_update_permissions(void *object, void *data, size_t
struct pw_resource *resource = object;
struct pw_permission *permissions;
struct spa_pod_parser prs;
struct spa_pod_frame f[1];
uint32_t i, n_permissions;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"[",
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&n_permissions), NULL) < 0)
return -EINVAL;
@ -1329,14 +1323,12 @@ static void link_marshal_info(void *object, const struct pw_link_info *info)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
uint32_t i, n_items;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_LINK_PROXY_EVENT_INFO);
n_items = info->props ? info->props->n_items : 0;
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
"[",
SPA_POD_Int(info->id),
SPA_POD_Long(info->change_mask),
SPA_POD_Int(info->output_node_id),
@ -1346,14 +1338,9 @@ static void link_marshal_info(void *object, const struct pw_link_info *info)
SPA_POD_Int(info->state),
SPA_POD_String(info->error),
SPA_POD_Pod(info->format),
SPA_POD_Int(n_items), NULL);
for (i = 0; i < n_items; i++) {
spa_pod_builder_add(b,
SPA_POD_String(info->props->items[i].key),
SPA_POD_String(info->props->items[i].value), NULL);
}
spa_pod_builder_add(b, "]", NULL);
NULL);
push_dict(b, info->props);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_resource(resource, b);
}
@ -1362,13 +1349,14 @@ static int link_demarshal_info(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_parser prs;
struct spa_pod_frame f[2];
struct spa_dict props;
struct pw_link_info info = { 0, };
uint32_t i;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&info.id),
SPA_POD_Long(&info.change_mask),
SPA_POD_Int(&info.output_node_id),
@ -1377,7 +1365,11 @@ static int link_demarshal_info(void *object, void *data, size_t size)
SPA_POD_Int(&info.input_port_id),
SPA_POD_Int(&info.state),
SPA_POD_String(&info.error),
SPA_POD_Pod(&info.format),
SPA_POD_Pod(&info.format), NULL) < 0)
return -EINVAL;
if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL;
@ -1397,17 +1389,22 @@ static int registry_demarshal_global(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_parser prs;
struct spa_pod_frame f[2];
uint32_t id, parent_id, permissions, type, version, i;
struct spa_dict props;
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&id),
SPA_POD_Int(&parent_id),
SPA_POD_Int(&permissions),
SPA_POD_Id(&type),
SPA_POD_Int(&version),
SPA_POD_Int(&version), NULL) < 0)
return -EINVAL;
if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
spa_pod_parser_get(&prs,
SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL;
@ -1431,7 +1428,7 @@ static int registry_demarshal_global_remove(void *object, void *data, size_t siz
struct spa_pod_parser prs;
uint32_t id;
spa_pod_parser_init(&prs, data, size, 0);
spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&id)) < 0)
return -EINVAL;

View File

@ -102,12 +102,15 @@ static struct monitor_item *add_item(struct pw_spa_monitor *this,
if (info) {
struct spa_pod_parser prs;
struct spa_pod_frame f;
spa_pod_parser_pod(&prs, info);
if (spa_pod_parser_get(&prs, "[", NULL) == 0) {
if (spa_pod_parser_push_struct(&prs, &f) == 0) {
while (true) {
const char *key, *val;
if (spa_pod_parser_get(&prs, "ss", &key, &val, NULL) < 0)
if (spa_pod_parser_get(&prs,
SPA_POD_String(&key),
SPA_POD_String(&val), NULL) < 0)
break;
pw_properties_set(props, key, val);
}

View File

@ -167,6 +167,7 @@ setup_props(struct pw_core *core, struct spa_node *spa_node, struct pw_propertie
uint32_t index = 0;
uint8_t buf[2048];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
const struct spa_pod_prop *prop = NULL;
if ((res = spa_node_enum_params(spa_node, SPA_PARAM_Props, &index, NULL, &props, &b)) <= 0) {
pw_log_debug("spa_node_get_props failed: %d", res);
@ -174,14 +175,13 @@ setup_props(struct pw_core *core, struct spa_node *spa_node, struct pw_propertie
}
while ((key = pw_properties_iterate(pw_props, &state))) {
struct spa_pod_prop *prop;
uint32_t type = 0;
type = spa_debug_type_find_type(NULL, key);
if (type == SPA_TYPE_None)
continue;
if ((prop = spa_pod_find_prop(props, type))) {
if ((prop = spa_pod_find_prop(props, prop, type))) {
const char *value = pw_properties_get(pw_props, key);
pw_log_info("configure prop %s", key);

View File

@ -727,9 +727,9 @@ static int do_allocation(struct pw_link *this, uint32_t in_state, uint32_t out_s
spa_pod_parse_object(param,
SPA_TYPE_OBJECT_ParamBuffers, NULL,
SPA_PARAM_BUFFERS_buffers, SPA_POD_Int(&qmax_buffers),
SPA_PARAM_BUFFERS_size, SPA_POD_Int(&qminsize),
SPA_PARAM_BUFFERS_stride, SPA_POD_Int(&qstride),
SPA_PARAM_BUFFERS_buffers, SPA_POD_Int(&qmax_buffers));
SPA_PARAM_BUFFERS_stride, SPA_POD_Int(&qstride));
max_buffers =
qmax_buffers == 0 ? max_buffers : SPA_MIN(qmax_buffers,

View File

@ -648,18 +648,19 @@ static int process_notify(struct stream *impl, struct spa_pod_sequence *sequence
{
struct spa_pod_builder b = { 0 };
bool changed;
struct spa_pod_frame f[2];
spa_pod_builder_init(&b, impl->io_notify, impl->io_notify_size);
spa_pod_builder_push_sequence(&b, 0);
spa_pod_builder_push_sequence(&b, &f[0], 0);
if ((changed = impl->props.changed)) {
spa_pod_builder_control(&b, 0, SPA_CONTROL_Properties);
spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props);
spa_pod_builder_push_object(&b, &f[1], SPA_TYPE_OBJECT_Props, SPA_PARAM_Props);
spa_pod_builder_prop(&b, SPA_PROP_volume, 0);
spa_pod_builder_float(&b, impl->props.volume);
spa_pod_builder_pop(&b);
spa_pod_builder_pop(&b, &f[1]);
impl->props.changed = false;
}
spa_pod_builder_pop(&b);
spa_pod_builder_pop(&b, &f[0]);
if (changed && pw_log_level_enabled(SPA_LOG_LEVEL_DEBUG))
spa_debug_pod(2, NULL, &impl->io_notify->sequence.pod);