diff --git a/Makefile.in b/Makefile.in index 6cfafc28c..f476f5044 100644 --- a/Makefile.in +++ b/Makefile.in @@ -25,6 +25,9 @@ valgrind: test: all ninja -C build test +benchmark: all + ninja -C build benchmark + monitor: all SPA_PLUGIN_DIR=build/spa/plugins \ PIPEWIRE_MODULE_DIR=build/src/modules/ \ diff --git a/pipewire-jack b/pipewire-jack index 4bdaa083d..c404942e9 160000 --- a/pipewire-jack +++ b/pipewire-jack @@ -1 +1 @@ -Subproject commit 4bdaa083d13771e37d7d2c1e20953c7b617dfa2b +Subproject commit c404942e9d15bd3340c57121753fed8d38b247c6 diff --git a/spa/examples/example-control.c b/spa/examples/example-control.c index 84db5ec34..e23f30b8b 100644 --- a/spa/examples/example-control.c +++ b/spa/examples/example-control.c @@ -198,27 +198,28 @@ static void update_props(struct data *data) { struct spa_pod_builder b; struct spa_pod *pod; + struct spa_pod_frame f[2]; spa_pod_builder_init(&b, data->ctrl, sizeof(data->ctrl)); #if 0 - spa_pod_builder_push_sequence(&b, 0); + spa_pod_builder_push_sequence(&b, &f[0], 0); spa_pod_builder_control(&b, 0, SPA_CONTROL_Properties); - spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_Props, 0); + spa_pod_builder_push_object(&b, &f[1], SPA_TYPE_OBJECT_Props, 0); spa_pod_builder_prop(&b, SPA_PROP_frequency, 0); spa_pod_builder_float(&b, ((sin(data->freq_accum) + 1.0) * 200.0) + 440.0); spa_pod_builder_prop(&b, SPA_PROP_volume, 0); spa_pod_builder_float(&b, (sin(data->volume_accum) / 2.0) + 0.5); - spa_pod_builder_pop(&b); - pod = spa_pod_builder_pop(&b); + spa_pod_builder_pop(&b, &f[1]); + pod = spa_pod_builder_pop(&b, &f[0]); #else - spa_pod_builder_push_sequence(&b, 0); + spa_pod_builder_push_sequence(&b, &f[0], 0); spa_pod_builder_control(&b, 0, SPA_CONTROL_Properties); spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_Props, 0, SPA_PROP_frequency, SPA_POD_Float(((sin(data->freq_accum) + 1.0) * 200.0) + 440.0), SPA_PROP_volume, SPA_POD_Float((sin(data->volume_accum) / 2.0) + 0.5)); - pod = spa_pod_builder_pop(&b); + pod = spa_pod_builder_pop(&b, &f[0]); #endif spa_debug_pod(0, NULL, pod); @@ -386,9 +387,10 @@ static int negotiate_formats(struct data *data) filter, &format, &b)) <= 0) return -EBADF; - spa_debug_pod(0, NULL, format); - spa_log_debug(&default_log.log, "sink set_param"); + spa_debug_pod(0, NULL, format); + spa_pod_fixate(format); + if ((res = spa_node_port_set_param(data->sink, SPA_DIRECTION_INPUT, 0, SPA_PARAM_Format, 0, format)) < 0) @@ -527,11 +529,11 @@ int main(int argc, char *argv[]) data.n_support = 3; if ((res = make_nodes(&data, argc > 1 ? argv[1] : NULL)) < 0) { - printf("can't make nodes: %d\n", res); + printf("can't make nodes: %d (%s)\n", res, spa_strerror(res)); return -1; } if ((res = negotiate_formats(&data)) < 0) { - printf("can't negotiate nodes: %d\n", res); + printf("can't negotiate nodes: %d (%s)\n", res, spa_strerror(res)); return -1; } diff --git a/spa/include/spa/param/audio/format-utils.h b/spa/include/spa/param/audio/format-utils.h index 1ee6084d6..39c52e32f 100644 --- a/spa/include/spa/param/audio/format-utils.h +++ b/spa/include/spa/param/audio/format-utils.h @@ -39,15 +39,13 @@ static inline int spa_format_audio_raw_parse(const struct spa_pod *format, struct spa_audio_info_raw *info) { struct spa_pod *position = NULL; - struct spa_pod_parser prs; int res; - spa_pod_parser_pod(&prs, format); - res = spa_pod_parser_get_object(&prs, + info->flags = 0; + res = spa_pod_parse_object(format, SPA_TYPE_OBJECT_Format, NULL, SPA_FORMAT_AUDIO_format, SPA_POD_Id(&info->format), SPA_FORMAT_AUDIO_rate, SPA_POD_Int(&info->rate), SPA_FORMAT_AUDIO_channels, SPA_POD_Int(&info->channels), - SPA_FORMAT_AUDIO_flags, SPA_POD_OPT_Int(&info->flags), SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position)); if (position && spa_pod_is_array(position) && SPA_POD_ARRAY_VALUE_TYPE(position) == SPA_TYPE_Id) { @@ -64,7 +62,8 @@ spa_format_audio_raw_parse(const struct spa_pod *format, struct spa_audio_info_r static inline struct spa_pod * spa_format_audio_raw_build(struct spa_pod_builder *builder, uint32_t id, struct spa_audio_info_raw *info) { - spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_Format, id); + struct spa_pod_frame f; + spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id); spa_pod_builder_add(builder, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), @@ -78,7 +77,7 @@ spa_format_audio_raw_build(struct spa_pod_builder *builder, uint32_t id, struct spa_pod_builder_array(builder, sizeof(uint32_t), SPA_TYPE_Id, info->channels, info->position); } - return (struct spa_pod*)spa_pod_builder_pop(builder); + return (struct spa_pod*)spa_pod_builder_pop(builder, &f); } diff --git a/spa/include/spa/pod/builder.h b/spa/include/spa/pod/builder.h index f5af63337..642bc4cb3 100644 --- a/spa/include/spa/pod/builder.h +++ b/spa/include/spa/pod/builder.h @@ -31,37 +31,31 @@ extern "C" { #include -#include - -struct spa_pod_frame { - struct spa_pod pod; - uint32_t ref; - uint32_t _padding; -}; +#include struct spa_pod_builder_state { uint32_t offset; #define SPA_POD_BUILDER_FLAG_BODY (1<<0) #define SPA_POD_BUILDER_FLAG_FIRST (1<<1) -#define SPA_POD_BUILDER_FLAG_OBJECT (1<<2) -#define SPA_POD_BUILDER_FLAG_SEQUENCE (1<<3) -#define SPA_POD_BUILDER_FLAG_HEADER (1<<4) uint32_t flags; - uint32_t depth; - uint32_t _padding; + struct spa_pod_frame *frame; +}; + +struct spa_pod_builder; + +struct spa_pod_builder_callbacks { +#define SPA_VERSION_POD_BUILDER_CALLBACKS 0 + uint32_t version; + int (*overflow) (void *callbacks_data, uint32_t size); }; struct spa_pod_builder { void *data; uint32_t size; uint32_t _padding; - - uint32_t (*write) (struct spa_pod_builder *builder, const void *data, uint32_t size); - void * (*deref) (struct spa_pod_builder *builder, uint32_t ref, bool safe); - void (*reset) (struct spa_pod_builder *builder, struct spa_pod_builder_state *state); - struct spa_pod_builder_state state; - struct spa_pod_frame frame[SPA_POD_MAX_DEPTH]; + const struct spa_pod_builder_callbacks *callbacks; + void *callbacks_data; }; #define SPA_POD_BUILDER_INIT(buffer,size) (struct spa_pod_builder){ buffer, size, } @@ -75,10 +69,7 @@ spa_pod_builder_get_state(struct spa_pod_builder *builder, struct spa_pod_builde static inline void spa_pod_builder_reset(struct spa_pod_builder *builder, struct spa_pod_builder_state *state) { - if (builder->reset) - builder->reset(builder, state); - else - builder->state = *state; + builder->state = *state; } static inline void spa_pod_builder_init(struct spa_pod_builder *builder, void *data, uint32_t size) @@ -86,128 +77,97 @@ static inline void spa_pod_builder_init(struct spa_pod_builder *builder, void *d *builder = SPA_POD_BUILDER_INIT(data, size); } -static inline struct spa_pod_frame * -spa_pod_builder_top(struct spa_pod_builder *builder) +static inline struct spa_pod * +spa_pod_builder_deref(struct spa_pod_builder *builder, uint32_t offset, uint32_t size) { - return builder->state.depth > 0 ? &builder->frame[builder->state.depth-1] : NULL; -} - -static inline void * -spa_pod_builder_deref_checked(struct spa_pod_builder *builder, uint32_t ref, bool safe) -{ - if (ref == SPA_ID_INVALID) - return NULL; - else if (builder->deref) - return builder->deref(builder, ref, safe); - else if (ref + 8 <= builder->size) { - struct spa_pod *pod = SPA_MEMBER(builder->data, ref, struct spa_pod); - if (!safe || SPA_POD_SIZE(pod) <= builder->size) - return (void *) pod; + if (offset + 8 <= size) { + struct spa_pod *pod = SPA_MEMBER(builder->data, offset, struct spa_pod); + if (offset + SPA_POD_SIZE(pod) <= size) + return pod; } return NULL; } -static inline void * -spa_pod_builder_deref(struct spa_pod_builder *builder, uint32_t ref) +static inline struct spa_pod * +spa_pod_builder_frame(struct spa_pod_builder *builder, struct spa_pod_frame *frame) { - return spa_pod_builder_deref_checked(builder, ref, false); + return spa_pod_builder_deref(builder, frame->offset, builder->size); } static inline void -spa_pod_builder_update_frame(struct spa_pod_builder *builder, struct spa_pod_frame *frame) -{ - switch (frame->pod.type) { - case SPA_TYPE_Array: - case SPA_TYPE_Choice: - builder->state.flags = SPA_POD_BUILDER_FLAG_BODY; - break; - case SPA_TYPE_Object: - builder->state.flags = SPA_POD_BUILDER_FLAG_OBJECT; - break; - case SPA_TYPE_Sequence: - builder->state.flags = SPA_POD_BUILDER_FLAG_SEQUENCE; - break; - } -} - -static inline uint32_t spa_pod_builder_push(struct spa_pod_builder *builder, + struct spa_pod_frame *frame, const struct spa_pod *pod, - uint32_t ref) + uint32_t offset) { - struct spa_pod_frame *frame = &builder->frame[builder->state.depth++]; frame->pod = *pod; - frame->ref = ref; - spa_pod_builder_update_frame(builder, frame); - if (builder->state.flags & SPA_POD_BUILDER_FLAG_BODY) - SPA_FLAG_SET(builder->state.flags, SPA_POD_BUILDER_FLAG_FIRST); - return ref; + frame->offset = offset; + frame->parent = builder->state.frame; + frame->flags = builder->state.flags; + builder->state.frame = frame; + + if (frame->pod.type == SPA_TYPE_Array || frame->pod.type == SPA_TYPE_Choice) + builder->state.flags = SPA_POD_BUILDER_FLAG_FIRST | SPA_POD_BUILDER_FLAG_BODY; } -static inline uint32_t -spa_pod_builder_raw(struct spa_pod_builder *builder, const void *data, uint32_t size) +static inline int spa_pod_builder_raw(struct spa_pod_builder *builder, const void *data, uint32_t size) { - uint32_t i, ref; + int res = 0; + struct spa_pod_frame *f; + uint32_t offset = builder->state.offset; - if (builder->write) { - ref = builder->write(builder, data, size); - } else { - ref = builder->state.offset; - if (ref + size > builder->size) - ref = SPA_ID_INVALID; + if (offset + size > builder->size) { + if (builder->callbacks && builder->callbacks->overflow) + res = builder->callbacks->overflow(builder->callbacks_data, offset + size); else - memcpy(SPA_MEMBER(builder->data, ref, void), data, size); + res = -ENOSPC; } + if (res == 0) + memcpy(SPA_MEMBER(builder->data, offset, void), data, size); builder->state.offset += size; - for (i = 0; i < builder->state.depth; i++) - builder->frame[i].pod.size += size; + for (f = builder->state.frame; f ; f = f->parent) + f->pod.size += size; - return ref; + return res; } -static inline void spa_pod_builder_pad(struct spa_pod_builder *builder, uint32_t size) +static inline int spa_pod_builder_pad(struct spa_pod_builder *builder, uint32_t size) { uint64_t zeroes = 0; size = SPA_ROUND_UP_N(size, 8) - size; - if (size) - spa_pod_builder_raw(builder, &zeroes, size); - SPA_FLAG_UNSET(builder->state.flags, SPA_POD_BUILDER_FLAG_HEADER); + return size ? spa_pod_builder_raw(builder, &zeroes, size) : 0; } -static inline uint32_t +static inline int spa_pod_builder_raw_padded(struct spa_pod_builder *builder, const void *data, uint32_t size) { - uint32_t ref = size ? spa_pod_builder_raw(builder, data, size) : SPA_ID_INVALID; - spa_pod_builder_pad(builder, size); - return ref; + int r, res = spa_pod_builder_raw(builder, data, size); + if ((r = spa_pod_builder_pad(builder, size)) < 0) + res = r; + return res; } -static inline void *spa_pod_builder_pop(struct spa_pod_builder *builder) +static inline void *spa_pod_builder_pop(struct spa_pod_builder *builder, struct spa_pod_frame *frame) { - struct spa_pod_frame *frame; struct spa_pod *pod; - frame = &builder->frame[--builder->state.depth]; - if ((pod = (struct spa_pod *) spa_pod_builder_deref_checked(builder, frame->ref, true)) != NULL) + if ((pod = (struct spa_pod *) spa_pod_builder_frame(builder, frame)) != NULL) *pod = frame->pod; - if ((frame = spa_pod_builder_top(builder)) != NULL) - spa_pod_builder_update_frame(builder, frame); - else - builder->state.flags = 0; - + builder->state.frame = frame->parent; + builder->state.flags = frame->flags; spa_pod_builder_pad(builder, builder->state.offset); - return pod; } -static inline uint32_t +static inline int spa_pod_builder_primitive(struct spa_pod_builder *builder, const struct spa_pod *p) { const void *data; - uint32_t size, ref; + uint32_t size; + int r, res; if (builder->state.flags == SPA_POD_BUILDER_FLAG_BODY) { data = SPA_POD_BODY_CONST(p); @@ -217,18 +177,18 @@ spa_pod_builder_primitive(struct spa_pod_builder *builder, const struct spa_pod size = SPA_POD_SIZE(p); SPA_FLAG_UNSET(builder->state.flags, SPA_POD_BUILDER_FLAG_FIRST); } - ref = spa_pod_builder_raw(builder, data, size); + res = spa_pod_builder_raw(builder, data, size); if (builder->state.flags != SPA_POD_BUILDER_FLAG_BODY) - spa_pod_builder_pad(builder, size); - - return ref; + if ((r = spa_pod_builder_pad(builder, size)) < 0) + res = r; + return res; } #define SPA_POD_INIT(size,type) (struct spa_pod) { size, type } #define SPA_POD_INIT_None() SPA_POD_INIT(0, SPA_TYPE_None) -static inline uint32_t spa_pod_builder_none(struct spa_pod_builder *builder) +static inline int spa_pod_builder_none(struct spa_pod_builder *builder) { const struct spa_pod p = SPA_POD_INIT_None(); return spa_pod_builder_primitive(builder, &p); @@ -236,7 +196,7 @@ static inline uint32_t spa_pod_builder_none(struct spa_pod_builder *builder) #define SPA_POD_INIT_Bool(val) (struct spa_pod_bool){ { sizeof(uint32_t), SPA_TYPE_Bool }, val ? 1 : 0, 0 } -static inline uint32_t spa_pod_builder_bool(struct spa_pod_builder *builder, bool val) +static inline int spa_pod_builder_bool(struct spa_pod_builder *builder, bool val) { const struct spa_pod_bool p = SPA_POD_INIT_Bool(val); return spa_pod_builder_primitive(builder, &p.pod); @@ -244,7 +204,7 @@ static inline uint32_t spa_pod_builder_bool(struct spa_pod_builder *builder, boo #define SPA_POD_INIT_Id(val) (struct spa_pod_id){ { sizeof(uint32_t), SPA_TYPE_Id }, (uint32_t)val, 0 } -static inline uint32_t spa_pod_builder_id(struct spa_pod_builder *builder, uint32_t val) +static inline int spa_pod_builder_id(struct spa_pod_builder *builder, uint32_t val) { const struct spa_pod_id p = SPA_POD_INIT_Id(val); return spa_pod_builder_primitive(builder, &p.pod); @@ -252,7 +212,7 @@ static inline uint32_t spa_pod_builder_id(struct spa_pod_builder *builder, uint3 #define SPA_POD_INIT_Int(val) (struct spa_pod_int){ { sizeof(int32_t), SPA_TYPE_Int }, (int32_t)val, 0 } -static inline uint32_t spa_pod_builder_int(struct spa_pod_builder *builder, int32_t val) +static inline int spa_pod_builder_int(struct spa_pod_builder *builder, int32_t val) { const struct spa_pod_int p = SPA_POD_INIT_Int(val); return spa_pod_builder_primitive(builder, &p.pod); @@ -260,7 +220,7 @@ static inline uint32_t spa_pod_builder_int(struct spa_pod_builder *builder, int3 #define SPA_POD_INIT_Long(val) (struct spa_pod_long){ { sizeof(int64_t), SPA_TYPE_Long }, (int64_t)val } -static inline uint32_t spa_pod_builder_long(struct spa_pod_builder *builder, int64_t val) +static inline int spa_pod_builder_long(struct spa_pod_builder *builder, int64_t val) { const struct spa_pod_long p = SPA_POD_INIT_Long(val); return spa_pod_builder_primitive(builder, &p.pod); @@ -268,7 +228,7 @@ static inline uint32_t spa_pod_builder_long(struct spa_pod_builder *builder, int #define SPA_POD_INIT_Float(val) (struct spa_pod_float){ { sizeof(float), SPA_TYPE_Float }, val } -static inline uint32_t spa_pod_builder_float(struct spa_pod_builder *builder, float val) +static inline int spa_pod_builder_float(struct spa_pod_builder *builder, float val) { const struct spa_pod_float p = SPA_POD_INIT_Float(val); return spa_pod_builder_primitive(builder, &p.pod); @@ -276,7 +236,7 @@ static inline uint32_t spa_pod_builder_float(struct spa_pod_builder *builder, fl #define SPA_POD_INIT_Double(val) (struct spa_pod_double){ { sizeof(double), SPA_TYPE_Double }, val } -static inline uint32_t spa_pod_builder_double(struct spa_pod_builder *builder, double val) +static inline int spa_pod_builder_double(struct spa_pod_builder *builder, double val) { const struct spa_pod_double p = SPA_POD_INIT_Double(val); return spa_pod_builder_primitive(builder, &p.pod); @@ -284,29 +244,29 @@ static inline uint32_t spa_pod_builder_double(struct spa_pod_builder *builder, d #define SPA_POD_INIT_String(len) (struct spa_pod_string){ { len, SPA_TYPE_String } } -static inline uint32_t +static inline int spa_pod_builder_write_string(struct spa_pod_builder *builder, const char *str, uint32_t len) { - uint32_t ref = 0; - if (spa_pod_builder_raw(builder, str, len) == SPA_ID_INVALID) - ref = SPA_ID_INVALID; - if (spa_pod_builder_raw(builder, "", 1) == SPA_ID_INVALID) - ref = SPA_ID_INVALID; - spa_pod_builder_pad(builder, builder->state.offset); - return ref; + int r, res; + res = spa_pod_builder_raw(builder, str, len); + if ((r = spa_pod_builder_raw(builder, "", 1)) < 0) + res = r; + if ((r = spa_pod_builder_pad(builder, builder->state.offset)) < 0) + res = r; + return res; } -static inline uint32_t +static inline int spa_pod_builder_string_len(struct spa_pod_builder *builder, const char *str, uint32_t len) { const struct spa_pod_string p = SPA_POD_INIT_String(len+1); - uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p)); - if (spa_pod_builder_write_string(builder, str, len) == SPA_ID_INVALID) - ref = SPA_ID_INVALID; - return ref; + int r, res = spa_pod_builder_raw(builder, &p, sizeof(p)); + if ((r = spa_pod_builder_write_string(builder, str, len)) < 0) + res = r; + return res; } -static inline uint32_t spa_pod_builder_string(struct spa_pod_builder *builder, const char *str) +static inline int spa_pod_builder_string(struct spa_pod_builder *builder, const char *str) { uint32_t len = str ? strlen(str) : 0; return spa_pod_builder_string_len(builder, str ? str : "", len); @@ -314,19 +274,19 @@ static inline uint32_t spa_pod_builder_string(struct spa_pod_builder *builder, c #define SPA_POD_INIT_Bytes(len) (struct spa_pod_bytes){ { len, SPA_TYPE_Bytes } } -static inline uint32_t +static inline int spa_pod_builder_bytes(struct spa_pod_builder *builder, const void *bytes, uint32_t len) { const struct spa_pod_bytes p = SPA_POD_INIT_Bytes(len); - uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p)); - if (spa_pod_builder_raw_padded(builder, bytes, len) == SPA_ID_INVALID) - ref = SPA_ID_INVALID; - return ref; + int r, res = spa_pod_builder_raw(builder, &p, sizeof(p)); + if ((r = spa_pod_builder_raw_padded(builder, bytes, len)) < 0) + res = r; + return res; } #define SPA_POD_INIT_Pointer(type,value) (struct spa_pod_pointer){ { sizeof(struct spa_pod_pointer_body), SPA_TYPE_Pointer }, { type, 0, value } } -static inline uint32_t +static inline int spa_pod_builder_pointer(struct spa_pod_builder *builder, uint32_t type, const void *val) { const struct spa_pod_pointer p = SPA_POD_INIT_Pointer(type, val); @@ -335,7 +295,7 @@ spa_pod_builder_pointer(struct spa_pod_builder *builder, uint32_t type, const vo #define SPA_POD_INIT_Fd(fd) (struct spa_pod_fd){ { sizeof(int64_t), SPA_TYPE_Fd }, fd } -static inline uint32_t spa_pod_builder_fd(struct spa_pod_builder *builder, int64_t fd) +static inline int spa_pod_builder_fd(struct spa_pod_builder *builder, int64_t fd) { const struct spa_pod_fd p = SPA_POD_INIT_Fd(fd); return spa_pod_builder_primitive(builder, &p.pod); @@ -343,7 +303,7 @@ static inline uint32_t spa_pod_builder_fd(struct spa_pod_builder *builder, int64 #define SPA_POD_INIT_Rectangle(val) (struct spa_pod_rectangle){ { sizeof(struct spa_rectangle), SPA_TYPE_Rectangle }, val } -static inline uint32_t +static inline int spa_pod_builder_rectangle(struct spa_pod_builder *builder, uint32_t width, uint32_t height) { const struct spa_pod_rectangle p = SPA_POD_INIT_Rectangle(SPA_RECTANGLE(width, height)); @@ -352,25 +312,26 @@ spa_pod_builder_rectangle(struct spa_pod_builder *builder, uint32_t width, uint3 #define SPA_POD_INIT_Fraction(val) (struct spa_pod_fraction){ { sizeof(struct spa_fraction), SPA_TYPE_Fraction }, val } -static inline uint32_t +static inline int spa_pod_builder_fraction(struct spa_pod_builder *builder, uint32_t num, uint32_t denom) { const struct spa_pod_fraction p = SPA_POD_INIT_Fraction(SPA_FRACTION(num, denom)); return spa_pod_builder_primitive(builder, &p.pod); } -static inline uint32_t -spa_pod_builder_push_array(struct spa_pod_builder *builder) +static inline int +spa_pod_builder_push_array(struct spa_pod_builder *builder, struct spa_pod_frame *frame) { const struct spa_pod_array p = { {sizeof(struct spa_pod_array_body) - sizeof(struct spa_pod), SPA_TYPE_Array}, {{0, 0}} }; - return spa_pod_builder_push(builder, &p.pod, - spa_pod_builder_raw(builder, &p, - sizeof(p) - sizeof(struct spa_pod))); + uint32_t offset = builder->state.offset; + int res = spa_pod_builder_raw(builder, &p, sizeof(p) - sizeof(struct spa_pod)); + spa_pod_builder_push(builder, frame, &p.pod, offset); + return res; } -static inline uint32_t +static inline int spa_pod_builder_array(struct spa_pod_builder *builder, uint32_t child_size, uint32_t child_type, uint32_t n_elems, const void *elems) { @@ -378,10 +339,10 @@ spa_pod_builder_array(struct spa_pod_builder *builder, {(uint32_t)(sizeof(struct spa_pod_array_body) + n_elems * child_size), SPA_TYPE_Array}, {{child_size, child_type}} }; - uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p)); - if (spa_pod_builder_raw_padded(builder, elems, child_size * n_elems) == SPA_ID_INVALID) - ref = SPA_ID_INVALID; - return ref; + int r, res = spa_pod_builder_raw(builder, &p, sizeof(p)); + if ((r = spa_pod_builder_raw_padded(builder, elems, child_size * n_elems)) < 0) + res = r; + return res; } #define SPA_POD_INIT_CHOICE_BODY(type, flags, child_size, child_type) \ @@ -392,69 +353,74 @@ spa_pod_builder_array(struct spa_pod_builder *builder, { { { n_vals * sizeof(ctype) + sizeof(struct spa_pod_choice_body), SPA_TYPE_Choice }, \ { type, 0, { sizeof(ctype), child_type } } }, { __VA_ARGS__ } } -static inline uint32_t -spa_pod_builder_push_choice(struct spa_pod_builder *builder, uint32_t type, uint32_t flags) +static inline int +spa_pod_builder_push_choice(struct spa_pod_builder *builder, struct spa_pod_frame *frame, + uint32_t type, uint32_t flags) { const struct spa_pod_choice p = { {sizeof(struct spa_pod_choice_body) - sizeof(struct spa_pod), SPA_TYPE_Choice}, { type, flags, {0, 0}} }; - return spa_pod_builder_push(builder, &p.pod, - spa_pod_builder_raw(builder, &p, - sizeof(p) - sizeof(struct spa_pod))); + uint32_t offset = builder->state.offset; + int res = spa_pod_builder_raw(builder, &p, sizeof(p) - sizeof(struct spa_pod)); + spa_pod_builder_push(builder, frame, &p.pod, offset); + return res; } #define SPA_POD_INIT_Struct(size) (struct spa_pod_struct){ { size, SPA_TYPE_Struct } } -static inline uint32_t -spa_pod_builder_push_struct(struct spa_pod_builder *builder) +static inline int +spa_pod_builder_push_struct(struct spa_pod_builder *builder, struct spa_pod_frame *frame) { const struct spa_pod_struct p = SPA_POD_INIT_Struct(0); - return spa_pod_builder_push(builder, &p.pod, - spa_pod_builder_raw(builder, &p, sizeof(p))); + uint32_t offset = builder->state.offset; + int res = spa_pod_builder_raw(builder, &p, sizeof(p)); + spa_pod_builder_push(builder, frame, &p.pod, offset); + return res; } #define SPA_POD_INIT_Object(size,type,id,...) (struct spa_pod_object){ { size, SPA_TYPE_Object }, { type, id }, ##__VA_ARGS__ } -static inline uint32_t -spa_pod_builder_push_object(struct spa_pod_builder *builder, uint32_t type, uint32_t id) +static inline int +spa_pod_builder_push_object(struct spa_pod_builder *builder, struct spa_pod_frame *frame, + uint32_t type, uint32_t id) { const struct spa_pod_object p = SPA_POD_INIT_Object(sizeof(struct spa_pod_object_body), type, id); - return spa_pod_builder_push(builder, &p.pod, - spa_pod_builder_raw(builder, &p, sizeof(p))); + uint32_t offset = builder->state.offset; + int res = spa_pod_builder_raw(builder, &p, sizeof(p)); + spa_pod_builder_push(builder, frame, &p.pod, offset); + return res; } #define SPA_POD_INIT_Prop(key,flags,size,type) \ (struct spa_pod_prop){ key, flags, { size, type } } -static inline uint32_t +static inline int spa_pod_builder_prop(struct spa_pod_builder *builder, uint32_t key, uint32_t flags) { const struct { uint32_t key; uint32_t flags; } p = { key, flags }; - uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p)); - SPA_FLAG_SET(builder->state.flags, SPA_POD_BUILDER_FLAG_HEADER); - return ref; + return spa_pod_builder_raw(builder, &p, sizeof(p)); } #define SPA_POD_INIT_Sequence(size,unit) \ (struct spa_pod_sequence){ { size, SPA_TYPE_Sequence}, {unit, 0 } } -static inline uint32_t -spa_pod_builder_push_sequence(struct spa_pod_builder *builder, uint32_t unit) +static inline int +spa_pod_builder_push_sequence(struct spa_pod_builder *builder, struct spa_pod_frame *frame, uint32_t unit) { const struct spa_pod_sequence p = SPA_POD_INIT_Sequence(sizeof(struct spa_pod_sequence_body), unit); - return spa_pod_builder_push(builder, &p.pod, - spa_pod_builder_raw(builder, &p, sizeof(p))); + uint32_t offset = builder->state.offset; + int res = spa_pod_builder_raw(builder, &p, sizeof(p)); + spa_pod_builder_push(builder, frame, &p.pod, offset); + return res; } static inline uint32_t spa_pod_builder_control(struct spa_pod_builder *builder, uint32_t offset, uint32_t type) { const struct { uint32_t offset; uint32_t type; } p = { offset, type }; - uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p)); - SPA_FLAG_SET(builder->state.flags, SPA_POD_BUILDER_FLAG_HEADER); - return ref; + return spa_pod_builder_raw(builder, &p, sizeof(p)); } static inline uint32_t spa_choice_from_id(char id) @@ -513,7 +479,7 @@ do { \ spa_pod_builder_string_len(builder, strval, len); \ break; \ } \ - case 'z': \ + case 'y': \ { \ void *ptr = va_arg(args, void *); \ int len = va_arg(args, int); \ @@ -569,94 +535,66 @@ do { \ } \ } while(false) -static inline void * +static inline int spa_pod_builder_addv(struct spa_pod_builder *builder, va_list args) { - const char *format = ""; - void *top = NULL; - do { - int n_values = 1; - bool do_pop = false; + int res = 0; + struct spa_pod_frame *f = builder->state.frame; + uint32_t ftype = f ? f->pod.type : SPA_TYPE_None; - if (builder->state.flags == SPA_POD_BUILDER_FLAG_OBJECT) { + do { + const char *format; + int n_values = 1; + struct spa_pod_frame f; + bool choice; + + switch (ftype) { + case SPA_TYPE_Object: + { uint32_t key = va_arg(args, uint32_t); if (key == 0) - break; - if (key != SPA_ID_INVALID) - spa_pod_builder_prop(builder, key, 0); + goto exit; + spa_pod_builder_prop(builder, key, 0); + break; } - else if (builder->state.flags == SPA_POD_BUILDER_FLAG_SEQUENCE) { + case SPA_TYPE_Sequence: + { uint32_t offset = va_arg(args, uint32_t); uint32_t type = va_arg(args, uint32_t); if (type == 0) - break; - if (type != SPA_ID_INVALID) - spa_pod_builder_control(builder, offset, type); + goto exit; + spa_pod_builder_control(builder, offset, type); } + default: + break; + } + if ((format = va_arg(args, const char *)) == NULL) + break; - again: - switch (*format) { - case '{': - { - uint32_t type = va_arg(args, uint32_t); - uint32_t id = va_arg(args, uint32_t); - spa_pod_builder_push_object(builder, type, id); - break; - } - case '[': - spa_pod_builder_push_struct(builder); - break; - case '(': - spa_pod_builder_push_array(builder); - break; - case '<': - { - uint32_t unit = va_arg(args, uint32_t); - spa_pod_builder_push_sequence(builder, unit); - break; - } - case '?': - { - uint32_t choice, flags = 0; - - format++; - choice = spa_choice_from_id(*format); + choice = *format == '?'; + if (choice) { + uint32_t type = spa_choice_from_id(*++format); if (*format != '\0') format++; - spa_pod_builder_push_choice(builder, choice, flags); + spa_pod_builder_push_choice(builder, &f, type, 0); n_values = va_arg(args, int); - do_pop = true; - goto do_collect; } - case ']': case ')': case '>': case '}': - top = spa_pod_builder_pop(builder); - break; - case ' ': case '\n': case '\t': case '\r': - break; - case '\0': - if ((format = va_arg(args, const char *)) != NULL) - goto again; - continue; - default: - do_collect: - while (n_values-- > 0) - SPA_POD_BUILDER_COLLECT(builder, *format, args); - if (do_pop) - top = spa_pod_builder_pop(builder); - break; - } - if (*format != '\0') - format++; - } while (format != NULL); + while (n_values-- > 0) + SPA_POD_BUILDER_COLLECT(builder, *format, args); - return top; + if (choice) + spa_pod_builder_pop(builder, &f); + } while (true); + + exit: + return res; } -static inline void *spa_pod_builder_add(struct spa_pod_builder *builder, ...) +static inline int spa_pod_builder_add(struct spa_pod_builder *builder, ...) { - void *res; + int res; va_list args; va_start(args, builder); @@ -666,29 +604,35 @@ static inline void *spa_pod_builder_add(struct spa_pod_builder *builder, ...) return res; } -#define SPA_POD_Object(type,id,...) \ - "{", type, id, ##__VA_ARGS__, SPA_ID_INVALID, "}" - #define SPA_POD_Prop(key,...) \ key, ##__VA_ARGS__ -#define SPA_POD_Struct(...) \ - "[", ##__VA_ARGS__, "]" - -#define SPA_POD_Sequence(unit,...) \ - "<", unit, ##__VA_ARGS__, 0, SPA_ID_INVALID, ">" - #define SPA_POD_Control(offset,type,...) \ offset, type, ##__VA_ARGS__ #define spa_pod_builder_add_object(b,type,id,...) \ - spa_pod_builder_add(b, SPA_POD_Object(type,id,##__VA_ARGS__), NULL, NULL, NULL) +({ \ + struct spa_pod_frame f; \ + spa_pod_builder_push_object(b, &f, type, id); \ + spa_pod_builder_add(b, ##__VA_ARGS__, 0); \ + spa_pod_builder_pop(b, &f); \ +}) #define spa_pod_builder_add_struct(b,...) \ - spa_pod_builder_add(b, SPA_POD_Struct(__VA_ARGS__), NULL, NULL, NULL) +({ \ + struct spa_pod_frame f; \ + spa_pod_builder_push_struct(b, &f); \ + spa_pod_builder_add(b, ##__VA_ARGS__, NULL); \ + spa_pod_builder_pop(b, &f); \ +}) #define spa_pod_builder_add_sequence(b,unit,...) \ - spa_pod_builder_add(b, SPA_POD_Sequence(unit,__VA_ARGS__), NULL, NULL, NULL) +({ \ + struct spa_pod_frame f; \ + spa_pod_builder_push_sequence(b, &f, unit); \ + spa_pod_builder_add(b, ##__VA_ARGS__, 0, 0); \ + spa_pod_builder_pop(b, &f); \ +}) #define SPA_CHOICE_RANGE(def,min,max) 3,(def),(min),(max) #define SPA_CHOICE_STEP(def,min,max,step) 4,(def),(min),(max),(step) @@ -724,7 +668,7 @@ static inline void *spa_pod_builder_add(struct spa_pod_builder *builder, ...) #define SPA_POD_String(val) "s",val #define SPA_POD_Stringn(val,len) "S",val,len -#define SPA_POD_Bytes(val,len) "z",val,len +#define SPA_POD_Bytes(val,len) "y",val,len #define SPA_POD_Rectangle(val) "R", val #define SPA_POD_CHOICE_ENUM_Rectangle(n_vals,...) "?eR", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) diff --git a/spa/include/spa/pod/compare.h b/spa/include/spa/pod/compare.h index 0d709486e..fdb02f8ed 100644 --- a/spa/include/spa/pod/compare.h +++ b/spa/include/spa/pod/compare.h @@ -142,14 +142,16 @@ static inline int spa_pod_compare(const struct spa_pod *pod1, o1 = (const struct spa_pod_object*)pod1; o2 = (const struct spa_pod_object*)pod2; + p2 = NULL; SPA_POD_OBJECT_FOREACH(o1, p1) { - if ((p2 = spa_pod_object_find_prop(o2, p1->key)) == NULL) + if ((p2 = spa_pod_object_find_prop(o2, p2, p1->key)) == NULL) return 1; if ((res = spa_pod_compare(&p1->value, &p2->value)) != 0) return res; } + p1 = NULL; SPA_POD_OBJECT_FOREACH(o2, p2) { - if ((p1 = spa_pod_object_find_prop(o1, p2->key)) == NULL) + if ((p1 = spa_pod_object_find_prop(o1, p1, p2->key)) == NULL) return -1; } break; diff --git a/spa/include/spa/pod/filter.h b/spa/include/spa/pod/filter.h index 4a7addeca..c6c0c5015 100644 --- a/spa/include/spa/pod/filter.h +++ b/spa/include/spa/pod/filter.h @@ -96,6 +96,7 @@ spa_pod_filter_prop(struct spa_pod_builder *b, uint32_t j, k, nalt1, nalt2; void *alt1, *alt2, *a1, *a2; uint32_t type, size, p1c, p2c; + struct spa_pod_frame f; v1 = spa_pod_get_values(&p1->value, &nalt1, &p1c); alt1 = SPA_POD_BODY(v1); @@ -125,7 +126,8 @@ spa_pod_filter_prop(struct spa_pod_builder *b, /* start with copying the property */ spa_pod_builder_prop(b, p1->key, 0); - nc = (struct spa_pod_choice*)spa_pod_builder_deref(b, spa_pod_builder_push_choice(b, 0, 0)); + spa_pod_builder_push_choice(b, &f, 0, 0); + nc = (struct spa_pod_choice*)spa_pod_builder_frame(b, &f); /* default value */ spa_pod_builder_primitive(b, v1); @@ -241,7 +243,7 @@ spa_pod_filter_prop(struct spa_pod_builder *b, if (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_Flags) return -ENOTSUP; - spa_pod_builder_pop(b); + spa_pod_builder_pop(b, &f); spa_pod_choice_fix_default(nc); return 0; @@ -259,20 +261,22 @@ static inline int spa_pod_filter_part(struct spa_pod_builder *b, SPA_POD_FOREACH(pod, pod_size, pp) { bool do_copy = false, do_advance = false; uint32_t filter_offset = 0; + struct spa_pod_frame f; switch (SPA_POD_TYPE(pp)) { case SPA_TYPE_Object: if (pf != NULL) { struct spa_pod_object *op = (struct spa_pod_object *) pp; struct spa_pod_object *of = (struct spa_pod_object *) pf; - struct spa_pod_prop *p1, *p2; + const struct spa_pod_prop *p1, *p2; if (SPA_POD_TYPE(pf) != SPA_POD_TYPE(pp)) return -EINVAL; - spa_pod_builder_push_object(b, op->body.type, op->body.id); + spa_pod_builder_push_object(b, &f, op->body.type, op->body.id); + p2 = NULL; SPA_POD_OBJECT_FOREACH(op, p1) { - p2 = spa_pod_object_find_prop(of, p1->key); + p2 = spa_pod_object_find_prop(of, p2, p1->key); if (p2 != NULL) res = spa_pod_filter_prop(b, p1, p2); else @@ -281,15 +285,16 @@ static inline int spa_pod_filter_part(struct spa_pod_builder *b, break; } if (res >= 0) { + p1 = NULL; SPA_POD_OBJECT_FOREACH(of, p2) { - p1 = spa_pod_object_find_prop(op, p2->key); + p1 = spa_pod_object_find_prop(op, p1, p2->key); if (p1 != NULL) continue; spa_pod_builder_raw_padded(b, p2, SPA_POD_PROP_SIZE(p2)); } } - spa_pod_builder_pop(b); + spa_pod_builder_pop(b, &f); do_advance = true; } else @@ -302,13 +307,13 @@ static inline int spa_pod_filter_part(struct spa_pod_builder *b, return -EINVAL; filter_offset = sizeof(struct spa_pod_struct); - spa_pod_builder_push_struct(b); + spa_pod_builder_push_struct(b, &f); res = spa_pod_filter_part(b, SPA_MEMBER(pp,filter_offset,const struct spa_pod), SPA_POD_SIZE(pp) - filter_offset, SPA_MEMBER(pf,filter_offset,const struct spa_pod), SPA_POD_SIZE(pf) - filter_offset); - spa_pod_builder_pop(b); + spa_pod_builder_pop(b, &f); do_advance = true; } else @@ -352,16 +357,17 @@ spa_pod_filter(struct spa_pod_builder *b, spa_return_val_if_fail(b != NULL, -EINVAL); if (filter == NULL) { - *result = (struct spa_pod*)spa_pod_builder_deref(b, - spa_pod_builder_raw_padded(b, pod, SPA_POD_SIZE(pod))); + spa_pod_builder_raw_padded(b, pod, SPA_POD_SIZE(pod)); + *result = (struct spa_pod*)b->data; return 0; } spa_pod_builder_get_state(b, &state); - if ((res = spa_pod_filter_part(b, pod, SPA_POD_SIZE(pod), filter, SPA_POD_SIZE(filter))) < 0) + if ((res = spa_pod_filter_part(b, pod, SPA_POD_SIZE(pod), filter, SPA_POD_SIZE(filter))) < 0) { spa_pod_builder_reset(b, &state); + } else - *result = (struct spa_pod*)spa_pod_builder_deref(b, state.offset); + *result = (struct spa_pod*)spa_pod_builder_deref(b, state.offset, b->size); return res; } diff --git a/spa/include/spa/pod/iter.h b/spa/include/spa/pod/iter.h index 8e50718ff..776df9325 100644 --- a/spa/include/spa/pod/iter.h +++ b/spa/include/spa/pod/iter.h @@ -30,40 +30,16 @@ extern "C" { #endif #include -#include #include -struct spa_pod_iter { - const void *data; - uint32_t size; +struct spa_pod_frame { + struct spa_pod pod; + struct spa_pod_frame *parent; uint32_t offset; + uint32_t flags; }; -static inline void spa_pod_iter_init(struct spa_pod_iter *iter, - const void *data, uint32_t size, uint32_t offset) -{ - iter->data = data; - iter->size = size; - iter->offset = offset; -} - -static inline struct spa_pod *spa_pod_iter_current(struct spa_pod_iter *iter) -{ - if (iter->offset + 8 <= iter->size) { - struct spa_pod *pod = SPA_MEMBER(iter->data, iter->offset, struct spa_pod); - if (SPA_POD_SIZE(pod) <= iter->size) - return pod; - } - return NULL; -} - -static inline void spa_pod_iter_advance(struct spa_pod_iter *iter, struct spa_pod *current) -{ - if (current) - iter->offset += SPA_ROUND_UP_N(SPA_POD_SIZE(current), 8); -} - static inline bool spa_pod_is_inside(const void *pod, uint32_t size, const void *iter) { return SPA_POD_BODY(iter) <= SPA_MEMBER(pod, size, void) && @@ -80,10 +56,11 @@ static inline struct spa_pod_prop *spa_pod_prop_first(const struct spa_pod_objec return SPA_MEMBER(body, sizeof(struct spa_pod_object_body), struct spa_pod_prop); } -static inline bool spa_pod_prop_is_inside(const void *pod, uint32_t size, const struct spa_pod_prop *iter) +static inline bool spa_pod_prop_is_inside(const struct spa_pod_object_body *body, + uint32_t size, const struct spa_pod_prop *iter) { - return SPA_POD_CONTENTS(struct spa_pod_prop, iter) <= SPA_MEMBER(pod, size, void) && - SPA_MEMBER(iter, SPA_POD_PROP_SIZE(iter), void) <= SPA_MEMBER(pod, size, void); + return SPA_POD_CONTENTS(struct spa_pod_prop, iter) <= SPA_MEMBER(body, size, void) && + SPA_MEMBER(iter, SPA_POD_PROP_SIZE(iter), void) <= SPA_MEMBER(body, size, void); } static inline struct spa_pod_prop *spa_pod_prop_next(const struct spa_pod_prop *iter) @@ -96,10 +73,11 @@ static inline struct spa_pod_control *spa_pod_control_first(const struct spa_pod return SPA_MEMBER(body, sizeof(struct spa_pod_sequence_body), struct spa_pod_control); } -static inline bool spa_pod_control_is_inside(const void *pod, uint32_t size, const struct spa_pod_control *iter) +static inline bool spa_pod_control_is_inside(const struct spa_pod_sequence_body *body, + uint32_t size, const struct spa_pod_control *iter) { - return SPA_POD_CONTENTS(struct spa_pod_control, iter) <= SPA_MEMBER(pod, size, void) && - SPA_MEMBER(iter, SPA_POD_CONTROL_SIZE(iter), void) <= SPA_MEMBER(pod, size, void); + return SPA_POD_CONTENTS(struct spa_pod_control, iter) <= SPA_MEMBER(body, size, void) && + SPA_MEMBER(iter, SPA_POD_CONTROL_SIZE(iter), void) <= SPA_MEMBER(body, size, void); } static inline struct spa_pod_control *spa_pod_control_next(const struct spa_pod_control *iter) @@ -327,6 +305,12 @@ static inline int spa_pod_get_fraction(const struct spa_pod *pod, struct spa_fra return 0; } +static inline int spa_pod_is_bitmap(const struct spa_pod *pod) +{ + return (SPA_POD_TYPE(pod) == SPA_TYPE_Bitmap && + SPA_POD_BODY_SIZE(pod) >= sizeof(uint8_t)); +} + static inline int spa_pod_is_array(const struct spa_pod *pod) { return (SPA_POD_TYPE(pod) == SPA_TYPE_Array && @@ -381,21 +365,32 @@ static inline int spa_pod_is_sequence(const struct spa_pod *pod) SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_sequence_body)); } -static inline struct spa_pod_prop *spa_pod_object_find_prop(const struct spa_pod_object *pod, uint32_t key) +static inline const struct spa_pod_prop *spa_pod_object_find_prop(const struct spa_pod_object *pod, + const struct spa_pod_prop *start, uint32_t key) { - struct spa_pod_prop *res; - SPA_POD_OBJECT_FOREACH(pod, res) { + const struct spa_pod_prop *first, *res; + + first = spa_pod_prop_first(&pod->body); + start = start ? spa_pod_prop_next(start) : first; + + for (res = start; spa_pod_prop_is_inside(&pod->body, pod->pod.size, res); + res = spa_pod_prop_next(res)) { + if (res->key == key) + return res; + } + for (res = first; res != start; res = spa_pod_prop_next(res)) { if (res->key == key) return res; } return NULL; } -static inline struct spa_pod_prop *spa_pod_find_prop(const struct spa_pod *pod, uint32_t key) +static inline const struct spa_pod_prop *spa_pod_find_prop(const struct spa_pod *pod, + const struct spa_pod_prop *start, uint32_t key) { if (!spa_pod_is_object(pod)) return NULL; - return spa_pod_object_find_prop((const struct spa_pod_object *)pod, key); + return spa_pod_object_find_prop((const struct spa_pod_object *)pod, start, key); } static inline int spa_pod_object_fixate(struct spa_pod_object *pod) diff --git a/spa/include/spa/pod/parser.h b/spa/include/spa/pod/parser.h index e83daa138..5107e4bad 100644 --- a/spa/include/spa/pod/parser.h +++ b/spa/include/spa/pod/parser.h @@ -34,74 +34,295 @@ extern "C" { #include -struct spa_pod_parser { - uint32_t depth; -#define SPA_POD_PARSER_FLAG_OBJECT (1<<0) -#define SPA_POD_PARSER_FLAG_STRUCT (1<<1) +struct spa_pod_parser_state { + uint32_t offset; uint32_t flags; - struct spa_pod_iter iter[SPA_POD_MAX_DEPTH]; + struct spa_pod_frame *frame; }; +struct spa_pod_parser { + const void *data; + uint32_t size; + uint32_t _padding; + struct spa_pod_parser_state state; +}; + +#define SPA_POD_PARSER_INIT(buffer,size) (struct spa_pod_parser){ buffer, size, } + static inline void spa_pod_parser_init(struct spa_pod_parser *parser, - const void *data, uint32_t size, uint32_t offset) + const void *data, uint32_t size) { - parser->depth = 0; - parser->flags = 0; - spa_pod_iter_init(&parser->iter[0], data, size, offset); + *parser = SPA_POD_PARSER_INIT(data, size); } static inline void spa_pod_parser_pod(struct spa_pod_parser *parser, const struct spa_pod *pod) { - spa_pod_parser_init(parser, pod, SPA_POD_SIZE(pod), 0); + spa_pod_parser_init(parser, pod, SPA_POD_SIZE(pod)); } -static inline bool spa_pod_parser_can_collect(struct spa_pod *pod, char type) +static inline void +spa_pod_parser_get_state(struct spa_pod_parser *parser, struct spa_pod_parser_state *state) +{ + *state = parser->state; +} + +static inline void +spa_pod_parser_reset(struct spa_pod_parser *parser, struct spa_pod_parser_state *state) +{ + parser->state = *state; +} + +static inline struct spa_pod * +spa_pod_parser_deref(struct spa_pod_parser *parser, uint32_t offset, uint32_t size) +{ + if (offset + 8 <= size) { + struct spa_pod *pod = SPA_MEMBER(parser->data, offset, struct spa_pod); + if (offset + SPA_POD_SIZE(pod) <= size) + return pod; + } + return NULL; +} + +static inline struct spa_pod *spa_pod_parser_frame(struct spa_pod_parser *parser, struct spa_pod_frame *frame) +{ + return SPA_MEMBER(parser->data, frame->offset, struct spa_pod); +} + +static inline void spa_pod_parser_push(struct spa_pod_parser *parser, + struct spa_pod_frame *frame, const struct spa_pod *pod, uint32_t offset) +{ + frame->pod = *pod; + frame->offset = offset; + frame->parent = parser->state.frame; + frame->flags = parser->state.flags; + parser->state.frame = frame; +} + +static inline struct spa_pod *spa_pod_parser_current(struct spa_pod_parser *parser) +{ + struct spa_pod_frame *f = parser->state.frame; + uint32_t size = f ? f->offset + SPA_POD_SIZE(&f->pod) : parser->size; + return spa_pod_parser_deref(parser, parser->state.offset, size); +} + +static inline void spa_pod_parser_advance(struct spa_pod_parser *parser, const struct spa_pod *pod) +{ + parser->state.offset += SPA_ROUND_UP_N(SPA_POD_SIZE(pod), 8); +} + +static inline struct spa_pod *spa_pod_parser_next(struct spa_pod_parser *parser) +{ + struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod) + spa_pod_parser_advance(parser, pod); + return pod; +} + +static inline int spa_pod_parser_pop(struct spa_pod_parser *parser, + struct spa_pod_frame *frame) +{ + parser->state.frame = frame->parent; + parser->state.offset = frame->offset + SPA_ROUND_UP_N(SPA_POD_SIZE(&frame->pod), 8); + return 0; +} + +static inline int spa_pod_parser_get_bool(struct spa_pod_parser *parser, bool *value) +{ + int res = -EPIPE; + const struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod != NULL && (res = spa_pod_get_bool(pod, value)) >= 0) + spa_pod_parser_advance(parser, pod); + return res; +} + +static inline int spa_pod_parser_get_id(struct spa_pod_parser *parser, uint32_t *value) +{ + int res = -EPIPE; + const struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod != NULL && (res = spa_pod_get_id(pod, value)) >= 0) + spa_pod_parser_advance(parser, pod); + return res; +} + +static inline int spa_pod_parser_get_int(struct spa_pod_parser *parser, int32_t *value) +{ + int res = -EPIPE; + const struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod != NULL && (res = spa_pod_get_int(pod, value)) >= 0) + spa_pod_parser_advance(parser, pod); + return res; +} + +static inline int spa_pod_parser_get_long(struct spa_pod_parser *parser, int64_t *value) +{ + int res = -EPIPE; + const struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod != NULL && (res = spa_pod_get_long(pod, value)) >= 0) + spa_pod_parser_advance(parser, pod); + return res; +} + +static inline int spa_pod_parser_get_float(struct spa_pod_parser *parser, float *value) +{ + int res = -EPIPE; + const struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod != NULL && (res = spa_pod_get_float(pod, value)) >= 0) + spa_pod_parser_advance(parser, pod); + return res; +} + +static inline int spa_pod_parser_get_double(struct spa_pod_parser *parser, double *value) +{ + int res = -EPIPE; + const struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod != NULL && (res = spa_pod_get_double(pod, value)) >= 0) + spa_pod_parser_advance(parser, pod); + return res; +} + +static inline int spa_pod_parser_get_string(struct spa_pod_parser *parser, const char **value) +{ + int res = -EPIPE; + const struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod != NULL && (res = spa_pod_get_string(pod, value)) >= 0) + spa_pod_parser_advance(parser, pod); + return res; +} + +static inline int spa_pod_parser_get_bytes(struct spa_pod_parser *parser, const void **value, uint32_t *len) +{ + int res = -EPIPE; + const struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod != NULL && (res = spa_pod_get_bytes(pod, value, len)) >= 0) + spa_pod_parser_advance(parser, pod); + return res; +} + +static inline int spa_pod_parser_get_pointer(struct spa_pod_parser *parser, uint32_t *type, const void **value) +{ + int res = -EPIPE; + const struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod != NULL && (res = spa_pod_get_pointer(pod, type, value)) >= 0) + spa_pod_parser_advance(parser, pod); + return res; +} + +static inline int spa_pod_parser_get_fd(struct spa_pod_parser *parser, int64_t *value) +{ + int res = -EPIPE; + const struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod != NULL && (res = spa_pod_get_fd(pod, value)) >= 0) + spa_pod_parser_advance(parser, pod); + return res; +} + +static inline int spa_pod_parser_get_rectangle(struct spa_pod_parser *parser, struct spa_rectangle *value) +{ + int res = -EPIPE; + const struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod != NULL && (res = spa_pod_get_rectangle(pod, value)) >= 0) + spa_pod_parser_advance(parser, pod); + return res; +} + +static inline int spa_pod_parser_get_fraction(struct spa_pod_parser *parser, struct spa_fraction *value) +{ + int res = -EPIPE; + const struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod != NULL && (res = spa_pod_get_fraction(pod, value)) >= 0) + spa_pod_parser_advance(parser, pod); + return res; +} + +static inline int spa_pod_parser_get_pod(struct spa_pod_parser *parser, struct spa_pod **value) +{ + struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod == NULL) + return -EPIPE; + *value = pod; + spa_pod_parser_advance(parser, pod); + return 0; +} +static inline int spa_pod_parser_push_struct(struct spa_pod_parser *parser, + struct spa_pod_frame *frame) +{ + const struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod == NULL) + return -EPIPE; + if (!spa_pod_is_struct(pod)) + return -EINVAL; + spa_pod_parser_push(parser, frame, pod, parser->state.offset); + parser->state.offset += sizeof(struct spa_pod_struct); + return 0; +} + +static inline int spa_pod_parser_push_object(struct spa_pod_parser *parser, + struct spa_pod_frame *frame, uint32_t type, uint32_t *id) +{ + const struct spa_pod *pod = spa_pod_parser_current(parser); + if (pod == NULL) + return -EPIPE; + if (!spa_pod_is_object(pod)) + return -EINVAL; + if (type != SPA_POD_OBJECT_TYPE(pod)) + return -EPROTO; + if (id != NULL) + *id = SPA_POD_OBJECT_ID(pod); + spa_pod_parser_push(parser, frame, pod, parser->state.offset); + parser->state.offset = parser->size; + return 0; +} + +static inline bool spa_pod_parser_can_collect(const struct spa_pod *pod, char type) { if (pod == NULL) return false; - if (type == 'P') + + if (spa_pod_is_choice(pod) && + SPA_POD_CHOICE_TYPE(pod) == SPA_CHOICE_None && + spa_pod_parser_can_collect(SPA_POD_CHOICE_CHILD(pod), type)) return true; - switch (SPA_POD_TYPE(pod)) { - case SPA_TYPE_None: - return type == 'T' || type == 'O' || type == 'V' || type == 's'; - case SPA_TYPE_Bool: - return type == 'b'; - case SPA_TYPE_Id: - return type == 'I'; - case SPA_TYPE_Int: - return type == 'i'; - case SPA_TYPE_Long: - return type == 'l'; - case SPA_TYPE_Float: - return type == 'f'; - case SPA_TYPE_Double: - return type == 'd'; - case SPA_TYPE_String: - return type == 's' || type == 'S'; - case SPA_TYPE_Bytes: - return type == 'z'; - case SPA_TYPE_Rectangle: - return type == 'R'; - case SPA_TYPE_Fraction: - return type == 'F'; - case SPA_TYPE_Bitmap: - return type == 'B'; - case SPA_TYPE_Array: - return type == 'a'; - case SPA_TYPE_Struct: - return type == 'T'; - case SPA_TYPE_Object: - return type == 'O'; - case SPA_TYPE_Pointer: - return type == 'p'; - case SPA_TYPE_Fd: - return type == 'h'; - case SPA_TYPE_Choice: - return type == 'V' || - (SPA_POD_CHOICE_TYPE(pod) == SPA_CHOICE_None && - spa_pod_parser_can_collect(SPA_POD_CHOICE_CHILD(pod), type)); + switch (type) { + case 'P': + return true; + case 'b': + return spa_pod_is_bool(pod); + case 'I': + return spa_pod_is_id(pod); + case 'i': + return spa_pod_is_int(pod); + case 'l': + return spa_pod_is_long(pod); + case 'f': + return spa_pod_is_float(pod); + case 'd': + return spa_pod_is_double(pod); + case 's': + return spa_pod_is_string(pod) || spa_pod_is_none(pod); + case 'S': + return spa_pod_is_string(pod); + case 'y': + return spa_pod_is_bytes(pod); + case 'R': + return spa_pod_is_rectangle(pod); + case 'F': + return spa_pod_is_fraction(pod); + case 'B': + return spa_pod_is_bitmap(pod); + case 'a': + return spa_pod_is_array(pod); + case 'p': + return spa_pod_is_pointer(pod); + case 'h': + return spa_pod_is_fd(pod); + case 'T': + return spa_pod_is_struct(pod) || spa_pod_is_none(pod); + case 'O': + return spa_pod_is_object(pod) || spa_pod_is_none(pod); + case 'V': + return spa_pod_is_choice(pod); default: return false; } @@ -139,7 +360,7 @@ do { \ strncpy(dest, (char *)SPA_POD_CONTENTS(struct spa_pod_string, pod), maxlen-1); \ break; \ } \ - case 'z': \ + case 'y': \ *(va_arg(args, void **)) = SPA_POD_CONTENTS(struct spa_pod_bytes, pod); \ *(va_arg(args, uint32_t *)) = SPA_POD_BODY_SIZE(pod); \ break; \ @@ -155,6 +376,12 @@ do { \ *va_arg(args, uint32_t **) = \ (uint32_t *) SPA_POD_CONTENTS(struct spa_pod_bitmap, pod); \ break; \ + case 'a': \ + *va_arg(args, uint32_t*) = SPA_POD_ARRAY_VALUE_SIZE(pod); \ + *va_arg(args, uint32_t*) = SPA_POD_ARRAY_VALUE_TYPE(pod); \ + *va_arg(args, uint32_t*) = SPA_POD_ARRAY_N_VALUES(pod); \ + *va_arg(args, void**) = SPA_POD_ARRAY_VALUES(pod); \ + break; \ case 'p': \ { \ struct spa_pod_pointer_body *b = \ @@ -166,17 +393,11 @@ do { \ case 'h': \ *va_arg(args, int64_t*) = SPA_POD_VALUE(struct spa_pod_fd, pod); \ break; \ - case 'a': \ - *va_arg(args, uint32_t*) = SPA_POD_ARRAY_VALUE_SIZE(pod); \ - *va_arg(args, uint32_t*) = SPA_POD_ARRAY_VALUE_TYPE(pod); \ - *va_arg(args, uint32_t*) = SPA_POD_ARRAY_N_VALUES(pod); \ - *va_arg(args, void**) = SPA_POD_ARRAY_VALUES(pod); \ - break; \ - case 'V': \ case 'P': \ - case 'O': \ case 'T': \ - *va_arg(args, struct spa_pod**) = \ + case 'O': \ + case 'V': \ + *va_arg(args, const struct spa_pod**) = \ (pod == NULL || (SPA_POD_TYPE(pod) == SPA_TYPE_None) \ ? NULL : pod); \ break; \ @@ -197,7 +418,7 @@ do { \ va_arg(args, void*); \ /* fallthrough */ \ case 'p': \ - case 'z': \ + case 'y': \ va_arg(args, void*); \ /* fallthrough */ \ case 'b': \ @@ -222,108 +443,53 @@ do { \ static inline int spa_pod_parser_getv(struct spa_pod_parser *parser, va_list args) { - struct spa_pod *pod = NULL, *current; - struct spa_pod_prop *prop = NULL; - bool required = true; - struct spa_pod_iter *it = &parser->iter[parser->depth]; - const char *format = ""; - uint32_t *idp; + struct spa_pod_frame *f = parser->state.frame; + uint32_t ftype = f ? f->pod.type : SPA_TYPE_Struct; + const struct spa_pod_prop *prop = NULL; int count = 0; - current = pod = spa_pod_iter_current(it); - do { - again: - switch (*format) { - case '{': - if (pod == NULL || SPA_POD_TYPE(pod) != SPA_TYPE_Object) - return -EINVAL; - if (va_arg(args, uint32_t) != SPA_POD_OBJECT_TYPE(pod)) - return -EPROTO; - if ((idp = va_arg(args, uint32_t*)) != NULL) - *idp = SPA_POD_OBJECT_ID(pod); - parser->flags = SPA_POD_PARSER_FLAG_OBJECT; - goto enter; - case '[': - if (pod == NULL || SPA_POD_TYPE(pod) != SPA_TYPE_Struct) - return -EINVAL; - parser->flags = SPA_POD_PARSER_FLAG_STRUCT; + bool optional; + const struct spa_pod *pod = NULL; + const char *format; - enter: - if (++parser->depth >= SPA_POD_MAX_DEPTH) - return -ENOSPC; - it = &parser->iter[parser->depth]; - spa_pod_iter_init(it, pod, SPA_POD_SIZE(pod), sizeof(struct spa_pod_struct)); - goto read_pod; - case ']': - case '}': - if (current != NULL) - return -EINVAL; - if (--parser->depth < 0) - return -EINVAL; - it = &parser->iter[parser->depth]; + if (ftype == SPA_TYPE_Object) { + uint32_t key = va_arg(args, uint32_t); + const struct spa_pod_object *object; - if (SPA_POD_TYPE(it->data) == SPA_TYPE_Object) - parser->flags = SPA_POD_PARSER_FLAG_OBJECT; - else if (SPA_POD_TYPE(it->data) == SPA_TYPE_Struct) - parser->flags = SPA_POD_PARSER_FLAG_STRUCT; - else - parser->flags = 0; + if (key == 0) + break; - current = spa_pod_iter_current(it); - spa_pod_iter_advance(it, current); - goto read_pod; - case '\0': - if (parser->flags & SPA_POD_PARSER_FLAG_OBJECT) { - uint32_t key = va_arg(args, uint32_t); - if (key == 0) { - format = NULL; - continue; - } - if (key != SPA_ID_INVALID) { - prop = spa_pod_object_find_prop( - (const struct spa_pod_object *) it->data, key); - if (prop != NULL) - pod = &prop->value; - else - pod = NULL; - - it->offset = it->size; - current = NULL; - } - } - if ((format = va_arg(args, char *)) != NULL) - goto again; - continue; - case ' ': case '\n': case '\t': case '\r': - break; - case '?': - required = false; - break; - default: - if (!spa_pod_parser_can_collect(pod, *format)) { - if (required) { - if (prop == NULL || pod == NULL) - return -ESRCH; - else - return -EPROTO; - } - SPA_POD_PARSER_SKIP(*format, args); - } else { - if (pod->type == SPA_TYPE_Choice && *format != 'V') - pod = SPA_POD_CHOICE_CHILD(pod); - SPA_POD_PARSER_COLLECT(pod, *format, args); - count++; - } - spa_pod_iter_advance(it, current); - read_pod: - pod = current = spa_pod_iter_current(it); - prop = NULL; - required = true; - break; + object = (const struct spa_pod_object *)spa_pod_parser_frame(parser, f); + prop = spa_pod_object_find_prop(object, prop, key); + pod = prop ? &prop->value : NULL; } - format++; - } while (format != NULL); + + if ((format = va_arg(args, char *)) == NULL) + break; + + if (ftype == SPA_TYPE_Struct) + pod = spa_pod_parser_next(parser); + + if ((optional = (*format == '?'))) + format++; + + if (!spa_pod_parser_can_collect(pod, *format)) { + if (!optional) { + if (pod == NULL) + return -ESRCH; + else + return -EPROTO; + } + SPA_POD_PARSER_SKIP(*format, args); + } else { + if (pod->type == SPA_TYPE_Choice && *format != 'V') + pod = SPA_POD_CHOICE_CHILD(pod); + + SPA_POD_PARSER_COLLECT(pod, *format, args); + count++; + } + } while (true); return count; } @@ -359,11 +525,27 @@ static inline int spa_pod_parser_get(struct spa_pod_parser *parser, ...) #define SPA_POD_OPT_PodStruct(val) "?" SPA_POD_PodStruct(val) #define SPA_POD_OPT_PodChoice(val) "?" SPA_POD_PodChoice(val) -#define spa_pod_parser_get_object(p,type,id,...) \ - spa_pod_parser_get(p, SPA_POD_Object(type,id,##__VA_ARGS__), NULL) +#define spa_pod_parser_get_object(p,type,id,...) \ +({ \ + struct spa_pod_frame _f; \ + int _res; \ + if ((_res = spa_pod_parser_push_object(p, &_f, type, id)) == 0) { \ + _res = spa_pod_parser_get(p,##__VA_ARGS__, 0); \ + spa_pod_parser_pop(p, &_f); \ + } \ + _res; \ +}) -#define spa_pod_parser_get_struct(p,...) \ - spa_pod_parser_get(p, SPA_POD_Struct(__VA_ARGS__), NULL) +#define spa_pod_parser_get_struct(p,...) \ +({ \ + struct spa_pod_frame _f; \ + int _res; \ + if ((_res = spa_pod_parser_push_struct(p, &_f)) == 0) { \ + _res = spa_pod_parser_get(p,##__VA_ARGS__, NULL); \ + spa_pod_parser_pop(p, &_f); \ + } \ + _res; \ +}) #define spa_pod_parse_object(pod,type,id,...) \ ({ \ diff --git a/spa/include/spa/pod/pod.h b/spa/include/spa/pod/pod.h index bab8df14f..515808af8 100644 --- a/spa/include/spa/pod/pod.h +++ b/spa/include/spa/pod/pod.h @@ -29,8 +29,6 @@ extern "C" { #endif -#include - #include #include diff --git a/spa/plugins/alsa/alsa-monitor.c b/spa/plugins/alsa/alsa-monitor.c index 539c7c86b..d034752ee 100644 --- a/spa/plugins/alsa/alsa-monitor.c +++ b/spa/plugins/alsa/alsa-monitor.c @@ -114,6 +114,7 @@ static int fill_item(struct impl *this, struct udev_device *dev, struct spa_pod **result, struct spa_pod_builder *builder) { const char *str, *name; + struct spa_pod_frame f[2]; name = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE"); if (!(name && *name)) { @@ -125,7 +126,7 @@ static int fill_item(struct impl *this, struct udev_device *dev, if (!(name && *name)) name = "Unknown"; - spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_MonitorItem, 0); + spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_MonitorItem, 0); spa_pod_builder_add(builder, SPA_MONITOR_ITEM_id, SPA_POD_String(udev_device_get_syspath(dev)), SPA_MONITOR_ITEM_flags, SPA_POD_Id(SPA_MONITOR_ITEM_FLAG_NONE), @@ -140,7 +141,7 @@ static int fill_item(struct impl *this, struct udev_device *dev, return 0; spa_pod_builder_prop(builder, SPA_MONITOR_ITEM_info, 0); - spa_pod_builder_push_struct(builder), + spa_pod_builder_push_struct(builder, &f[1]), add_dict(builder, "udev-probed", "1", "device.path", udev_device_get_devnode(dev), @@ -195,8 +196,8 @@ static int fill_item(struct impl *this, struct udev_device *dev, if ((str = udev_device_get_property_value(dev, "SOUND_FORM_FACTOR")) && *str) { add_dict(builder, "device.form_factor", str, 0); } - spa_pod_builder_pop(builder); - *result = spa_pod_builder_pop(builder); + spa_pod_builder_pop(builder, &f[1]); + *result = spa_pod_builder_pop(builder, &f[0]); return 1; } diff --git a/spa/plugins/alsa/alsa-sink.c b/spa/plugins/alsa/alsa-sink.c index bc017caea..7d2da205e 100644 --- a/spa/plugins/alsa/alsa-sink.c +++ b/spa/plugins/alsa/alsa-sink.c @@ -29,6 +29,7 @@ #include #include #include +#include #define NAME "alsa-sink" @@ -486,6 +487,8 @@ static int port_set_format(struct spa_node *node, info.media_subtype != SPA_MEDIA_SUBTYPE_raw) return -EINVAL; + spa_debug_pod(0, NULL, format); + if (spa_format_audio_raw_parse(format, &info.info.raw) < 0) return -EINVAL; diff --git a/spa/plugins/alsa/alsa-utils.c b/spa/plugins/alsa/alsa-utils.c index d03a5d794..c4eab5d36 100644 --- a/spa/plugins/alsa/alsa-utils.c +++ b/spa/plugins/alsa/alsa-utils.c @@ -236,6 +236,7 @@ spa_alsa_enum_format(struct state *state, uint32_t *index, struct spa_pod *fmt; int res; bool opened; + struct spa_pod_frame f[2]; opened = state->opened; if ((err = spa_alsa_open(state)) < 0) @@ -248,7 +249,7 @@ spa_alsa_enum_format(struct state *state, uint32_t *index, snd_pcm_hw_params_alloca(¶ms); CHECK(snd_pcm_hw_params_any(hndl, params), "Broken configuration: no configurations available"); - spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat); + spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat); spa_pod_builder_add(&b, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), @@ -262,8 +263,8 @@ spa_alsa_enum_format(struct state *state, uint32_t *index, spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_format, 0); - choice = spa_pod_builder_deref(&b, - spa_pod_builder_push_choice(&b, SPA_CHOICE_None, 0)); + spa_pod_builder_push_choice(&b, &f[1], SPA_CHOICE_None, 0); + choice = (struct spa_pod_choice*)spa_pod_builder_frame(&b, &f[1]); for (i = 1, j = 0; i < SPA_N_ELEMENTS(format_info); i++) { const struct format_info *fi = &format_info[i]; @@ -284,7 +285,7 @@ spa_alsa_enum_format(struct state *state, uint32_t *index, } if (j > 1) choice->body.type = SPA_CHOICE_Enum; - spa_pod_builder_pop(&b); + spa_pod_builder_pop(&b, &f[1]); CHECK(snd_pcm_hw_params_get_rate_min(params, &min, &dir), "get_rate_min"); @@ -292,8 +293,8 @@ spa_alsa_enum_format(struct state *state, uint32_t *index, spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_rate, 0); - choice = spa_pod_builder_deref(&b, - spa_pod_builder_push_choice(&b, SPA_CHOICE_None, 0)); + spa_pod_builder_push_choice(&b, &f[1], SPA_CHOICE_None, 0); + choice = (struct spa_pod_choice*)spa_pod_builder_frame(&b, &f[1]); spa_pod_builder_int(&b, SPA_CLAMP(DEFAULT_RATE, min, max)); if (min != max) { @@ -301,7 +302,7 @@ spa_alsa_enum_format(struct state *state, uint32_t *index, spa_pod_builder_int(&b, max); choice->body.type = SPA_CHOICE_Range; } - spa_pod_builder_pop(&b); + spa_pod_builder_pop(&b, &f[1]); CHECK(snd_pcm_hw_params_get_channels_min(params, &min), "get_channels_min"); CHECK(snd_pcm_hw_params_get_channels_max(params, &max), "get_channels_max"); @@ -323,13 +324,13 @@ spa_alsa_enum_format(struct state *state, uint32_t *index, spa_pod_builder_int(&b, map->channels); spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_position, 0); - spa_pod_builder_push_array(&b); + spa_pod_builder_push_array(&b, &f[1]); for (j = 0; j < map->channels; j++) { spa_log_debug(state->log, "position %zd %d", j, map->pos[j]); channel = chmap_position_to_channel(map->pos[j]); spa_pod_builder_id(&b, channel); } - spa_pod_builder_pop(&b); + spa_pod_builder_pop(&b, &f[1]); snd_pcm_free_chmaps(maps); } @@ -339,18 +340,18 @@ spa_alsa_enum_format(struct state *state, uint32_t *index, goto exit; } - choice = spa_pod_builder_deref(&b, - spa_pod_builder_push_choice(&b, SPA_CHOICE_None, 0)); + spa_pod_builder_push_choice(&b, &f[1], SPA_CHOICE_None, 0); + choice = (struct spa_pod_choice*)spa_pod_builder_frame(&b, &f[1]); spa_pod_builder_int(&b, SPA_CLAMP(DEFAULT_CHANNELS, min, max)); if (min != max) { spa_pod_builder_int(&b, min); spa_pod_builder_int(&b, max); choice->body.type = SPA_CHOICE_Range; } - spa_pod_builder_pop(&b); + spa_pod_builder_pop(&b, &f[1]); } - fmt = spa_pod_builder_pop(&b); + fmt = spa_pod_builder_pop(&b, &f[0]); (*index)++; @@ -395,8 +396,10 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_ /* set the sample format */ format = spa_format_to_alsa(info->format); - if (format == SND_PCM_FORMAT_UNKNOWN) + if (format == SND_PCM_FORMAT_UNKNOWN) { + spa_log_warn(state->log, "unknown format %u", info->format); return -EINVAL; + } spa_log_info(state->log, "Stream parameters are %iHz, %s, %i channels", info->rate, snd_pcm_format_name(format), info->channels); diff --git a/spa/plugins/audioconvert/fmtconvert.c b/spa/plugins/audioconvert/fmtconvert.c index 15c0dde67..a99216f5a 100644 --- a/spa/plugins/audioconvert/fmtconvert.c +++ b/spa/plugins/audioconvert/fmtconvert.c @@ -344,12 +344,13 @@ static int port_enum_formats(struct spa_node *node, } else if (other->have_format) { struct spa_audio_info info; + struct spa_pod_frame f; info = other->format; qsort(info.info.raw.position, info.info.raw.channels, sizeof(uint32_t), int32_cmp); - spa_pod_builder_push_object(builder, + spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat); spa_pod_builder_add(builder, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), @@ -367,7 +368,7 @@ static int port_enum_formats(struct spa_node *node, spa_pod_builder_array(builder, sizeof(uint32_t), SPA_TYPE_Id, info.info.raw.channels, info.info.raw.position); } - *param = spa_pod_builder_pop(builder); + *param = spa_pod_builder_pop(builder, &f); } else { *param = spa_pod_builder_add_object(builder, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, diff --git a/spa/plugins/audioconvert/resample.c b/spa/plugins/audioconvert/resample.c index e2b1e6ba2..889eb608b 100644 --- a/spa/plugins/audioconvert/resample.c +++ b/spa/plugins/audioconvert/resample.c @@ -327,13 +327,14 @@ static int port_enum_formats(struct spa_node *node, { struct impl *this = SPA_CONTAINER_OF(node, struct impl, node); struct port *other; + struct spa_pod_frame f; other = GET_PORT(this, SPA_DIRECTION_REVERSE(direction), 0); switch (*index) { case 0: if (other->have_format) { - spa_pod_builder_push_object(builder, + spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat); spa_pod_builder_add(builder, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), @@ -346,7 +347,7 @@ static int port_enum_formats(struct spa_node *node, spa_pod_builder_prop(builder, SPA_FORMAT_AUDIO_position, 0); spa_pod_builder_array(builder, sizeof(uint32_t), SPA_TYPE_Id, other->format.info.raw.channels, other->format.info.raw.position); - *param = spa_pod_builder_pop(builder); + *param = spa_pod_builder_pop(builder, &f); } else { *param = spa_pod_builder_add_object(builder, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, diff --git a/spa/plugins/audiotestsrc/audiotestsrc.c b/spa/plugins/audiotestsrc/audiotestsrc.c index 1c2d92664..59ae69e86 100644 --- a/spa/plugins/audiotestsrc/audiotestsrc.c +++ b/spa/plugins/audiotestsrc/audiotestsrc.c @@ -162,6 +162,7 @@ static int impl_node_enum_params(struct spa_node *node, case SPA_PARAM_PropInfo: { struct props *p = &this->props; + struct spa_pod_frame f[2]; switch (*index) { case 0: @@ -172,20 +173,20 @@ static int impl_node_enum_params(struct spa_node *node, SPA_PROP_INFO_type, SPA_POD_Bool(p->live)); break; case 1: - spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_PropInfo, id); + spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_PropInfo, id); spa_pod_builder_add(&b, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_waveType), SPA_PROP_INFO_name, SPA_POD_String("Select the waveform"), SPA_PROP_INFO_type, SPA_POD_Int(p->wave), 0); spa_pod_builder_prop(&b, SPA_PROP_INFO_labels, 0); - spa_pod_builder_push_struct(&b); + spa_pod_builder_push_struct(&b, &f[1]); spa_pod_builder_int(&b, WAVE_SINE); spa_pod_builder_string(&b, "Sine wave"); spa_pod_builder_int(&b, WAVE_SQUARE); spa_pod_builder_string(&b, "Square wave"); - spa_pod_builder_pop(&b); - param = spa_pod_builder_pop(&b); + spa_pod_builder_pop(&b, &f[1]); + param = spa_pod_builder_pop(&b, &f[0]); break; case 2: param = spa_pod_builder_add_object(&b, diff --git a/spa/plugins/bluez5/bluez5-monitor.c b/spa/plugins/bluez5/bluez5-monitor.c index 7916c9118..7f9dd3498 100644 --- a/spa/plugins/bluez5/bluez5-monitor.c +++ b/spa/plugins/bluez5/bluez5-monitor.c @@ -89,8 +89,9 @@ static void fill_item(struct spa_bt_monitor *this, struct spa_bt_device *device, struct spa_pod **result, struct spa_pod_builder *builder) { char dev[16]; + struct spa_pod_frame f[2]; - spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_MonitorItem, 0); + spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_MonitorItem, 0); spa_pod_builder_add(builder, SPA_MONITOR_ITEM_id, SPA_POD_String(device->path), SPA_MONITOR_ITEM_flags, SPA_POD_Id(SPA_MONITOR_ITEM_FLAG_NONE), @@ -103,7 +104,7 @@ static void fill_item(struct spa_bt_monitor *this, struct spa_bt_device *device, 0); spa_pod_builder_prop(builder, SPA_MONITOR_ITEM_info, 0); - spa_pod_builder_push_struct(builder); + spa_pod_builder_push_struct(builder, &f[1]); snprintf(dev, sizeof(dev), "%p", device); add_dict(builder, "device.api", "bluez5"); @@ -113,8 +114,8 @@ static void fill_item(struct spa_bt_monitor *this, struct spa_bt_device *device, add_dict(builder, "device.bluez5.address", device->address); add_dict(builder, "bluez5.device", dev); - spa_pod_builder_pop(builder); - *result = spa_pod_builder_pop(builder); + spa_pod_builder_pop(builder, &f[1]); + *result = spa_pod_builder_pop(builder, &f[0]); } static uint8_t a2dp_default_bitpool(struct spa_bt_monitor *monitor, uint8_t freq, uint8_t mode) { diff --git a/spa/plugins/v4l2/v4l2-monitor.c b/spa/plugins/v4l2/v4l2-monitor.c index cd23528c2..022775435 100644 --- a/spa/plugins/v4l2/v4l2-monitor.c +++ b/spa/plugins/v4l2/v4l2-monitor.c @@ -84,6 +84,7 @@ static void fill_item(struct impl *this, struct udev_device *dev, struct spa_pod **result, struct spa_pod_builder *builder) { const char *str, *name; + struct spa_pod_frame f[2]; name = udev_device_get_property_value(dev, "ID_V4L_PRODUCT"); if (!(name && *name)) { @@ -98,7 +99,7 @@ static void fill_item(struct impl *this, struct udev_device *dev, if (!(name && *name)) name = "Unknown"; - spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_MonitorItem, 0); + spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_MonitorItem, 0); spa_pod_builder_add(builder, SPA_MONITOR_ITEM_id, SPA_POD_String(udev_device_get_syspath(dev)), SPA_MONITOR_ITEM_flags, SPA_POD_Id(SPA_MONITOR_ITEM_FLAG_NONE), @@ -110,7 +111,7 @@ static void fill_item(struct impl *this, struct udev_device *dev, 0); spa_pod_builder_prop(builder, SPA_MONITOR_ITEM_info, 0); - spa_pod_builder_push_struct(builder); + spa_pod_builder_push_struct(builder, &f[1]); add_dict(builder, "udev-probed", "1"); add_dict(builder, "device.path", udev_device_get_devnode(dev)); @@ -159,8 +160,8 @@ static void fill_item(struct impl *this, struct udev_device *dev, add_dict(builder, "device.capabilities", str); } - spa_pod_builder_pop(builder); - *result = spa_pod_builder_pop(builder); + spa_pod_builder_pop(builder, &f[1]); + *result = spa_pod_builder_pop(builder, &f[0]); } static int emit_device(struct impl *this, uint32_t id, struct udev_device *dev) diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index e0d64bf4d..2436d3d55 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -430,13 +430,14 @@ static int port_get_format(struct spa_node *node, { struct impl *this = SPA_CONTAINER_OF(node, struct impl, node); struct port *port = GET_PORT(this, direction, port_id); + struct spa_pod_frame f; if (!port->have_format) return -EIO; if (*index > 0) return 0; - spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_Format, SPA_PARAM_Format); + spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, SPA_PARAM_Format); spa_pod_builder_add(builder, SPA_FORMAT_mediaType, SPA_POD_Id(port->current_format.media_type), SPA_FORMAT_mediaSubtype, SPA_POD_Id(port->current_format.media_subtype), @@ -467,7 +468,7 @@ static int port_get_format(struct spa_node *node, return -EIO; } - *param = spa_pod_builder_pop(builder); + *param = spa_pod_builder_pop(builder, &f); return 1; } diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index eb5c84aa2..60309540e 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -402,12 +402,12 @@ enum_filter_format(uint32_t media_type, int32_t media_subtype, case SPA_MEDIA_TYPE_video: case SPA_MEDIA_TYPE_image: if (media_subtype == SPA_MEDIA_SUBTYPE_raw) { - struct spa_pod_prop *p; + const struct spa_pod_prop *p; const struct spa_pod *val; uint32_t n_values, choice; const uint32_t *values; - if (!(p = spa_pod_find_prop(filter, SPA_FORMAT_VIDEO_format))) + if (!(p = spa_pod_find_prop(filter, NULL, SPA_FORMAT_VIDEO_format))) return SPA_VIDEO_FORMAT_UNKNOWN; val = spa_pod_get_values(&p->value, &n_values, &choice); @@ -532,6 +532,7 @@ spa_v4l2_enum_format(struct impl *this, struct spa_pod_choice *choice; uint32_t filter_media_type, filter_media_subtype, video_format; struct spa_v4l2_device *dev = &port->dev; + struct spa_pod_frame f[2]; if ((res = spa_v4l2_open(dev, this->props.device)) < 0) return res; @@ -592,12 +593,12 @@ spa_v4l2_enum_format(struct impl *this, next_frmsize: while (port->next_frmsize) { if (filter) { - struct spa_pod_prop *p; + const struct spa_pod_prop *p; struct spa_pod *val; uint32_t n_vals, choice; /* check if we have a fixed frame size */ - if (!(p = spa_pod_find_prop(filter, SPA_FORMAT_VIDEO_size))) + if (!(p = spa_pod_find_prop(filter, NULL, SPA_FORMAT_VIDEO_size))) goto do_frmsize; val = spa_pod_get_values(&p->value, &n_vals, &choice); @@ -626,13 +627,13 @@ spa_v4l2_enum_format(struct impl *this, goto exit; } if (filter) { - struct spa_pod_prop *p; + const struct spa_pod_prop *p; struct spa_pod *val; const struct spa_rectangle step = { 1, 1 }, *values; uint32_t choice, i, n_values; /* check if we have a fixed frame size */ - if (!(p = spa_pod_find_prop(filter, SPA_FORMAT_VIDEO_size))) + if (!(p = spa_pod_find_prop(filter, NULL, SPA_FORMAT_VIDEO_size))) goto have_size; val = spa_pod_get_values(&p->value, &n_values, &choice); @@ -680,7 +681,7 @@ spa_v4l2_enum_format(struct impl *this, } } - spa_pod_builder_push_object(builder, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat); + spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat); spa_pod_builder_add(builder, SPA_FORMAT_mediaType, SPA_POD_Id(info->media_type), SPA_FORMAT_mediaSubtype, SPA_POD_Id(info->media_subtype), @@ -697,8 +698,8 @@ spa_v4l2_enum_format(struct impl *this, n_fractions = 0; - choice = spa_pod_builder_deref(builder, - spa_pod_builder_push_choice(builder, SPA_CHOICE_None, 0)); + spa_pod_builder_push_choice(builder, &f[1], SPA_CHOICE_None, 0); + choice = (struct spa_pod_choice*)spa_pod_builder_frame(builder, &f[1]); port->frmival.index = 0; while (true) { @@ -715,12 +716,12 @@ spa_v4l2_enum_format(struct impl *this, goto exit; } if (filter) { - struct spa_pod_prop *p; + const struct spa_pod_prop *p; struct spa_pod *val; uint32_t i, n_values, choice; const struct spa_fraction step = { 1, 1 }, *values; - if (!(p = spa_pod_find_prop(filter, SPA_FORMAT_VIDEO_framerate))) + if (!(p = spa_pod_find_prop(filter, NULL, SPA_FORMAT_VIDEO_framerate))) goto have_framerate; val = spa_pod_get_values(&p->value, &n_values, &choice); @@ -800,8 +801,8 @@ spa_v4l2_enum_format(struct impl *this, if (n_fractions <= 1) choice->body.type = SPA_CHOICE_None; - spa_pod_builder_pop(builder); - *result = spa_pod_builder_pop(builder); + spa_pod_builder_pop(builder, &f[1]); + *result = spa_pod_builder_pop(builder, &f[0]); (*index)++; @@ -1009,6 +1010,7 @@ spa_v4l2_enum_controls(struct impl *this, uint8_t buffer[1024]; int res; const unsigned next_fl = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND; + struct spa_pod_frame f[2]; if ((res = spa_v4l2_open(dev, this->props.device)) < 0) return res; @@ -1091,7 +1093,7 @@ spa_v4l2_enum_controls(struct impl *this, { struct v4l2_querymenu querymenu; - spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo); + spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo); spa_pod_builder_add(&b, SPA_PROP_INFO_id, SPA_POD_Id(prop_id), SPA_PROP_INFO_type, SPA_POD_CHOICE_ENUM_Int(1, queryctrl.default_value), @@ -1102,7 +1104,7 @@ spa_v4l2_enum_controls(struct impl *this, querymenu.id = queryctrl.id; spa_pod_builder_prop(&b, SPA_PROP_INFO_labels, 0); - spa_pod_builder_push_struct(&b); + spa_pod_builder_push_struct(&b, &f[1]); for (querymenu.index = queryctrl.minimum; querymenu.index <= queryctrl.maximum; querymenu.index++) { @@ -1111,8 +1113,8 @@ spa_v4l2_enum_controls(struct impl *this, spa_pod_builder_string(&b, (const char *)querymenu.name); } } - spa_pod_builder_pop(&b); - param = spa_pod_builder_pop(&b); + spa_pod_builder_pop(&b, &f[1]); + param = spa_pod_builder_pop(&b, &f[0]); break; } case V4L2_CTRL_TYPE_INTEGER_MENU: diff --git a/spa/plugins/videotestsrc/videotestsrc.c b/spa/plugins/videotestsrc/videotestsrc.c index 94f495fec..ef2fb32af 100644 --- a/spa/plugins/videotestsrc/videotestsrc.c +++ b/spa/plugins/videotestsrc/videotestsrc.c @@ -146,6 +146,7 @@ static int impl_node_enum_params(struct spa_node *node, case SPA_PARAM_PropInfo: { struct props *p = &this->props; + struct spa_pod_frame f[2]; switch (*index) { case 0: @@ -156,20 +157,20 @@ static int impl_node_enum_params(struct spa_node *node, SPA_PROP_INFO_type, SPA_POD_Bool(p->live)); break; case 1: - spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_PropInfo, id); + spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_PropInfo, id); spa_pod_builder_add(&b, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_patternType), SPA_PROP_INFO_name, SPA_POD_String("The pattern"), SPA_PROP_INFO_type, SPA_POD_Int(p->pattern), 0); spa_pod_builder_prop(&b, SPA_PROP_INFO_labels, 0), - spa_pod_builder_push_struct(&b); + spa_pod_builder_push_struct(&b, &f[1]); spa_pod_builder_int(&b, PATTERN_SMPTE_SNOW); spa_pod_builder_string(&b, "SMPTE snow"); spa_pod_builder_int(&b, PATTERN_SNOW); spa_pod_builder_string(&b, "Snow"); - spa_pod_builder_pop(&b); - param = spa_pod_builder_pop(&b); + spa_pod_builder_pop(&b, &f[1]); + param = spa_pod_builder_pop(&b, &f[0]); break; default: return 0; diff --git a/spa/tests/meson.build b/spa/tests/meson.build index d76afd860..9b1bded5d 100644 --- a/spa/tests/meson.build +++ b/spa/tests/meson.build @@ -2,7 +2,6 @@ test_apps = [ 'test-buffer', 'test-pod', 'test-utils', - 'stress-ringbuffer', ] foreach a : test_apps @@ -24,3 +23,20 @@ test_cpp = executable('test-cpp', 'test-cpp.cpp', install : false) test('test-cpp', test_cpp) endif + +benchmark_apps = [ + 'stress-ringbuffer', + 'benchmark-pod', +] + +foreach a : benchmark_apps + benchmark(a, + executable(a, a + '.c', + dependencies : [dl_lib, pthread_lib], + include_directories : [spa_inc ], + c_args : [ '-D_GNU_SOURCE' ], + install : false), + env : [ + 'SPA_PLUGIN_DIR=@0@/spa/plugins/'.format(meson.build_root()), + ]) +endforeach diff --git a/spa/tests/stress-ringbuffer.c b/spa/tests/stress-ringbuffer.c index 8aed4f7a4..d00e8be17 100644 --- a/spa/tests/stress-ringbuffer.c +++ b/spa/tests/stress-ringbuffer.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include @@ -9,9 +11,10 @@ #define ARRAY_SIZE 63 #define MAX_VALUE 0x10000 -struct spa_ringbuffer rb; -int32_t size; -uint8_t *data; +static struct spa_ringbuffer rb; +static uint32_t size; +static void *data; +static sem_t sem; static int fill_int_array(int *array, int start, int count) { @@ -53,10 +56,14 @@ static void *reader_start(void *arg) spa_ringbuffer_read_data(&rb, data, size, index % size, b, sizeof(b)); spa_ringbuffer_read_update(&rb, index + sizeof(b)); + if (index >= INT32_MAX - sizeof(a)) + break; + spa_assert(cmp_array(a, b, ARRAY_SIZE)); i = fill_int_array(a, i, ARRAY_SIZE); } } + sem_post(&sem); return NULL; } @@ -78,15 +85,26 @@ static void *writer_start(void *arg) spa_ringbuffer_write_data(&rb, data, size, index % size, a, sizeof(a)); spa_ringbuffer_write_update(&rb, index + sizeof(a)); + if (index >= INT32_MAX - sizeof(a)) + break; + i = fill_int_array(a, i, ARRAY_SIZE); } } + sem_post(&sem); return NULL; } +#define exit_error(msg) \ +do { perror(msg); exit(EXIT_FAILURE); } while (0) + int main(int argc, char *argv[]) { + pthread_t reader_thread, writer_thread; + struct timespec ts; + int s; + printf("starting ringbuffer stress test\n"); if (argc > 1) @@ -100,11 +118,21 @@ int main(int argc, char *argv[]) spa_ringbuffer_init(&rb); data = malloc(size); - pthread_t reader_thread, writer_thread; + if (sem_init(&sem, 0, 0) != 0) + exit_error("init_sem"); + pthread_create(&reader_thread, NULL, reader_start, NULL); pthread_create(&writer_thread, NULL, writer_start, NULL); - sleep(5); + if (clock_gettime(CLOCK_REALTIME, &ts) != 0) + exit_error("clock_gettime"); + + ts.tv_sec += 2; + + while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR) + continue; + while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR) + continue; printf("read %u, written %u\n", rb.readindex, rb.writeindex); diff --git a/spa/tests/test-pod.c b/spa/tests/test-pod.c index dfe75fd12..045e42229 100644 --- a/spa/tests/test-pod.c +++ b/spa/tests/test-pod.c @@ -69,9 +69,9 @@ static void test_abi(void) spa_assert(sizeof(struct spa_pod_sequence) == 16); /* builder */ - spa_assert(sizeof(struct spa_pod_frame) == 16); + spa_assert(sizeof(struct spa_pod_frame) == 24); spa_assert(sizeof(struct spa_pod_builder_state) == 16); - spa_assert(sizeof(struct spa_pod_builder) == 312); + spa_assert(sizeof(struct spa_pod_builder) == 48); /* command */ spa_assert(sizeof(struct spa_command_body) == 8); @@ -81,11 +81,9 @@ static void test_abi(void) spa_assert(sizeof(struct spa_event_body) == 8); spa_assert(sizeof(struct spa_event) == 16); - /* iter */ - spa_assert(sizeof(struct spa_pod_iter) == 16); - /* parser */ - spa_assert(sizeof(struct spa_pod_parser) == 264); + spa_assert(sizeof(struct spa_pod_parser_state) == 16); + spa_assert(sizeof(struct spa_pod_parser) == 32); } @@ -339,10 +337,10 @@ static void test_build(void) uint8_t buffer[4096]; struct spa_pod_builder b; struct spa_pod *array, *choice, *head, *pod, *it; - struct spa_pod_prop *prop; + const struct spa_pod_prop *prop; struct spa_pod_control *control; int64_t longs[] = { 5, 7, 11, 13, 17 }, *al; - uint32_t i, len, zl, *ai; + uint32_t i, len, yl, *ai; union { bool b; uint32_t I; @@ -351,103 +349,131 @@ static void test_build(void) float f; double d; const char *s; - const void *z; + const void *y; const void *p; int64_t h; struct spa_rectangle R; struct spa_fraction F; } val; + struct spa_pod_frame f; spa_pod_builder_init(&b, buffer, sizeof(buffer)); spa_assert(b.data == buffer); spa_assert(b.size == sizeof(buffer)); spa_assert(b.state.offset == 0); spa_assert(b.state.flags == 0); - spa_assert(b.state.depth == 0); spa_assert(spa_pod_builder_none(&b) == 0); - spa_assert(spa_pod_builder_bool(&b, true) == 8); - spa_assert(spa_pod_builder_id(&b, SPA_TYPE_Object) == 24); - spa_assert(spa_pod_builder_int(&b, 21) == 40); - spa_assert(spa_pod_builder_float(&b, 0.8f) == 56); - spa_assert(spa_pod_builder_double(&b, -1.56) == 72); - spa_assert(spa_pod_builder_string(&b, "test") == 88); - spa_assert(spa_pod_builder_bytes(&b, "PipeWire", 8) == 104); - spa_assert(spa_pod_builder_pointer(&b, SPA_TYPE_Object, &b) == 120); - spa_assert(spa_pod_builder_fd(&b, 4) == 144); - spa_assert(spa_pod_builder_rectangle(&b, 320, 240) == 160); - spa_assert(spa_pod_builder_fraction(&b, 25, 1) == 176); + spa_assert(b.state.offset == 8); + spa_assert(spa_pod_builder_bool(&b, true) == 0); + spa_assert(b.state.offset == 24); + spa_assert(spa_pod_builder_id(&b, SPA_TYPE_Object) == 0); + spa_assert(b.state.offset == 40); + spa_assert(spa_pod_builder_int(&b, 21) == 0); + spa_assert(b.state.offset == 56); + spa_assert(spa_pod_builder_float(&b, 0.8f) == 0); + spa_assert(b.state.offset == 72); + spa_assert(spa_pod_builder_double(&b, -1.56) == 0); + spa_assert(b.state.offset == 88); + spa_assert(spa_pod_builder_string(&b, "test") == 0); + spa_assert(b.state.offset == 104); + spa_assert(spa_pod_builder_bytes(&b, "PipeWire", 8) == 0); + spa_assert(b.state.offset == 120); + spa_assert(spa_pod_builder_pointer(&b, SPA_TYPE_Object, &b) == 0); + spa_assert(b.state.offset == 144); + spa_assert(spa_pod_builder_fd(&b, 4) == 0); + spa_assert(b.state.offset == 160); + spa_assert(spa_pod_builder_rectangle(&b, 320, 240) == 0); + spa_assert(b.state.offset == 176); + spa_assert(spa_pod_builder_fraction(&b, 25, 1) == 0); - spa_assert(spa_pod_builder_push_array(&b) == 192); + spa_assert(b.state.offset == 192); + spa_assert(spa_pod_builder_push_array(&b, &f) == 0); + spa_assert(f.offset == 192); spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_BODY | SPA_POD_BUILDER_FLAG_FIRST)); - spa_assert(b.state.depth == 1); - spa_assert(spa_pod_builder_int(&b, 1) == 200); + spa_assert(b.state.offset == 200); + spa_assert(spa_pod_builder_int(&b, 1) == 0); spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_BODY); - spa_assert(spa_pod_builder_int(&b, 2) == 212); - spa_assert(spa_pod_builder_int(&b, 3) == 216); - array = spa_pod_builder_pop(&b); + spa_assert(b.state.offset == 212); + spa_assert(spa_pod_builder_int(&b, 2) == 0); + spa_assert(b.state.offset == 216); + spa_assert(spa_pod_builder_int(&b, 3) == 0); + array = spa_pod_builder_pop(&b, &f); + spa_assert(f.pod.size == 20); spa_assert(array != NULL); + spa_assert(SPA_POD_BODY_SIZE(array) == 8 + 12); spa_assert(b.state.flags == 0); - spa_assert(b.state.depth == 0); + spa_assert(b.state.offset == 224); spa_assert(spa_pod_builder_array(&b, sizeof(int64_t), SPA_TYPE_Long, - SPA_N_ELEMENTS(longs), longs) == 224); + SPA_N_ELEMENTS(longs), longs) == 0); spa_assert(b.state.flags == 0); - spa_assert(b.state.depth == 0); - spa_assert(spa_pod_builder_push_choice(&b, SPA_CHOICE_Enum, 0) == 280); + spa_assert(b.state.offset == 280); + spa_assert(spa_pod_builder_push_choice(&b, &f, SPA_CHOICE_Enum, 0) == 0); spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_BODY | SPA_POD_BUILDER_FLAG_FIRST)); - spa_assert(b.state.depth == 1); - spa_assert(spa_pod_builder_long(&b, 1) == 296); + spa_assert(b.state.offset == 296); + spa_assert(spa_pod_builder_long(&b, 1) == 0); spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_BODY); - spa_assert(spa_pod_builder_long(&b, 2) == 312); - spa_assert(spa_pod_builder_long(&b, 3) == 320); - choice = spa_pod_builder_pop(&b); + spa_assert(b.state.offset == 312); + spa_assert(spa_pod_builder_long(&b, 2) == 0); + spa_assert(b.state.offset == 320); + spa_assert(spa_pod_builder_long(&b, 3) == 0); + choice = spa_pod_builder_pop(&b, &f); spa_assert(choice != NULL); spa_assert(b.state.flags == 0); - spa_assert(b.state.depth == 0); - spa_assert(spa_pod_builder_push_struct(&b) == 328); + spa_assert(b.state.offset == 328); + spa_assert(spa_pod_builder_push_struct(&b, &f) == 0); spa_assert(b.state.flags == 0); - spa_assert(b.state.depth == 1); - spa_assert(spa_pod_builder_int(&b, 21) == 336); - spa_assert(spa_pod_builder_float(&b, 0.8f) == 352); - spa_assert(spa_pod_builder_double(&b, -1.56) == 368); - spa_assert(spa_pod_builder_pop(&b) != NULL); - spa_assert(b.state.depth == 0); + spa_assert(b.state.offset == 336); + spa_assert(spa_pod_builder_int(&b, 21) == 0); + spa_assert(b.state.offset == 352); + spa_assert(spa_pod_builder_float(&b, 0.8f) == 0); + spa_assert(b.state.offset == 368); + spa_assert(spa_pod_builder_double(&b, -1.56) == 0); + spa_assert(spa_pod_builder_pop(&b, &f) != NULL); - spa_assert(spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_Props, 0) == 384); - spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_OBJECT); - spa_assert(b.state.depth == 1); - spa_assert(spa_pod_builder_prop(&b, 1, 0) == 400); - spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_OBJECT | SPA_POD_BUILDER_FLAG_HEADER)); - spa_assert(spa_pod_builder_int(&b, 21) == 408); - spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_OBJECT); - spa_assert(spa_pod_builder_prop(&b, 2, 0) == 424); - spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_OBJECT | SPA_POD_BUILDER_FLAG_HEADER)); - spa_assert(spa_pod_builder_long(&b, 42) == 432); - spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_OBJECT); - spa_assert(spa_pod_builder_prop(&b, 3, 0) == 448); - spa_assert(spa_pod_builder_string(&b, "test123") == 456); - spa_assert(spa_pod_builder_pop(&b) != NULL); + spa_assert(b.state.offset == 384); + spa_assert(spa_pod_builder_push_object(&b, &f, SPA_TYPE_OBJECT_Props, 0) == 0); + spa_assert(b.state.flags == 0); + spa_assert(b.state.offset == 400); + spa_assert(spa_pod_builder_prop(&b, 1, 0) == 0); + spa_assert(b.state.flags == 0); + spa_assert(b.state.offset == 408); + spa_assert(spa_pod_builder_int(&b, 21) == 0); + spa_assert(b.state.flags == 0); + spa_assert(b.state.offset == 424); + spa_assert(spa_pod_builder_prop(&b, 2, 0) == 0); + spa_assert(b.state.flags == 0); + spa_assert(b.state.offset == 432); + spa_assert(spa_pod_builder_long(&b, 42) == 0); + spa_assert(b.state.flags == 0); + spa_assert(b.state.offset == 448); + spa_assert(spa_pod_builder_prop(&b, 3, 0) == 0); + spa_assert(b.state.offset == 456); + spa_assert(spa_pod_builder_string(&b, "test123") == 0); + spa_assert(spa_pod_builder_pop(&b, &f) != NULL); spa_assert(b.state.flags == 0); - spa_assert(b.state.depth == 0); - spa_assert(spa_pod_builder_push_sequence(&b, 0) == 472); - spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_SEQUENCE); - spa_assert(b.state.depth == 1); - spa_assert(spa_pod_builder_control(&b, 0, 0) == 488); - spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_SEQUENCE | SPA_POD_BUILDER_FLAG_HEADER)); - spa_assert(spa_pod_builder_float(&b, 0.667f) == 496); - spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_SEQUENCE); - spa_assert(spa_pod_builder_control(&b, 12, 0) == 512); - spa_assert(b.state.flags == (SPA_POD_BUILDER_FLAG_SEQUENCE | SPA_POD_BUILDER_FLAG_HEADER)); - spa_assert(spa_pod_builder_double(&b, 1.22) == 520); - spa_assert(b.state.flags == SPA_POD_BUILDER_FLAG_SEQUENCE); - spa_assert(spa_pod_builder_pop(&b) != NULL); + spa_assert(b.state.offset == 472); + spa_assert(spa_pod_builder_push_sequence(&b, &f, 0) == 0); + spa_assert(b.state.flags == 0); + spa_assert(b.state.offset == 488); + spa_assert(spa_pod_builder_control(&b, 0, 0) == 0); + spa_assert(b.state.flags == 0); + spa_assert(b.state.offset == 496); + spa_assert(spa_pod_builder_float(&b, 0.667f) == 0); + spa_assert(b.state.flags == 0); + spa_assert(b.state.offset == 512); + spa_assert(spa_pod_builder_control(&b, 12, 0) == 0); + spa_assert(b.state.flags == 0); + spa_assert(b.state.offset == 520); + spa_assert(spa_pod_builder_double(&b, 1.22) == 0); + spa_assert(b.state.flags == 0); + spa_assert(spa_pod_builder_pop(&b, &f) != NULL); spa_assert(b.state.flags == 0); - spa_assert(b.state.depth == 0); spa_assert(b.state.offset == 536); @@ -482,13 +508,13 @@ static void test_build(void) spa_assert(strcmp(val.s, "test") == 0); spa_assert((pod = spa_pod_next(pod)) != NULL && spa_pod_is_inside(head, len, pod)); spa_assert(spa_pod_is_bytes(pod)); - spa_assert(spa_pod_get_bytes(pod, &val.z, &zl) == 0); - spa_assert(zl == 8); - spa_assert(memcmp(val.z, "PipeWire", zl) == 0); + spa_assert(spa_pod_get_bytes(pod, &val.y, &yl) == 0); + spa_assert(yl == 8); + spa_assert(memcmp(val.y, "PipeWire", yl) == 0); spa_assert((pod = spa_pod_next(pod)) != NULL && spa_pod_is_inside(head, len, pod)); spa_assert(spa_pod_is_pointer(pod)); - spa_assert(spa_pod_get_pointer(pod, &zl, &val.p) == 0); - spa_assert(zl == SPA_TYPE_Object); + spa_assert(spa_pod_get_pointer(pod, &yl, &val.p) == 0); + spa_assert(yl == SPA_TYPE_Object); spa_assert(val.p == &b); spa_assert((pod = spa_pod_next(pod)) != NULL && spa_pod_is_inside(head, len, pod)); spa_assert(spa_pod_is_fd(pod)); @@ -605,17 +631,22 @@ static void test_build(void) break; } } - spa_assert((prop = spa_pod_find_prop(pod, 3)) != NULL); + spa_assert((prop = spa_pod_find_prop(pod, NULL, 3)) != NULL); spa_assert(prop->key == 3); spa_assert(spa_pod_get_string(&prop->value, &val.s) == 0 && strcmp(val.s, "test123") == 0); - spa_assert((prop = spa_pod_find_prop(pod, 1)) != NULL); + spa_assert((prop = spa_pod_find_prop(pod, prop, 1)) != NULL); spa_assert(prop->key == 1); spa_assert(spa_pod_get_int(&prop->value, &val.i) == 0 && val.i == 21); - spa_assert((prop = spa_pod_find_prop(pod, 2)) != NULL); + spa_assert((prop = spa_pod_find_prop(pod, prop, 2)) != NULL); spa_assert(prop->key == 2); spa_assert(spa_pod_get_long(&prop->value, &val.l) == 0 && val.l == 42); - spa_assert((prop = spa_pod_find_prop(pod, 5)) == NULL); + spa_assert((prop = spa_pod_find_prop(pod, prop, 5)) == NULL); + + spa_assert((prop = spa_pod_find_prop(pod, NULL, 3)) != NULL); + spa_assert(prop->key == 3); + spa_assert(spa_pod_get_string(&prop->value, &val.s) == 0 && + strcmp(val.s, "test123") == 0); spa_assert((pod = spa_pod_next(pod)) != NULL && spa_pod_is_inside(head, len, pod)); spa_assert(spa_pod_is_sequence(pod)); @@ -655,7 +686,7 @@ static void test_varargs(void) float f; double d; const char *s; - const void *z; + const void *y; const void *p; int64_t h; struct spa_rectangle R; @@ -826,8 +857,8 @@ static void test_varargs2(void) float f; double d; const char *s; - uint32_t zl; - const void *z; + uint32_t yl; + const void *y; uint32_t ptype; const void *p; uint32_t asize, atype, anvals; @@ -903,9 +934,9 @@ static void test_varargs2(void) case 7: spa_assert(prop->key == 8); spa_assert(SPA_POD_PROP_SIZE(prop) == 21); - spa_assert(spa_pod_get_bytes(&prop->value, &val.z, &val.zl) == 0); - spa_assert(val.zl == sizeof(bytes)); - spa_assert(memcmp(val.z, bytes, val.zl) == 0); + spa_assert(spa_pod_get_bytes(&prop->value, &val.y, &val.yl) == 0); + spa_assert(val.yl == sizeof(bytes)); + spa_assert(memcmp(val.y, bytes, val.yl) == 0); break; case 8: spa_assert(prop->key == 9); @@ -969,7 +1000,7 @@ static void test_varargs2(void) 5, SPA_POD_Float(&val.f), 6, SPA_POD_Double(&val.d), 7, SPA_POD_String(&val.s), - 8, SPA_POD_Bytes(&val.z, &val.zl), + 8, SPA_POD_Bytes(&val.y, &val.yl), 9, SPA_POD_Rectangle(&val.R), 10, SPA_POD_Fraction(&val.F), 11, SPA_POD_Array(&val.asize, &val.atype, &val.anvals, &val.a), @@ -984,8 +1015,8 @@ static void test_varargs2(void) spa_assert(val.f == 0.453f); spa_assert(val.d == 0.871); spa_assert(strcmp(val.s, "test") == 0); - spa_assert(val.zl == sizeof(bytes)); - spa_assert(memcmp(val.z, bytes, sizeof(bytes)) == 0); + spa_assert(val.yl == sizeof(bytes)); + spa_assert(memcmp(val.y, bytes, sizeof(bytes)) == 0); spa_assert(memcmp(&val.R, &SPA_RECTANGLE(3, 4), sizeof(struct spa_rectangle)) == 0); spa_assert(memcmp(&val.F, &SPA_FRACTION(24, 1), sizeof(struct spa_fraction)) == 0); spa_assert(val.asize == sizeof(int64_t)); @@ -1007,7 +1038,7 @@ static void test_varargs2(void) 0, SPA_POD_OPT_Float(&val.f), 0, SPA_POD_OPT_Double(&val.d), 0, SPA_POD_OPT_String(&val.s), - 0, SPA_POD_OPT_Bytes(&val.z, &val.zl), + 0, SPA_POD_OPT_Bytes(&val.y, &val.yl), 0, SPA_POD_OPT_Rectangle(&val.R), 0, SPA_POD_OPT_Fraction(&val.F), 0, SPA_POD_OPT_Array(&val.asize, &val.atype, &val.anvals, &val.a), @@ -1026,7 +1057,7 @@ static void test_varargs2(void) i, SPA_POD_OPT_Float(&val.f), i, SPA_POD_OPT_Double(&val.d), i, SPA_POD_OPT_String(&val.s), - i, SPA_POD_OPT_Bytes(&val.z, &val.zl), + i, SPA_POD_OPT_Bytes(&val.y, &val.yl), i, SPA_POD_OPT_Rectangle(&val.R), i, SPA_POD_OPT_Fraction(&val.F), i, SPA_POD_OPT_Array(&val.asize, &val.atype, &val.anvals, &val.a), @@ -1036,6 +1067,392 @@ static void test_varargs2(void) } } +static void test_parser(void) +{ + uint8_t buffer[4096]; + struct spa_pod_builder b; + struct spa_pod_parser p; + struct spa_pod_frame f; + struct spa_pod *pod; + struct { + bool b; + uint32_t I; + int32_t i; + int64_t l; + float f; + double d; + const char *s; + uint32_t yl; + const void *y; + uint32_t ptype; + const void *p; + uint32_t asize, atype, anvals; + const void *a; + int64_t h; + struct spa_rectangle R; + struct spa_fraction F; + struct spa_pod *P; + } val; + uint8_t bytes[] = { 0x56, 0x00, 0x12, 0xf3, 0xba }; + int64_t longs[] = { 1002, 5383, 28944, 1237748 }; + struct spa_pod_int pi = SPA_POD_INIT_Int(77); + + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + pod = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_Props, 0, + 1, SPA_POD_Bool(true), + 2, SPA_POD_Id(SPA_TYPE_Id), + 3, SPA_POD_Int(3), + 4, SPA_POD_Long(4), + 5, SPA_POD_Float(0.453f), + 6, SPA_POD_Double(0.871), + 7, SPA_POD_String("test"), + 8, SPA_POD_Bytes(bytes, sizeof(bytes)), + 9, SPA_POD_Rectangle(&SPA_RECTANGLE(3,4)), + 10, SPA_POD_Fraction(&SPA_FRACTION(24,1)), + 11, SPA_POD_Array(sizeof(int64_t), SPA_TYPE_Long, SPA_N_ELEMENTS(longs), longs), + 12, SPA_POD_Pointer(SPA_TYPE_Object, &b), + 13, SPA_POD_Fd(3), + 14, SPA_POD_Pod(&pi)); + + spa_debug_pod(0, NULL, pod); + + spa_pod_parser_pod(&p, pod); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_bool(&p, &val.b) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_id(&p, &val.I) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_int(&p, &val.i) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_long(&p, &val.l) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_float(&p, &val.f) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_double(&p, &val.d) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_string(&p, &val.s) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_bytes(&p, &val.y, &val.yl) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_rectangle(&p, &val.R) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_fraction(&p, &val.F) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_pointer(&p, &val.ptype, &val.p) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_fd(&p, &val.h) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_pod(&p, &val.P) == 0); + spa_assert(p.state.offset == 392); + spa_assert(spa_pod_is_object(val.P)); + + spa_pod_parser_pod(&p, val.P); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_push_struct(&p, &f) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_push_object(&p, &f, SPA_TYPE_OBJECT_Format, NULL) == -EPROTO); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_push_object(&p, &f, SPA_TYPE_OBJECT_Props, NULL) == 0); + spa_assert(p.state.offset == 392); + spa_assert(spa_pod_parser_frame(&p, &f) == val.P); + + spa_zero(val); + spa_assert(spa_pod_parser_get(&p, + 1, SPA_POD_OPT_Bool(&val.b), + 2, SPA_POD_OPT_Id(&val.I), + 3, SPA_POD_OPT_Int(&val.i), + 4, SPA_POD_OPT_Long(&val.l), + 5, SPA_POD_OPT_Float(&val.f), + 6, SPA_POD_OPT_Double(&val.d), + 7, SPA_POD_OPT_String(&val.s), + 8, SPA_POD_OPT_Bytes(&val.y, &val.yl), + 9, SPA_POD_OPT_Rectangle(&val.R), + 10, SPA_POD_OPT_Fraction(&val.F), + 11, SPA_POD_OPT_Array(&val.asize, &val.atype, &val.anvals, &val.a), + 12, SPA_POD_OPT_Pointer(&val.ptype, &val.p), + 13, SPA_POD_OPT_Fd(&val.h), + 14, SPA_POD_OPT_Pod(&val.P), 0) == 14); + spa_pod_parser_pop(&p, &f); + + spa_assert(val.b == true); + spa_assert(val.I == SPA_TYPE_Id); + spa_assert(val.i == 3); + spa_assert(val.l == 4); + spa_assert(val.f == 0.453f); + spa_assert(val.d == 0.871); + spa_assert(strcmp(val.s, "test") == 0); + spa_assert(val.yl == sizeof(bytes)); + spa_assert(memcmp(val.y, bytes, sizeof(bytes)) == 0); + spa_assert(memcmp(&val.R, &SPA_RECTANGLE(3, 4), sizeof(struct spa_rectangle)) == 0); + spa_assert(memcmp(&val.F, &SPA_FRACTION(24, 1), sizeof(struct spa_fraction)) == 0); + spa_assert(val.asize == sizeof(int64_t)); + spa_assert(val.atype == SPA_TYPE_Long); + spa_assert(val.anvals == SPA_N_ELEMENTS(longs)); + spa_assert(memcmp(val.a, longs, val.anvals * val.asize) == 0); + spa_assert(val.ptype == SPA_TYPE_Object); + spa_assert(val.p == &b); + spa_assert(val.h == 3); + spa_assert(memcmp(val.P, &pi, sizeof(pi)) == 0); + + spa_assert(p.state.offset == 392); +} + +static void test_parser2(void) +{ + uint8_t buffer[4096]; + struct spa_pod_builder b; + struct spa_pod_parser p; + struct spa_pod_frame f; + struct spa_pod *pod; + struct { + bool b; + uint32_t I; + int32_t i; + int64_t l; + float f; + double d; + const char *s; + uint32_t yl; + const void *y; + uint32_t ptype; + const void *p; + uint32_t asize, atype, anvals; + const void *a; + int64_t h; + struct spa_rectangle R; + struct spa_fraction F; + struct spa_pod *P; + } val; + uint8_t bytes[] = { 0x56, 0x00, 0x12, 0xf3, 0xba }; + int64_t longs[] = { 1002, 5383, 28944, 1237748 }; + struct spa_pod_int pi = SPA_POD_INIT_Int(77); + + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + pod = spa_pod_builder_add_struct(&b, + SPA_POD_Bool(true), + SPA_POD_Id(SPA_TYPE_Id), + SPA_POD_Int(3), + SPA_POD_Long(4), + SPA_POD_Float(0.453f), + SPA_POD_Double(0.871), + SPA_POD_String("test"), + SPA_POD_Bytes(bytes, sizeof(bytes)), + SPA_POD_Rectangle(&SPA_RECTANGLE(3,4)), + SPA_POD_Fraction(&SPA_FRACTION(24,1)), + SPA_POD_Array(sizeof(int64_t), SPA_TYPE_Long, SPA_N_ELEMENTS(longs), longs), + SPA_POD_Pointer(SPA_TYPE_Object, &b), + SPA_POD_Fd(3), + SPA_POD_Pod(&pi)); + + spa_debug_pod(0, NULL, pod); + + spa_pod_parser_pod(&p, pod); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_bool(&p, &val.b) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_id(&p, &val.I) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_int(&p, &val.i) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_long(&p, &val.l) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_float(&p, &val.f) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_double(&p, &val.d) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_string(&p, &val.s) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_bytes(&p, &val.y, &val.yl) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_rectangle(&p, &val.R) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_fraction(&p, &val.F) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_pointer(&p, &val.ptype, &val.p) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_fd(&p, &val.h) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_get_pod(&p, &val.P) == 0); + spa_assert(p.state.offset == 272); + spa_assert(spa_pod_is_struct(val.P)); + + spa_pod_parser_pod(&p, val.P); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_push_object(&p, &f, SPA_TYPE_OBJECT_Format, NULL) == -EINVAL); + spa_assert(p.state.offset == 0); + spa_assert(spa_pod_parser_push_struct(&p, &f) == 0); + spa_assert(f.pod.type == SPA_TYPE_Struct); + spa_assert(f.pod.size == 264); + spa_assert(f.offset == 0); + spa_assert(p.state.frame == &f); + spa_assert(spa_pod_parser_frame(&p, &f) == val.P); + spa_assert(p.state.offset == 8); + spa_assert(spa_pod_parser_get_bool(&p, &val.b) == 0 && val.b == true); + spa_assert(p.state.offset == 24); + spa_assert(spa_pod_parser_get_id(&p, &val.I) == 0 && val.I == SPA_TYPE_Id); + spa_assert(p.state.offset == 40); + spa_assert(spa_pod_parser_get_int(&p, &val.i) == 0 && val.i == 3); + spa_assert(p.state.offset == 56); + spa_assert(spa_pod_parser_get_long(&p, &val.l) == 0 && val.l == 4); + spa_assert(p.state.offset == 72); + spa_assert(spa_pod_parser_get_float(&p, &val.f) == 0 && val.f == 0.453f); + spa_assert(p.state.offset == 88); + spa_assert(spa_pod_parser_get_double(&p, &val.d) == 0 && val.d == 0.871); + spa_assert(p.state.offset == 104); + spa_assert(spa_pod_parser_get_string(&p, &val.s) == 0 && strcmp(val.s, "test") == 0); + spa_assert(p.state.offset == 120); + spa_assert(spa_pod_parser_get_bytes(&p, &val.y, &val.yl) == 0); + spa_assert(val.yl == sizeof(bytes)); + spa_assert(memcmp(bytes, val.y, sizeof(bytes)) == 0); + spa_assert(p.state.offset == 136); + spa_assert(spa_pod_parser_get_rectangle(&p, &val.R) == 0); + spa_assert(memcmp(&val.R, &SPA_RECTANGLE(3,4), sizeof(struct spa_rectangle)) == 0); + spa_assert(p.state.offset == 152); + spa_assert(spa_pod_parser_get_fraction(&p, &val.F) == 0); + spa_assert(memcmp(&val.F, &SPA_FRACTION(24,1), sizeof(struct spa_fraction)) == 0); + spa_assert(p.state.offset == 168); + spa_assert((val.P = spa_pod_parser_next(&p)) != NULL); + spa_assert(spa_pod_is_array(val.P)); + spa_assert(p.state.offset == 216); + spa_assert(SPA_POD_ARRAY_VALUE_TYPE(val.P) == SPA_TYPE_Long); + spa_assert(SPA_POD_ARRAY_VALUE_SIZE(val.P) == sizeof(int64_t)); + spa_assert(SPA_POD_ARRAY_N_VALUES(val.P) == SPA_N_ELEMENTS(longs)); + spa_assert(spa_pod_parser_get_pointer(&p, &val.ptype, &val.p) == 0); + spa_assert(val.ptype == SPA_TYPE_Object); + spa_assert(val.p == &b); + spa_assert(p.state.offset == 240); + spa_assert(spa_pod_parser_get_fd(&p, &val.h) == 0); + spa_assert(val.h == 3); + spa_assert(p.state.offset == 256); + spa_assert(spa_pod_parser_get_pod(&p, &val.P) == 0); + spa_assert(p.state.offset == 272); + spa_assert(spa_pod_is_int(val.P)); + spa_pod_parser_pop(&p, &f); + spa_assert(p.state.offset == 272); + spa_assert(p.state.frame == NULL); +} + +static void test_static(void) +{ + struct _test_format { + struct spa_pod_object fmt; + + struct { + struct spa_pod_prop prop_media_type SPA_ALIGNED(8); + uint32_t media_type; + + struct spa_pod_prop prop_media_subtype SPA_ALIGNED(8); + uint32_t media_subtype; + + struct spa_pod_prop prop_format SPA_ALIGNED(8); + struct { + struct spa_pod_choice_body choice; + uint32_t def_format; + uint32_t enum_format[2]; + } format_vals; + + struct spa_pod_prop prop_size SPA_ALIGNED(8); + struct { + struct spa_pod_choice_body choice; + struct spa_rectangle def_size; + struct spa_rectangle min_size; + struct spa_rectangle max_size; + } size_vals; + + struct spa_pod_prop prop_framerate SPA_ALIGNED(8); + struct { + struct spa_pod_choice_body choice; + struct spa_fraction def_framerate; + struct spa_fraction min_framerate; + struct spa_fraction max_framerate; + } framerate_vals; + } props; + } test_format = { + SPA_POD_INIT_Object(sizeof(test_format.props) + sizeof(struct spa_pod_object_body), + SPA_TYPE_OBJECT_Format, 0), + { + SPA_POD_INIT_Prop(SPA_FORMAT_mediaType, 0, + sizeof(test_format.props.media_type), SPA_TYPE_Id), + SPA_MEDIA_TYPE_video, + + SPA_POD_INIT_Prop(SPA_FORMAT_mediaSubtype, 0, + sizeof(test_format.props.media_subtype), SPA_TYPE_Id), + SPA_MEDIA_SUBTYPE_raw, + + SPA_POD_INIT_Prop(SPA_FORMAT_VIDEO_format, 0, + sizeof(test_format.props.format_vals), SPA_TYPE_Choice), + { + SPA_POD_INIT_CHOICE_BODY(SPA_CHOICE_Enum, 0, + sizeof(uint32_t), SPA_TYPE_Id), + SPA_VIDEO_FORMAT_I420, + { SPA_VIDEO_FORMAT_I420, SPA_VIDEO_FORMAT_YUY2 } + }, + SPA_POD_INIT_Prop(SPA_FORMAT_VIDEO_size, 0, + sizeof(test_format.props.size_vals), SPA_TYPE_Choice), + + { + SPA_POD_INIT_CHOICE_BODY(SPA_CHOICE_Range, 0, + sizeof(struct spa_rectangle), SPA_TYPE_Rectangle), + SPA_RECTANGLE(320,243), + SPA_RECTANGLE(1,1), SPA_RECTANGLE(INT32_MAX, INT32_MAX) + }, + SPA_POD_INIT_Prop(SPA_FORMAT_VIDEO_framerate, 0, + sizeof(test_format.props.framerate_vals), SPA_TYPE_Choice), + { + SPA_POD_INIT_CHOICE_BODY(SPA_CHOICE_Range, 0, + sizeof(struct spa_fraction), SPA_TYPE_Fraction), + SPA_FRACTION(25,1), + SPA_FRACTION(0,1), SPA_FRACTION(INT32_MAX,1) + } + } + }; + struct { + uint32_t media_type; + uint32_t media_subtype; + uint32_t format; + struct spa_rectangle size; + struct spa_fraction framerate; + } vals; + int res; + + spa_debug_pod(0, NULL, &test_format.fmt.pod); + + spa_zero(vals); + res = spa_pod_parse_object(&test_format.fmt.pod, + SPA_TYPE_OBJECT_Format, NULL, + SPA_FORMAT_mediaType, SPA_POD_Id(&vals.media_type), + SPA_FORMAT_mediaSubtype, SPA_POD_Id(&vals.media_subtype), + SPA_FORMAT_VIDEO_format, SPA_POD_Id(&vals.format), + SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&vals.size), + SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&vals.framerate)); + + spa_assert(res == -EPROTO); + spa_assert(vals.media_type == SPA_MEDIA_TYPE_video); + spa_assert(vals.media_subtype == SPA_MEDIA_SUBTYPE_raw); + spa_assert(vals.format == 0); + spa_assert(vals.size.width == 0 && vals.size.height == 0); + spa_assert(vals.framerate.num == 0 && vals.framerate.denom == 0); + + spa_pod_fixate(&test_format.fmt.pod); + + spa_zero(vals); + res = spa_pod_parse_object(&test_format.fmt.pod, + SPA_TYPE_OBJECT_Format, NULL, + SPA_FORMAT_mediaType, SPA_POD_Id(&vals.media_type), + SPA_FORMAT_mediaSubtype, SPA_POD_Id(&vals.media_subtype), + SPA_FORMAT_VIDEO_format, SPA_POD_Id(&vals.format), + SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&vals.size), + SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&vals.framerate)); + + spa_assert(res == 5); + spa_assert(vals.media_type == SPA_MEDIA_TYPE_video); + spa_assert(vals.media_subtype == SPA_MEDIA_SUBTYPE_raw); + spa_assert(vals.format == SPA_VIDEO_FORMAT_I420); + spa_assert(vals.size.width == 320 && vals.size.height == 243); + spa_assert(vals.framerate.num == 25 && vals.framerate.denom == 1); +} + int main(int argc, char *argv[]) { test_abi(); @@ -1043,5 +1460,8 @@ int main(int argc, char *argv[]) test_build(); test_varargs(); test_varargs2(); + test_parser(); + test_parser2(); + test_static(); return 0; } diff --git a/src/examples/export-sink.c b/src/examples/export-sink.c index 9a416d141..319ee6334 100644 --- a/src/examples/export-sink.c +++ b/src/examples/export-sink.c @@ -110,18 +110,19 @@ static void handle_events(struct data *data) static void update_param(struct data *data) { struct spa_pod_builder b = { 0, }; + struct spa_pod_frame f[2]; if (data->io_notify == NULL) return; spa_pod_builder_init(&b, data->io_notify, data->io_notify_size); - spa_pod_builder_push_sequence(&b, 0); + spa_pod_builder_push_sequence(&b, &f[0], 0); spa_pod_builder_control(&b, 0, SPA_CONTROL_Properties); - spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_Props, 0); + spa_pod_builder_push_object(&b, &f[1], SPA_TYPE_OBJECT_Props, 0); spa_pod_builder_prop(&b, SPA_PROP_contrast, 0); spa_pod_builder_float(&b, (sin(data->param_accum) * 127.0) + 127.0); - spa_pod_builder_pop(&b); - spa_pod_builder_pop(&b); + spa_pod_builder_pop(&b, &f[1]); + spa_pod_builder_pop(&b, &f[0]); data->param_accum += M_PI_M2 / 30.0; if (data->param_accum >= M_PI_M2) diff --git a/src/examples/export-source.c b/src/examples/export-source.c index a94496cea..818cbc2bf 100644 --- a/src/examples/export-source.c +++ b/src/examples/export-source.c @@ -81,18 +81,19 @@ struct data { static void update_volume(struct data *data) { struct spa_pod_builder b = { 0, }; + struct spa_pod_frame f[2]; if (data->io_notify == NULL) return; spa_pod_builder_init(&b, data->io_notify, data->io_notify_size); - spa_pod_builder_push_sequence(&b, 0); + spa_pod_builder_push_sequence(&b, &f[0], 0); spa_pod_builder_control(&b, 0, SPA_CONTROL_Properties); - spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_Props, 0); + spa_pod_builder_push_object(&b, &f[1], SPA_TYPE_OBJECT_Props, 0); spa_pod_builder_prop(&b, SPA_PROP_volume, 0); spa_pod_builder_float(&b, (sin(data->volume_accum) / 2.0) + 0.5); - spa_pod_builder_pop(&b); - spa_pod_builder_pop(&b); + spa_pod_builder_pop(&b, &f[1]); + spa_pod_builder_pop(&b, &f[0]); data->volume_accum += M_PI_M2 / 1000.0; if (data->volume_accum >= M_PI_M2) diff --git a/src/examples/sdl.h b/src/examples/sdl.h index a2a25e127..f940eca84 100644 --- a/src/examples/sdl.h +++ b/src/examples/sdl.h @@ -101,15 +101,16 @@ static Uint32 id_to_sdl_format(uint32_t id) static struct spa_pod *sdl_build_formats(SDL_RendererInfo *info, struct spa_pod_builder *b) { uint32_t i, c; + struct spa_pod_frame f[2]; - spa_pod_builder_push_object(b, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat); + spa_pod_builder_push_object(b, &f[0], SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat); spa_pod_builder_prop(b, SPA_FORMAT_mediaType, 0); spa_pod_builder_id(b, SPA_MEDIA_TYPE_video); spa_pod_builder_prop(b, SPA_FORMAT_mediaSubtype, 0); spa_pod_builder_id(b, SPA_MEDIA_SUBTYPE_raw); spa_pod_builder_prop(b, SPA_FORMAT_VIDEO_format, 0); - spa_pod_builder_push_choice(b, SPA_CHOICE_Enum, 0); + spa_pod_builder_push_choice(b, &f[1], SPA_CHOICE_Enum, 0); for (i = 0, c = 0; i < info->num_texture_formats; i++) { uint32_t id = sdl_format_to_id(info->texture_formats[i]); if (id == 0) @@ -123,7 +124,7 @@ static struct spa_pod *sdl_build_formats(SDL_RendererInfo *info, struct spa_pod_ if (id != SPA_VIDEO_FORMAT_UNKNOWN) spa_pod_builder_id(b, id); } - spa_pod_builder_pop(b); + spa_pod_builder_pop(b, &f[1]); spa_pod_builder_add(b, SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle( &SPA_RECTANGLE(WIDTH, HEIGHT), @@ -135,5 +136,5 @@ static struct spa_pod *sdl_build_formats(SDL_RendererInfo *info, struct spa_pod_ &SPA_FRACTION(0,1), &SPA_FRACTION(30,1)), 0); - return spa_pod_builder_pop(b); + return spa_pod_builder_pop(b, &f[0]); } diff --git a/src/gst/gstpipewireformat.c b/src/gst/gstpipewireformat.c index 85c653757..e070932bc 100644 --- a/src/gst/gstpipewireformat.c +++ b/src/gst/gstpipewireformat.c @@ -362,6 +362,7 @@ handle_video_fields (ConvertData *d) const GValue *value, *value2; int i; struct spa_pod_choice *choice; + struct spa_pod_frame f; value = gst_structure_get_value (d->cs, "format"); if (value) { @@ -370,14 +371,14 @@ handle_video_fields (ConvertData *d) for (i = 0; (v = get_nth_string (value, i)); i++) { if (i == 0) { spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_format, 0); - spa_pod_builder_push_choice(&d->b, get_range_type (value), 0); + spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0); } idx = gst_video_format_from_string (v); if (idx < (int)SPA_N_ELEMENTS (video_format_map)) spa_pod_builder_id (&d->b, video_format_map[idx]); } - choice = spa_pod_builder_pop(&d->b); + choice = spa_pod_builder_pop(&d->b, &f); if (i <= 1) choice->body.type = SPA_CHOICE_None; } @@ -388,12 +389,12 @@ handle_video_fields (ConvertData *d) for (i = 0; get_nth_rectangle (value, value2, i, &v); i++) { if (i == 0) { spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_size, 0); - spa_pod_builder_push_choice(&d->b, get_range_type2 (value, value2), 0); + spa_pod_builder_push_choice(&d->b, &f, get_range_type2 (value, value2), 0); } spa_pod_builder_rectangle (&d->b, v.width, v.height); } - choice = spa_pod_builder_pop(&d->b); + choice = spa_pod_builder_pop(&d->b, &f); if (i <= 1) choice->body.type = SPA_CHOICE_None; } @@ -404,12 +405,12 @@ handle_video_fields (ConvertData *d) for (i = 0; get_nth_fraction (value, i, &v); i++) { if (i == 0) { spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_framerate, 0); - spa_pod_builder_push_choice(&d->b, get_range_type (value), 0); + spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0); } spa_pod_builder_fraction (&d->b, v.num, v.denom); } - choice = spa_pod_builder_pop(&d->b); + choice = spa_pod_builder_pop(&d->b, &f); if (i <= 1) choice->body.type = SPA_CHOICE_None; } @@ -420,12 +421,12 @@ handle_video_fields (ConvertData *d) for (i = 0; get_nth_fraction (value, i, &v); i++) { if (i == 0) { spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_maxFramerate, 0); - spa_pod_builder_push_choice(&d->b, get_range_type (value), 0); + spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0); } spa_pod_builder_fraction (&d->b, v.num, v.denom); } - choice = spa_pod_builder_pop(&d->b); + choice = spa_pod_builder_pop(&d->b, &f); if (i <= 1) choice->body.type = SPA_CHOICE_None; } @@ -437,6 +438,7 @@ handle_audio_fields (ConvertData *d) { const GValue *value; struct spa_pod_choice *choice; + struct spa_pod_frame f; int i = 0; value = gst_structure_get_value (d->cs, "format"); @@ -446,14 +448,14 @@ handle_audio_fields (ConvertData *d) for (i = 0; (v = get_nth_string (value, i)); i++) { if (i == 0) { spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_format, 0); - spa_pod_builder_push_choice(&d->b, get_range_type (value), 0); + spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0); } idx = gst_audio_format_from_string (v); if (idx < (int)SPA_N_ELEMENTS (audio_format_map)) spa_pod_builder_id (&d->b, audio_format_map[idx]); } - choice = spa_pod_builder_pop(&d->b); + choice = spa_pod_builder_pop(&d->b, &f); if (i <= 1) choice->body.type = SPA_CHOICE_None; } @@ -474,12 +476,12 @@ handle_audio_fields (ConvertData *d) if (i == 0) { spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_layout, 0); - spa_pod_builder_push_choice(&d->b, get_range_type (value), 0); + spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0); } spa_pod_builder_id (&d->b, layout); } - choice = spa_pod_builder_pop(&d->b); + choice = spa_pod_builder_pop(&d->b, &f); if (i <= 1) choice->body.type = SPA_CHOICE_None; } @@ -490,12 +492,12 @@ handle_audio_fields (ConvertData *d) for (i = 0; get_nth_int (value, i, &v); i++) { if (i == 0) { spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_rate, 0); - spa_pod_builder_push_choice(&d->b, get_range_type (value), 0); + spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0); } spa_pod_builder_int (&d->b, v); } - choice = spa_pod_builder_pop(&d->b); + choice = spa_pod_builder_pop(&d->b, &f); if (i <= 1) choice->body.type = SPA_CHOICE_None; } @@ -505,42 +507,46 @@ handle_audio_fields (ConvertData *d) for (i = 0; get_nth_int (value, i, &v); i++) { if (i == 0) { spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_channels, 0); - spa_pod_builder_push_choice(&d->b, get_range_type (value), 0); + spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0); } spa_pod_builder_int (&d->b, v); } - choice = spa_pod_builder_pop(&d->b); + choice = spa_pod_builder_pop(&d->b, &f); if (i <= 1) choice->body.type = SPA_CHOICE_None; } return TRUE; } -static uint32_t -write_pod (struct spa_pod_builder *b, const void *data, uint32_t size) +static int +builder_overflow (void *event_data, uint32_t size) { - uint32_t ref = b->state.offset; - - if (b->size <= ref) { - b->size = SPA_ROUND_UP_N (ref + size, 512); - b->data = realloc (b->data, b->size); - if (b->data == NULL) - return -1; - } - memcpy (SPA_MEMBER(b->data, ref, void), data, size); - return ref; + struct spa_pod_builder *b = event_data; + b->size = SPA_ROUND_UP_N (size, 512); + b->data = realloc (b->data, b->size); + if (b->data == NULL) + return -ENOMEM; + return 0; } +static const struct spa_pod_builder_callbacks builder_callbacks = { + SPA_VERSION_POD_BUILDER_CALLBACKS, + .overflow = builder_overflow +}; + static struct spa_pod * convert_1 (ConvertData *d) { + struct spa_pod_frame f; + if (!(d->type = find_media_types (gst_structure_get_name (d->cs)))) return NULL; - d->b.write = write_pod; + d->b.callbacks = &builder_callbacks; + d->b.callbacks_data = &d->b; - spa_pod_builder_push_object (&d->b, SPA_TYPE_OBJECT_Format, d->id); + spa_pod_builder_push_object (&d->b, &f, SPA_TYPE_OBJECT_Format, d->id); spa_pod_builder_prop (&d->b, SPA_FORMAT_mediaType, 0); spa_pod_builder_id(&d->b, d->type->media_type); @@ -553,7 +559,7 @@ convert_1 (ConvertData *d) else if (d->type->media_type == SPA_MEDIA_TYPE_audio) handle_audio_fields (d); - spa_pod_builder_pop (&d->b); + spa_pod_builder_pop (&d->b, &f); return SPA_MEMBER (d->b.data, 0, struct spa_pod); } @@ -628,7 +634,7 @@ static const char *audio_id_to_string(uint32_t id) } static void -handle_id_prop (struct spa_pod_prop *prop, const char *key, id_to_string_func func, GstCaps *res) +handle_id_prop (const struct spa_pod_prop *prop, const char *key, id_to_string_func func, GstCaps *res) { const char * str; struct spa_pod *val; @@ -670,7 +676,7 @@ handle_id_prop (struct spa_pod_prop *prop, const char *key, id_to_string_func fu } static void -handle_int_prop (struct spa_pod_prop *prop, const char *key, GstCaps *res) +handle_int_prop (const struct spa_pod_prop *prop, const char *key, GstCaps *res) { struct spa_pod *val; uint32_t *ints; @@ -714,7 +720,7 @@ handle_int_prop (struct spa_pod_prop *prop, const char *key, GstCaps *res) } static void -handle_rect_prop (struct spa_pod_prop *prop, const char *width, const char *height, GstCaps *res) +handle_rect_prop (const struct spa_pod_prop *prop, const char *width, const char *height, GstCaps *res) { struct spa_pod *val; struct spa_rectangle *rect; @@ -767,7 +773,7 @@ handle_rect_prop (struct spa_pod_prop *prop, const char *width, const char *heig } static void -handle_fraction_prop (struct spa_pod_prop *prop, const char *key, GstCaps *res) +handle_fraction_prop (const struct spa_pod_prop *prop, const char *key, GstCaps *res) { struct spa_pod *val; struct spa_fraction *fract; @@ -815,7 +821,7 @@ gst_caps_from_format (const struct spa_pod *format) { GstCaps *res = NULL; uint32_t media_type, media_subtype; - struct spa_pod_prop *prop; + const struct spa_pod_prop *prop = NULL; const struct spa_pod_object *obj = (const struct spa_pod_object *) format; if (spa_format_parse(format, &media_type, &media_subtype) < 0) @@ -824,7 +830,7 @@ gst_caps_from_format (const struct spa_pod *format) if (media_type == SPA_MEDIA_TYPE_video) { if (media_subtype == SPA_MEDIA_SUBTYPE_raw) { res = gst_caps_new_empty_simple ("video/x-raw"); - if ((prop = spa_pod_object_find_prop (obj, SPA_FORMAT_VIDEO_format))) { + if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_VIDEO_format))) { handle_id_prop (prop, "format", video_id_to_string, res); } } @@ -837,13 +843,13 @@ gst_caps_from_format (const struct spa_pod *format) "alignment", G_TYPE_STRING, "au", NULL); } - if ((prop = spa_pod_object_find_prop (obj, SPA_FORMAT_VIDEO_size))) { + if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_VIDEO_size))) { handle_rect_prop (prop, "width", "height", res); } - if ((prop = spa_pod_object_find_prop (obj, SPA_FORMAT_VIDEO_framerate))) { + if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_VIDEO_framerate))) { handle_fraction_prop (prop, "framerate", res); } - if ((prop = spa_pod_object_find_prop (obj, SPA_FORMAT_VIDEO_maxFramerate))) { + if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_VIDEO_maxFramerate))) { handle_fraction_prop (prop, "max-framerate", res); } } else if (media_type == SPA_MEDIA_TYPE_audio) { @@ -851,13 +857,13 @@ gst_caps_from_format (const struct spa_pod *format) res = gst_caps_new_simple ("audio/x-raw", "layout", G_TYPE_STRING, "interleaved", NULL); - if ((prop = spa_pod_object_find_prop (obj, SPA_FORMAT_AUDIO_format))) { + if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_AUDIO_format))) { handle_id_prop (prop, "format", audio_id_to_string, res); } - if ((prop = spa_pod_object_find_prop (obj, SPA_FORMAT_AUDIO_rate))) { + if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_AUDIO_rate))) { handle_int_prop (prop, "rate", res); } - if ((prop = spa_pod_object_find_prop (obj, SPA_FORMAT_AUDIO_channels))) { + if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_AUDIO_channels))) { handle_int_prop (prop, "channels", res); } } diff --git a/src/gst/gstpipewiresink.c b/src/gst/gstpipewiresink.c index d7dbb1827..976e50e87 100644 --- a/src/gst/gstpipewiresink.c +++ b/src/gst/gstpipewiresink.c @@ -230,12 +230,13 @@ pool_activated (GstPipeWirePool *pool, GstPipeWireSink *sink) const struct spa_pod *port_params[2]; struct spa_pod_builder b = { NULL }; uint8_t buffer[1024]; + struct spa_pod_frame f; config = gst_buffer_pool_get_config (GST_BUFFER_POOL (pool)); gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers); spa_pod_builder_init (&b, buffer, sizeof (buffer)); - spa_pod_builder_push_object (&b, SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers); + spa_pod_builder_push_object (&b, &f, SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers); if (size == 0) spa_pod_builder_add (&b, SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int(0, 0, INT32_MAX), @@ -251,7 +252,7 @@ pool_activated (GstPipeWirePool *pool, GstPipeWireSink *sink) max_buffers ? max_buffers : INT32_MAX), SPA_PARAM_BUFFERS_align, SPA_POD_Int(16), 0); - port_params[0] = spa_pod_builder_pop (&b); + port_params[0] = spa_pod_builder_pop (&b, &f); port_params[1] = spa_pod_builder_add_object (&b, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, diff --git a/src/modules/module-client-node/protocol-native.c b/src/modules/module-client-node/protocol-native.c index 12ddb3f8d..ae526e9e8 100644 --- a/src/modules/module-client-node/protocol-native.c +++ b/src/modules/module-client-node/protocol-native.c @@ -58,12 +58,13 @@ client_node_marshal_update(void *object, { struct pw_proxy *proxy = object; struct spa_pod_builder *b; + struct spa_pod_frame f; uint32_t i, n_items; b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_NODE_PROXY_METHOD_UPDATE); + spa_pod_builder_push_struct(b, &f); spa_pod_builder_add(b, - "[", SPA_POD_Int(change_mask), SPA_POD_Int(max_input_ports), SPA_POD_Int(max_output_ports), @@ -80,7 +81,7 @@ client_node_marshal_update(void *object, SPA_POD_String(props->items[i].key), SPA_POD_String(props->items[i].value), NULL); } - spa_pod_builder_add(b, "]", NULL); + spa_pod_builder_pop(b, &f); pw_protocol_native_end_proxy(proxy, b); } @@ -96,12 +97,13 @@ client_node_marshal_port_update(void *object, { struct pw_proxy *proxy = object; struct spa_pod_builder *b; + struct spa_pod_frame f[2]; uint32_t i, n_items; b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_NODE_PROXY_METHOD_PORT_UPDATE); + spa_pod_builder_push_struct(b, &f[0]); spa_pod_builder_add(b, - "[", SPA_POD_Int(direction), SPA_POD_Int(port_id), SPA_POD_Int(change_mask), @@ -114,8 +116,8 @@ client_node_marshal_port_update(void *object, if (info) { n_items = info->props ? info->props->n_items : 0; + spa_pod_builder_push_struct(b, &f[1]); spa_pod_builder_add(b, - "[", SPA_POD_Int(info->flags), SPA_POD_Int(info->rate), SPA_POD_Int(n_items), NULL); @@ -124,13 +126,12 @@ client_node_marshal_port_update(void *object, SPA_POD_String(info->props->items[i].key), SPA_POD_String(info->props->items[i].value), NULL); } - spa_pod_builder_add(b, - "]", NULL); + spa_pod_builder_pop(b, &f[1]); } else { spa_pod_builder_add(b, SPA_POD_Pod(NULL), NULL); } - spa_pod_builder_add(b, "]", NULL); + spa_pod_builder_pop(b, &f[0]); pw_protocol_native_end_proxy(proxy, b); } @@ -168,7 +169,7 @@ static int client_node_demarshal_add_mem(void *object, void *data, size_t size) uint32_t mem_id, type, memfd_idx, flags; int memfd; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&mem_id), SPA_POD_Id(&type), @@ -192,7 +193,7 @@ static int client_node_demarshal_transport(void *object, void *data, size_t size uint32_t node_id, ridx, widx; int readfd, writefd; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&node_id), SPA_POD_Int(&ridx), @@ -217,7 +218,7 @@ static int client_node_demarshal_set_param(void *object, void *data, size_t size uint32_t seq, id, flags; const struct spa_pod *param = NULL; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&seq), SPA_POD_Id(&id), @@ -235,7 +236,7 @@ static int client_node_demarshal_event_event(void *object, void *data, size_t si struct spa_pod_parser prs; const struct spa_event *event; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_PodObject(&event)) < 0) return -EINVAL; @@ -251,7 +252,7 @@ static int client_node_demarshal_command(void *object, void *data, size_t size) const struct spa_command *command; uint32_t seq; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&seq), SPA_POD_PodObject(&command)) < 0) @@ -267,7 +268,7 @@ static int client_node_demarshal_add_port(void *object, void *data, size_t size) struct spa_pod_parser prs; int32_t seq, direction, port_id; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&seq), SPA_POD_Int(&direction), @@ -284,7 +285,7 @@ static int client_node_demarshal_remove_port(void *object, void *data, size_t si struct spa_pod_parser prs; int32_t seq, direction, port_id; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&seq), SPA_POD_Int(&direction), @@ -302,7 +303,7 @@ static int client_node_demarshal_port_set_param(void *object, void *data, size_t uint32_t seq, direction, port_id, id, flags; const struct spa_pod *param = NULL; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&seq), SPA_POD_Int(&direction), @@ -321,13 +322,14 @@ static int client_node_demarshal_port_use_buffers(void *object, void *data, size { struct pw_proxy *proxy = object; struct spa_pod_parser prs; + struct spa_pod_frame f; uint32_t seq, direction, port_id, mix_id, n_buffers, data_id; struct pw_client_node_buffer *buffers; uint32_t i, j; - spa_pod_parser_init(&prs, data, size, 0); - if (spa_pod_parser_get(&prs, - "[" + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&seq), SPA_POD_Int(&direction), SPA_POD_Int(&port_id), @@ -389,7 +391,7 @@ static int client_node_demarshal_port_command(void *object, void *data, size_t s const struct spa_command *command; uint32_t direction, port_id; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&direction), SPA_POD_Int(&port_id), @@ -408,7 +410,7 @@ static int client_node_demarshal_port_set_io(void *object, void *data, size_t si struct spa_pod_parser prs; uint32_t seq, direction, port_id, mix_id, id, memid, off, sz; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&seq), SPA_POD_Int(&direction), @@ -434,7 +436,7 @@ static int client_node_demarshal_set_io(void *object, void *data, size_t size) struct spa_pod_parser prs; uint32_t id, memid, off, sz; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Id(&id), SPA_POD_Int(&memid), @@ -597,12 +599,13 @@ client_node_marshal_port_use_buffers(void *object, { struct pw_resource *resource = object; struct spa_pod_builder *b; + struct spa_pod_frame f; uint32_t i, j; b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_PROXY_EVENT_PORT_USE_BUFFERS); + spa_pod_builder_push_struct(b, &f); spa_pod_builder_add(b, - "[", SPA_POD_Int(seq), SPA_POD_Int(direction), SPA_POD_Int(port_id), @@ -636,7 +639,7 @@ client_node_marshal_port_use_buffers(void *object, SPA_POD_Int(d->maxsize), NULL); } } - spa_pod_builder_add(b, "]", NULL); + spa_pod_builder_pop(b, &f); pw_protocol_native_end_resource(resource, b); } @@ -714,7 +717,7 @@ static int client_node_demarshal_done(void *object, void *data, size_t size) struct spa_pod_parser prs; uint32_t seq, res; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&seq), SPA_POD_Int(&res)) < 0) @@ -728,14 +731,15 @@ static int client_node_demarshal_update(void *object, void *data, size_t size) { struct pw_resource *resource = object; struct spa_pod_parser prs; + struct spa_pod_frame f; uint32_t change_mask, max_input_ports, max_output_ports, n_params; const struct spa_pod **params; struct spa_dict props; uint32_t i; - spa_pod_parser_init(&prs, data, size, 0); - if (spa_pod_parser_get(&prs, - "[" + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&change_mask), SPA_POD_Int(&max_input_ports), SPA_POD_Int(&max_output_ports), @@ -774,15 +778,16 @@ static int client_node_demarshal_port_update(void *object, void *data, size_t si { struct pw_resource *resource = object; struct spa_pod_parser prs; + struct spa_pod_frame f; uint32_t i, direction, port_id, change_mask, n_params; const struct spa_pod **params = NULL; struct spa_port_info info = { 0 }, *infop = NULL; struct spa_pod *ipod; struct spa_dict props; - spa_pod_parser_init(&prs, data, size, 0); - if (spa_pod_parser_get(&prs, - "[" + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&direction), SPA_POD_Int(&port_id), SPA_POD_Int(&change_mask), @@ -801,11 +806,12 @@ static int client_node_demarshal_port_update(void *object, void *data, size_t si if (ipod) { struct spa_pod_parser p2; + struct spa_pod_frame f2; infop = &info; spa_pod_parser_pod(&p2, ipod); - if (spa_pod_parser_get(&p2, - "[" + if (spa_pod_parser_push_struct(&p2, &f2) < 0 || + spa_pod_parser_get(&p2, SPA_POD_Int(&info.flags), SPA_POD_Int(&info.rate), SPA_POD_Int(&props.n_items), NULL) < 0) @@ -838,7 +844,7 @@ static int client_node_demarshal_set_active(void *object, void *data, size_t siz struct spa_pod_parser prs; int active; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Bool(&active)) < 0) return -EINVAL; @@ -853,7 +859,7 @@ static int client_node_demarshal_event_method(void *object, void *data, size_t s struct spa_pod_parser prs; struct spa_event *event; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_PodObject(&event)) < 0) return -EINVAL; diff --git a/src/modules/module-protocol-native/connection.c b/src/modules/module-protocol-native/connection.c index bd20b7e9a..c4225eacf 100644 --- a/src/modules/module-protocol-native/connection.c +++ b/src/modules/module-protocol-native/connection.c @@ -352,20 +352,22 @@ static inline void *begin_write(struct pw_protocol_native_connection *conn, uint return p + 2; } -static uint32_t write_pod(struct spa_pod_builder *b, const void *data, uint32_t size) +static int builder_overflow(void *callbacks_data, uint32_t size) { - struct impl *impl = SPA_CONTAINER_OF(b, struct impl, builder); - uint32_t ref = b->state.offset; + struct impl *impl = callbacks_data; + struct spa_pod_builder *b = &impl->builder; - if (b->size <= ref) { - b->size = SPA_ROUND_UP_N(ref + size, 4096); - b->data = begin_write(&impl->this, b->size); - } - memcpy(SPA_MEMBER(b->data, ref, void), data, size); - - return ref; + b->size = SPA_ROUND_UP_N(size, 4096); + if ((b->data = begin_write(&impl->this, b->size)) == NULL) + return -ENOMEM; + return 0; } +static const struct spa_pod_builder_callbacks builder_callbacks = { + SPA_VERSION_POD_BUILDER_CALLBACKS, + .overflow = builder_overflow +}; + struct spa_pod_builder * pw_protocol_native_connection_begin_resource(struct pw_protocol_native_connection *conn, struct pw_resource *resource, @@ -375,8 +377,9 @@ pw_protocol_native_connection_begin_resource(struct pw_protocol_native_connectio impl->dest_id = resource->id; impl->opcode = opcode; - impl->builder = (struct spa_pod_builder) { NULL, 0, 0, write_pod }; - + impl->builder = SPA_POD_BUILDER_INIT(NULL, 0); + impl->builder.callbacks = &builder_callbacks; + impl->builder.callbacks_data = impl; return &impl->builder; } @@ -389,8 +392,9 @@ pw_protocol_native_connection_begin_proxy(struct pw_protocol_native_connection * impl->dest_id = proxy->id; impl->opcode = opcode; - impl->builder = (struct spa_pod_builder) { NULL, 0, 0, write_pod, }; - + impl->builder = SPA_POD_BUILDER_INIT(NULL, 0); + impl->builder.callbacks = &builder_callbacks; + impl->builder.callbacks_data = impl; return &impl->builder; } diff --git a/src/modules/module-protocol-native/protocol-native.c b/src/modules/module-protocol-native/protocol-native.c index 142a1c267..6ea572b50 100644 --- a/src/modules/module-protocol-native/protocol-native.c +++ b/src/modules/module-protocol-native/protocol-native.c @@ -72,6 +72,22 @@ static void core_marshal_get_registry(void *object, uint32_t version, uint32_t n pw_protocol_native_end_proxy(proxy, b); } +static void push_dict(struct spa_pod_builder *b, const struct spa_dict *dict) +{ + uint32_t i, n_items; + struct spa_pod_frame f; + + n_items = dict ? dict->n_items : 0; + + spa_pod_builder_push_struct(b, &f); + spa_pod_builder_int(b, n_items); + for (i = 0; i < n_items; i++) { + spa_pod_builder_string(b, dict->items[i].key); + spa_pod_builder_string(b, dict->items[i].value); + } + spa_pod_builder_pop(b, &f); +} + static void core_marshal_create_object(void *object, const char *factory_name, @@ -80,29 +96,19 @@ core_marshal_create_object(void *object, { struct pw_proxy *proxy = object; struct spa_pod_builder *b; - uint32_t i, n_items; + struct spa_pod_frame f; b = pw_protocol_native_begin_proxy(proxy, PW_CORE_PROXY_METHOD_CREATE_OBJECT); - n_items = props ? props->n_items : 0; - - spa_pod_builder_add(b, "[" + spa_pod_builder_push_struct(b, &f); + spa_pod_builder_add(b, SPA_POD_String(factory_name), SPA_POD_Id(type), SPA_POD_Int(version), - SPA_POD_Int(n_items), - NULL); - - for (i = 0; i < n_items; i++) { - spa_pod_builder_add(b, - SPA_POD_String(props->items[i].key), - SPA_POD_String(props->items[i].value), - NULL); - } - spa_pod_builder_add(b, - SPA_POD_Int(new_id), - "]", NULL); + push_dict(b, props); + spa_pod_builder_int(b, new_id); + spa_pod_builder_pop(b, &f); pw_protocol_native_end_proxy(proxy, b); } @@ -125,20 +131,27 @@ static int core_demarshal_info(void *object, void *data, size_t size) { struct pw_proxy *proxy = object; struct spa_dict props; + struct spa_pod_frame f[2]; struct pw_core_info info; struct spa_pod_parser prs; uint32_t i; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f[0]) < 0) + return -EINVAL; if (spa_pod_parser_get(&prs, - "[" SPA_POD_Int(&info.id), SPA_POD_Long(&info.change_mask), SPA_POD_String(&info.user_name), SPA_POD_String(&info.host_name), SPA_POD_String(&info.version), SPA_POD_String(&info.name), - SPA_POD_Int(&info.cookie), + SPA_POD_Int(&info.cookie), NULL) < 0) + return -EINVAL; + + if (spa_pod_parser_push_struct(&prs, &f[1]) < 0) + return -EINVAL; + if (spa_pod_parser_get(&prs, SPA_POD_Int(&props.n_items), NULL) < 0) return -EINVAL; @@ -161,7 +174,7 @@ static int core_demarshal_done(void *object, void *data, size_t size) struct spa_pod_parser prs; uint32_t seq; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&seq)) < 0) return -EINVAL; @@ -177,7 +190,7 @@ static int core_demarshal_error(void *object, void *data, size_t size) uint32_t id, res; const char *error; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&id), SPA_POD_Int(&res), @@ -194,7 +207,7 @@ static int core_demarshal_remove_id(void *object, void *data, size_t size) struct spa_pod_parser prs; uint32_t id; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&id)) < 0) return -EINVAL; @@ -206,14 +219,12 @@ static void core_marshal_info(void *object, const struct pw_core_info *info) { struct pw_resource *resource = object; struct spa_pod_builder *b; - uint32_t i, n_items; + struct spa_pod_frame f; b = pw_protocol_native_begin_resource(resource, PW_CORE_PROXY_EVENT_INFO); - n_items = info->props ? info->props->n_items : 0; - + spa_pod_builder_push_struct(b, &f); spa_pod_builder_add(b, - "[", SPA_POD_Int(info->id), SPA_POD_Long(info->change_mask), SPA_POD_String(info->user_name), @@ -221,16 +232,9 @@ static void core_marshal_info(void *object, const struct pw_core_info *info) SPA_POD_String(info->version), SPA_POD_String(info->name), SPA_POD_Int(info->cookie), - SPA_POD_Int(n_items), NULL); - - for (i = 0; i < n_items; i++) { - spa_pod_builder_add(b, - SPA_POD_String(info->props->items[i].key), - SPA_POD_String(info->props->items[i].value), - NULL); - } - spa_pod_builder_add(b, "]", NULL); + push_dict(b, info->props); + spa_pod_builder_pop(b, &f); pw_protocol_native_end_resource(resource, b); } @@ -288,7 +292,7 @@ static int core_demarshal_hello(void *object, void *data, size_t size) struct spa_pod_parser prs; uint32_t version; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&version)) < 0) return -EINVAL; @@ -303,7 +307,7 @@ static int core_demarshal_sync(void *object, void *data, size_t size) struct spa_pod_parser prs; uint32_t seq; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&seq)) < 0) return -EINVAL; @@ -318,7 +322,7 @@ static int core_demarshal_get_registry(void *object, void *data, size_t size) struct spa_pod_parser prs; int32_t version, new_id; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&version), SPA_POD_Int(&new_id)) < 0) @@ -332,16 +336,22 @@ static int core_demarshal_create_object(void *object, void *data, size_t size) { struct pw_resource *resource = object; struct spa_pod_parser prs; + struct spa_pod_frame f[2]; uint32_t version, type, new_id, i; const char *factory_name; struct spa_dict props; - spa_pod_parser_init(&prs, data, size, 0); - if (spa_pod_parser_get(&prs, - "[" + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_String(&factory_name), SPA_POD_Id(&type), SPA_POD_Int(&version), + NULL) < 0) + return -EINVAL; + + if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&props.n_items), NULL) < 0) return -EINVAL; @@ -352,6 +362,8 @@ static int core_demarshal_create_object(void *object, void *data, size_t size) SPA_POD_String(&props.items[i].value), NULL) < 0) return -EINVAL; } + spa_pod_parser_pop(&prs, &f[1]); + if (spa_pod_parser_get(&prs, SPA_POD_Int(&new_id), NULL) < 0) return -EINVAL; @@ -368,7 +380,7 @@ static int core_demarshal_destroy(void *object, void *data, size_t size) struct spa_pod_parser prs; uint32_t id; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&id)) < 0) return -EINVAL; @@ -382,27 +394,20 @@ static void registry_marshal_global(void *object, uint32_t id, uint32_t parent_i { struct pw_resource *resource = object; struct spa_pod_builder *b; - uint32_t i, n_items; + struct spa_pod_frame f; b = pw_protocol_native_begin_resource(resource, PW_REGISTRY_PROXY_EVENT_GLOBAL); - n_items = props ? props->n_items : 0; - + spa_pod_builder_push_struct(b, &f); spa_pod_builder_add(b, - "[", SPA_POD_Int(id), SPA_POD_Int(parent_id), SPA_POD_Int(permissions), SPA_POD_Id(type), SPA_POD_Int(version), - SPA_POD_Int(n_items), NULL); - - for (i = 0; i < n_items; i++) { - spa_pod_builder_add(b, - SPA_POD_String(props->items[i].key), - SPA_POD_String(props->items[i].value), NULL); - } - spa_pod_builder_add(b, "]", NULL); + NULL); + push_dict(b, props); + spa_pod_builder_pop(b, &f); pw_protocol_native_end_resource(resource, b); } @@ -425,7 +430,7 @@ static int registry_demarshal_bind(void *object, void *data, size_t size) struct spa_pod_parser prs; uint32_t id, version, type, new_id; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&id), SPA_POD_Id(&type), @@ -443,7 +448,7 @@ static int registry_demarshal_destroy(void *object, void *data, size_t size) struct spa_pod_parser prs; uint32_t id; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&id)) < 0) return -EINVAL; @@ -456,27 +461,20 @@ static void module_marshal_info(void *object, const struct pw_module_info *info) { struct pw_resource *resource = object; struct spa_pod_builder *b; - uint32_t i, n_items; + struct spa_pod_frame f; b = pw_protocol_native_begin_resource(resource, PW_MODULE_PROXY_EVENT_INFO); - n_items = info->props ? info->props->n_items : 0; - + spa_pod_builder_push_struct(b, &f); spa_pod_builder_add(b, - "[", SPA_POD_Int(info->id), SPA_POD_Long(info->change_mask), SPA_POD_String(info->name), SPA_POD_String(info->filename), SPA_POD_String(info->args), - SPA_POD_Int(n_items), NULL); - - for (i = 0; i < n_items; i++) { - spa_pod_builder_add(b, - SPA_POD_String(info->props->items[i].key), - SPA_POD_String(info->props->items[i].value), NULL); - } - spa_pod_builder_add(b, "]", NULL); + NULL); + push_dict(b, info->props); + spa_pod_builder_pop(b, &f); pw_protocol_native_end_resource(resource, b); } @@ -485,18 +483,23 @@ static int module_demarshal_info(void *object, void *data, size_t size) { struct pw_proxy *proxy = object; struct spa_pod_parser prs; + struct spa_pod_frame f[2]; struct spa_dict props; struct pw_module_info info; uint32_t i; - spa_pod_parser_init(&prs, data, size, 0); - if (spa_pod_parser_get(&prs, - "[" + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&info.id), SPA_POD_Long(&info.change_mask), SPA_POD_String(&info.name), SPA_POD_String(&info.filename), - SPA_POD_String(&info.args), + SPA_POD_String(&info.args), NULL) < 0) + return -EINVAL; + + if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&props.n_items), NULL) < 0) return -EINVAL; @@ -516,25 +519,18 @@ static void device_marshal_info(void *object, const struct pw_device_info *info) { struct pw_resource *resource = object; struct spa_pod_builder *b; - uint32_t i, n_items; + struct spa_pod_frame f; b = pw_protocol_native_begin_resource(resource, PW_DEVICE_PROXY_EVENT_INFO); - n_items = info->props ? info->props->n_items : 0; - + spa_pod_builder_push_struct(b, &f); spa_pod_builder_add(b, - "[", SPA_POD_Int(info->id), SPA_POD_String(info->name), SPA_POD_Long(info->change_mask), - SPA_POD_Int(n_items), NULL); - - for (i = 0; i < n_items; i++) { - spa_pod_builder_add(b, - SPA_POD_String(info->props->items[i].key), - SPA_POD_String(info->props->items[i].value), NULL); - } - spa_pod_builder_add(b, "]", NULL); + NULL); + push_dict(b, info->props); + spa_pod_builder_pop(b, &f); pw_protocol_native_end_resource(resource, b); } @@ -543,16 +539,21 @@ static int device_demarshal_info(void *object, void *data, size_t size) { struct pw_proxy *proxy = object; struct spa_pod_parser prs; + struct spa_pod_frame f[2]; struct spa_dict props; struct pw_device_info info; uint32_t i; - spa_pod_parser_init(&prs, data, size, 0); - if (spa_pod_parser_get(&prs, - "[" + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&info.id), SPA_POD_String(&info.name), - SPA_POD_Long(&info.change_mask), + SPA_POD_Long(&info.change_mask), NULL) < 0) + return -EINVAL; + + if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&props.n_items), NULL) < 0) return -EINVAL; @@ -592,7 +593,7 @@ static int device_demarshal_param(void *object, void *data, size_t size) uint32_t id, index, next; struct spa_pod *param; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Id(&id), SPA_POD_Int(&index), @@ -628,7 +629,7 @@ static int device_demarshal_enum_params(void *object, void *data, size_t size) uint32_t id, index, num; struct spa_pod *filter; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Id(&id), SPA_POD_Int(&index), @@ -662,7 +663,7 @@ static int device_demarshal_set_param(void *object, void *data, size_t size) uint32_t id, flags; struct spa_pod *param; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Id(&id), SPA_POD_Int(&flags), @@ -677,27 +678,20 @@ static void factory_marshal_info(void *object, const struct pw_factory_info *inf { struct pw_resource *resource = object; struct spa_pod_builder *b; - uint32_t i, n_items; + struct spa_pod_frame f; b = pw_protocol_native_begin_resource(resource, PW_FACTORY_PROXY_EVENT_INFO); - n_items = info->props ? info->props->n_items : 0; - + spa_pod_builder_push_struct(b, &f); spa_pod_builder_add(b, - "[", SPA_POD_Int(info->id), SPA_POD_Long(info->change_mask), SPA_POD_String(info->name), SPA_POD_Id(info->type), SPA_POD_Int(info->version), - SPA_POD_Int(n_items), NULL); - - for (i = 0; i < n_items; i++) { - spa_pod_builder_add(b, - SPA_POD_String(info->props->items[i].key), - SPA_POD_String(info->props->items[i].value), NULL); - } - spa_pod_builder_add(b, "]", NULL); + NULL); + push_dict(b, info->props); + spa_pod_builder_pop(b, &f); pw_protocol_native_end_resource(resource, b); } @@ -706,18 +700,23 @@ static int factory_demarshal_info(void *object, void *data, size_t size) { struct pw_proxy *proxy = object; struct spa_pod_parser prs; + struct spa_pod_frame f[2]; struct spa_dict props; struct pw_factory_info info; uint32_t i; - spa_pod_parser_init(&prs, data, size, 0); - if (spa_pod_parser_get(&prs, - "[" + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&info.id), SPA_POD_Long(&info.change_mask), SPA_POD_String(&info.name), SPA_POD_Id(&info.type), - SPA_POD_Int(&info.version), + SPA_POD_Int(&info.version), NULL) < 0) + return -EINVAL; + + if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&props.n_items), NULL) < 0) return -EINVAL; @@ -737,14 +736,12 @@ static void node_marshal_info(void *object, const struct pw_node_info *info) { struct pw_resource *resource = object; struct spa_pod_builder *b; - uint32_t i, n_items; + struct spa_pod_frame f; b = pw_protocol_native_begin_resource(resource, PW_NODE_PROXY_EVENT_INFO); - n_items = info->props ? info->props->n_items : 0; - + spa_pod_builder_push_struct(b, &f); spa_pod_builder_add(b, - "[", SPA_POD_Int(info->id), SPA_POD_Long(info->change_mask), SPA_POD_String(info->name), @@ -754,14 +751,9 @@ static void node_marshal_info(void *object, const struct pw_node_info *info) SPA_POD_Int(info->n_output_ports), SPA_POD_Id(info->state), SPA_POD_String(info->error), - SPA_POD_Int(n_items), NULL); - - for (i = 0; i < n_items; i++) { - spa_pod_builder_add(b, - SPA_POD_String(info->props->items[i].key), - SPA_POD_String(info->props->items[i].value), NULL); - } - spa_pod_builder_add(b, "]", NULL); + NULL); + push_dict(b, info->props); + spa_pod_builder_pop(b, &f); pw_protocol_native_end_resource(resource, b); } @@ -770,13 +762,14 @@ static int node_demarshal_info(void *object, void *data, size_t size) { struct pw_proxy *proxy = object; struct spa_pod_parser prs; + struct spa_pod_frame f[2]; struct spa_dict props; struct pw_node_info info; uint32_t i; - spa_pod_parser_init(&prs, data, size, 0); - if (spa_pod_parser_get(&prs, - "[" + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&info.id), SPA_POD_Long(&info.change_mask), SPA_POD_String(&info.name), @@ -785,7 +778,11 @@ static int node_demarshal_info(void *object, void *data, size_t size) SPA_POD_Int(&info.max_output_ports), SPA_POD_Int(&info.n_output_ports), SPA_POD_Id(&info.state), - SPA_POD_String(&info.error), + SPA_POD_String(&info.error), NULL) < 0) + return -EINVAL; + + if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&props.n_items), NULL) < 0) return -EINVAL; @@ -825,7 +822,7 @@ static int node_demarshal_param(void *object, void *data, size_t size) uint32_t id, index, next; struct spa_pod *param; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Id(&id), SPA_POD_Int(&index), @@ -861,7 +858,7 @@ static int node_demarshal_enum_params(void *object, void *data, size_t size) uint32_t id, index, num; struct spa_pod *filter; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Id(&id), SPA_POD_Int(&index), @@ -895,7 +892,7 @@ static int node_demarshal_set_param(void *object, void *data, size_t size) uint32_t id, flags; struct spa_pod *param; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Id(&id), SPA_POD_Int(&flags), @@ -923,7 +920,7 @@ static int node_demarshal_send_command(void *object, void *data, size_t size) struct spa_pod_parser prs; struct spa_command *command; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Pod(&command)) < 0) return -EINVAL; @@ -936,25 +933,18 @@ static void port_marshal_info(void *object, const struct pw_port_info *info) { struct pw_resource *resource = object; struct spa_pod_builder *b; - uint32_t i, n_items; + struct spa_pod_frame f; b = pw_protocol_native_begin_resource(resource, PW_PORT_PROXY_EVENT_INFO); - n_items = info->props ? info->props->n_items : 0; - + spa_pod_builder_push_struct(b, &f); spa_pod_builder_add(b, - "[", SPA_POD_Int(info->id), SPA_POD_Int(info->direction), SPA_POD_Long(info->change_mask), - SPA_POD_Int(n_items), NULL); - - for (i = 0; i < n_items; i++) { - spa_pod_builder_add(b, - SPA_POD_String(info->props->items[i].key), - SPA_POD_String(info->props->items[i].value), NULL); - } - spa_pod_builder_add(b, "]", NULL); + NULL); + push_dict(b, info->props); + spa_pod_builder_pop(b, &f); pw_protocol_native_end_resource(resource, b); } @@ -963,16 +953,21 @@ static int port_demarshal_info(void *object, void *data, size_t size) { struct pw_proxy *proxy = object; struct spa_pod_parser prs; + struct spa_pod_frame f[2]; struct spa_dict props; struct pw_port_info info; uint32_t i; - spa_pod_parser_init(&prs, data, size, 0); - if (spa_pod_parser_get(&prs, - "[" + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&info.id), SPA_POD_Int(&info.direction), - SPA_POD_Long(&info.change_mask), + SPA_POD_Long(&info.change_mask), NULL) < 0) + return -EINVAL; + + if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&props.n_items), NULL) < 0) return -EINVAL; @@ -1012,7 +1007,7 @@ static int port_demarshal_param(void *object, void *data, size_t size) uint32_t id, index, next; struct spa_pod *param; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Id(&id), SPA_POD_Int(&index), @@ -1048,7 +1043,7 @@ static int port_demarshal_enum_params(void *object, void *data, size_t size) uint32_t id, index, num; struct spa_pod *filter; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Id(&id), SPA_POD_Int(&index), @@ -1064,24 +1059,17 @@ static void client_marshal_info(void *object, const struct pw_client_info *info) { struct pw_resource *resource = object; struct spa_pod_builder *b; - uint32_t i, n_items; + struct spa_pod_frame f; b = pw_protocol_native_begin_resource(resource, PW_CLIENT_PROXY_EVENT_INFO); - n_items = info->props ? info->props->n_items : 0; - + spa_pod_builder_push_struct(b, &f); spa_pod_builder_add(b, - "[", SPA_POD_Int(info->id), SPA_POD_Long(info->change_mask), - SPA_POD_Int(n_items), NULL); - - for (i = 0; i < n_items; i++) { - spa_pod_builder_add(b, - SPA_POD_String(info->props->items[i].key), - SPA_POD_String(info->props->items[i].value), NULL); - } - spa_pod_builder_add(b, "]", NULL); + NULL); + push_dict(b, info->props); + spa_pod_builder_pop(b, &f); pw_protocol_native_end_resource(resource, b); } @@ -1090,15 +1078,20 @@ static int client_demarshal_info(void *object, void *data, size_t size) { struct pw_proxy *proxy = object; struct spa_pod_parser prs; + struct spa_pod_frame f[2]; struct spa_dict props; struct pw_client_info info; uint32_t i; - spa_pod_parser_init(&prs, data, size, 0); - if (spa_pod_parser_get(&prs, - "[" + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&info.id), - SPA_POD_Long(&info.change_mask), + SPA_POD_Long(&info.change_mask), NULL) < 0) + return -EINVAL; + + if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&props.n_items), NULL) < 0) return -EINVAL; @@ -1119,6 +1112,7 @@ static void client_marshal_permissions(void *object, uint32_t index, uint32_t n_ { struct pw_resource *resource = object; struct spa_pod_builder *b; + struct spa_pod_frame f[2]; uint32_t i, n = 0; b = pw_protocol_native_begin_resource(resource, PW_CLIENT_PROXY_EVENT_PERMISSIONS); @@ -1128,19 +1122,19 @@ static void client_marshal_permissions(void *object, uint32_t index, uint32_t n_ n++; } - spa_pod_builder_add(b, - "[", - SPA_POD_Int(index), - SPA_POD_Int(n), NULL); + spa_pod_builder_push_struct(b, &f[0]); + spa_pod_builder_int(b, index); + spa_pod_builder_push_struct(b, &f[1]); + spa_pod_builder_int(b, n); for (i = 0; i < n_permissions; i++) { if (permissions[i].permissions == SPA_ID_INVALID) continue; - spa_pod_builder_add(b, - SPA_POD_Int(permissions[i].id), - SPA_POD_Int(permissions[i].permissions), NULL); + spa_pod_builder_int(b, permissions[i].id); + spa_pod_builder_int(b, permissions[i].permissions); } - spa_pod_builder_add(b, "]", NULL); + spa_pod_builder_pop(b, &f[1]); + spa_pod_builder_pop(b, &f[0]); pw_protocol_native_end_resource(resource, b); } @@ -1150,12 +1144,18 @@ static int client_demarshal_permissions(void *object, void *data, size_t size) struct pw_proxy *proxy = object; struct pw_permission *permissions; struct spa_pod_parser prs; + struct spa_pod_frame f[2]; uint32_t i, index, n_permissions; - spa_pod_parser_init(&prs, data, size, 0); - if (spa_pod_parser_get(&prs, "[", - SPA_POD_Int(&index), - SPA_POD_Int(&n_permissions), NULL) < 0) + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || + spa_pod_parser_get(&prs, + SPA_POD_Int(&index), NULL) < 0) + return -EINVAL; + + if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 || + spa_pod_parser_get(&prs, + SPA_POD_Int(&n_permissions), NULL) < 0) return -EINVAL; permissions = alloca(n_permissions * sizeof(struct pw_permission)); @@ -1189,7 +1189,7 @@ static int client_demarshal_error(void *object, void *data, size_t size) uint32_t id, res; const char *error; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&id), SPA_POD_Int(&res), @@ -1218,21 +1218,13 @@ static void client_marshal_update_properties(void *object, const struct spa_dict { struct pw_proxy *proxy = object; struct spa_pod_builder *b; - uint32_t i, n_items; + struct spa_pod_frame f; b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_PROXY_METHOD_UPDATE_PROPERTIES); - n_items = props ? props->n_items : 0; - - spa_pod_builder_add(b, "[", - SPA_POD_Int(n_items), NULL); - - for (i = 0; i < n_items; i++) { - spa_pod_builder_add(b, - SPA_POD_String(props->items[i].key), - SPA_POD_String(props->items[i].value), NULL); - } - spa_pod_builder_add(b, "]", NULL); + spa_pod_builder_push_struct(b, &f); + push_dict(b, props); + spa_pod_builder_pop(b, &f); pw_protocol_native_end_proxy(proxy, b); } @@ -1242,12 +1234,14 @@ static int client_demarshal_update_properties(void *object, void *data, size_t s struct pw_resource *resource = object; struct spa_dict props; struct spa_pod_parser prs; + struct spa_pod_frame f[2]; uint32_t i; - spa_pod_parser_init(&prs, data, size, 0); - if (spa_pod_parser_get(&prs, - "[", - SPA_POD_Int(&props.n_items), NULL) < 0) + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || + spa_pod_parser_push_struct(&prs, &f[1]) < 0 || + spa_pod_parser_get(&prs, + SPA_POD_Int(&props.n_items), NULL) < 0) return -EINVAL; props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); @@ -1268,7 +1262,7 @@ static int client_demarshal_get_permissions(void *object, void *data, size_t siz struct spa_pod_parser prs; uint32_t index, num; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&index), SPA_POD_Int(&num)) < 0) @@ -1283,19 +1277,18 @@ static void client_marshal_update_permissions(void *object, uint32_t n_permissio { struct pw_proxy *proxy = object; struct spa_pod_builder *b; + struct spa_pod_frame f; uint32_t i; b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_PROXY_METHOD_UPDATE_PERMISSIONS); - spa_pod_builder_add(b, "[", - SPA_POD_Int(n_permissions), NULL); - + spa_pod_builder_push_struct(b, &f); + spa_pod_builder_int(b, n_permissions); for (i = 0; i < n_permissions; i++) { - spa_pod_builder_add(b, - SPA_POD_Int(permissions[i].id), - SPA_POD_Int(permissions[i].permissions), NULL); + spa_pod_builder_int(b, permissions[i].id); + spa_pod_builder_int(b, permissions[i].permissions); } - spa_pod_builder_add(b, "]", NULL); + spa_pod_builder_pop(b, &f); pw_protocol_native_end_proxy(proxy, b); } @@ -1305,11 +1298,12 @@ static int client_demarshal_update_permissions(void *object, void *data, size_t struct pw_resource *resource = object; struct pw_permission *permissions; struct spa_pod_parser prs; + struct spa_pod_frame f[1]; uint32_t i, n_permissions; - spa_pod_parser_init(&prs, data, size, 0); - if (spa_pod_parser_get(&prs, - "[", + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&n_permissions), NULL) < 0) return -EINVAL; @@ -1329,14 +1323,12 @@ static void link_marshal_info(void *object, const struct pw_link_info *info) { struct pw_resource *resource = object; struct spa_pod_builder *b; - uint32_t i, n_items; + struct spa_pod_frame f; b = pw_protocol_native_begin_resource(resource, PW_LINK_PROXY_EVENT_INFO); - n_items = info->props ? info->props->n_items : 0; - + spa_pod_builder_push_struct(b, &f); spa_pod_builder_add(b, - "[", SPA_POD_Int(info->id), SPA_POD_Long(info->change_mask), SPA_POD_Int(info->output_node_id), @@ -1346,14 +1338,9 @@ static void link_marshal_info(void *object, const struct pw_link_info *info) SPA_POD_Int(info->state), SPA_POD_String(info->error), SPA_POD_Pod(info->format), - SPA_POD_Int(n_items), NULL); - - for (i = 0; i < n_items; i++) { - spa_pod_builder_add(b, - SPA_POD_String(info->props->items[i].key), - SPA_POD_String(info->props->items[i].value), NULL); - } - spa_pod_builder_add(b, "]", NULL); + NULL); + push_dict(b, info->props); + spa_pod_builder_pop(b, &f); pw_protocol_native_end_resource(resource, b); } @@ -1362,13 +1349,14 @@ static int link_demarshal_info(void *object, void *data, size_t size) { struct pw_proxy *proxy = object; struct spa_pod_parser prs; + struct spa_pod_frame f[2]; struct spa_dict props; struct pw_link_info info = { 0, }; uint32_t i; - spa_pod_parser_init(&prs, data, size, 0); - if (spa_pod_parser_get(&prs, - "[" + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&info.id), SPA_POD_Long(&info.change_mask), SPA_POD_Int(&info.output_node_id), @@ -1377,7 +1365,11 @@ static int link_demarshal_info(void *object, void *data, size_t size) SPA_POD_Int(&info.input_port_id), SPA_POD_Int(&info.state), SPA_POD_String(&info.error), - SPA_POD_Pod(&info.format), + SPA_POD_Pod(&info.format), NULL) < 0) + return -EINVAL; + + if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&props.n_items), NULL) < 0) return -EINVAL; @@ -1397,17 +1389,22 @@ static int registry_demarshal_global(void *object, void *data, size_t size) { struct pw_proxy *proxy = object; struct spa_pod_parser prs; + struct spa_pod_frame f[2]; uint32_t id, parent_id, permissions, type, version, i; struct spa_dict props; - spa_pod_parser_init(&prs, data, size, 0); - if (spa_pod_parser_get(&prs, - "[" + spa_pod_parser_init(&prs, data, size); + if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&id), SPA_POD_Int(&parent_id), SPA_POD_Int(&permissions), SPA_POD_Id(&type), - SPA_POD_Int(&version), + SPA_POD_Int(&version), NULL) < 0) + return -EINVAL; + + if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 || + spa_pod_parser_get(&prs, SPA_POD_Int(&props.n_items), NULL) < 0) return -EINVAL; @@ -1431,7 +1428,7 @@ static int registry_demarshal_global_remove(void *object, void *data, size_t siz struct spa_pod_parser prs; uint32_t id; - spa_pod_parser_init(&prs, data, size, 0); + spa_pod_parser_init(&prs, data, size); if (spa_pod_parser_get_struct(&prs, SPA_POD_Int(&id)) < 0) return -EINVAL; diff --git a/src/modules/spa/spa-monitor.c b/src/modules/spa/spa-monitor.c index 136824ad6..ac7591af4 100644 --- a/src/modules/spa/spa-monitor.c +++ b/src/modules/spa/spa-monitor.c @@ -102,12 +102,15 @@ static struct monitor_item *add_item(struct pw_spa_monitor *this, if (info) { struct spa_pod_parser prs; + struct spa_pod_frame f; spa_pod_parser_pod(&prs, info); - if (spa_pod_parser_get(&prs, "[", NULL) == 0) { + if (spa_pod_parser_push_struct(&prs, &f) == 0) { while (true) { const char *key, *val; - if (spa_pod_parser_get(&prs, "ss", &key, &val, NULL) < 0) + if (spa_pod_parser_get(&prs, + SPA_POD_String(&key), + SPA_POD_String(&val), NULL) < 0) break; pw_properties_set(props, key, val); } diff --git a/src/modules/spa/spa-node.c b/src/modules/spa/spa-node.c index e9abe18f3..8772f3736 100644 --- a/src/modules/spa/spa-node.c +++ b/src/modules/spa/spa-node.c @@ -167,6 +167,7 @@ setup_props(struct pw_core *core, struct spa_node *spa_node, struct pw_propertie uint32_t index = 0; uint8_t buf[2048]; struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf)); + const struct spa_pod_prop *prop = NULL; if ((res = spa_node_enum_params(spa_node, SPA_PARAM_Props, &index, NULL, &props, &b)) <= 0) { pw_log_debug("spa_node_get_props failed: %d", res); @@ -174,14 +175,13 @@ setup_props(struct pw_core *core, struct spa_node *spa_node, struct pw_propertie } while ((key = pw_properties_iterate(pw_props, &state))) { - struct spa_pod_prop *prop; uint32_t type = 0; type = spa_debug_type_find_type(NULL, key); if (type == SPA_TYPE_None) continue; - if ((prop = spa_pod_find_prop(props, type))) { + if ((prop = spa_pod_find_prop(props, prop, type))) { const char *value = pw_properties_get(pw_props, key); pw_log_info("configure prop %s", key); diff --git a/src/pipewire/link.c b/src/pipewire/link.c index b52f7b9f6..2d7abdabd 100644 --- a/src/pipewire/link.c +++ b/src/pipewire/link.c @@ -727,9 +727,9 @@ static int do_allocation(struct pw_link *this, uint32_t in_state, uint32_t out_s spa_pod_parse_object(param, SPA_TYPE_OBJECT_ParamBuffers, NULL, + SPA_PARAM_BUFFERS_buffers, SPA_POD_Int(&qmax_buffers), SPA_PARAM_BUFFERS_size, SPA_POD_Int(&qminsize), - SPA_PARAM_BUFFERS_stride, SPA_POD_Int(&qstride), - SPA_PARAM_BUFFERS_buffers, SPA_POD_Int(&qmax_buffers)); + SPA_PARAM_BUFFERS_stride, SPA_POD_Int(&qstride)); max_buffers = qmax_buffers == 0 ? max_buffers : SPA_MIN(qmax_buffers, diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index 1db2c1e36..0f3b42d0c 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -648,18 +648,19 @@ static int process_notify(struct stream *impl, struct spa_pod_sequence *sequence { struct spa_pod_builder b = { 0 }; bool changed; + struct spa_pod_frame f[2]; spa_pod_builder_init(&b, impl->io_notify, impl->io_notify_size); - spa_pod_builder_push_sequence(&b, 0); + spa_pod_builder_push_sequence(&b, &f[0], 0); if ((changed = impl->props.changed)) { spa_pod_builder_control(&b, 0, SPA_CONTROL_Properties); - spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props); + spa_pod_builder_push_object(&b, &f[1], SPA_TYPE_OBJECT_Props, SPA_PARAM_Props); spa_pod_builder_prop(&b, SPA_PROP_volume, 0); spa_pod_builder_float(&b, impl->props.volume); - spa_pod_builder_pop(&b); + spa_pod_builder_pop(&b, &f[1]); impl->props.changed = false; } - spa_pod_builder_pop(&b); + spa_pod_builder_pop(&b, &f[0]); if (changed && pw_log_level_enabled(SPA_LOG_LEVEL_DEBUG)) spa_debug_pod(2, NULL, &impl->io_notify->sequence.pod);