diff --git a/spa/include/spa/defs.h b/spa/include/spa/defs.h index 67f41eddb..939b676b2 100644 --- a/spa/include/spa/defs.h +++ b/spa/include/spa/defs.h @@ -88,6 +88,16 @@ typedef enum { SPA_DIRECTION_OUTPUT, } SpaDirection; +typedef struct { + uint32_t width; + uint32_t height; +} SpaRectangle; + +typedef struct { + uint32_t num; + uint32_t denom; +} SpaFraction; + typedef void (*SpaNotify) (void *data); #define SPA_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0])) diff --git a/spa/include/spa/format.h b/spa/include/spa/format.h index 35a705bdc..d794bf780 100644 --- a/spa/include/spa/format.h +++ b/spa/include/spa/format.h @@ -98,6 +98,8 @@ typedef enum { } SpaFormatProps; + + static inline SpaResult spa_format_fixate (SpaFormat *format) { diff --git a/spa/include/spa/meson.build b/spa/include/spa/meson.build index efd448a73..6ea8bf635 100644 --- a/spa/include/spa/meson.build +++ b/spa/include/spa/meson.build @@ -14,6 +14,8 @@ spa_headers = [ 'node-event.h', 'node.h', 'plugin.h', + 'pod.h', + 'pod-builder.h', 'port.h', 'props.h', 'ringbuffer.h' diff --git a/spa/include/spa/pod-builder.h b/spa/include/spa/pod-builder.h new file mode 100644 index 000000000..83c7ae207 --- /dev/null +++ b/spa/include/spa/pod-builder.h @@ -0,0 +1,264 @@ +/* Simple Plugin API + * Copyright (C) 2017 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __SPA_POD_BUILDER_H__ +#define __SPA_POD_BUILDER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _SpaPodFrame { + struct _SpaPodFrame *parent; + off_t offset; +} SpaPODFrame; + +typedef struct { + void *data; + size_t size; + off_t offset; + SpaPODFrame *stack; +} SpaPODBuilder; + +static inline uint32_t +spa_pod_builder_top (SpaPODBuilder *builder) +{ + if (builder->stack && builder->stack->offset != -1) + return SPA_MEMBER(builder->data, builder->stack->offset, SpaPOD)->type; + return SPA_POD_TYPE_INVALID; +} + +static inline bool +spa_pod_builder_in_array (SpaPODBuilder *builder) +{ + if (builder->stack && builder->stack->offset != -1) { + SpaPOD *p = SPA_MEMBER(builder->data, builder->stack->offset, SpaPOD); + if (p->type == SPA_POD_TYPE_ARRAY && p->size > 0) + return true; + if (p->type == SPA_POD_TYPE_PROP && p->size > (sizeof (SpaPODPropBody) - sizeof(SpaPOD))) + return true; + } + return false; +} + +static inline off_t +spa_pod_builder_push (SpaPODBuilder *builder, + SpaPODFrame *frame, + off_t offset) +{ + frame->parent = builder->stack; + frame->offset = offset; + builder->stack = frame; + return offset; +} + +static inline void +spa_pod_builder_advance (SpaPODBuilder *builder, uint32_t size, bool pad) +{ + SpaPODFrame *f; + + if (pad) { + size += SPA_ROUND_UP_N (builder->offset, 8) - builder->offset; + } + builder->offset += size; + + for (f = builder->stack; f; f = f->parent) { + if (f->offset != -1) + SPA_MEMBER (builder->data, f->offset, SpaPOD)->size += size; + } +} + +static inline void +spa_pod_builder_pop (SpaPODBuilder *builder, + SpaPODFrame *frame) +{ + builder->stack = frame->parent; + spa_pod_builder_advance (builder, 0, true); +} + +static inline off_t +spa_pod_builder_raw (SpaPODBuilder *builder, const void *data, uint32_t size, bool pad) +{ + off_t offset = builder->offset; + + if (offset + size <= builder->size) + memcpy (builder->data + offset, data, size); + else + offset = -1; + + spa_pod_builder_advance (builder, size, pad); + + return offset; +} + +static inline off_t +spa_pod_builder_string_body (SpaPODBuilder *builder, + const char *str, + uint32_t len) +{ + off_t out = spa_pod_builder_raw (builder, str, len + 1 , true); + if (out != -1) + *SPA_MEMBER (builder->data, out + len, char) = '\0'; + return out; +} + +static inline off_t +spa_pod_builder_pod (SpaPODBuilder *builder, uint32_t size, uint32_t type) +{ + const SpaPOD p = { size, type }; + return spa_pod_builder_raw (builder, &p, sizeof (p), false); +} + +static inline off_t +spa_pod_builder_primitive (SpaPODBuilder *builder, const SpaPOD *p) +{ + const void *data; + size_t size; + bool pad; + + if (spa_pod_builder_in_array (builder)) { + data = SPA_POD_BODY_CONST (p); + size = SPA_POD_BODY_SIZE (p); + pad = false; + } else { + data = p; + size = SPA_POD_SIZE (p); + pad = true; + } + return spa_pod_builder_raw (builder, data, size, pad); +} + +static inline off_t +spa_pod_builder_bool (SpaPODBuilder *builder, bool val) +{ + const SpaPODBool p = { { sizeof (uint32_t), SPA_POD_TYPE_BOOL }, val ? 1 : 0 }; + return spa_pod_builder_primitive (builder, &p.pod); +} + +static inline off_t +spa_pod_builder_int (SpaPODBuilder *builder, int32_t val) +{ + const SpaPODInt p = { { sizeof (val), SPA_POD_TYPE_INT }, val }; + return spa_pod_builder_primitive (builder, &p.pod); +} + +static inline off_t +spa_pod_builder_long (SpaPODBuilder *builder, int64_t val) +{ + const SpaPODLong p = { { sizeof (val), SPA_POD_TYPE_LONG }, val }; + return spa_pod_builder_primitive (builder, &p.pod); +} + +static inline off_t +spa_pod_builder_float (SpaPODBuilder *builder, float val) +{ + const SpaPODFloat p = { { sizeof (val), SPA_POD_TYPE_FLOAT }, val }; + return spa_pod_builder_primitive (builder, &p.pod); +} + +static inline off_t +spa_pod_builder_double (SpaPODBuilder *builder, double val) +{ + const SpaPODDouble p = { { sizeof (val), SPA_POD_TYPE_DOUBLE }, val }; + return spa_pod_builder_primitive (builder, &p.pod); +} + +static inline off_t +spa_pod_builder_string (SpaPODBuilder *builder, const char *str, uint32_t len) +{ + const SpaPODString p = { { len + 1, SPA_POD_TYPE_STRING } }; + off_t out = spa_pod_builder_raw (builder, &p, sizeof (p) , false); + if (spa_pod_builder_string_body (builder, str, len) == -1) + out = -1; + return out; +} + +static inline off_t +spa_pod_builder_rectangle (SpaPODBuilder *builder, SpaRectangle *val) +{ + const SpaPODRectangle p = { { sizeof (val), SPA_POD_TYPE_RECTANGLE }, *val }; + return spa_pod_builder_primitive (builder, &p.pod); +} + +static inline off_t +spa_pod_builder_fraction (SpaPODBuilder *builder, SpaFraction *val) +{ + const SpaPODFraction p = { { sizeof (val), SPA_POD_TYPE_FRACTION }, *val }; + return spa_pod_builder_primitive (builder, &p.pod); +} + +static inline off_t +spa_pod_builder_push_array (SpaPODBuilder *builder, + SpaPODFrame *frame) +{ + const SpaPODArray p = { { sizeof (SpaPODArrayBody) - sizeof (SpaPOD), SPA_POD_TYPE_ARRAY }, { { 0, 0 } } }; + return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p) - sizeof(SpaPOD), false)); +} + +static inline off_t +spa_pod_builder_array (SpaPODBuilder *builder, + uint32_t child_size, + uint32_t child_type, + uint32_t n_elems, + const void* elems) +{ + const SpaPODArray p = { + { (uint32_t)(sizeof (SpaPODArrayBody) + n_elems * child_size), SPA_POD_TYPE_ARRAY }, + { { child_size, child_type } } + }; + off_t out = spa_pod_builder_raw (builder, &p, sizeof(p), true); + if (spa_pod_builder_raw (builder, elems, child_size * n_elems, true) == -1) + out = -1; + return out; +} + +static inline off_t +spa_pod_builder_push_struct (SpaPODBuilder *builder, + SpaPODFrame *frame) +{ + const SpaPODStruct p = { { 0, SPA_POD_TYPE_STRUCT } }; + return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p), false)); +} + +static inline off_t +spa_pod_builder_push_object (SpaPODBuilder *builder, + SpaPODFrame *frame, + uint32_t id, + uint32_t type) +{ + const SpaPODObject p = { { sizeof (SpaPODObjectBody), SPA_POD_TYPE_OBJECT }, { id, type } }; + return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p), false)); +} + +static inline off_t +spa_pod_builder_push_prop (SpaPODBuilder *builder, + SpaPODFrame *frame, + uint32_t key, + uint32_t flags) +{ + const SpaPODProp p = { { sizeof (SpaPODPropBody) - sizeof(SpaPOD), SPA_POD_TYPE_PROP}, + { key, flags | SPA_POD_PROP_RANGE_NONE, { 0, 0 } } }; + return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p) - sizeof(SpaPOD), false)); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __SPA_POD_BUILDER_H__ */ diff --git a/spa/include/spa/pod.h b/spa/include/spa/pod.h new file mode 100644 index 000000000..0b0254bee --- /dev/null +++ b/spa/include/spa/pod.h @@ -0,0 +1,194 @@ +/* Simple Plugin API + * Copyright (C) 2017 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __SPA_POD_H__ +#define __SPA_POD_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPA_POD_URI "http://spaplug.in/ns/pod" +#define SPA_POD_PREFIX SPA_POD_URI "#" + +#include + +/** + * SpaPODType: + */ +typedef enum { + SPA_POD_TYPE_INVALID = 0, + SPA_POD_TYPE_BOOL, + SPA_POD_TYPE_INT, + SPA_POD_TYPE_LONG, + SPA_POD_TYPE_FLOAT, + SPA_POD_TYPE_DOUBLE, + SPA_POD_TYPE_STRING, + SPA_POD_TYPE_RECTANGLE, + SPA_POD_TYPE_FRACTION, + SPA_POD_TYPE_BITMASK, + SPA_POD_TYPE_ARRAY, + SPA_POD_TYPE_STRUCT, + SPA_POD_TYPE_OBJECT, + SPA_POD_TYPE_PROP +} SpaPODType; + +typedef struct { + uint32_t size; + uint32_t type; +} SpaPOD; + +#define SPA_POD_BODY_SIZE(pod) ((pod)->size) +#define SPA_POD_SIZE(pod) (sizeof(SpaPOD) + SPA_POD_BODY_SIZE(pod)) + +#define SPA_POD_CONTENTS(type,pod) SPA_MEMBER((pod),sizeof(type),void) +#define SPA_POD_CONTENTS_CONST(type,pod) SPA_MEMBER((pod),sizeof(type),const void) +#define SPA_POD_BODY(pod) SPA_MEMBER((pod),sizeof(SpaPOD),void) +#define SPA_POD_BODY_CONST(pod) SPA_MEMBER((pod),sizeof(SpaPOD),const void) + + +typedef struct { + SpaPOD pod; + int32_t value; +} SpaPODInt; + +typedef SpaPODInt SpaPODBool; + +typedef struct { + SpaPOD pod; + int64_t value; +} SpaPODLong; + +typedef struct { + SpaPOD pod; + float value; +} SpaPODFloat; + +typedef struct { + SpaPOD pod; + double value; +} SpaPODDouble; + +typedef struct { + SpaPOD pod; + /* value here */ +} SpaPODString; + +typedef struct { + SpaPOD pod; + SpaRectangle value; +} SpaPODRectangle; + +typedef struct { + SpaPOD pod; + SpaFraction value; +} SpaPODFraction; + +typedef struct { + SpaPOD pod; + /* array of uint32_t follows with the bitmap */ +} SpaPODBitmap; + +typedef struct { + SpaPOD child; + /* array with elements of child.size follows */ +} SpaPODArrayBody; + +typedef struct { + SpaPOD pod; + SpaPODArrayBody body; +} SpaPODArray; + +typedef struct { + SpaPOD pod; + /* one or more SpaPOD follow */ +} SpaPODStruct; + +typedef struct { + uint32_t key; +#define SPA_POD_PROP_FLAG_UNSET (1 << 4) +#define SPA_POD_PROP_FLAG_OPTIONAL (1 << 5) +#define SPA_POD_PROP_FLAG_READABLE (1 << 6) +#define SPA_POD_PROP_FLAG_WRITABLE (1 << 7) +#define SPA_POD_PROP_FLAG_READWRITE (SPA_POD_PROP_FLAG_READABLE | SPA_POD_PROP_FLAG_WRITABLE) +#define SPA_POD_PROP_FLAG_DEPRECATED (1 << 8) +#define SPA_POD_PROP_RANGE_NONE 0 +#define SPA_POD_PROP_RANGE_MIN_MAX 1 +#define SPA_POD_PROP_RANGE_STEP 2 +#define SPA_POD_PROP_RANGE_ENUM 3 +#define SPA_POD_PROP_RANGE_FLAGS 4 + uint32_t flags; + SpaPOD value; + /* array with elements of value.size follows, + * first element is value/default, rest are alternatives */ +} SpaPODPropBody; + +typedef struct { + SpaPOD pod; + SpaPODPropBody body; +} SpaPODProp; + +typedef struct { + uint32_t id; + uint32_t type; + /* contents follow, series of SpaPODProp */ +} SpaPODObjectBody; + +typedef struct { + SpaPOD pod; + SpaPODObjectBody body; +} SpaPODObject; + +#define SPA_POD_ARRAY_BODY_FOREACH(body, size, iter) \ + for ((iter) = SPA_MEMBER (body, sizeof(SpaPODArrayBody), __typeof__(*iter)); \ + (iter) < SPA_MEMBER (body, (size), __typeof__(*iter)); \ + (iter) = SPA_MEMBER ((iter), (body)->child.size, __typeof__(*iter))) + +#define SPA_POD_STRUCT_BODY_FOREACH(body, size, iter) \ + for ((iter) = SPA_MEMBER ((body), 0, SpaPOD); \ + (iter) < SPA_MEMBER ((body), (size), SpaPOD); \ + (iter) = SPA_MEMBER ((iter), SPA_ROUND_UP_N (SPA_POD_SIZE (iter), 8), SpaPOD)) + +#define SPA_POD_OBJECT_BODY_FOREACH(body, size, iter) \ + for ((iter) = SPA_MEMBER ((body), sizeof (SpaPODObjectBody), SpaPODProp); \ + (iter) < SPA_MEMBER ((body), (size), SpaPODProp); \ + (iter) = SPA_MEMBER ((iter), SPA_ROUND_UP_N (SPA_POD_SIZE (&(iter)->pod), 8), SpaPODProp)) + +#define SPA_POD_PROP_ALTERNATIVE_FOREACH(body, _size, iter) \ + for ((iter) = SPA_MEMBER ((body), (body)->value.size + sizeof (SpaPODPropBody), __typeof__(*iter)); \ + (iter) < SPA_MEMBER ((body), (_size), __typeof__(*iter)); \ + (iter) = SPA_MEMBER ((iter), (body)->value.size, __typeof__(*iter))) + +static inline SpaPODProp * +spa_pod_object_body_find_prop (SpaPODObjectBody *body, uint32_t size, uint32_t key) +{ + SpaPODProp *res; + SPA_POD_OBJECT_BODY_FOREACH (body, size, res) { + if (res->body.key == key) + return res; + } + return NULL; +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __SPA_POD_H__ */ diff --git a/spa/include/spa/props.h b/spa/include/spa/props.h index 57e2aa983..357a5bf2a 100644 --- a/spa/include/spa/props.h +++ b/spa/include/spa/props.h @@ -58,16 +58,6 @@ typedef enum { SPA_PROP_TYPE_POINTER } SpaPropType; -typedef struct { - uint32_t width; - uint32_t height; -} SpaRectangle; - -typedef struct { - uint32_t num; - uint32_t denom; -} SpaFraction; - /** * SpaPropFlags: * @SPA_PROP_FLAG_NONE: no flags diff --git a/spa/tests/meson.build b/spa/tests/meson.build index 42b774596..1d1c2cb3e 100644 --- a/spa/tests/meson.build +++ b/spa/tests/meson.build @@ -11,6 +11,11 @@ # install : false) executable('test-props', 'test-props.c', include_directories : [spa_inc, spa_libinc ], - dependencies : [dl_lib, sdl_dep, pthread_lib], + dependencies : [], + link_with : spalib, + install : false) +executable('test-props2', 'test-props2.c', + include_directories : [spa_inc, spa_libinc ], + dependencies : [], link_with : spalib, install : false) diff --git a/spa/tests/test-props2.c b/spa/tests/test-props2.c new file mode 100644 index 000000000..625e46a24 --- /dev/null +++ b/spa/tests/test-props2.c @@ -0,0 +1,179 @@ +/* Spa + * Copyright (C) 2017 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include + + +#include +#include + +#include +#include +#include +#include +#include + +static void +print_value (uint32_t size, uint32_t type, void *body, int prefix, uint32_t flags) +{ + switch (type) { + case SPA_POD_TYPE_BOOL: + printf ("%-*sBool %d\n", prefix, "", *(int32_t *) body); + break; + case SPA_POD_TYPE_INT: + printf ("%-*sInt %d\n", prefix, "", *(int32_t *) body); + break; + case SPA_POD_TYPE_LONG: + printf ("%-*sLong %"PRIi64"\n", prefix, "", *(int64_t *) body); + break; + case SPA_POD_TYPE_FLOAT: + printf ("%-*sFloat %f\n", prefix, "", *(float *) body); + break; + case SPA_POD_TYPE_DOUBLE: + printf ("%-*sDouble %g\n", prefix, "", *(double *) body); + break; + case SPA_POD_TYPE_STRING: + printf ("%-*sString %s\n", prefix, "", (char *) body); + break; + case SPA_POD_TYPE_RECTANGLE: + { + SpaRectangle *r = body; + printf ("%-*sRectangle %dx%d\n", prefix, "", r->width, r->height); + break; + } + case SPA_POD_TYPE_FRACTION: + { + SpaFraction *f = body; + printf ("%-*sFraction %d/%d\n", prefix, "", f->num, f->denom); + break; + } + case SPA_POD_TYPE_BITMASK: + printf ("%-*sBitmask\n", prefix, ""); + break; + case SPA_POD_TYPE_ARRAY: + { + SpaPODArrayBody *b = body; + void *p; + printf ("%-*sArray: child.size %d, child.type %d\n", prefix, "", b->child.size, b->child.type); + + SPA_POD_ARRAY_BODY_FOREACH (b, size, p) + print_value (b->child.size, b->child.type, p, prefix + 2, flags); + break; + } + case SPA_POD_TYPE_STRUCT: + { + SpaPOD *b = body, *p; + printf ("%-*sStruct: size %d\n", prefix, "", size); + SPA_POD_STRUCT_BODY_FOREACH (b, size, p) + print_value (p->size, p->type, SPA_POD_BODY (p), prefix + 2, flags); + break; + } + case SPA_POD_TYPE_OBJECT: + { + SpaPODObjectBody *b = body; + SpaPODProp *p; + void *alt; + int i; + + printf ("%-*sObject: size %d\n", prefix, "", size); + SPA_POD_OBJECT_BODY_FOREACH (b, size, p) { + printf ("%-*sProp: key %d, flags %d\n", prefix + 2, "", p->body.key, p->body.flags); + if (p->body.flags & SPA_POD_PROP_FLAG_UNSET) + printf ("%-*sUnset (Default):\n", prefix + 4, ""); + else + printf ("%-*sValue:\n", prefix + 4, ""); + print_value (p->body.value.size, p->body.value.type, SPA_POD_BODY (&p->body.value), prefix + 6, p->body.flags); + + i = 0; + SPA_POD_PROP_ALTERNATIVE_FOREACH (&p->body, p->pod.size, alt) { + if (i == 0) + printf ("%-*sAlternatives:\n", prefix + 4, ""); + print_value (p->body.value.size, p->body.value.type, alt, prefix + 6, p->body.flags); + i++; + } + } + break; + } + } +} + +int +main (int argc, char *argv[]) +{ + SpaPODBuilder b = { NULL, }; + SpaPODFrame frame[4]; + uint8_t buffer[1024]; + SpaPOD *obj; + + b.data = buffer; + b.size = 1024; + + obj = SPA_MEMBER (buffer, spa_pod_builder_push_object (&b, &frame[0], 0, 0), SpaPOD); + + uint32_t formats[] = { 1, 2 }; + spa_pod_builder_push_prop (&b, &frame[1], + 1, SPA_POD_PROP_RANGE_ENUM | SPA_POD_PROP_FLAG_READWRITE); + spa_pod_builder_int (&b, 1); + spa_pod_builder_int (&b, formats[0]); + spa_pod_builder_int (&b, formats[1]); + spa_pod_builder_pop (&b, &frame[1]); + + spa_pod_builder_push_prop (&b, &frame[1], + 2, SPA_POD_PROP_RANGE_NONE | SPA_POD_PROP_FLAG_READWRITE); + spa_pod_builder_int (&b, 42); + spa_pod_builder_pop (&b, &frame[1]); + + SpaRectangle def = { 320, 240 }, sizes[] = { { 0, 0 }, { 1024, 1024} }; + spa_pod_builder_push_prop (&b, &frame[1], + 3, SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE); + spa_pod_builder_rectangle (&b, &def); + spa_pod_builder_raw (&b, sizes, sizeof (sizes), false); + spa_pod_builder_pop (&b, &frame[1]); + + spa_pod_builder_push_prop (&b, &frame[1], 4, SPA_POD_PROP_RANGE_NONE | SPA_POD_PROP_FLAG_READABLE); + spa_pod_builder_push_struct (&b, &frame[2]); + spa_pod_builder_int (&b, 4); + spa_pod_builder_long (&b, 6000); + spa_pod_builder_float (&b, 4.0); + spa_pod_builder_double (&b, 3.14); + spa_pod_builder_string (&b, "test123", strlen ("test123")); + spa_pod_builder_rectangle (&b, &def); + SpaFraction f = { 25, 1 }; + spa_pod_builder_fraction (&b, &f); + spa_pod_builder_push_array (&b, &frame[3]); + spa_pod_builder_int (&b, 4); + spa_pod_builder_int (&b, 5); + spa_pod_builder_int (&b, 6); + spa_pod_builder_pop (&b, &frame[3]); + spa_pod_builder_pop (&b, &frame[2]); + spa_pod_builder_pop (&b, &frame[1]); + spa_pod_builder_pop (&b, &frame[0]); + + print_value (obj->size, obj->type, SPA_POD_BODY (obj), 0, 0); + + SpaPODProp *p = spa_pod_object_body_find_prop (SPA_POD_BODY (obj), obj->size, 4); + printf ("%d %d\n", p->body.key, p->body.flags); + print_value (p->body.value.size, p->body.value.type, SPA_POD_BODY (&p->body.value), 0, 0); + + return 0; +}