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 test: all
ninja -C build test ninja -C build test
benchmark: all
ninja -C build benchmark
monitor: all monitor: all
SPA_PLUGIN_DIR=build/spa/plugins \ SPA_PLUGIN_DIR=build/spa/plugins \
PIPEWIRE_MODULE_DIR=build/src/modules/ \ 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_builder b;
struct spa_pod *pod; struct spa_pod *pod;
struct spa_pod_frame f[2];
spa_pod_builder_init(&b, data->ctrl, sizeof(data->ctrl)); spa_pod_builder_init(&b, data->ctrl, sizeof(data->ctrl));
#if 0 #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_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_prop(&b, SPA_PROP_frequency, 0);
spa_pod_builder_float(&b, ((sin(data->freq_accum) + 1.0) * 200.0) + 440.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_prop(&b, SPA_PROP_volume, 0);
spa_pod_builder_float(&b, (sin(data->volume_accum) / 2.0) + 0.5); spa_pod_builder_float(&b, (sin(data->volume_accum) / 2.0) + 0.5);
spa_pod_builder_pop(&b); spa_pod_builder_pop(&b, &f[1]);
pod = spa_pod_builder_pop(&b); pod = spa_pod_builder_pop(&b, &f[0]);
#else #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_control(&b, 0, SPA_CONTROL_Properties);
spa_pod_builder_add_object(&b, spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Props, 0, SPA_TYPE_OBJECT_Props, 0,
SPA_PROP_frequency, SPA_POD_Float(((sin(data->freq_accum) + 1.0) * 200.0) + 440.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)); 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 #endif
spa_debug_pod(0, NULL, pod); spa_debug_pod(0, NULL, pod);
@ -386,9 +387,10 @@ static int negotiate_formats(struct data *data)
filter, &format, &b)) <= 0) filter, &format, &b)) <= 0)
return -EBADF; return -EBADF;
spa_debug_pod(0, NULL, format);
spa_log_debug(&default_log.log, "sink set_param"); 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, if ((res = spa_node_port_set_param(data->sink,
SPA_DIRECTION_INPUT, 0, SPA_DIRECTION_INPUT, 0,
SPA_PARAM_Format, 0, format)) < 0) SPA_PARAM_Format, 0, format)) < 0)
@ -527,11 +529,11 @@ int main(int argc, char *argv[])
data.n_support = 3; data.n_support = 3;
if ((res = make_nodes(&data, argc > 1 ? argv[1] : NULL)) < 0) { 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; return -1;
} }
if ((res = negotiate_formats(&data)) < 0) { 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; 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) spa_format_audio_raw_parse(const struct spa_pod *format, struct spa_audio_info_raw *info)
{ {
struct spa_pod *position = NULL; struct spa_pod *position = NULL;
struct spa_pod_parser prs;
int res; int res;
spa_pod_parser_pod(&prs, format); info->flags = 0;
res = spa_pod_parser_get_object(&prs, res = spa_pod_parse_object(format,
SPA_TYPE_OBJECT_Format, NULL, SPA_TYPE_OBJECT_Format, NULL,
SPA_FORMAT_AUDIO_format, SPA_POD_Id(&info->format), SPA_FORMAT_AUDIO_format, SPA_POD_Id(&info->format),
SPA_FORMAT_AUDIO_rate, SPA_POD_Int(&info->rate), SPA_FORMAT_AUDIO_rate, SPA_POD_Int(&info->rate),
SPA_FORMAT_AUDIO_channels, SPA_POD_Int(&info->channels), 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)); SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position));
if (position && spa_pod_is_array(position) && if (position && spa_pod_is_array(position) &&
SPA_POD_ARRAY_VALUE_TYPE(position) == SPA_TYPE_Id) { 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 * 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_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_pod_builder_add(builder,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), 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, spa_pod_builder_array(builder, sizeof(uint32_t), SPA_TYPE_Id,
info->channels, info->position); 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 <stdarg.h>
#include <spa/pod/pod.h> #include <spa/pod/iter.h>
struct spa_pod_frame {
struct spa_pod pod;
uint32_t ref;
uint32_t _padding;
};
struct spa_pod_builder_state { struct spa_pod_builder_state {
uint32_t offset; uint32_t offset;
#define SPA_POD_BUILDER_FLAG_BODY (1<<0) #define SPA_POD_BUILDER_FLAG_BODY (1<<0)
#define SPA_POD_BUILDER_FLAG_FIRST (1<<1) #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 flags;
uint32_t depth; struct spa_pod_frame *frame;
uint32_t _padding; };
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 { struct spa_pod_builder {
void *data; void *data;
uint32_t size; uint32_t size;
uint32_t _padding; 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_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, } #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 static inline void
spa_pod_builder_reset(struct spa_pod_builder *builder, struct spa_pod_builder_state *state) spa_pod_builder_reset(struct spa_pod_builder *builder, struct spa_pod_builder_state *state)
{ {
if (builder->reset) builder->state = *state;
builder->reset(builder, state);
else
builder->state = *state;
} }
static inline void spa_pod_builder_init(struct spa_pod_builder *builder, void *data, uint32_t size) 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); *builder = SPA_POD_BUILDER_INIT(data, size);
} }
static inline struct spa_pod_frame * static inline struct spa_pod *
spa_pod_builder_top(struct spa_pod_builder *builder) 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; if (offset + 8 <= size) {
} struct spa_pod *pod = SPA_MEMBER(builder->data, offset, struct spa_pod);
if (offset + SPA_POD_SIZE(pod) <= size)
static inline void * return pod;
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;
} }
return NULL; return NULL;
} }
static inline void * static inline struct spa_pod *
spa_pod_builder_deref(struct spa_pod_builder *builder, uint32_t ref) 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 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, spa_pod_builder_push(struct spa_pod_builder *builder,
struct spa_pod_frame *frame,
const struct spa_pod *pod, 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->pod = *pod;
frame->ref = ref; frame->offset = offset;
spa_pod_builder_update_frame(builder, frame); frame->parent = builder->state.frame;
if (builder->state.flags & SPA_POD_BUILDER_FLAG_BODY) frame->flags = builder->state.flags;
SPA_FLAG_SET(builder->state.flags, SPA_POD_BUILDER_FLAG_FIRST); builder->state.frame = frame;
return ref;
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 static inline int spa_pod_builder_raw(struct spa_pod_builder *builder, const void *data, uint32_t size)
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) { if (offset + size > builder->size) {
ref = builder->write(builder, data, size); if (builder->callbacks && builder->callbacks->overflow)
} else { res = builder->callbacks->overflow(builder->callbacks_data, offset + size);
ref = builder->state.offset;
if (ref + size > builder->size)
ref = SPA_ID_INVALID;
else 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; builder->state.offset += size;
for (i = 0; i < builder->state.depth; i++) for (f = builder->state.frame; f ; f = f->parent)
builder->frame[i].pod.size += size; 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; uint64_t zeroes = 0;
size = SPA_ROUND_UP_N(size, 8) - size; size = SPA_ROUND_UP_N(size, 8) - size;
if (size) return size ? spa_pod_builder_raw(builder, &zeroes, size) : 0;
spa_pod_builder_raw(builder, &zeroes, size);
SPA_FLAG_UNSET(builder->state.flags, SPA_POD_BUILDER_FLAG_HEADER);
} }
static inline uint32_t static inline int
spa_pod_builder_raw_padded(struct spa_pod_builder *builder, const void *data, uint32_t size) 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; int r, res = spa_pod_builder_raw(builder, data, size);
spa_pod_builder_pad(builder, size); if ((r = spa_pod_builder_pad(builder, size)) < 0)
return ref; 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; struct spa_pod *pod;
frame = &builder->frame[--builder->state.depth]; if ((pod = (struct spa_pod *) spa_pod_builder_frame(builder, frame)) != NULL)
if ((pod = (struct spa_pod *) spa_pod_builder_deref_checked(builder, frame->ref, true)) != NULL)
*pod = frame->pod; *pod = frame->pod;
if ((frame = spa_pod_builder_top(builder)) != NULL) builder->state.frame = frame->parent;
spa_pod_builder_update_frame(builder, frame); builder->state.flags = frame->flags;
else
builder->state.flags = 0;
spa_pod_builder_pad(builder, builder->state.offset); spa_pod_builder_pad(builder, builder->state.offset);
return pod; return pod;
} }
static inline uint32_t static inline int
spa_pod_builder_primitive(struct spa_pod_builder *builder, const struct spa_pod *p) spa_pod_builder_primitive(struct spa_pod_builder *builder, const struct spa_pod *p)
{ {
const void *data; const void *data;
uint32_t size, ref; uint32_t size;
int r, res;
if (builder->state.flags == SPA_POD_BUILDER_FLAG_BODY) { if (builder->state.flags == SPA_POD_BUILDER_FLAG_BODY) {
data = SPA_POD_BODY_CONST(p); 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); size = SPA_POD_SIZE(p);
SPA_FLAG_UNSET(builder->state.flags, SPA_POD_BUILDER_FLAG_FIRST); 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) if (builder->state.flags != SPA_POD_BUILDER_FLAG_BODY)
spa_pod_builder_pad(builder, size); if ((r = spa_pod_builder_pad(builder, size)) < 0)
res = r;
return ref; return res;
} }
#define SPA_POD_INIT(size,type) (struct spa_pod) { size, type } #define SPA_POD_INIT(size,type) (struct spa_pod) { size, type }
#define SPA_POD_INIT_None() SPA_POD_INIT(0, SPA_TYPE_None) #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(); const struct spa_pod p = SPA_POD_INIT_None();
return spa_pod_builder_primitive(builder, &p); 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 } #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); const struct spa_pod_bool p = SPA_POD_INIT_Bool(val);
return spa_pod_builder_primitive(builder, &p.pod); 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 } #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); const struct spa_pod_id p = SPA_POD_INIT_Id(val);
return spa_pod_builder_primitive(builder, &p.pod); 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 } #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); const struct spa_pod_int p = SPA_POD_INIT_Int(val);
return spa_pod_builder_primitive(builder, &p.pod); 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 } #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); const struct spa_pod_long p = SPA_POD_INIT_Long(val);
return spa_pod_builder_primitive(builder, &p.pod); 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 } #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); const struct spa_pod_float p = SPA_POD_INIT_Float(val);
return spa_pod_builder_primitive(builder, &p.pod); 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 } #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); const struct spa_pod_double p = SPA_POD_INIT_Double(val);
return spa_pod_builder_primitive(builder, &p.pod); 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 } } #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) spa_pod_builder_write_string(struct spa_pod_builder *builder, const char *str, uint32_t len)
{ {
uint32_t ref = 0; int r, res;
if (spa_pod_builder_raw(builder, str, len) == SPA_ID_INVALID) res = spa_pod_builder_raw(builder, str, len);
ref = SPA_ID_INVALID; if ((r = spa_pod_builder_raw(builder, "", 1)) < 0)
if (spa_pod_builder_raw(builder, "", 1) == SPA_ID_INVALID) res = r;
ref = SPA_ID_INVALID; if ((r = spa_pod_builder_pad(builder, builder->state.offset)) < 0)
spa_pod_builder_pad(builder, builder->state.offset); res = r;
return ref; 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) 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); const struct spa_pod_string p = SPA_POD_INIT_String(len+1);
uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p)); int r, res = spa_pod_builder_raw(builder, &p, sizeof(p));
if (spa_pod_builder_write_string(builder, str, len) == SPA_ID_INVALID) if ((r = spa_pod_builder_write_string(builder, str, len)) < 0)
ref = SPA_ID_INVALID; res = r;
return ref; 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; uint32_t len = str ? strlen(str) : 0;
return spa_pod_builder_string_len(builder, str ? str : "", len); 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 } } #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) 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); const struct spa_pod_bytes p = SPA_POD_INIT_Bytes(len);
uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p)); int r, res = spa_pod_builder_raw(builder, &p, sizeof(p));
if (spa_pod_builder_raw_padded(builder, bytes, len) == SPA_ID_INVALID) if ((r = spa_pod_builder_raw_padded(builder, bytes, len)) < 0)
ref = SPA_ID_INVALID; res = r;
return ref; 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 } } #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) 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); 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 } #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); const struct spa_pod_fd p = SPA_POD_INIT_Fd(fd);
return spa_pod_builder_primitive(builder, &p.pod); 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 } #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) 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)); 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 } #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) 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)); const struct spa_pod_fraction p = SPA_POD_INIT_Fraction(SPA_FRACTION(num, denom));
return spa_pod_builder_primitive(builder, &p.pod); return spa_pod_builder_primitive(builder, &p.pod);
} }
static inline uint32_t static inline int
spa_pod_builder_push_array(struct spa_pod_builder *builder) spa_pod_builder_push_array(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
{ {
const struct spa_pod_array p = const struct spa_pod_array p =
{ {sizeof(struct spa_pod_array_body) - sizeof(struct spa_pod), SPA_TYPE_Array}, { {sizeof(struct spa_pod_array_body) - sizeof(struct spa_pod), SPA_TYPE_Array},
{{0, 0}} }; {{0, 0}} };
return spa_pod_builder_push(builder, &p.pod, uint32_t offset = builder->state.offset;
spa_pod_builder_raw(builder, &p, int res = spa_pod_builder_raw(builder, &p, sizeof(p) - sizeof(struct spa_pod));
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, spa_pod_builder_array(struct spa_pod_builder *builder,
uint32_t child_size, uint32_t child_type, uint32_t n_elems, const void *elems) 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}, {(uint32_t)(sizeof(struct spa_pod_array_body) + n_elems * child_size), SPA_TYPE_Array},
{{child_size, child_type}} {{child_size, child_type}}
}; };
uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p)); int r, res = spa_pod_builder_raw(builder, &p, sizeof(p));
if (spa_pod_builder_raw_padded(builder, elems, child_size * n_elems) == SPA_ID_INVALID) if ((r = spa_pod_builder_raw_padded(builder, elems, child_size * n_elems)) < 0)
ref = SPA_ID_INVALID; res = r;
return ref; return res;
} }
#define SPA_POD_INIT_CHOICE_BODY(type, flags, child_size, child_type) \ #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 }, \ { { { n_vals * sizeof(ctype) + sizeof(struct spa_pod_choice_body), SPA_TYPE_Choice }, \
{ type, 0, { sizeof(ctype), child_type } } }, { __VA_ARGS__ } } { type, 0, { sizeof(ctype), child_type } } }, { __VA_ARGS__ } }
static inline uint32_t static inline int
spa_pod_builder_push_choice(struct spa_pod_builder *builder, uint32_t type, uint32_t flags) 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 = const struct spa_pod_choice p =
{ {sizeof(struct spa_pod_choice_body) - sizeof(struct spa_pod), SPA_TYPE_Choice}, { {sizeof(struct spa_pod_choice_body) - sizeof(struct spa_pod), SPA_TYPE_Choice},
{ type, flags, {0, 0}} }; { type, flags, {0, 0}} };
return spa_pod_builder_push(builder, &p.pod, uint32_t offset = builder->state.offset;
spa_pod_builder_raw(builder, &p, int res = spa_pod_builder_raw(builder, &p, sizeof(p) - sizeof(struct spa_pod));
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 } } #define SPA_POD_INIT_Struct(size) (struct spa_pod_struct){ { size, SPA_TYPE_Struct } }
static inline uint32_t static inline int
spa_pod_builder_push_struct(struct spa_pod_builder *builder) 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); const struct spa_pod_struct p = SPA_POD_INIT_Struct(0);
return spa_pod_builder_push(builder, &p.pod, uint32_t offset = builder->state.offset;
spa_pod_builder_raw(builder, &p, sizeof(p))); 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__ } #define SPA_POD_INIT_Object(size,type,id,...) (struct spa_pod_object){ { size, SPA_TYPE_Object }, { type, id }, ##__VA_ARGS__ }
static inline uint32_t static inline int
spa_pod_builder_push_object(struct spa_pod_builder *builder, uint32_t type, uint32_t id) 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 = const struct spa_pod_object p =
SPA_POD_INIT_Object(sizeof(struct spa_pod_object_body), type, id); SPA_POD_INIT_Object(sizeof(struct spa_pod_object_body), type, id);
return spa_pod_builder_push(builder, &p.pod, uint32_t offset = builder->state.offset;
spa_pod_builder_raw(builder, &p, sizeof(p))); 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) \ #define SPA_POD_INIT_Prop(key,flags,size,type) \
(struct spa_pod_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) 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 }; const struct { uint32_t key; uint32_t flags; } p = { key, flags };
uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p)); return spa_pod_builder_raw(builder, &p, sizeof(p));
SPA_FLAG_SET(builder->state.flags, SPA_POD_BUILDER_FLAG_HEADER);
return ref;
} }
#define SPA_POD_INIT_Sequence(size,unit) \ #define SPA_POD_INIT_Sequence(size,unit) \
(struct spa_pod_sequence){ { size, SPA_TYPE_Sequence}, {unit, 0 } } (struct spa_pod_sequence){ { size, SPA_TYPE_Sequence}, {unit, 0 } }
static inline uint32_t static inline int
spa_pod_builder_push_sequence(struct spa_pod_builder *builder, uint32_t unit) spa_pod_builder_push_sequence(struct spa_pod_builder *builder, struct spa_pod_frame *frame, uint32_t unit)
{ {
const struct spa_pod_sequence p = const struct spa_pod_sequence p =
SPA_POD_INIT_Sequence(sizeof(struct spa_pod_sequence_body), unit); SPA_POD_INIT_Sequence(sizeof(struct spa_pod_sequence_body), unit);
return spa_pod_builder_push(builder, &p.pod, uint32_t offset = builder->state.offset;
spa_pod_builder_raw(builder, &p, sizeof(p))); 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 static inline uint32_t
spa_pod_builder_control(struct spa_pod_builder *builder, uint32_t offset, uint32_t type) 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 }; const struct { uint32_t offset; uint32_t type; } p = { offset, type };
uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p)); return spa_pod_builder_raw(builder, &p, sizeof(p));
SPA_FLAG_SET(builder->state.flags, SPA_POD_BUILDER_FLAG_HEADER);
return ref;
} }
static inline uint32_t spa_choice_from_id(char id) static inline uint32_t spa_choice_from_id(char id)
@ -513,7 +479,7 @@ do { \
spa_pod_builder_string_len(builder, strval, len); \ spa_pod_builder_string_len(builder, strval, len); \
break; \ break; \
} \ } \
case 'z': \ case 'y': \
{ \ { \
void *ptr = va_arg(args, void *); \ void *ptr = va_arg(args, void *); \
int len = va_arg(args, int); \ int len = va_arg(args, int); \
@ -569,94 +535,66 @@ do { \
} \ } \
} while(false) } while(false)
static inline void * static inline int
spa_pod_builder_addv(struct spa_pod_builder *builder, va_list args) spa_pod_builder_addv(struct spa_pod_builder *builder, va_list args)
{ {
const char *format = ""; int res = 0;
void *top = NULL; struct spa_pod_frame *f = builder->state.frame;
do { uint32_t ftype = f ? f->pod.type : SPA_TYPE_None;
int n_values = 1;
bool do_pop = false;
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); uint32_t key = va_arg(args, uint32_t);
if (key == 0) if (key == 0)
break; goto exit;
if (key != SPA_ID_INVALID) spa_pod_builder_prop(builder, key, 0);
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 offset = va_arg(args, uint32_t);
uint32_t type = va_arg(args, uint32_t); uint32_t type = va_arg(args, uint32_t);
if (type == 0) if (type == 0)
break; goto exit;
if (type != SPA_ID_INVALID) spa_pod_builder_control(builder, offset, type);
spa_pod_builder_control(builder, offset, type);
} }
default:
break;
}
if ((format = va_arg(args, const char *)) == NULL)
break;
again: choice = *format == '?';
switch (*format) { if (choice) {
case '{': uint32_t type = spa_choice_from_id(*++format);
{
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);
if (*format != '\0') if (*format != '\0')
format++; format++;
spa_pod_builder_push_choice(builder, choice, flags); spa_pod_builder_push_choice(builder, &f, type, 0);
n_values = va_arg(args, int); n_values = va_arg(args, int);
do_pop = true;
goto do_collect;
} }
case ']': case ')': case '>': case '}': while (n_values-- > 0)
top = spa_pod_builder_pop(builder); SPA_POD_BUILDER_COLLECT(builder, *format, args);
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);
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_list args;
va_start(args, builder); va_start(args, builder);
@ -666,29 +604,35 @@ static inline void *spa_pod_builder_add(struct spa_pod_builder *builder, ...)
return res; return res;
} }
#define SPA_POD_Object(type,id,...) \
"{", type, id, ##__VA_ARGS__, SPA_ID_INVALID, "}"
#define SPA_POD_Prop(key,...) \ #define SPA_POD_Prop(key,...) \
key, ##__VA_ARGS__ 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,...) \ #define SPA_POD_Control(offset,type,...) \
offset, type, ##__VA_ARGS__ offset, type, ##__VA_ARGS__
#define spa_pod_builder_add_object(b,type,id,...) \ #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,...) \ #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,...) \ #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_RANGE(def,min,max) 3,(def),(min),(max)
#define SPA_CHOICE_STEP(def,min,max,step) 4,(def),(min),(max),(step) #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_String(val) "s",val
#define SPA_POD_Stringn(val,len) "S",val,len #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_Rectangle(val) "R", val
#define SPA_POD_CHOICE_ENUM_Rectangle(n_vals,...) "?eR", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) #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; o1 = (const struct spa_pod_object*)pod1;
o2 = (const struct spa_pod_object*)pod2; o2 = (const struct spa_pod_object*)pod2;
p2 = NULL;
SPA_POD_OBJECT_FOREACH(o1, p1) { 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; return 1;
if ((res = spa_pod_compare(&p1->value, &p2->value)) != 0) if ((res = spa_pod_compare(&p1->value, &p2->value)) != 0)
return res; return res;
} }
p1 = NULL;
SPA_POD_OBJECT_FOREACH(o2, p2) { 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; return -1;
} }
break; break;

View file

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

View file

@ -30,40 +30,16 @@ extern "C" {
#endif #endif
#include <errno.h> #include <errno.h>
#include <stdarg.h>
#include <spa/pod/pod.h> #include <spa/pod/pod.h>
struct spa_pod_iter { struct spa_pod_frame {
const void *data; struct spa_pod pod;
uint32_t size; struct spa_pod_frame *parent;
uint32_t offset; 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) 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) && 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); 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) && 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(pod, 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) 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); 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) && 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(pod, 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) 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; 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) static inline int spa_pod_is_array(const struct spa_pod *pod)
{ {
return (SPA_POD_TYPE(pod) == SPA_TYPE_Array && 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)); 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; const struct spa_pod_prop *first, *res;
SPA_POD_OBJECT_FOREACH(pod, 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) if (res->key == key)
return res; return res;
} }
return NULL; 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)) if (!spa_pod_is_object(pod))
return NULL; 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) 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> #include <spa/pod/iter.h>
struct spa_pod_parser { struct spa_pod_parser_state {
uint32_t depth; uint32_t offset;
#define SPA_POD_PARSER_FLAG_OBJECT (1<<0)
#define SPA_POD_PARSER_FLAG_STRUCT (1<<1)
uint32_t flags; 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, 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 = SPA_POD_PARSER_INIT(data, size);
parser->flags = 0;
spa_pod_iter_init(&parser->iter[0], data, size, offset);
} }
static inline void spa_pod_parser_pod(struct spa_pod_parser *parser, static inline void spa_pod_parser_pod(struct spa_pod_parser *parser,
const struct spa_pod *pod) 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) if (pod == NULL)
return false; 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; return true;
switch (SPA_POD_TYPE(pod)) { switch (type) {
case SPA_TYPE_None: case 'P':
return type == 'T' || type == 'O' || type == 'V' || type == 's'; return true;
case SPA_TYPE_Bool: case 'b':
return type == 'b'; return spa_pod_is_bool(pod);
case SPA_TYPE_Id: case 'I':
return type == 'I'; return spa_pod_is_id(pod);
case SPA_TYPE_Int: case 'i':
return type == 'i'; return spa_pod_is_int(pod);
case SPA_TYPE_Long: case 'l':
return type == 'l'; return spa_pod_is_long(pod);
case SPA_TYPE_Float: case 'f':
return type == 'f'; return spa_pod_is_float(pod);
case SPA_TYPE_Double: case 'd':
return type == 'd'; return spa_pod_is_double(pod);
case SPA_TYPE_String: case 's':
return type == 's' || type == 'S'; return spa_pod_is_string(pod) || spa_pod_is_none(pod);
case SPA_TYPE_Bytes: case 'S':
return type == 'z'; return spa_pod_is_string(pod);
case SPA_TYPE_Rectangle: case 'y':
return type == 'R'; return spa_pod_is_bytes(pod);
case SPA_TYPE_Fraction: case 'R':
return type == 'F'; return spa_pod_is_rectangle(pod);
case SPA_TYPE_Bitmap: case 'F':
return type == 'B'; return spa_pod_is_fraction(pod);
case SPA_TYPE_Array: case 'B':
return type == 'a'; return spa_pod_is_bitmap(pod);
case SPA_TYPE_Struct: case 'a':
return type == 'T'; return spa_pod_is_array(pod);
case SPA_TYPE_Object: case 'p':
return type == 'O'; return spa_pod_is_pointer(pod);
case SPA_TYPE_Pointer: case 'h':
return type == 'p'; return spa_pod_is_fd(pod);
case SPA_TYPE_Fd: case 'T':
return type == 'h'; return spa_pod_is_struct(pod) || spa_pod_is_none(pod);
case SPA_TYPE_Choice: case 'O':
return type == 'V' || return spa_pod_is_object(pod) || spa_pod_is_none(pod);
(SPA_POD_CHOICE_TYPE(pod) == SPA_CHOICE_None && case 'V':
spa_pod_parser_can_collect(SPA_POD_CHOICE_CHILD(pod), type)); return spa_pod_is_choice(pod);
default: default:
return false; return false;
} }
@ -139,7 +360,7 @@ do { \
strncpy(dest, (char *)SPA_POD_CONTENTS(struct spa_pod_string, pod), maxlen-1); \ strncpy(dest, (char *)SPA_POD_CONTENTS(struct spa_pod_string, pod), maxlen-1); \
break; \ break; \
} \ } \
case 'z': \ case 'y': \
*(va_arg(args, void **)) = SPA_POD_CONTENTS(struct spa_pod_bytes, pod); \ *(va_arg(args, void **)) = SPA_POD_CONTENTS(struct spa_pod_bytes, pod); \
*(va_arg(args, uint32_t *)) = SPA_POD_BODY_SIZE(pod); \ *(va_arg(args, uint32_t *)) = SPA_POD_BODY_SIZE(pod); \
break; \ break; \
@ -155,6 +376,12 @@ do { \
*va_arg(args, uint32_t **) = \ *va_arg(args, uint32_t **) = \
(uint32_t *) SPA_POD_CONTENTS(struct spa_pod_bitmap, pod); \ (uint32_t *) SPA_POD_CONTENTS(struct spa_pod_bitmap, pod); \
break; \ 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': \ case 'p': \
{ \ { \
struct spa_pod_pointer_body *b = \ struct spa_pod_pointer_body *b = \
@ -166,17 +393,11 @@ do { \
case 'h': \ case 'h': \
*va_arg(args, int64_t*) = SPA_POD_VALUE(struct spa_pod_fd, pod); \ *va_arg(args, int64_t*) = SPA_POD_VALUE(struct spa_pod_fd, pod); \
break; \ 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 'P': \
case 'O': \
case 'T': \ 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) \ (pod == NULL || (SPA_POD_TYPE(pod) == SPA_TYPE_None) \
? NULL : pod); \ ? NULL : pod); \
break; \ break; \
@ -197,7 +418,7 @@ do { \
va_arg(args, void*); \ va_arg(args, void*); \
/* fallthrough */ \ /* fallthrough */ \
case 'p': \ case 'p': \
case 'z': \ case 'y': \
va_arg(args, void*); \ va_arg(args, void*); \
/* fallthrough */ \ /* fallthrough */ \
case 'b': \ case 'b': \
@ -222,108 +443,53 @@ do { \
static inline int spa_pod_parser_getv(struct spa_pod_parser *parser, va_list args) static inline int spa_pod_parser_getv(struct spa_pod_parser *parser, va_list args)
{ {
struct spa_pod *pod = NULL, *current; struct spa_pod_frame *f = parser->state.frame;
struct spa_pod_prop *prop = NULL; uint32_t ftype = f ? f->pod.type : SPA_TYPE_Struct;
bool required = true; const struct spa_pod_prop *prop = NULL;
struct spa_pod_iter *it = &parser->iter[parser->depth];
const char *format = "";
uint32_t *idp;
int count = 0; int count = 0;
current = pod = spa_pod_iter_current(it);
do { do {
again: bool optional;
switch (*format) { const struct spa_pod *pod = NULL;
case '{': const char *format;
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;
enter: if (ftype == SPA_TYPE_Object) {
if (++parser->depth >= SPA_POD_MAX_DEPTH) uint32_t key = va_arg(args, uint32_t);
return -ENOSPC; const struct spa_pod_object *object;
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 (SPA_POD_TYPE(it->data) == SPA_TYPE_Object) if (key == 0)
parser->flags = SPA_POD_PARSER_FLAG_OBJECT; break;
else if (SPA_POD_TYPE(it->data) == SPA_TYPE_Struct)
parser->flags = SPA_POD_PARSER_FLAG_STRUCT;
else
parser->flags = 0;
current = spa_pod_iter_current(it); object = (const struct spa_pod_object *)spa_pod_parser_frame(parser, f);
spa_pod_iter_advance(it, current); prop = spa_pod_object_find_prop(object, prop, key);
goto read_pod; pod = prop ? &prop->value : NULL;
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;
} }
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; 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_PodStruct(val) "?" SPA_POD_PodStruct(val)
#define SPA_POD_OPT_PodChoice(val) "?" SPA_POD_PodChoice(val) #define SPA_POD_OPT_PodChoice(val) "?" SPA_POD_PodChoice(val)
#define spa_pod_parser_get_object(p,type,id,...) \ #define spa_pod_parser_get_object(p,type,id,...) \
spa_pod_parser_get(p, SPA_POD_Object(type,id,##__VA_ARGS__), NULL) ({ \
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,...) \ #define spa_pod_parser_get_struct(p,...) \
spa_pod_parser_get(p, SPA_POD_Struct(__VA_ARGS__), NULL) ({ \
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,...) \ #define spa_pod_parse_object(pod,type,id,...) \
({ \ ({ \

View file

@ -29,8 +29,6 @@
extern "C" { extern "C" {
#endif #endif
#include <stdarg.h>
#include <spa/utils/defs.h> #include <spa/utils/defs.h>
#include <spa/utils/type.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) struct spa_pod **result, struct spa_pod_builder *builder)
{ {
const char *str, *name; const char *str, *name;
struct spa_pod_frame f[2];
name = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE"); name = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE");
if (!(name && *name)) { if (!(name && *name)) {
@ -125,7 +126,7 @@ static int fill_item(struct impl *this, struct udev_device *dev,
if (!(name && *name)) if (!(name && *name))
name = "Unknown"; 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_pod_builder_add(builder,
SPA_MONITOR_ITEM_id, SPA_POD_String(udev_device_get_syspath(dev)), SPA_MONITOR_ITEM_id, SPA_POD_String(udev_device_get_syspath(dev)),
SPA_MONITOR_ITEM_flags, SPA_POD_Id(SPA_MONITOR_ITEM_FLAG_NONE), 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; return 0;
spa_pod_builder_prop(builder, SPA_MONITOR_ITEM_info, 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, add_dict(builder,
"udev-probed", "1", "udev-probed", "1",
"device.path", udev_device_get_devnode(dev), "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) { if ((str = udev_device_get_property_value(dev, "SOUND_FORM_FACTOR")) && *str) {
add_dict(builder, "device.form_factor", str, 0); add_dict(builder, "device.form_factor", str, 0);
} }
spa_pod_builder_pop(builder); spa_pod_builder_pop(builder, &f[1]);
*result = spa_pod_builder_pop(builder); *result = spa_pod_builder_pop(builder, &f[0]);
return 1; return 1;
} }

View file

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

View file

@ -236,6 +236,7 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
struct spa_pod *fmt; struct spa_pod *fmt;
int res; int res;
bool opened; bool opened;
struct spa_pod_frame f[2];
opened = state->opened; opened = state->opened;
if ((err = spa_alsa_open(state)) < 0) 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); snd_pcm_hw_params_alloca(&params);
CHECK(snd_pcm_hw_params_any(hndl, params), "Broken configuration: no configurations available"); 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_pod_builder_add(&b,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), 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); spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_format, 0);
choice = spa_pod_builder_deref(&b, spa_pod_builder_push_choice(&b, &f[1], SPA_CHOICE_None, 0);
spa_pod_builder_push_choice(&b, 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++) { for (i = 1, j = 0; i < SPA_N_ELEMENTS(format_info); i++) {
const struct format_info *fi = &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) if (j > 1)
choice->body.type = SPA_CHOICE_Enum; 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"); 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); spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_rate, 0);
choice = spa_pod_builder_deref(&b, spa_pod_builder_push_choice(&b, &f[1], SPA_CHOICE_None, 0);
spa_pod_builder_push_choice(&b, 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)); spa_pod_builder_int(&b, SPA_CLAMP(DEFAULT_RATE, min, max));
if (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); spa_pod_builder_int(&b, max);
choice->body.type = SPA_CHOICE_Range; 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_min(params, &min), "get_channels_min");
CHECK(snd_pcm_hw_params_get_channels_max(params, &max), "get_channels_max"); 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_int(&b, map->channels);
spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_position, 0); 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++) { for (j = 0; j < map->channels; j++) {
spa_log_debug(state->log, "position %zd %d", j, map->pos[j]); spa_log_debug(state->log, "position %zd %d", j, map->pos[j]);
channel = chmap_position_to_channel(map->pos[j]); channel = chmap_position_to_channel(map->pos[j]);
spa_pod_builder_id(&b, channel); spa_pod_builder_id(&b, channel);
} }
spa_pod_builder_pop(&b); spa_pod_builder_pop(&b, &f[1]);
snd_pcm_free_chmaps(maps); snd_pcm_free_chmaps(maps);
} }
@ -339,18 +340,18 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
goto exit; goto exit;
} }
choice = spa_pod_builder_deref(&b, spa_pod_builder_push_choice(&b, &f[1], SPA_CHOICE_None, 0);
spa_pod_builder_push_choice(&b, 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)); spa_pod_builder_int(&b, SPA_CLAMP(DEFAULT_CHANNELS, min, max));
if (min != max) { if (min != max) {
spa_pod_builder_int(&b, min); spa_pod_builder_int(&b, min);
spa_pod_builder_int(&b, max); spa_pod_builder_int(&b, max);
choice->body.type = SPA_CHOICE_Range; 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)++; (*index)++;
@ -395,8 +396,10 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
/* set the sample format */ /* set the sample format */
format = spa_format_to_alsa(info->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; return -EINVAL;
}
spa_log_info(state->log, "Stream parameters are %iHz, %s, %i channels", info->rate, snd_pcm_format_name(format), spa_log_info(state->log, "Stream parameters are %iHz, %s, %i channels", info->rate, snd_pcm_format_name(format),
info->channels); info->channels);

View file

@ -344,12 +344,13 @@ static int port_enum_formats(struct spa_node *node,
} }
else if (other->have_format) { else if (other->have_format) {
struct spa_audio_info info; struct spa_audio_info info;
struct spa_pod_frame f;
info = other->format; info = other->format;
qsort(info.info.raw.position, info.info.raw.channels, sizeof(uint32_t), int32_cmp); 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_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
spa_pod_builder_add(builder, spa_pod_builder_add(builder,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), 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, spa_pod_builder_array(builder, sizeof(uint32_t), SPA_TYPE_Id,
info.info.raw.channels, info.info.raw.position); info.info.raw.channels, info.info.raw.position);
} }
*param = spa_pod_builder_pop(builder); *param = spa_pod_builder_pop(builder, &f);
} else { } else {
*param = spa_pod_builder_add_object(builder, *param = spa_pod_builder_add_object(builder,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, 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 impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct port *other; struct port *other;
struct spa_pod_frame f;
other = GET_PORT(this, SPA_DIRECTION_REVERSE(direction), 0); other = GET_PORT(this, SPA_DIRECTION_REVERSE(direction), 0);
switch (*index) { switch (*index) {
case 0: case 0:
if (other->have_format) { 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_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
spa_pod_builder_add(builder, spa_pod_builder_add(builder,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), 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_prop(builder, SPA_FORMAT_AUDIO_position, 0);
spa_pod_builder_array(builder, sizeof(uint32_t), SPA_TYPE_Id, spa_pod_builder_array(builder, sizeof(uint32_t), SPA_TYPE_Id,
other->format.info.raw.channels, other->format.info.raw.position); other->format.info.raw.channels, other->format.info.raw.position);
*param = spa_pod_builder_pop(builder); *param = spa_pod_builder_pop(builder, &f);
} else { } else {
*param = spa_pod_builder_add_object(builder, *param = spa_pod_builder_add_object(builder,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, 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: case SPA_PARAM_PropInfo:
{ {
struct props *p = &this->props; struct props *p = &this->props;
struct spa_pod_frame f[2];
switch (*index) { switch (*index) {
case 0: 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)); SPA_PROP_INFO_type, SPA_POD_Bool(p->live));
break; break;
case 1: 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_pod_builder_add(&b,
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_waveType), SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_waveType),
SPA_PROP_INFO_name, SPA_POD_String("Select the waveform"), SPA_PROP_INFO_name, SPA_POD_String("Select the waveform"),
SPA_PROP_INFO_type, SPA_POD_Int(p->wave), SPA_PROP_INFO_type, SPA_POD_Int(p->wave),
0); 0);
spa_pod_builder_prop(&b, SPA_PROP_INFO_labels, 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_int(&b, WAVE_SINE);
spa_pod_builder_string(&b, "Sine wave"); spa_pod_builder_string(&b, "Sine wave");
spa_pod_builder_int(&b, WAVE_SQUARE); spa_pod_builder_int(&b, WAVE_SQUARE);
spa_pod_builder_string(&b, "Square wave"); spa_pod_builder_string(&b, "Square wave");
spa_pod_builder_pop(&b); spa_pod_builder_pop(&b, &f[1]);
param = spa_pod_builder_pop(&b); param = spa_pod_builder_pop(&b, &f[0]);
break; break;
case 2: case 2:
param = spa_pod_builder_add_object(&b, 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) struct spa_pod **result, struct spa_pod_builder *builder)
{ {
char dev[16]; 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_pod_builder_add(builder,
SPA_MONITOR_ITEM_id, SPA_POD_String(device->path), SPA_MONITOR_ITEM_id, SPA_POD_String(device->path),
SPA_MONITOR_ITEM_flags, SPA_POD_Id(SPA_MONITOR_ITEM_FLAG_NONE), 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); 0);
spa_pod_builder_prop(builder, SPA_MONITOR_ITEM_info, 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); snprintf(dev, sizeof(dev), "%p", device);
add_dict(builder, "device.api", "bluez5"); 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, "device.bluez5.address", device->address);
add_dict(builder, "bluez5.device", dev); add_dict(builder, "bluez5.device", dev);
spa_pod_builder_pop(builder); spa_pod_builder_pop(builder, &f[1]);
*result = spa_pod_builder_pop(builder); *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) { 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) struct spa_pod **result, struct spa_pod_builder *builder)
{ {
const char *str, *name; const char *str, *name;
struct spa_pod_frame f[2];
name = udev_device_get_property_value(dev, "ID_V4L_PRODUCT"); name = udev_device_get_property_value(dev, "ID_V4L_PRODUCT");
if (!(name && *name)) { if (!(name && *name)) {
@ -98,7 +99,7 @@ static void fill_item(struct impl *this, struct udev_device *dev,
if (!(name && *name)) if (!(name && *name))
name = "Unknown"; 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_pod_builder_add(builder,
SPA_MONITOR_ITEM_id, SPA_POD_String(udev_device_get_syspath(dev)), SPA_MONITOR_ITEM_id, SPA_POD_String(udev_device_get_syspath(dev)),
SPA_MONITOR_ITEM_flags, SPA_POD_Id(SPA_MONITOR_ITEM_FLAG_NONE), 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); 0);
spa_pod_builder_prop(builder, SPA_MONITOR_ITEM_info, 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, "udev-probed", "1");
add_dict(builder, "device.path", udev_device_get_devnode(dev)); 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); add_dict(builder, "device.capabilities", str);
} }
spa_pod_builder_pop(builder); spa_pod_builder_pop(builder, &f[1]);
*result = spa_pod_builder_pop(builder); *result = spa_pod_builder_pop(builder, &f[0]);
} }
static int emit_device(struct impl *this, uint32_t id, struct udev_device *dev) 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 impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct port *port = GET_PORT(this, direction, port_id); struct port *port = GET_PORT(this, direction, port_id);
struct spa_pod_frame f;
if (!port->have_format) if (!port->have_format)
return -EIO; return -EIO;
if (*index > 0) if (*index > 0)
return 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_pod_builder_add(builder,
SPA_FORMAT_mediaType, SPA_POD_Id(port->current_format.media_type), SPA_FORMAT_mediaType, SPA_POD_Id(port->current_format.media_type),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(port->current_format.media_subtype), 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; return -EIO;
} }
*param = spa_pod_builder_pop(builder); *param = spa_pod_builder_pop(builder, &f);
return 1; 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_video:
case SPA_MEDIA_TYPE_image: case SPA_MEDIA_TYPE_image:
if (media_subtype == SPA_MEDIA_SUBTYPE_raw) { if (media_subtype == SPA_MEDIA_SUBTYPE_raw) {
struct spa_pod_prop *p; const struct spa_pod_prop *p;
const struct spa_pod *val; const struct spa_pod *val;
uint32_t n_values, choice; uint32_t n_values, choice;
const uint32_t *values; 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; return SPA_VIDEO_FORMAT_UNKNOWN;
val = spa_pod_get_values(&p->value, &n_values, &choice); 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; struct spa_pod_choice *choice;
uint32_t filter_media_type, filter_media_subtype, video_format; uint32_t filter_media_type, filter_media_subtype, video_format;
struct spa_v4l2_device *dev = &port->dev; struct spa_v4l2_device *dev = &port->dev;
struct spa_pod_frame f[2];
if ((res = spa_v4l2_open(dev, this->props.device)) < 0) if ((res = spa_v4l2_open(dev, this->props.device)) < 0)
return res; return res;
@ -592,12 +593,12 @@ spa_v4l2_enum_format(struct impl *this,
next_frmsize: next_frmsize:
while (port->next_frmsize) { while (port->next_frmsize) {
if (filter) { if (filter) {
struct spa_pod_prop *p; const struct spa_pod_prop *p;
struct spa_pod *val; struct spa_pod *val;
uint32_t n_vals, choice; uint32_t n_vals, choice;
/* check if we have a fixed frame size */ /* 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; goto do_frmsize;
val = spa_pod_get_values(&p->value, &n_vals, &choice); val = spa_pod_get_values(&p->value, &n_vals, &choice);
@ -626,13 +627,13 @@ spa_v4l2_enum_format(struct impl *this,
goto exit; goto exit;
} }
if (filter) { if (filter) {
struct spa_pod_prop *p; const struct spa_pod_prop *p;
struct spa_pod *val; struct spa_pod *val;
const struct spa_rectangle step = { 1, 1 }, *values; const struct spa_rectangle step = { 1, 1 }, *values;
uint32_t choice, i, n_values; uint32_t choice, i, n_values;
/* check if we have a fixed frame size */ /* 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; goto have_size;
val = spa_pod_get_values(&p->value, &n_values, &choice); 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_pod_builder_add(builder,
SPA_FORMAT_mediaType, SPA_POD_Id(info->media_type), SPA_FORMAT_mediaType, SPA_POD_Id(info->media_type),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(info->media_subtype), SPA_FORMAT_mediaSubtype, SPA_POD_Id(info->media_subtype),
@ -697,8 +698,8 @@ spa_v4l2_enum_format(struct impl *this,
n_fractions = 0; n_fractions = 0;
choice = spa_pod_builder_deref(builder, spa_pod_builder_push_choice(builder, &f[1], SPA_CHOICE_None, 0);
spa_pod_builder_push_choice(builder, SPA_CHOICE_None, 0)); choice = (struct spa_pod_choice*)spa_pod_builder_frame(builder, &f[1]);
port->frmival.index = 0; port->frmival.index = 0;
while (true) { while (true) {
@ -715,12 +716,12 @@ spa_v4l2_enum_format(struct impl *this,
goto exit; goto exit;
} }
if (filter) { if (filter) {
struct spa_pod_prop *p; const struct spa_pod_prop *p;
struct spa_pod *val; struct spa_pod *val;
uint32_t i, n_values, choice; uint32_t i, n_values, choice;
const struct spa_fraction step = { 1, 1 }, *values; 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; goto have_framerate;
val = spa_pod_get_values(&p->value, &n_values, &choice); 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) if (n_fractions <= 1)
choice->body.type = SPA_CHOICE_None; choice->body.type = SPA_CHOICE_None;
spa_pod_builder_pop(builder); spa_pod_builder_pop(builder, &f[1]);
*result = spa_pod_builder_pop(builder); *result = spa_pod_builder_pop(builder, &f[0]);
(*index)++; (*index)++;
@ -1009,6 +1010,7 @@ spa_v4l2_enum_controls(struct impl *this,
uint8_t buffer[1024]; uint8_t buffer[1024];
int res; int res;
const unsigned next_fl = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND; 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) if ((res = spa_v4l2_open(dev, this->props.device)) < 0)
return res; return res;
@ -1091,7 +1093,7 @@ spa_v4l2_enum_controls(struct impl *this,
{ {
struct v4l2_querymenu querymenu; 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_pod_builder_add(&b,
SPA_PROP_INFO_id, SPA_POD_Id(prop_id), SPA_PROP_INFO_id, SPA_POD_Id(prop_id),
SPA_PROP_INFO_type, SPA_POD_CHOICE_ENUM_Int(1, queryctrl.default_value), 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; querymenu.id = queryctrl.id;
spa_pod_builder_prop(&b, SPA_PROP_INFO_labels, 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]);
for (querymenu.index = queryctrl.minimum; for (querymenu.index = queryctrl.minimum;
querymenu.index <= queryctrl.maximum; querymenu.index <= queryctrl.maximum;
querymenu.index++) { 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_string(&b, (const char *)querymenu.name);
} }
} }
spa_pod_builder_pop(&b); spa_pod_builder_pop(&b, &f[1]);
param = spa_pod_builder_pop(&b); param = spa_pod_builder_pop(&b, &f[0]);
break; break;
} }
case V4L2_CTRL_TYPE_INTEGER_MENU: 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: case SPA_PARAM_PropInfo:
{ {
struct props *p = &this->props; struct props *p = &this->props;
struct spa_pod_frame f[2];
switch (*index) { switch (*index) {
case 0: 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)); SPA_PROP_INFO_type, SPA_POD_Bool(p->live));
break; break;
case 1: 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_pod_builder_add(&b,
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_patternType), SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_patternType),
SPA_PROP_INFO_name, SPA_POD_String("The pattern"), SPA_PROP_INFO_name, SPA_POD_String("The pattern"),
SPA_PROP_INFO_type, SPA_POD_Int(p->pattern), SPA_PROP_INFO_type, SPA_POD_Int(p->pattern),
0); 0);
spa_pod_builder_prop(&b, SPA_PROP_INFO_labels, 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_int(&b, PATTERN_SMPTE_SNOW);
spa_pod_builder_string(&b, "SMPTE snow"); spa_pod_builder_string(&b, "SMPTE snow");
spa_pod_builder_int(&b, PATTERN_SNOW); spa_pod_builder_int(&b, PATTERN_SNOW);
spa_pod_builder_string(&b, "Snow"); spa_pod_builder_string(&b, "Snow");
spa_pod_builder_pop(&b); spa_pod_builder_pop(&b, &f[1]);
param = spa_pod_builder_pop(&b); param = spa_pod_builder_pop(&b, &f[0]);
break; break;
default: default:
return 0; return 0;

View file

@ -2,7 +2,6 @@ test_apps = [
'test-buffer', 'test-buffer',
'test-pod', 'test-pod',
'test-utils', 'test-utils',
'stress-ringbuffer',
] ]
foreach a : test_apps foreach a : test_apps
@ -24,3 +23,20 @@ test_cpp = executable('test-cpp', 'test-cpp.cpp',
install : false) install : false)
test('test-cpp', test_cpp) test('test-cpp', test_cpp)
endif 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 <pthread.h>
#include <stdio.h> #include <stdio.h>
#include <sched.h> #include <sched.h>
#include <errno.h>
#include <semaphore.h>
#include <spa/utils/ringbuffer.h> #include <spa/utils/ringbuffer.h>
@ -9,9 +11,10 @@
#define ARRAY_SIZE 63 #define ARRAY_SIZE 63
#define MAX_VALUE 0x10000 #define MAX_VALUE 0x10000
struct spa_ringbuffer rb; static struct spa_ringbuffer rb;
int32_t size; static uint32_t size;
uint8_t *data; static void *data;
static sem_t sem;
static int fill_int_array(int *array, int start, int count) 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_data(&rb, data, size, index % size, b, sizeof(b));
spa_ringbuffer_read_update(&rb, index + 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)); spa_assert(cmp_array(a, b, ARRAY_SIZE));
i = fill_int_array(a, i, ARRAY_SIZE); i = fill_int_array(a, i, ARRAY_SIZE);
} }
} }
sem_post(&sem);
return NULL; 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_data(&rb, data, size, index % size, a, sizeof(a));
spa_ringbuffer_write_update(&rb, index + 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); i = fill_int_array(a, i, ARRAY_SIZE);
} }
} }
sem_post(&sem);
return NULL; return NULL;
} }
#define exit_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
pthread_t reader_thread, writer_thread;
struct timespec ts;
int s;
printf("starting ringbuffer stress test\n"); printf("starting ringbuffer stress test\n");
if (argc > 1) if (argc > 1)
@ -100,11 +118,21 @@ int main(int argc, char *argv[])
spa_ringbuffer_init(&rb); spa_ringbuffer_init(&rb);
data = malloc(size); 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(&reader_thread, NULL, reader_start, NULL);
pthread_create(&writer_thread, NULL, writer_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); 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); spa_assert(sizeof(struct spa_pod_sequence) == 16);
/* builder */ /* 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_state) == 16);
spa_assert(sizeof(struct spa_pod_builder) == 312); spa_assert(sizeof(struct spa_pod_builder) == 48);
/* command */ /* command */
spa_assert(sizeof(struct spa_command_body) == 8); 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_body) == 8);
spa_assert(sizeof(struct spa_event) == 16); spa_assert(sizeof(struct spa_event) == 16);
/* iter */
spa_assert(sizeof(struct spa_pod_iter) == 16);
/* parser */ /* 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]; uint8_t buffer[4096];
struct spa_pod_builder b; struct spa_pod_builder b;
struct spa_pod *array, *choice, *head, *pod, *it; struct spa_pod *array, *choice, *head, *pod, *it;
struct spa_pod_prop *prop; const struct spa_pod_prop *prop;
struct spa_pod_control *control; struct spa_pod_control *control;
int64_t longs[] = { 5, 7, 11, 13, 17 }, *al; int64_t longs[] = { 5, 7, 11, 13, 17 }, *al;
uint32_t i, len, zl, *ai; uint32_t i, len, yl, *ai;
union { union {
bool b; bool b;
uint32_t I; uint32_t I;
@ -351,103 +349,131 @@ static void test_build(void)
float f; float f;
double d; double d;
const char *s; const char *s;
const void *z; const void *y;
const void *p; const void *p;
int64_t h; int64_t h;
struct spa_rectangle R; struct spa_rectangle R;
struct spa_fraction F; struct spa_fraction F;
} val; } val;
struct spa_pod_frame f;
spa_pod_builder_init(&b, buffer, sizeof(buffer)); spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_assert(b.data == buffer); spa_assert(b.data == buffer);
spa_assert(b.size == sizeof(buffer)); spa_assert(b.size == sizeof(buffer));
spa_assert(b.state.offset == 0); spa_assert(b.state.offset == 0);
spa_assert(b.state.flags == 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_none(&b) == 0);
spa_assert(spa_pod_builder_bool(&b, true) == 8); spa_assert(b.state.offset == 8);
spa_assert(spa_pod_builder_id(&b, SPA_TYPE_Object) == 24); spa_assert(spa_pod_builder_bool(&b, true) == 0);
spa_assert(spa_pod_builder_int(&b, 21) == 40); spa_assert(b.state.offset == 24);
spa_assert(spa_pod_builder_float(&b, 0.8f) == 56); spa_assert(spa_pod_builder_id(&b, SPA_TYPE_Object) == 0);
spa_assert(spa_pod_builder_double(&b, -1.56) == 72); spa_assert(b.state.offset == 40);
spa_assert(spa_pod_builder_string(&b, "test") == 88); spa_assert(spa_pod_builder_int(&b, 21) == 0);
spa_assert(spa_pod_builder_bytes(&b, "PipeWire", 8) == 104); spa_assert(b.state.offset == 56);
spa_assert(spa_pod_builder_pointer(&b, SPA_TYPE_Object, &b) == 120); spa_assert(spa_pod_builder_float(&b, 0.8f) == 0);
spa_assert(spa_pod_builder_fd(&b, 4) == 144); spa_assert(b.state.offset == 72);
spa_assert(spa_pod_builder_rectangle(&b, 320, 240) == 160); spa_assert(spa_pod_builder_double(&b, -1.56) == 0);
spa_assert(spa_pod_builder_fraction(&b, 25, 1) == 176); 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.flags == (SPA_POD_BUILDER_FLAG_BODY | SPA_POD_BUILDER_FLAG_FIRST));
spa_assert(b.state.depth == 1); spa_assert(b.state.offset == 200);
spa_assert(spa_pod_builder_int(&b, 1) == 200); spa_assert(spa_pod_builder_int(&b, 1) == 0);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_BODY); spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_BODY);
spa_assert(spa_pod_builder_int(&b, 2) == 212); spa_assert(b.state.offset == 212);
spa_assert(spa_pod_builder_int(&b, 3) == 216); spa_assert(spa_pod_builder_int(&b, 2) == 0);
array = spa_pod_builder_pop(&b); 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(array != NULL);
spa_assert(SPA_POD_BODY_SIZE(array) == 8 + 12);
spa_assert(b.state.flags == 0); 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, spa_assert(spa_pod_builder_array(&b,
sizeof(int64_t), SPA_TYPE_Long, 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.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.flags == (SPA_POD_BUILDER_FLAG_BODY | SPA_POD_BUILDER_FLAG_FIRST));
spa_assert(b.state.depth == 1); spa_assert(b.state.offset == 296);
spa_assert(spa_pod_builder_long(&b, 1) == 296); spa_assert(spa_pod_builder_long(&b, 1) == 0);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_BODY); spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_BODY);
spa_assert(spa_pod_builder_long(&b, 2) == 312); spa_assert(b.state.offset == 312);
spa_assert(spa_pod_builder_long(&b, 3) == 320); spa_assert(spa_pod_builder_long(&b, 2) == 0);
choice = spa_pod_builder_pop(&b); 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(choice != NULL);
spa_assert(b.state.flags == 0); 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.flags == 0);
spa_assert(b.state.depth == 1); spa_assert(b.state.offset == 336);
spa_assert(spa_pod_builder_int(&b, 21) == 336); spa_assert(spa_pod_builder_int(&b, 21) == 0);
spa_assert(spa_pod_builder_float(&b, 0.8f) == 352); spa_assert(b.state.offset == 352);
spa_assert(spa_pod_builder_double(&b, -1.56) == 368); spa_assert(spa_pod_builder_float(&b, 0.8f) == 0);
spa_assert(spa_pod_builder_pop(&b) != NULL); spa_assert(b.state.offset == 368);
spa_assert(b.state.depth == 0); 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.offset == 384);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_OBJECT); spa_assert(spa_pod_builder_push_object(&b, &f, SPA_TYPE_OBJECT_Props, 0) == 0);
spa_assert(b.state.depth == 1); spa_assert(b.state.flags == 0);
spa_assert(spa_pod_builder_prop(&b, 1, 0) == 400); spa_assert(b.state.offset == 400);
spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_OBJECT | SPA_POD_BUILDER_FLAG_HEADER)); spa_assert(spa_pod_builder_prop(&b, 1, 0) == 0);
spa_assert(spa_pod_builder_int(&b, 21) == 408); spa_assert(b.state.flags == 0);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_OBJECT); spa_assert(b.state.offset == 408);
spa_assert(spa_pod_builder_prop(&b, 2, 0) == 424); spa_assert(spa_pod_builder_int(&b, 21) == 0);
spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_OBJECT | SPA_POD_BUILDER_FLAG_HEADER)); spa_assert(b.state.flags == 0);
spa_assert(spa_pod_builder_long(&b, 42) == 432); spa_assert(b.state.offset == 424);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_OBJECT); spa_assert(spa_pod_builder_prop(&b, 2, 0) == 0);
spa_assert(spa_pod_builder_prop(&b, 3, 0) == 448); spa_assert(b.state.flags == 0);
spa_assert(spa_pod_builder_string(&b, "test123") == 456); spa_assert(b.state.offset == 432);
spa_assert(spa_pod_builder_pop(&b) != NULL); 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.flags == 0);
spa_assert(b.state.depth == 0);
spa_assert(spa_pod_builder_push_sequence(&b, 0) == 472); spa_assert(b.state.offset == 472);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_SEQUENCE); spa_assert(spa_pod_builder_push_sequence(&b, &f, 0) == 0);
spa_assert(b.state.depth == 1); spa_assert(b.state.flags == 0);
spa_assert(spa_pod_builder_control(&b, 0, 0) == 488); spa_assert(b.state.offset == 488);
spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_SEQUENCE | SPA_POD_BUILDER_FLAG_HEADER)); spa_assert(spa_pod_builder_control(&b, 0, 0) == 0);
spa_assert(spa_pod_builder_float(&b, 0.667f) == 496); spa_assert(b.state.flags == 0);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_SEQUENCE); spa_assert(b.state.offset == 496);
spa_assert(spa_pod_builder_control(&b, 12, 0) == 512); spa_assert(spa_pod_builder_float(&b, 0.667f) == 0);
spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_SEQUENCE | SPA_POD_BUILDER_FLAG_HEADER)); spa_assert(b.state.flags == 0);
spa_assert(spa_pod_builder_double(&b, 1.22) == 520); spa_assert(b.state.offset == 512);
spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_SEQUENCE); spa_assert(spa_pod_builder_control(&b, 12, 0) == 0);
spa_assert(spa_pod_builder_pop(&b) != NULL); 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.flags == 0);
spa_assert(b.state.depth == 0);
spa_assert(b.state.offset == 536); spa_assert(b.state.offset == 536);
@ -482,13 +508,13 @@ static void test_build(void)
spa_assert(strcmp(val.s, "test") == 0); spa_assert(strcmp(val.s, "test") == 0);
spa_assert((pod = spa_pod_next(pod)) != NULL && spa_pod_is_inside(head, len, pod)); 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_is_bytes(pod));
spa_assert(spa_pod_get_bytes(pod, &val.z, &zl) == 0); spa_assert(spa_pod_get_bytes(pod, &val.y, &yl) == 0);
spa_assert(zl == 8); spa_assert(yl == 8);
spa_assert(memcmp(val.z, "PipeWire", zl) == 0); 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((pod = spa_pod_next(pod)) != NULL && spa_pod_is_inside(head, len, pod));
spa_assert(spa_pod_is_pointer(pod)); spa_assert(spa_pod_is_pointer(pod));
spa_assert(spa_pod_get_pointer(pod, &zl, &val.p) == 0); spa_assert(spa_pod_get_pointer(pod, &yl, &val.p) == 0);
spa_assert(zl == SPA_TYPE_Object); spa_assert(yl == SPA_TYPE_Object);
spa_assert(val.p == &b); spa_assert(val.p == &b);
spa_assert((pod = spa_pod_next(pod)) != NULL && spa_pod_is_inside(head, len, pod)); spa_assert((pod = spa_pod_next(pod)) != NULL && spa_pod_is_inside(head, len, pod));
spa_assert(spa_pod_is_fd(pod)); spa_assert(spa_pod_is_fd(pod));
@ -605,17 +631,22 @@ static void test_build(void)
break; 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(prop->key == 3);
spa_assert(spa_pod_get_string(&prop->value, &val.s) == 0 && spa_assert(spa_pod_get_string(&prop->value, &val.s) == 0 &&
strcmp(val.s, "test123") == 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(prop->key == 1);
spa_assert(spa_pod_get_int(&prop->value, &val.i) == 0 && val.i == 21); 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(prop->key == 2);
spa_assert(spa_pod_get_long(&prop->value, &val.l) == 0 && val.l == 42); 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((pod = spa_pod_next(pod)) != NULL && spa_pod_is_inside(head, len, pod));
spa_assert(spa_pod_is_sequence(pod)); spa_assert(spa_pod_is_sequence(pod));
@ -655,7 +686,7 @@ static void test_varargs(void)
float f; float f;
double d; double d;
const char *s; const char *s;
const void *z; const void *y;
const void *p; const void *p;
int64_t h; int64_t h;
struct spa_rectangle R; struct spa_rectangle R;
@ -826,8 +857,8 @@ static void test_varargs2(void)
float f; float f;
double d; double d;
const char *s; const char *s;
uint32_t zl; uint32_t yl;
const void *z; const void *y;
uint32_t ptype; uint32_t ptype;
const void *p; const void *p;
uint32_t asize, atype, anvals; uint32_t asize, atype, anvals;
@ -903,9 +934,9 @@ static void test_varargs2(void)
case 7: case 7:
spa_assert(prop->key == 8); spa_assert(prop->key == 8);
spa_assert(SPA_POD_PROP_SIZE(prop) == 21); spa_assert(SPA_POD_PROP_SIZE(prop) == 21);
spa_assert(spa_pod_get_bytes(&prop->value, &val.z, &val.zl) == 0); spa_assert(spa_pod_get_bytes(&prop->value, &val.y, &val.yl) == 0);
spa_assert(val.zl == sizeof(bytes)); spa_assert(val.yl == sizeof(bytes));
spa_assert(memcmp(val.z, bytes, val.zl) == 0); spa_assert(memcmp(val.y, bytes, val.yl) == 0);
break; break;
case 8: case 8:
spa_assert(prop->key == 9); spa_assert(prop->key == 9);
@ -969,7 +1000,7 @@ static void test_varargs2(void)
5, SPA_POD_Float(&val.f), 5, SPA_POD_Float(&val.f),
6, SPA_POD_Double(&val.d), 6, SPA_POD_Double(&val.d),
7, SPA_POD_String(&val.s), 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), 9, SPA_POD_Rectangle(&val.R),
10, SPA_POD_Fraction(&val.F), 10, SPA_POD_Fraction(&val.F),
11, SPA_POD_Array(&val.asize, &val.atype, &val.anvals, &val.a), 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.f == 0.453f);
spa_assert(val.d == 0.871); spa_assert(val.d == 0.871);
spa_assert(strcmp(val.s, "test") == 0); spa_assert(strcmp(val.s, "test") == 0);
spa_assert(val.zl == sizeof(bytes)); spa_assert(val.yl == sizeof(bytes));
spa_assert(memcmp(val.z, bytes, sizeof(bytes)) == 0); 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.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(memcmp(&val.F, &SPA_FRACTION(24, 1), sizeof(struct spa_fraction)) == 0);
spa_assert(val.asize == sizeof(int64_t)); 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_Float(&val.f),
0, SPA_POD_OPT_Double(&val.d), 0, SPA_POD_OPT_Double(&val.d),
0, SPA_POD_OPT_String(&val.s), 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_Rectangle(&val.R),
0, SPA_POD_OPT_Fraction(&val.F), 0, SPA_POD_OPT_Fraction(&val.F),
0, SPA_POD_OPT_Array(&val.asize, &val.atype, &val.anvals, &val.a), 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_Float(&val.f),
i, SPA_POD_OPT_Double(&val.d), i, SPA_POD_OPT_Double(&val.d),
i, SPA_POD_OPT_String(&val.s), 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_Rectangle(&val.R),
i, SPA_POD_OPT_Fraction(&val.F), i, SPA_POD_OPT_Fraction(&val.F),
i, SPA_POD_OPT_Array(&val.asize, &val.atype, &val.anvals, &val.a), 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[]) int main(int argc, char *argv[])
{ {
test_abi(); test_abi();
@ -1043,5 +1460,8 @@ int main(int argc, char *argv[])
test_build(); test_build();
test_varargs(); test_varargs();
test_varargs2(); test_varargs2();
test_parser();
test_parser2();
test_static();
return 0; return 0;
} }

View file

@ -110,18 +110,19 @@ static void handle_events(struct data *data)
static void update_param(struct data *data) static void update_param(struct data *data)
{ {
struct spa_pod_builder b = { 0, }; struct spa_pod_builder b = { 0, };
struct spa_pod_frame f[2];
if (data->io_notify == NULL) if (data->io_notify == NULL)
return; return;
spa_pod_builder_init(&b, data->io_notify, data->io_notify_size); 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_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_prop(&b, SPA_PROP_contrast, 0);
spa_pod_builder_float(&b, (sin(data->param_accum) * 127.0) + 127.0); spa_pod_builder_float(&b, (sin(data->param_accum) * 127.0) + 127.0);
spa_pod_builder_pop(&b); spa_pod_builder_pop(&b, &f[1]);
spa_pod_builder_pop(&b); spa_pod_builder_pop(&b, &f[0]);
data->param_accum += M_PI_M2 / 30.0; data->param_accum += M_PI_M2 / 30.0;
if (data->param_accum >= M_PI_M2) if (data->param_accum >= M_PI_M2)

View file

@ -81,18 +81,19 @@ struct data {
static void update_volume(struct data *data) static void update_volume(struct data *data)
{ {
struct spa_pod_builder b = { 0, }; struct spa_pod_builder b = { 0, };
struct spa_pod_frame f[2];
if (data->io_notify == NULL) if (data->io_notify == NULL)
return; return;
spa_pod_builder_init(&b, data->io_notify, data->io_notify_size); 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_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_prop(&b, SPA_PROP_volume, 0);
spa_pod_builder_float(&b, (sin(data->volume_accum) / 2.0) + 0.5); spa_pod_builder_float(&b, (sin(data->volume_accum) / 2.0) + 0.5);
spa_pod_builder_pop(&b); spa_pod_builder_pop(&b, &f[1]);
spa_pod_builder_pop(&b); spa_pod_builder_pop(&b, &f[0]);
data->volume_accum += M_PI_M2 / 1000.0; data->volume_accum += M_PI_M2 / 1000.0;
if (data->volume_accum >= M_PI_M2) 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) static struct spa_pod *sdl_build_formats(SDL_RendererInfo *info, struct spa_pod_builder *b)
{ {
uint32_t i, c; 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_prop(b, SPA_FORMAT_mediaType, 0);
spa_pod_builder_id(b, SPA_MEDIA_TYPE_video); spa_pod_builder_id(b, SPA_MEDIA_TYPE_video);
spa_pod_builder_prop(b, SPA_FORMAT_mediaSubtype, 0); spa_pod_builder_prop(b, SPA_FORMAT_mediaSubtype, 0);
spa_pod_builder_id(b, SPA_MEDIA_SUBTYPE_raw); spa_pod_builder_id(b, SPA_MEDIA_SUBTYPE_raw);
spa_pod_builder_prop(b, SPA_FORMAT_VIDEO_format, 0); 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++) { for (i = 0, c = 0; i < info->num_texture_formats; i++) {
uint32_t id = sdl_format_to_id(info->texture_formats[i]); uint32_t id = sdl_format_to_id(info->texture_formats[i]);
if (id == 0) 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) if (id != SPA_VIDEO_FORMAT_UNKNOWN)
spa_pod_builder_id(b, id); spa_pod_builder_id(b, id);
} }
spa_pod_builder_pop(b); spa_pod_builder_pop(b, &f[1]);
spa_pod_builder_add(b, spa_pod_builder_add(b,
SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle( SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle(
&SPA_RECTANGLE(WIDTH, HEIGHT), &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(0,1),
&SPA_FRACTION(30,1)), &SPA_FRACTION(30,1)),
0); 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; const GValue *value, *value2;
int i; int i;
struct spa_pod_choice *choice; struct spa_pod_choice *choice;
struct spa_pod_frame f;
value = gst_structure_get_value (d->cs, "format"); value = gst_structure_get_value (d->cs, "format");
if (value) { if (value) {
@ -370,14 +371,14 @@ handle_video_fields (ConvertData *d)
for (i = 0; (v = get_nth_string (value, i)); i++) { for (i = 0; (v = get_nth_string (value, i)); i++) {
if (i == 0) { if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_format, 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); idx = gst_video_format_from_string (v);
if (idx < (int)SPA_N_ELEMENTS (video_format_map)) if (idx < (int)SPA_N_ELEMENTS (video_format_map))
spa_pod_builder_id (&d->b, video_format_map[idx]); 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) if (i <= 1)
choice->body.type = SPA_CHOICE_None; 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++) { for (i = 0; get_nth_rectangle (value, value2, i, &v); i++) {
if (i == 0) { if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_size, 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); 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) if (i <= 1)
choice->body.type = SPA_CHOICE_None; 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++) { for (i = 0; get_nth_fraction (value, i, &v); i++) {
if (i == 0) { if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_framerate, 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); 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) if (i <= 1)
choice->body.type = SPA_CHOICE_None; 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++) { for (i = 0; get_nth_fraction (value, i, &v); i++) {
if (i == 0) { if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_maxFramerate, 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); 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) if (i <= 1)
choice->body.type = SPA_CHOICE_None; choice->body.type = SPA_CHOICE_None;
} }
@ -437,6 +438,7 @@ handle_audio_fields (ConvertData *d)
{ {
const GValue *value; const GValue *value;
struct spa_pod_choice *choice; struct spa_pod_choice *choice;
struct spa_pod_frame f;
int i = 0; int i = 0;
value = gst_structure_get_value (d->cs, "format"); 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++) { for (i = 0; (v = get_nth_string (value, i)); i++) {
if (i == 0) { if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_format, 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); idx = gst_audio_format_from_string (v);
if (idx < (int)SPA_N_ELEMENTS (audio_format_map)) if (idx < (int)SPA_N_ELEMENTS (audio_format_map))
spa_pod_builder_id (&d->b, audio_format_map[idx]); 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) if (i <= 1)
choice->body.type = SPA_CHOICE_None; choice->body.type = SPA_CHOICE_None;
} }
@ -474,12 +476,12 @@ handle_audio_fields (ConvertData *d)
if (i == 0) { if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_layout, 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); 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) if (i <= 1)
choice->body.type = SPA_CHOICE_None; 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++) { for (i = 0; get_nth_int (value, i, &v); i++) {
if (i == 0) { if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_rate, 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); 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) if (i <= 1)
choice->body.type = SPA_CHOICE_None; 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++) { for (i = 0; get_nth_int (value, i, &v); i++) {
if (i == 0) { if (i == 0) {
spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_channels, 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); 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) if (i <= 1)
choice->body.type = SPA_CHOICE_None; choice->body.type = SPA_CHOICE_None;
} }
return TRUE; return TRUE;
} }
static uint32_t static int
write_pod (struct spa_pod_builder *b, const void *data, uint32_t size) builder_overflow (void *event_data, uint32_t size)
{ {
uint32_t ref = b->state.offset; struct spa_pod_builder *b = event_data;
b->size = SPA_ROUND_UP_N (size, 512);
if (b->size <= ref) { b->data = realloc (b->data, b->size);
b->size = SPA_ROUND_UP_N (ref + size, 512); if (b->data == NULL)
b->data = realloc (b->data, b->size); return -ENOMEM;
if (b->data == NULL) return 0;
return -1;
}
memcpy (SPA_MEMBER(b->data, ref, void), data, size);
return ref;
} }
static const struct spa_pod_builder_callbacks builder_callbacks = {
SPA_VERSION_POD_BUILDER_CALLBACKS,
.overflow = builder_overflow
};
static struct spa_pod * static struct spa_pod *
convert_1 (ConvertData *d) convert_1 (ConvertData *d)
{ {
struct spa_pod_frame f;
if (!(d->type = find_media_types (gst_structure_get_name (d->cs)))) if (!(d->type = find_media_types (gst_structure_get_name (d->cs))))
return NULL; 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_prop (&d->b, SPA_FORMAT_mediaType, 0);
spa_pod_builder_id(&d->b, d->type->media_type); 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) else if (d->type->media_type == SPA_MEDIA_TYPE_audio)
handle_audio_fields (d); 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); 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 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; const char * str;
struct spa_pod *val; 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 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; struct spa_pod *val;
uint32_t *ints; uint32_t *ints;
@ -714,7 +720,7 @@ handle_int_prop (struct spa_pod_prop *prop, const char *key, GstCaps *res)
} }
static void 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_pod *val;
struct spa_rectangle *rect; struct spa_rectangle *rect;
@ -767,7 +773,7 @@ handle_rect_prop (struct spa_pod_prop *prop, const char *width, const char *heig
} }
static void 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_pod *val;
struct spa_fraction *fract; struct spa_fraction *fract;
@ -815,7 +821,7 @@ gst_caps_from_format (const struct spa_pod *format)
{ {
GstCaps *res = NULL; GstCaps *res = NULL;
uint32_t media_type, media_subtype; 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; const struct spa_pod_object *obj = (const struct spa_pod_object *) format;
if (spa_format_parse(format, &media_type, &media_subtype) < 0) 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_type == SPA_MEDIA_TYPE_video) {
if (media_subtype == SPA_MEDIA_SUBTYPE_raw) { if (media_subtype == SPA_MEDIA_SUBTYPE_raw) {
res = gst_caps_new_empty_simple ("video/x-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); 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", "alignment", G_TYPE_STRING, "au",
NULL); 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); 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); 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); handle_fraction_prop (prop, "max-framerate", res);
} }
} else if (media_type == SPA_MEDIA_TYPE_audio) { } 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", res = gst_caps_new_simple ("audio/x-raw",
"layout", G_TYPE_STRING, "interleaved", "layout", G_TYPE_STRING, "interleaved",
NULL); 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); 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); 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); 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]; const struct spa_pod *port_params[2];
struct spa_pod_builder b = { NULL }; struct spa_pod_builder b = { NULL };
uint8_t buffer[1024]; uint8_t buffer[1024];
struct spa_pod_frame f;
config = gst_buffer_pool_get_config (GST_BUFFER_POOL (pool)); config = gst_buffer_pool_get_config (GST_BUFFER_POOL (pool));
gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers); gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers);
spa_pod_builder_init (&b, buffer, sizeof (buffer)); 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) if (size == 0)
spa_pod_builder_add (&b, spa_pod_builder_add (&b,
SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int(0, 0, INT32_MAX), 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), max_buffers ? max_buffers : INT32_MAX),
SPA_PARAM_BUFFERS_align, SPA_POD_Int(16), SPA_PARAM_BUFFERS_align, SPA_POD_Int(16),
0); 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, port_params[1] = spa_pod_builder_add_object (&b,
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, 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 pw_proxy *proxy = object;
struct spa_pod_builder *b; struct spa_pod_builder *b;
struct spa_pod_frame f;
uint32_t i, n_items; uint32_t i, n_items;
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_NODE_PROXY_METHOD_UPDATE); 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_builder_add(b,
"[",
SPA_POD_Int(change_mask), SPA_POD_Int(change_mask),
SPA_POD_Int(max_input_ports), SPA_POD_Int(max_input_ports),
SPA_POD_Int(max_output_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].key),
SPA_POD_String(props->items[i].value), NULL); 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); pw_protocol_native_end_proxy(proxy, b);
} }
@ -96,12 +97,13 @@ client_node_marshal_port_update(void *object,
{ {
struct pw_proxy *proxy = object; struct pw_proxy *proxy = object;
struct spa_pod_builder *b; struct spa_pod_builder *b;
struct spa_pod_frame f[2];
uint32_t i, n_items; uint32_t i, n_items;
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_NODE_PROXY_METHOD_PORT_UPDATE); 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_builder_add(b,
"[",
SPA_POD_Int(direction), SPA_POD_Int(direction),
SPA_POD_Int(port_id), SPA_POD_Int(port_id),
SPA_POD_Int(change_mask), SPA_POD_Int(change_mask),
@ -114,8 +116,8 @@ client_node_marshal_port_update(void *object,
if (info) { if (info) {
n_items = info->props ? info->props->n_items : 0; n_items = info->props ? info->props->n_items : 0;
spa_pod_builder_push_struct(b, &f[1]);
spa_pod_builder_add(b, spa_pod_builder_add(b,
"[",
SPA_POD_Int(info->flags), SPA_POD_Int(info->flags),
SPA_POD_Int(info->rate), SPA_POD_Int(info->rate),
SPA_POD_Int(n_items), NULL); 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].key),
SPA_POD_String(info->props->items[i].value), NULL); SPA_POD_String(info->props->items[i].value), NULL);
} }
spa_pod_builder_add(b, spa_pod_builder_pop(b, &f[1]);
"]", NULL);
} else { } else {
spa_pod_builder_add(b, spa_pod_builder_add(b,
SPA_POD_Pod(NULL), NULL); 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); 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; uint32_t mem_id, type, memfd_idx, flags;
int memfd; int memfd;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&mem_id), SPA_POD_Int(&mem_id),
SPA_POD_Id(&type), 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; uint32_t node_id, ridx, widx;
int readfd, writefd; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&node_id), SPA_POD_Int(&node_id),
SPA_POD_Int(&ridx), 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; uint32_t seq, id, flags;
const struct spa_pod *param = NULL; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq), SPA_POD_Int(&seq),
SPA_POD_Id(&id), 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; struct spa_pod_parser prs;
const struct spa_event *event; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_PodObject(&event)) < 0) SPA_POD_PodObject(&event)) < 0)
return -EINVAL; return -EINVAL;
@ -251,7 +252,7 @@ static int client_node_demarshal_command(void *object, void *data, size_t size)
const struct spa_command *command; const struct spa_command *command;
uint32_t seq; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq), SPA_POD_Int(&seq),
SPA_POD_PodObject(&command)) < 0) 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; struct spa_pod_parser prs;
int32_t seq, direction, port_id; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq), SPA_POD_Int(&seq),
SPA_POD_Int(&direction), 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; struct spa_pod_parser prs;
int32_t seq, direction, port_id; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq), SPA_POD_Int(&seq),
SPA_POD_Int(&direction), 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; uint32_t seq, direction, port_id, id, flags;
const struct spa_pod *param = NULL; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq), SPA_POD_Int(&seq),
SPA_POD_Int(&direction), 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 pw_proxy *proxy = object;
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f;
uint32_t seq, direction, port_id, mix_id, n_buffers, data_id; uint32_t seq, direction, port_id, mix_id, n_buffers, data_id;
struct pw_client_node_buffer *buffers; struct pw_client_node_buffer *buffers;
uint32_t i, j; uint32_t i, j;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get(&prs, if (spa_pod_parser_push_struct(&prs, &f) < 0 ||
"[" spa_pod_parser_get(&prs,
SPA_POD_Int(&seq), SPA_POD_Int(&seq),
SPA_POD_Int(&direction), SPA_POD_Int(&direction),
SPA_POD_Int(&port_id), 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; const struct spa_command *command;
uint32_t direction, port_id; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&direction), SPA_POD_Int(&direction),
SPA_POD_Int(&port_id), 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; struct spa_pod_parser prs;
uint32_t seq, direction, port_id, mix_id, id, memid, off, sz; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq), SPA_POD_Int(&seq),
SPA_POD_Int(&direction), 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; struct spa_pod_parser prs;
uint32_t id, memid, off, sz; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id), SPA_POD_Id(&id),
SPA_POD_Int(&memid), SPA_POD_Int(&memid),
@ -597,12 +599,13 @@ client_node_marshal_port_use_buffers(void *object,
{ {
struct pw_resource *resource = object; struct pw_resource *resource = object;
struct spa_pod_builder *b; struct spa_pod_builder *b;
struct spa_pod_frame f;
uint32_t i, j; uint32_t i, j;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_PROXY_EVENT_PORT_USE_BUFFERS); 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_builder_add(b,
"[",
SPA_POD_Int(seq), SPA_POD_Int(seq),
SPA_POD_Int(direction), SPA_POD_Int(direction),
SPA_POD_Int(port_id), 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_Int(d->maxsize), NULL);
} }
} }
spa_pod_builder_add(b, "]", NULL); spa_pod_builder_pop(b, &f);
pw_protocol_native_end_resource(resource, b); 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; struct spa_pod_parser prs;
uint32_t seq, res; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq), SPA_POD_Int(&seq),
SPA_POD_Int(&res)) < 0) 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 pw_resource *resource = object;
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f;
uint32_t change_mask, max_input_ports, max_output_ports, n_params; uint32_t change_mask, max_input_ports, max_output_ports, n_params;
const struct spa_pod **params; const struct spa_pod **params;
struct spa_dict props; struct spa_dict props;
uint32_t i; uint32_t i;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get(&prs, if (spa_pod_parser_push_struct(&prs, &f) < 0 ||
"[" spa_pod_parser_get(&prs,
SPA_POD_Int(&change_mask), SPA_POD_Int(&change_mask),
SPA_POD_Int(&max_input_ports), SPA_POD_Int(&max_input_ports),
SPA_POD_Int(&max_output_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 pw_resource *resource = object;
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f;
uint32_t i, direction, port_id, change_mask, n_params; uint32_t i, direction, port_id, change_mask, n_params;
const struct spa_pod **params = NULL; const struct spa_pod **params = NULL;
struct spa_port_info info = { 0 }, *infop = NULL; struct spa_port_info info = { 0 }, *infop = NULL;
struct spa_pod *ipod; struct spa_pod *ipod;
struct spa_dict props; struct spa_dict props;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get(&prs, if (spa_pod_parser_push_struct(&prs, &f) < 0 ||
"[" spa_pod_parser_get(&prs,
SPA_POD_Int(&direction), SPA_POD_Int(&direction),
SPA_POD_Int(&port_id), SPA_POD_Int(&port_id),
SPA_POD_Int(&change_mask), 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) { if (ipod) {
struct spa_pod_parser p2; struct spa_pod_parser p2;
struct spa_pod_frame f2;
infop = &info; infop = &info;
spa_pod_parser_pod(&p2, ipod); 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.flags),
SPA_POD_Int(&info.rate), SPA_POD_Int(&info.rate),
SPA_POD_Int(&props.n_items), NULL) < 0) 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; struct spa_pod_parser prs;
int active; int active;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get_struct(&prs, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Bool(&active)) < 0) SPA_POD_Bool(&active)) < 0)
return -EINVAL; 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_pod_parser prs;
struct spa_event *event; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_PodObject(&event)) < 0) SPA_POD_PodObject(&event)) < 0)
return -EINVAL; return -EINVAL;

View file

@ -352,20 +352,22 @@ static inline void *begin_write(struct pw_protocol_native_connection *conn, uint
return p + 2; 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); struct impl *impl = callbacks_data;
uint32_t ref = b->state.offset; struct spa_pod_builder *b = &impl->builder;
if (b->size <= ref) { b->size = SPA_ROUND_UP_N(size, 4096);
b->size = SPA_ROUND_UP_N(ref + size, 4096); if ((b->data = begin_write(&impl->this, b->size)) == NULL)
b->data = begin_write(&impl->this, b->size); return -ENOMEM;
} return 0;
memcpy(SPA_MEMBER(b->data, ref, void), data, size);
return ref;
} }
static const struct spa_pod_builder_callbacks builder_callbacks = {
SPA_VERSION_POD_BUILDER_CALLBACKS,
.overflow = builder_overflow
};
struct spa_pod_builder * struct spa_pod_builder *
pw_protocol_native_connection_begin_resource(struct pw_protocol_native_connection *conn, pw_protocol_native_connection_begin_resource(struct pw_protocol_native_connection *conn,
struct pw_resource *resource, 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->dest_id = resource->id;
impl->opcode = opcode; 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; return &impl->builder;
} }
@ -389,8 +392,9 @@ pw_protocol_native_connection_begin_proxy(struct pw_protocol_native_connection *
impl->dest_id = proxy->id; impl->dest_id = proxy->id;
impl->opcode = opcode; 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; 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); 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 static void
core_marshal_create_object(void *object, core_marshal_create_object(void *object,
const char *factory_name, const char *factory_name,
@ -80,29 +96,19 @@ core_marshal_create_object(void *object,
{ {
struct pw_proxy *proxy = object; struct pw_proxy *proxy = object;
struct spa_pod_builder *b; 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); b = pw_protocol_native_begin_proxy(proxy, PW_CORE_PROXY_METHOD_CREATE_OBJECT);
n_items = props ? props->n_items : 0; spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
spa_pod_builder_add(b, "["
SPA_POD_String(factory_name), SPA_POD_String(factory_name),
SPA_POD_Id(type), SPA_POD_Id(type),
SPA_POD_Int(version), 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); 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); 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 pw_proxy *proxy = object;
struct spa_dict props; struct spa_dict props;
struct spa_pod_frame f[2];
struct pw_core_info info; struct pw_core_info info;
struct spa_pod_parser prs; struct spa_pod_parser prs;
uint32_t i; 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, if (spa_pod_parser_get(&prs,
"["
SPA_POD_Int(&info.id), SPA_POD_Int(&info.id),
SPA_POD_Long(&info.change_mask), SPA_POD_Long(&info.change_mask),
SPA_POD_String(&info.user_name), SPA_POD_String(&info.user_name),
SPA_POD_String(&info.host_name), SPA_POD_String(&info.host_name),
SPA_POD_String(&info.version), SPA_POD_String(&info.version),
SPA_POD_String(&info.name), 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) SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL; return -EINVAL;
@ -161,7 +174,7 @@ static int core_demarshal_done(void *object, void *data, size_t size)
struct spa_pod_parser prs; struct spa_pod_parser prs;
uint32_t seq; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq)) < 0) SPA_POD_Int(&seq)) < 0)
return -EINVAL; return -EINVAL;
@ -177,7 +190,7 @@ static int core_demarshal_error(void *object, void *data, size_t size)
uint32_t id, res; uint32_t id, res;
const char *error; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&id), SPA_POD_Int(&id),
SPA_POD_Int(&res), 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; struct spa_pod_parser prs;
uint32_t id; 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) if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&id)) < 0)
return -EINVAL; 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 pw_resource *resource = object;
struct spa_pod_builder *b; 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); 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_builder_add(b,
"[",
SPA_POD_Int(info->id), SPA_POD_Int(info->id),
SPA_POD_Long(info->change_mask), SPA_POD_Long(info->change_mask),
SPA_POD_String(info->user_name), 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->version),
SPA_POD_String(info->name), SPA_POD_String(info->name),
SPA_POD_Int(info->cookie), SPA_POD_Int(info->cookie),
SPA_POD_Int(n_items),
NULL); NULL);
push_dict(b, info->props);
for (i = 0; i < n_items; i++) { spa_pod_builder_pop(b, &f);
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);
pw_protocol_native_end_resource(resource, b); 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; struct spa_pod_parser prs;
uint32_t version; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&version)) < 0) SPA_POD_Int(&version)) < 0)
return -EINVAL; return -EINVAL;
@ -303,7 +307,7 @@ static int core_demarshal_sync(void *object, void *data, size_t size)
struct spa_pod_parser prs; struct spa_pod_parser prs;
uint32_t seq; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&seq)) < 0) SPA_POD_Int(&seq)) < 0)
return -EINVAL; return -EINVAL;
@ -318,7 +322,7 @@ static int core_demarshal_get_registry(void *object, void *data, size_t size)
struct spa_pod_parser prs; struct spa_pod_parser prs;
int32_t version, new_id; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&version), SPA_POD_Int(&version),
SPA_POD_Int(&new_id)) < 0) 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 pw_resource *resource = object;
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f[2];
uint32_t version, type, new_id, i; uint32_t version, type, new_id, i;
const char *factory_name; const char *factory_name;
struct spa_dict props; struct spa_dict props;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get(&prs, if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
"[" spa_pod_parser_get(&prs,
SPA_POD_String(&factory_name), SPA_POD_String(&factory_name),
SPA_POD_Id(&type), 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) SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL; 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) SPA_POD_String(&props.items[i].value), NULL) < 0)
return -EINVAL; return -EINVAL;
} }
spa_pod_parser_pop(&prs, &f[1]);
if (spa_pod_parser_get(&prs, if (spa_pod_parser_get(&prs,
SPA_POD_Int(&new_id), NULL) < 0) SPA_POD_Int(&new_id), NULL) < 0)
return -EINVAL; return -EINVAL;
@ -368,7 +380,7 @@ static int core_demarshal_destroy(void *object, void *data, size_t size)
struct spa_pod_parser prs; struct spa_pod_parser prs;
uint32_t id; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&id)) < 0) SPA_POD_Int(&id)) < 0)
return -EINVAL; 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 pw_resource *resource = object;
struct spa_pod_builder *b; 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); 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_builder_add(b,
"[",
SPA_POD_Int(id), SPA_POD_Int(id),
SPA_POD_Int(parent_id), SPA_POD_Int(parent_id),
SPA_POD_Int(permissions), SPA_POD_Int(permissions),
SPA_POD_Id(type), SPA_POD_Id(type),
SPA_POD_Int(version), SPA_POD_Int(version),
SPA_POD_Int(n_items), NULL); NULL);
push_dict(b, props);
for (i = 0; i < n_items; i++) { spa_pod_builder_pop(b, &f);
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);
pw_protocol_native_end_resource(resource, b); 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; struct spa_pod_parser prs;
uint32_t id, version, type, new_id; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&id), SPA_POD_Int(&id),
SPA_POD_Id(&type), 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; struct spa_pod_parser prs;
uint32_t id; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&id)) < 0) SPA_POD_Int(&id)) < 0)
return -EINVAL; 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 pw_resource *resource = object;
struct spa_pod_builder *b; 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); 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_builder_add(b,
"[",
SPA_POD_Int(info->id), SPA_POD_Int(info->id),
SPA_POD_Long(info->change_mask), SPA_POD_Long(info->change_mask),
SPA_POD_String(info->name), SPA_POD_String(info->name),
SPA_POD_String(info->filename), SPA_POD_String(info->filename),
SPA_POD_String(info->args), SPA_POD_String(info->args),
SPA_POD_Int(n_items), NULL); NULL);
push_dict(b, info->props);
for (i = 0; i < n_items; i++) { spa_pod_builder_pop(b, &f);
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);
pw_protocol_native_end_resource(resource, b); 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 pw_proxy *proxy = object;
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f[2];
struct spa_dict props; struct spa_dict props;
struct pw_module_info info; struct pw_module_info info;
uint32_t i; uint32_t i;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get(&prs, if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
"[" spa_pod_parser_get(&prs,
SPA_POD_Int(&info.id), SPA_POD_Int(&info.id),
SPA_POD_Long(&info.change_mask), SPA_POD_Long(&info.change_mask),
SPA_POD_String(&info.name), SPA_POD_String(&info.name),
SPA_POD_String(&info.filename), 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) SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL; 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 pw_resource *resource = object;
struct spa_pod_builder *b; 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); 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_builder_add(b,
"[",
SPA_POD_Int(info->id), SPA_POD_Int(info->id),
SPA_POD_String(info->name), SPA_POD_String(info->name),
SPA_POD_Long(info->change_mask), SPA_POD_Long(info->change_mask),
SPA_POD_Int(n_items), NULL); NULL);
push_dict(b, info->props);
for (i = 0; i < n_items; i++) { spa_pod_builder_pop(b, &f);
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);
pw_protocol_native_end_resource(resource, b); 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 pw_proxy *proxy = object;
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f[2];
struct spa_dict props; struct spa_dict props;
struct pw_device_info info; struct pw_device_info info;
uint32_t i; uint32_t i;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get(&prs, if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
"[" spa_pod_parser_get(&prs,
SPA_POD_Int(&info.id), SPA_POD_Int(&info.id),
SPA_POD_String(&info.name), 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) SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL; return -EINVAL;
@ -592,7 +593,7 @@ static int device_demarshal_param(void *object, void *data, size_t size)
uint32_t id, index, next; uint32_t id, index, next;
struct spa_pod *param; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id), SPA_POD_Id(&id),
SPA_POD_Int(&index), 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; uint32_t id, index, num;
struct spa_pod *filter; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id), SPA_POD_Id(&id),
SPA_POD_Int(&index), 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; uint32_t id, flags;
struct spa_pod *param; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id), SPA_POD_Id(&id),
SPA_POD_Int(&flags), 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 pw_resource *resource = object;
struct spa_pod_builder *b; 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); 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_builder_add(b,
"[",
SPA_POD_Int(info->id), SPA_POD_Int(info->id),
SPA_POD_Long(info->change_mask), SPA_POD_Long(info->change_mask),
SPA_POD_String(info->name), SPA_POD_String(info->name),
SPA_POD_Id(info->type), SPA_POD_Id(info->type),
SPA_POD_Int(info->version), SPA_POD_Int(info->version),
SPA_POD_Int(n_items), NULL); NULL);
push_dict(b, info->props);
for (i = 0; i < n_items; i++) { spa_pod_builder_pop(b, &f);
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);
pw_protocol_native_end_resource(resource, b); 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 pw_proxy *proxy = object;
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f[2];
struct spa_dict props; struct spa_dict props;
struct pw_factory_info info; struct pw_factory_info info;
uint32_t i; uint32_t i;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get(&prs, if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
"[" spa_pod_parser_get(&prs,
SPA_POD_Int(&info.id), SPA_POD_Int(&info.id),
SPA_POD_Long(&info.change_mask), SPA_POD_Long(&info.change_mask),
SPA_POD_String(&info.name), SPA_POD_String(&info.name),
SPA_POD_Id(&info.type), 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) SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL; 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 pw_resource *resource = object;
struct spa_pod_builder *b; 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); 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_builder_add(b,
"[",
SPA_POD_Int(info->id), SPA_POD_Int(info->id),
SPA_POD_Long(info->change_mask), SPA_POD_Long(info->change_mask),
SPA_POD_String(info->name), 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_Int(info->n_output_ports),
SPA_POD_Id(info->state), SPA_POD_Id(info->state),
SPA_POD_String(info->error), SPA_POD_String(info->error),
SPA_POD_Int(n_items), NULL); NULL);
push_dict(b, info->props);
for (i = 0; i < n_items; i++) { spa_pod_builder_pop(b, &f);
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);
pw_protocol_native_end_resource(resource, b); 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 pw_proxy *proxy = object;
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f[2];
struct spa_dict props; struct spa_dict props;
struct pw_node_info info; struct pw_node_info info;
uint32_t i; uint32_t i;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get(&prs, if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
"[" spa_pod_parser_get(&prs,
SPA_POD_Int(&info.id), SPA_POD_Int(&info.id),
SPA_POD_Long(&info.change_mask), SPA_POD_Long(&info.change_mask),
SPA_POD_String(&info.name), 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.max_output_ports),
SPA_POD_Int(&info.n_output_ports), SPA_POD_Int(&info.n_output_ports),
SPA_POD_Id(&info.state), 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) SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL; return -EINVAL;
@ -825,7 +822,7 @@ static int node_demarshal_param(void *object, void *data, size_t size)
uint32_t id, index, next; uint32_t id, index, next;
struct spa_pod *param; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id), SPA_POD_Id(&id),
SPA_POD_Int(&index), 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; uint32_t id, index, num;
struct spa_pod *filter; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id), SPA_POD_Id(&id),
SPA_POD_Int(&index), 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; uint32_t id, flags;
struct spa_pod *param; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id), SPA_POD_Id(&id),
SPA_POD_Int(&flags), 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_pod_parser prs;
struct spa_command *command; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Pod(&command)) < 0) SPA_POD_Pod(&command)) < 0)
return -EINVAL; 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 pw_resource *resource = object;
struct spa_pod_builder *b; 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); 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_builder_add(b,
"[",
SPA_POD_Int(info->id), SPA_POD_Int(info->id),
SPA_POD_Int(info->direction), SPA_POD_Int(info->direction),
SPA_POD_Long(info->change_mask), SPA_POD_Long(info->change_mask),
SPA_POD_Int(n_items), NULL); NULL);
push_dict(b, info->props);
for (i = 0; i < n_items; i++) { spa_pod_builder_pop(b, &f);
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);
pw_protocol_native_end_resource(resource, b); 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 pw_proxy *proxy = object;
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f[2];
struct spa_dict props; struct spa_dict props;
struct pw_port_info info; struct pw_port_info info;
uint32_t i; uint32_t i;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get(&prs, if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
"[" spa_pod_parser_get(&prs,
SPA_POD_Int(&info.id), SPA_POD_Int(&info.id),
SPA_POD_Int(&info.direction), 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) SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL; return -EINVAL;
@ -1012,7 +1007,7 @@ static int port_demarshal_param(void *object, void *data, size_t size)
uint32_t id, index, next; uint32_t id, index, next;
struct spa_pod *param; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id), SPA_POD_Id(&id),
SPA_POD_Int(&index), 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; uint32_t id, index, num;
struct spa_pod *filter; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Id(&id), SPA_POD_Id(&id),
SPA_POD_Int(&index), 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 pw_resource *resource = object;
struct spa_pod_builder *b; 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); 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_builder_add(b,
"[",
SPA_POD_Int(info->id), SPA_POD_Int(info->id),
SPA_POD_Long(info->change_mask), SPA_POD_Long(info->change_mask),
SPA_POD_Int(n_items), NULL); NULL);
push_dict(b, info->props);
for (i = 0; i < n_items; i++) { spa_pod_builder_pop(b, &f);
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);
pw_protocol_native_end_resource(resource, b); 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 pw_proxy *proxy = object;
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f[2];
struct spa_dict props; struct spa_dict props;
struct pw_client_info info; struct pw_client_info info;
uint32_t i; uint32_t i;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get(&prs, if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
"[" spa_pod_parser_get(&prs,
SPA_POD_Int(&info.id), 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) SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL; 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 pw_resource *resource = object;
struct spa_pod_builder *b; struct spa_pod_builder *b;
struct spa_pod_frame f[2];
uint32_t i, n = 0; uint32_t i, n = 0;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_PROXY_EVENT_PERMISSIONS); 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++; n++;
} }
spa_pod_builder_add(b, spa_pod_builder_push_struct(b, &f[0]);
"[", spa_pod_builder_int(b, index);
SPA_POD_Int(index), spa_pod_builder_push_struct(b, &f[1]);
SPA_POD_Int(n), NULL); spa_pod_builder_int(b, n);
for (i = 0; i < n_permissions; i++) { for (i = 0; i < n_permissions; i++) {
if (permissions[i].permissions == SPA_ID_INVALID) if (permissions[i].permissions == SPA_ID_INVALID)
continue; continue;
spa_pod_builder_add(b, spa_pod_builder_int(b, permissions[i].id);
SPA_POD_Int(permissions[i].id), spa_pod_builder_int(b, permissions[i].permissions);
SPA_POD_Int(permissions[i].permissions), NULL);
} }
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); 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_proxy *proxy = object;
struct pw_permission *permissions; struct pw_permission *permissions;
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f[2];
uint32_t i, index, n_permissions; uint32_t i, index, n_permissions;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get(&prs, "[", if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
SPA_POD_Int(&index), spa_pod_parser_get(&prs,
SPA_POD_Int(&n_permissions), NULL) < 0) 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; return -EINVAL;
permissions = alloca(n_permissions * sizeof(struct pw_permission)); 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; uint32_t id, res;
const char *error; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&id), SPA_POD_Int(&id),
SPA_POD_Int(&res), 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 pw_proxy *proxy = object;
struct spa_pod_builder *b; 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); b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_PROXY_METHOD_UPDATE_PROPERTIES);
n_items = props ? props->n_items : 0; spa_pod_builder_push_struct(b, &f);
push_dict(b, props);
spa_pod_builder_add(b, "[", spa_pod_builder_pop(b, &f);
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);
pw_protocol_native_end_proxy(proxy, b); 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 pw_resource *resource = object;
struct spa_dict props; struct spa_dict props;
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f[2];
uint32_t i; uint32_t i;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get(&prs, if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
"[", spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
SPA_POD_Int(&props.n_items), NULL) < 0) spa_pod_parser_get(&prs,
SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL; return -EINVAL;
props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); 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; struct spa_pod_parser prs;
uint32_t index, num; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&index), SPA_POD_Int(&index),
SPA_POD_Int(&num)) < 0) 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 pw_proxy *proxy = object;
struct spa_pod_builder *b; struct spa_pod_builder *b;
struct spa_pod_frame f;
uint32_t i; uint32_t i;
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_PROXY_METHOD_UPDATE_PERMISSIONS); b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_PROXY_METHOD_UPDATE_PERMISSIONS);
spa_pod_builder_add(b, "[", spa_pod_builder_push_struct(b, &f);
SPA_POD_Int(n_permissions), NULL); spa_pod_builder_int(b, n_permissions);
for (i = 0; i < n_permissions; i++) { for (i = 0; i < n_permissions; i++) {
spa_pod_builder_add(b, spa_pod_builder_int(b, permissions[i].id);
SPA_POD_Int(permissions[i].id), spa_pod_builder_int(b, permissions[i].permissions);
SPA_POD_Int(permissions[i].permissions), NULL);
} }
spa_pod_builder_add(b, "]", NULL); spa_pod_builder_pop(b, &f);
pw_protocol_native_end_proxy(proxy, b); 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_resource *resource = object;
struct pw_permission *permissions; struct pw_permission *permissions;
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f[1];
uint32_t i, n_permissions; uint32_t i, n_permissions;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get(&prs, if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
"[", spa_pod_parser_get(&prs,
SPA_POD_Int(&n_permissions), NULL) < 0) SPA_POD_Int(&n_permissions), NULL) < 0)
return -EINVAL; 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 pw_resource *resource = object;
struct spa_pod_builder *b; 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); 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_builder_add(b,
"[",
SPA_POD_Int(info->id), SPA_POD_Int(info->id),
SPA_POD_Long(info->change_mask), SPA_POD_Long(info->change_mask),
SPA_POD_Int(info->output_node_id), 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_Int(info->state),
SPA_POD_String(info->error), SPA_POD_String(info->error),
SPA_POD_Pod(info->format), SPA_POD_Pod(info->format),
SPA_POD_Int(n_items), NULL); NULL);
push_dict(b, info->props);
for (i = 0; i < n_items; i++) { spa_pod_builder_pop(b, &f);
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);
pw_protocol_native_end_resource(resource, b); 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 pw_proxy *proxy = object;
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f[2];
struct spa_dict props; struct spa_dict props;
struct pw_link_info info = { 0, }; struct pw_link_info info = { 0, };
uint32_t i; uint32_t i;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get(&prs, if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
"[" spa_pod_parser_get(&prs,
SPA_POD_Int(&info.id), SPA_POD_Int(&info.id),
SPA_POD_Long(&info.change_mask), SPA_POD_Long(&info.change_mask),
SPA_POD_Int(&info.output_node_id), 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.input_port_id),
SPA_POD_Int(&info.state), SPA_POD_Int(&info.state),
SPA_POD_String(&info.error), 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) SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL; return -EINVAL;
@ -1397,17 +1389,22 @@ static int registry_demarshal_global(void *object, void *data, size_t size)
{ {
struct pw_proxy *proxy = object; struct pw_proxy *proxy = object;
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f[2];
uint32_t id, parent_id, permissions, type, version, i; uint32_t id, parent_id, permissions, type, version, i;
struct spa_dict props; struct spa_dict props;
spa_pod_parser_init(&prs, data, size, 0); spa_pod_parser_init(&prs, data, size);
if (spa_pod_parser_get(&prs, if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
"[" spa_pod_parser_get(&prs,
SPA_POD_Int(&id), SPA_POD_Int(&id),
SPA_POD_Int(&parent_id), SPA_POD_Int(&parent_id),
SPA_POD_Int(&permissions), SPA_POD_Int(&permissions),
SPA_POD_Id(&type), 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) SPA_POD_Int(&props.n_items), NULL) < 0)
return -EINVAL; return -EINVAL;
@ -1431,7 +1428,7 @@ static int registry_demarshal_global_remove(void *object, void *data, size_t siz
struct spa_pod_parser prs; struct spa_pod_parser prs;
uint32_t id; 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, if (spa_pod_parser_get_struct(&prs,
SPA_POD_Int(&id)) < 0) SPA_POD_Int(&id)) < 0)
return -EINVAL; return -EINVAL;

View file

@ -102,12 +102,15 @@ static struct monitor_item *add_item(struct pw_spa_monitor *this,
if (info) { if (info) {
struct spa_pod_parser prs; struct spa_pod_parser prs;
struct spa_pod_frame f;
spa_pod_parser_pod(&prs, info); 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) { while (true) {
const char *key, *val; 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; break;
pw_properties_set(props, key, val); 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; uint32_t index = 0;
uint8_t buf[2048]; uint8_t buf[2048];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf)); 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) { 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); 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))) { while ((key = pw_properties_iterate(pw_props, &state))) {
struct spa_pod_prop *prop;
uint32_t type = 0; uint32_t type = 0;
type = spa_debug_type_find_type(NULL, key); type = spa_debug_type_find_type(NULL, key);
if (type == SPA_TYPE_None) if (type == SPA_TYPE_None)
continue; 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); const char *value = pw_properties_get(pw_props, key);
pw_log_info("configure prop %s", 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_pod_parse_object(param,
SPA_TYPE_OBJECT_ParamBuffers, NULL, 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_size, SPA_POD_Int(&qminsize),
SPA_PARAM_BUFFERS_stride, SPA_POD_Int(&qstride), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(&qstride));
SPA_PARAM_BUFFERS_buffers, SPA_POD_Int(&qmax_buffers));
max_buffers = max_buffers =
qmax_buffers == 0 ? max_buffers : SPA_MIN(qmax_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 }; struct spa_pod_builder b = { 0 };
bool changed; bool changed;
struct spa_pod_frame f[2];
spa_pod_builder_init(&b, impl->io_notify, impl->io_notify_size); 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)) { if ((changed = impl->props.changed)) {
spa_pod_builder_control(&b, 0, SPA_CONTROL_Properties); 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_prop(&b, SPA_PROP_volume, 0);
spa_pod_builder_float(&b, impl->props.volume); spa_pod_builder_float(&b, impl->props.volume);
spa_pod_builder_pop(&b); spa_pod_builder_pop(&b, &f[1]);
impl->props.changed = false; 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)) if (changed && pw_log_level_enabled(SPA_LOG_LEVEL_DEBUG))
spa_debug_pod(2, NULL, &impl->io_notify->sequence.pod); spa_debug_pod(2, NULL, &impl->io_notify->sequence.pod);