diff options
author | Wim Taymans <wtaymans@redhat.com> | 2017-11-09 17:07:04 +0100 |
---|---|---|
committer | Wim Taymans <wtaymans@redhat.com> | 2017-11-09 17:16:54 +0100 |
commit | 58451d626ca9824c753009b77c61a31c37c97aea (patch) | |
tree | dcd09bb49d22aae20490ff10ea65829456854769 | |
parent | cc47fb7e3addeef7c0bc9dee5ed8a37c5dc0d1b0 (diff) |
Implement param filtering
Make a new pod filter function and use it in the plugins to filter
in enum_params.
Small tweaks to the pod_builder
35 files changed, 1114 insertions, 881 deletions
diff --git a/spa/include/spa/pod-builder.h b/spa/include/spa/pod-builder.h index 320c7ce8..feb2ed2f 100644 --- a/spa/include/spa/pod-builder.h +++ b/spa/include/spa/pod-builder.h @@ -36,9 +36,10 @@ struct spa_pod_builder { void *data; uint32_t size; uint32_t offset; - uint32_t (*write) (struct spa_pod_builder *builder, uint32_t ref, const void *data, - uint32_t size); + + uint32_t (*write) (struct spa_pod_builder *builder, const void *data, uint32_t size); void * (*deref) (struct spa_pod_builder *builder, uint32_t ref); + void (*reset) (struct spa_pod_builder *builder, uint32_t offset); bool in_array; bool first; int depth; @@ -47,15 +48,21 @@ struct spa_pod_builder { #define SPA_POD_BUILDER_INIT(buffer,size) { buffer, size, } -static inline void spa_pod_builder_init(struct spa_pod_builder *builder, void *data, uint32_t size) +static inline void +spa_pod_builder_reset(struct spa_pod_builder *builder, uint32_t offset) { - builder->data = data; - builder->size = size; - builder->offset = 0; + if (builder->reset) + builder->reset(builder, offset); + builder->offset = offset; builder->depth = 0; builder->in_array = builder->first = false; } +static inline void spa_pod_builder_init(struct spa_pod_builder *builder, void *data, uint32_t size) +{ + *builder = (struct spa_pod_builder) SPA_POD_BUILDER_INIT(data, size); +} + static inline void * spa_pod_builder_deref(struct spa_pod_builder *builder, uint32_t ref) { @@ -85,7 +92,7 @@ spa_pod_builder_raw(struct spa_pod_builder *builder, const void *data, uint32_t int i; if (builder->write) { - ref = builder->write(builder, -1, data, size); + ref = builder->write(builder, data, size); } else { ref = builder->offset; if (ref + size > builder->size) @@ -123,10 +130,8 @@ static inline uint32_t spa_pod_builder_pop(struct spa_pod_builder *builder) struct spa_pod_frame *frame = &builder->frame[--builder->depth], *top; if (frame->ref != -1) { - if (builder->write) - builder->write(builder, frame->ref, &frame->pod, sizeof(struct spa_pod)); - else - memcpy(builder->data + frame->ref, &frame->pod, sizeof(struct spa_pod)); + struct spa_pod *pod = spa_pod_builder_deref(builder, frame->ref); + *pod = frame->pod; } top = builder->depth > 0 ? &builder->frame[builder->depth-1] : NULL; builder->in_array = (top && (top->pod.type == SPA_POD_TYPE_ARRAY || diff --git a/spa/include/spa/pod-utils.h b/spa/include/spa/pod-utils.h index 091337da..86a36567 100644 --- a/spa/include/spa/pod-utils.h +++ b/spa/include/spa/pod-utils.h @@ -46,7 +46,8 @@ static inline bool spa_pod_is_object_type(struct spa_pod *pod, uint32_t type) return (pod->type == SPA_POD_TYPE_OBJECT && ((struct spa_pod_object *) pod)->body.type == type); } -static inline bool spa_pod_has_next(const void *pod, uint32_t size, const struct spa_pod *iter) + +static inline bool spa_pod_is_iter(const void *pod, uint32_t size, const struct spa_pod *iter) { return iter < SPA_MEMBER(pod, size, struct spa_pod); } @@ -63,18 +64,25 @@ static inline struct spa_pod *spa_pod_next(const struct spa_pod *iter) #define SPA_POD_FOREACH(pod, size, iter) \ for ((iter) = (pod); \ - spa_pod_has_next(pod, size, iter); \ + spa_pod_is_iter(pod, size, iter); \ (iter) = spa_pod_next(iter)) +#define SPA_POD_FOREACH_SAFE(pod, size, iter, tmp) \ + for ((iter) = (pod), (tmp) = spa_pod_next(iter); \ + spa_pod_is_iter(pod, size, iter); \ + (iter) = (tmp), \ + (tmp) = spa_pod_next(iter)) + + #define SPA_POD_CONTENTS_FOREACH(pod, offset, iter) \ SPA_POD_FOREACH(SPA_MEMBER((pod), (offset), struct spa_pod),SPA_POD_SIZE (pod)-(offset),iter) #define SPA_POD_OBJECT_BODY_FOREACH(body, size, iter) \ for ((iter) = SPA_MEMBER((body), sizeof(struct spa_pod_object_body), struct spa_pod); \ - spa_pod_has_next(body, size, iter); \ + spa_pod_is_iter(body, size, iter); \ (iter) = spa_pod_next(iter)) -#define SPA_POD_OBJECT_FOREACH(obj, iter) \ +#define SPA_POD_OBJECT_FOREACH(obj, iter) \ SPA_POD_OBJECT_BODY_FOREACH(&obj->body, SPA_POD_BODY_SIZE(obj), iter) #define SPA_POD_PROP_ALTERNATIVE_FOREACH(body, _size, iter) \ diff --git a/spa/lib/debug.c b/spa/lib/debug.c index 1d18032f..627b6320 100644 --- a/spa/lib/debug.c +++ b/spa/lib/debug.c @@ -259,11 +259,45 @@ print_pod_value(uint32_t size, uint32_t type, void *body, int prefix) prefix + 4); i = 0; - SPA_POD_PROP_ALTERNATIVE_FOREACH(b, size, alt) { - if (i == 0) - printf("%-*sAlternatives:\n", prefix + 2, ""); - print_pod_value(b->value.size, b->value.type, alt, prefix + 4); - i++; + switch (b->flags & SPA_POD_PROP_RANGE_MASK) { + case SPA_POD_PROP_RANGE_NONE: + break; + case SPA_POD_PROP_RANGE_MIN_MAX: + SPA_POD_PROP_ALTERNATIVE_FOREACH(b, size, alt) { + if (i == 0) + printf("%-*sMin: ", prefix + 2, ""); + else if (i == 1) + printf("%-*sMax: ", prefix + 2, ""); + else + break; + print_pod_value(b->value.size, b->value.type, alt, 0); + i++; + } + break; + case SPA_POD_PROP_RANGE_STEP: + SPA_POD_PROP_ALTERNATIVE_FOREACH(b, size, alt) { + if (i == 0) + printf("%-*sMin: ", prefix + 2, ""); + else if (i == 1) + printf("%-*sMax: ", prefix + 2, ""); + else if (i == 2) + printf("%-*sStep: ", prefix + 2, ""); + else + break; + print_pod_value(b->value.size, b->value.type, alt, 0); + i++; + } + break; + case SPA_POD_PROP_RANGE_ENUM: + SPA_POD_PROP_ALTERNATIVE_FOREACH(b, size, alt) { + if (i == 0) + printf("%-*sEnum:\n", prefix + 2, ""); + print_pod_value(b->value.size, b->value.type, alt, prefix + 4); + i++; + } + break; + case SPA_POD_PROP_RANGE_FLAGS: + break; } break; } diff --git a/spa/lib/format.c b/spa/lib/format.c deleted file mode 100644 index cf5ffe59..00000000 --- a/spa/lib/format.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Simple Plugin API - * Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com> - * - * 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 <stdint.h> -#include <stddef.h> -#include <stdio.h> -#include <string.h> - -#include <lib/props.h> - -int -spa_pod_object_filter(const struct spa_pod_object *obj, - struct spa_pod_object *filter, - struct spa_pod_builder *result) -{ - int res; - - if (obj == NULL || result == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - if (filter == NULL) { - spa_pod_builder_raw_padded(result, obj, SPA_POD_SIZE(obj)); - return SPA_RESULT_OK; - } - - spa_pod_builder_push_object(result, obj->body.id, obj->body.type); - res = spa_props_filter(result, - SPA_POD_CONTENTS(struct spa_pod_object, obj), - SPA_POD_CONTENTS_SIZE(struct spa_pod_object, obj), - SPA_POD_CONTENTS(struct spa_pod_object, filter), - SPA_POD_CONTENTS_SIZE(struct spa_pod_object, filter)); - spa_pod_builder_pop(result); - - return res; -} - -int -spa_pod_object_compare(const struct spa_pod_object *obj1, - const struct spa_pod_object *obj2) -{ - if (obj1 == NULL || obj2 == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - return spa_props_compare(SPA_POD_CONTENTS(struct spa_pod_object, obj1), - SPA_POD_CONTENTS_SIZE(struct spa_pod_object, obj1), - SPA_POD_CONTENTS(struct spa_pod_object, obj2), - SPA_POD_CONTENTS_SIZE(struct spa_pod_object, obj2)); -} diff --git a/spa/lib/meson.build b/spa/lib/meson.build index 9acd00f0..8f85ae48 100644 --- a/spa/lib/meson.build +++ b/spa/lib/meson.build @@ -1,14 +1,12 @@ spalib_headers = [ 'debug.h', - 'format.h', - 'props.h', + 'pod.h', ] install_headers(spalib_headers, subdir : 'spa/lib') spalib_sources = ['debug.c', - 'props.c', - 'format.c'] + 'pod.c' ] spalib = shared_library('spa-lib', spalib_sources, diff --git a/spa/lib/pod.c b/spa/lib/pod.c new file mode 100644 index 00000000..671e83fc --- /dev/null +++ b/spa/lib/pod.c @@ -0,0 +1,507 @@ +/* Simple Plugin API + * Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com> + * + * 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 <stdint.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> + +#include <spa/props.h> +#include <spa/pod-builder.h> + +static int compare_value(enum spa_pod_type type, const void *r1, const void *r2) +{ + switch (type) { + case SPA_POD_TYPE_INVALID: + return 0; + case SPA_POD_TYPE_BOOL: + case SPA_POD_TYPE_ID: + return *(int32_t *) r1 == *(uint32_t *) r2 ? 0 : 1; + case SPA_POD_TYPE_INT: + return *(int32_t *) r1 - *(int32_t *) r2; + case SPA_POD_TYPE_LONG: + return *(int64_t *) r1 - *(int64_t *) r2; + case SPA_POD_TYPE_FLOAT: + return *(float *) r1 - *(float *) r2; + case SPA_POD_TYPE_DOUBLE: + return *(double *) r1 - *(double *) r2; + case SPA_POD_TYPE_STRING: + return strcmp(r1, r2); + case SPA_POD_TYPE_RECTANGLE: + { + const struct spa_rectangle *rec1 = (struct spa_rectangle *) r1, + *rec2 = (struct spa_rectangle *) r2; + if (rec1->width == rec2->width && rec1->height == rec2->height) + return 0; + else if (rec1->width < rec2->width || rec1->height < rec2->height) + return -1; + else + return 1; + } + case SPA_POD_TYPE_FRACTION: + { + const struct spa_fraction *f1 = (struct spa_fraction *) r1, + *f2 = (struct spa_fraction *) r2; + int64_t n1, n2; + n1 = ((int64_t) f1->num) * f2->denom; + n2 = ((int64_t) f2->num) * f1->denom; + if (n1 < n2) + return -1; + else if (n1 > n2) + return 1; + else + return 0; + } + default: + break; + } + return 0; +} + +static void fix_default(struct spa_pod_prop *prop) +{ + void *val = SPA_MEMBER(prop, sizeof(struct spa_pod_prop), void), + *alt = SPA_MEMBER(val, prop->body.value.size, void); + int i, nalt = SPA_POD_PROP_N_VALUES(prop) - 1; + + switch (prop->body.flags & SPA_POD_PROP_RANGE_MASK) { + case SPA_POD_PROP_RANGE_NONE: + break; + case SPA_POD_PROP_RANGE_MIN_MAX: + case SPA_POD_PROP_RANGE_STEP: + if (compare_value(prop->body.value.type, val, alt) < 0) + memcpy(val, alt, prop->body.value.size); + alt = SPA_MEMBER(alt, prop->body.value.size, void); + if (compare_value(prop->body.value.type, val, alt) > 0) + memcpy(val, alt, prop->body.value.size); + break; + case SPA_POD_PROP_RANGE_ENUM: + { + void *best = NULL; + + for (i = 0; i < nalt; i++) { + if (compare_value(prop->body.value.type, val, alt) == 0) { + best = alt; + break; + } + if (best == NULL) + best = alt; + alt = SPA_MEMBER(alt, prop->body.value.size, void); + } + if (best) + memcpy(val, best, prop->body.value.size); + + if (nalt <= 1) { + prop->body.flags &= ~SPA_POD_PROP_FLAG_UNSET; + prop->body.flags &= ~SPA_POD_PROP_RANGE_MASK; + prop->body.flags |= SPA_POD_PROP_RANGE_NONE; + } + break; + } + case SPA_POD_PROP_RANGE_FLAGS: + break; + } +} + +static inline struct spa_pod_prop *find_prop(const struct spa_pod *pod, uint32_t size, uint32_t key) +{ + const struct spa_pod *res; + SPA_POD_FOREACH(pod, size, res) { + if (res->type == SPA_POD_TYPE_PROP + && ((struct spa_pod_prop *) res)->body.key == key) + return (struct spa_pod_prop *) res; + } + return NULL; +} + +static int +filter_prop(struct spa_pod_builder *b, + const struct spa_pod_prop *p1, + const struct spa_pod_prop *p2) +{ + struct spa_pod_prop *np; + int nalt1, nalt2; + void *alt1, *alt2, *a1, *a2; + uint32_t rt1, rt2; + int j, k; + + /* incompatible property types */ + if (p1->body.value.type != p2->body.value.type) + return SPA_RESULT_INCOMPATIBLE_PROPS; + + rt1 = p1->body.flags & SPA_POD_PROP_RANGE_MASK; + rt2 = p2->body.flags & SPA_POD_PROP_RANGE_MASK; + + alt1 = SPA_MEMBER(p1, sizeof(struct spa_pod_prop), void); + nalt1 = SPA_POD_PROP_N_VALUES(p1); + alt2 = SPA_MEMBER(p2, sizeof(struct spa_pod_prop), void); + nalt2 = SPA_POD_PROP_N_VALUES(p2); + + if (p1->body.flags & SPA_POD_PROP_FLAG_UNSET) { + alt1 = SPA_MEMBER(alt1, p1->body.value.size, void); + nalt1--; + } else { + nalt1 = 1; + rt1 = SPA_POD_PROP_RANGE_NONE; + } + + if (p2->body.flags & SPA_POD_PROP_FLAG_UNSET) { + alt2 = SPA_MEMBER(alt2, p2->body.value.size, void); + nalt2--; + } else { + nalt2 = 1; + rt2 = SPA_POD_PROP_RANGE_NONE; + } + + /* start with copying the property */ + np = spa_pod_builder_deref(b, spa_pod_builder_push_prop(b, p1->body.key, 0)); + + /* default value */ + spa_pod_builder_raw(b, &p1->body.value, sizeof(p1->body.value) + p1->body.value.size); + + if ((rt1 == SPA_POD_PROP_RANGE_NONE && rt2 == SPA_POD_PROP_RANGE_NONE) || + (rt1 == SPA_POD_PROP_RANGE_NONE && rt2 == SPA_POD_PROP_RANGE_ENUM) || + (rt1 == SPA_POD_PROP_RANGE_ENUM && rt2 == SPA_POD_PROP_RANGE_NONE) || + (rt1 == SPA_POD_PROP_RANGE_ENUM && rt2 == SPA_POD_PROP_RANGE_ENUM)) { + int n_copied = 0; + /* copy all equal values but don't copy the default value again */ + for (j = 0, a1 = alt1; j < nalt1; j++, a1 += p1->body.value.size) { + for (k = 0, a2 = alt2; k < nalt2; k++, a2 += p2->body.value.size) { + if (compare_value(p1->body.value.type, a1, a2) == 0) { + if (rt1 == SPA_POD_PROP_RANGE_ENUM || j > 0) + spa_pod_builder_raw(b, a1, p1->body.value.size); + n_copied++; + } + } + } + if (n_copied == 0) + return SPA_RESULT_INCOMPATIBLE_PROPS; + np->body.flags |= SPA_POD_PROP_RANGE_ENUM | SPA_POD_PROP_FLAG_UNSET; + } + + if ((rt1 == SPA_POD_PROP_RANGE_NONE && rt2 == SPA_POD_PROP_RANGE_MIN_MAX) || + (rt1 == SPA_POD_PROP_RANGE_ENUM && rt2 == SPA_POD_PROP_RANGE_MIN_MAX)) { + int n_copied = 0; + /* copy all values inside the range */ + for (j = 0, a1 = alt1, a2 = alt2; j < nalt1; j++, a1 += p1->body.value.size) { + if (compare_value(p1->body.value.type, a1, a2) < 0) + continue; + if (compare_value(p1->body.value.type, a1, a2 + p2->body.value.size) > 0) + continue; + spa_pod_builder_raw(b, a1, p1->body.value.size); + n_copied++; + } + if (n_copied == 0) + return SPA_RESULT_INCOMPATIBLE_PROPS; + np->body.flags |= SPA_POD_PROP_RANGE_ENUM | SPA_POD_PROP_FLAG_UNSET; + } + + if ((rt1 == SPA_POD_PROP_RANGE_NONE && rt2 == SPA_POD_PROP_RANGE_STEP) || + (rt1 == SPA_POD_PROP_RANGE_ENUM && rt2 == SPA_POD_PROP_RANGE_STEP)) { + return SPA_RESULT_NOT_IMPLEMENTED; + } + + if ((rt1 == SPA_POD_PROP_RANGE_MIN_MAX && rt2 == SPA_POD_PROP_RANGE_NONE) || + (rt1 == SPA_POD_PROP_RANGE_MIN_MAX && rt2 == SPA_POD_PROP_RANGE_ENUM)) { + int n_copied = 0; + /* copy all values inside the range */ + for (k = 0, a1 = alt1, a2 = alt2; k < nalt2; k++, a2 += p2->body.value.size) { + if (compare_value(p1->body.value.type, a2, a1) < 0) + continue; + if (compare_value(p1->body.value.type, a2, a1 + p1->body.value.size) > 0) + continue; + spa_pod_builder_raw(b, a2, p2->body.value.size); + n_copied++; + } + if (n_copied == 0) + return SPA_RESULT_INCOMPATIBLE_PROPS; + np->body.flags |= SPA_POD_PROP_RANGE_ENUM | SPA_POD_PROP_FLAG_UNSET; + } + + if (rt1 == SPA_POD_PROP_RANGE_MIN_MAX && rt2 == SPA_POD_PROP_RANGE_MIN_MAX) { + if (compare_value(p1->body.value.type, alt1, alt2) < 0) + spa_pod_builder_raw(b, alt2, p2->body.value.size); + else + spa_pod_builder_raw(b, alt1, p1->body.value.size); + + alt1 += p1->body.value.size; + alt2 += p2->body.value.size; + + if (compare_value(p1->body.value.type, alt1, alt2) < 0) + spa_pod_builder_raw(b, alt1, p1->body.value.size); + else + spa_pod_builder_raw(b, alt2, p2->body.value.size); + + np->body.flags |= SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET; + } + + if (rt1 == SPA_POD_PROP_RANGE_NONE && rt2 == SPA_POD_PROP_RANGE_FLAGS) + return SPA_RESULT_NOT_IMPLEMENTED; + + if (rt1 == SPA_POD_PROP_RANGE_MIN_MAX && rt2 == SPA_POD_PROP_RANGE_STEP) + return SPA_RESULT_NOT_IMPLEMENTED; + + if (rt1 == SPA_POD_PROP_RANGE_MIN_MAX && rt2 == SPA_POD_PROP_RANGE_FLAGS) + return SPA_RESULT_NOT_IMPLEMENTED; + + if (rt1 == SPA_POD_PROP_RANGE_ENUM && rt2 == SPA_POD_PROP_RANGE_FLAGS) + return SPA_RESULT_NOT_IMPLEMENTED; + + if (rt1 == SPA_POD_PROP_RANGE_STEP && rt2 == SPA_POD_PROP_RANGE_NONE) + return SPA_RESULT_NOT_IMPLEMENTED; + if (rt1 == SPA_POD_PROP_RANGE_STEP && rt2 == SPA_POD_PROP_RANGE_MIN_MAX) + return SPA_RESULT_NOT_IMPLEMENTED; + + if (rt1 == SPA_POD_PROP_RANGE_STEP && rt2 == SPA_POD_PROP_RANGE_STEP) + return SPA_RESULT_NOT_IMPLEMENTED; + if (rt1 == SPA_POD_PROP_RANGE_STEP && rt2 == SPA_POD_PROP_RANGE_ENUM) + return SPA_RESULT_NOT_IMPLEMENTED; + if (rt1 == SPA_POD_PROP_RANGE_STEP && rt2 == SPA_POD_PROP_RANGE_FLAGS) + return SPA_RESULT_NOT_IMPLEMENTED; + + if (rt1 == SPA_POD_PROP_RANGE_FLAGS && rt2 == SPA_POD_PROP_RANGE_NONE) + return SPA_RESULT_NOT_IMPLEMENTED; + if (rt1 == SPA_POD_PROP_RANGE_FLAGS && rt2 == SPA_POD_PROP_RANGE_MIN_MAX) + return SPA_RESULT_NOT_IMPLEMENTED; + if (rt1 == SPA_POD_PROP_RANGE_FLAGS && rt2 == SPA_POD_PROP_RANGE_STEP) + return SPA_RESULT_NOT_IMPLEMENTED; + if (rt1 == SPA_POD_PROP_RANGE_FLAGS && rt2 == SPA_POD_PROP_RANGE_ENUM) + return SPA_RESULT_NOT_IMPLEMENTED; + if (rt1 == SPA_POD_PROP_RANGE_FLAGS && rt2 == SPA_POD_PROP_RANGE_FLAGS) + return SPA_RESULT_NOT_IMPLEMENTED; + + spa_pod_builder_pop(b); + fix_default(np); + + return SPA_RESULT_OK; +} + +int pod_filter(struct spa_pod_builder *b, + const struct spa_pod *pod, + uint32_t pod_size, + const struct spa_pod *filter, + uint32_t filter_size) +{ + const struct spa_pod *pp, *pf, *tmp; + int res = SPA_RESULT_OK; + + pf = filter; + + SPA_POD_FOREACH_SAFE(pod, pod_size, pp, tmp) { + bool do_copy = false, do_filter = false, do_advance = false; + void *pc, *fc; + uint32_t pcs, fcs; + + switch (SPA_POD_TYPE(pp)) { + case SPA_POD_TYPE_STRUCT: + if (pf != NULL) { + if (SPA_POD_TYPE(pf) != SPA_POD_TYPE_STRUCT) + return SPA_RESULT_INCOMPATIBLE_PROPS; + + pc = SPA_POD_CONTENTS(struct spa_pod_struct, pp); + pcs = SPA_POD_CONTENTS_SIZE(struct spa_pod_struct, pp); + fc = SPA_POD_CONTENTS(struct spa_pod_struct, pf); + fcs = SPA_POD_CONTENTS_SIZE(struct spa_pod_struct, pf); + + spa_pod_builder_push_struct(b); + do_filter = true; + do_advance = true; + } + else + do_copy = true; + break; + case SPA_POD_TYPE_OBJECT: + if (pf != NULL) { + struct spa_pod_object *p1; + + p1 = (struct spa_pod_object *) pp; + + if (SPA_POD_TYPE(pf) != SPA_POD_TYPE_OBJECT) + return SPA_RESULT_INCOMPATIBLE_PROPS; + + pc = SPA_POD_CONTENTS(struct spa_pod_object, pp); + pcs = SPA_POD_CONTENTS_SIZE(struct spa_pod_object, pp); + fc = SPA_POD_CONTENTS(struct spa_pod_object, pf); + fcs = SPA_POD_CONTENTS_SIZE(struct spa_pod_object, pf); + + spa_pod_builder_push_object(b, p1->body.id, p1->body.type); + do_filter = true; + do_advance = true; + } + else + do_copy = true; + break; + + case SPA_POD_TYPE_PROP: + { + struct spa_pod_prop *p1, *p2; + + p1 = (struct spa_pod_prop *) pp; + p2 = find_prop(filter, filter_size, p1->body.key); + + if (p2 != NULL) + res = filter_prop(b, p1, p2); + else + do_copy = true; + break; + } + default: + if (pf != NULL) { + if (SPA_POD_SIZE(pp) != SPA_POD_SIZE(pf)) + return SPA_RESULT_INCOMPATIBLE_PROPS; + if (memcmp(pp, pf, SPA_POD_SIZE(pp)) != 0) + return SPA_RESULT_INCOMPATIBLE_PROPS; + do_advance = true; + } + do_copy = true; + break; + } + if (do_copy) + spa_pod_builder_raw_padded(b, pp, SPA_POD_SIZE(pp)); + else if (do_filter) { + res = pod_filter(b, pc, pcs, fc, fcs); + spa_pod_builder_pop(b); + } + if (do_advance) { + pf = spa_pod_next(pf); + if (!spa_pod_is_iter(filter, filter_size, pf)) + pf = NULL; + } + + if (res < 0) + break; + } + return res; +} + +int +spa_pod_filter(struct spa_pod_builder *b, + const struct spa_pod *pod, + const struct spa_pod *filter) +{ + spa_return_val_if_fail(pod != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(b != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + if (filter == NULL) { + spa_pod_builder_raw_padded(b, pod, SPA_POD_SIZE(pod)); + return SPA_RESULT_OK; + } + return pod_filter(b, pod, SPA_POD_SIZE(pod), filter, SPA_POD_SIZE(filter)); + +} + +int pod_compare(const struct spa_pod *pod1, + uint32_t pod1_size, + const struct spa_pod *pod2, + uint32_t pod2_size) +{ + const struct spa_pod *p1, *p2; + int res; + + p2 = pod2; + + SPA_POD_FOREACH(pod1, pod1_size, p1) { + bool do_recurse = false, do_advance = true; + void *a1, *a2; + void *p1c, *p2c; + uint32_t p1cs, p2cs; + + if (p2 == NULL) + return SPA_RESULT_INCOMPATIBLE_PROPS; + + switch (SPA_POD_TYPE(p1)) { + case SPA_POD_TYPE_STRUCT: + if (SPA_POD_TYPE(p2) != SPA_POD_TYPE_STRUCT) + return SPA_RESULT_INCOMPATIBLE_PROPS; + + p1c = SPA_POD_CONTENTS(struct spa_pod_struct, p1); + p1cs = SPA_POD_CONTENTS_SIZE(struct spa_pod_struct, p1); + p2c = SPA_POD_CONTENTS(struct spa_pod_struct, p2); + p2cs = SPA_POD_CONTENTS_SIZE(struct spa_pod_struct, p2); + do_recurse = true; + do_advance = true; + break; + case SPA_POD_TYPE_OBJECT: + if (SPA_POD_TYPE(p2) != SPA_POD_TYPE_OBJECT) + return SPA_RESULT_INCOMPATIBLE_PROPS; + + p1c = SPA_POD_CONTENTS(struct spa_pod_object, p1); + p1cs = SPA_POD_CONTENTS_SIZE(struct spa_pod_object, p1); + p2c = SPA_POD_CONTENTS(struct spa_pod_object, p2); + p2cs = SPA_POD_CONTENTS_SIZE(struct spa_pod_object, p2); + do_recurse = true; + do_advance = true; + break; + case SPA_POD_TYPE_PROP: + { + struct spa_pod_prop *pr1, *pr2; + + pr1 = (struct spa_pod_prop *) p1; + pr2 = find_prop(pod2, pod2_size, pr1->body.key); + + if (pr2 == NULL) + return SPA_RESULT_INCOMPATIBLE_PROPS; + + /* incompatible property types */ + if (pr1->body.value.type != pr2->body.value.type) + return SPA_RESULT_INCOMPATIBLE_PROPS; + + if (pr1->body.flags & SPA_POD_PROP_FLAG_UNSET || + pr2->body.flags & SPA_POD_PROP_FLAG_UNSET) + return SPA_RESULT_INCOMPATIBLE_PROPS; + + a1 = SPA_MEMBER(pr1, sizeof(struct spa_pod_prop), void); + a2 = SPA_MEMBER(pr2, sizeof(struct spa_pod_prop), void); + + res = compare_value(pr1->body.value.type, a1, a2); + break; + } + default: + if (SPA_POD_TYPE(p1) != SPA_POD_TYPE(p2)) + return SPA_RESULT_INCOMPATIBLE_PROPS; + + res = compare_value(SPA_POD_TYPE(p1), SPA_POD_BODY(p1), SPA_POD_BODY(p2)); + do_advance = true; + break; + } + if (do_advance) { + p2 = spa_pod_next(p2); + if (!spa_pod_is_iter(pod2, pod2_size, p2)) + p2 = NULL; + } + if (do_recurse) { + res = pod_compare(p1c, p1cs, p2c, p2cs); + } + if (res != 0) + return res; + } + if (p2 != NULL) + return SPA_RESULT_INCOMPATIBLE_PROPS; + + return SPA_RESULT_OK; +} + +int spa_pod_compare(const struct spa_pod *pod1, + const struct spa_pod *pod2) +{ + spa_return_val_if_fail(pod1 != NULL, SPA_RESULT_INVALID_ARGUMENTS); + spa_return_val_if_fail(pod2 != NULL, SPA_RESULT_INVALID_ARGUMENTS); + + return pod_compare(pod1, SPA_POD_SIZE(pod1), pod2, SPA_POD_SIZE(pod2)); +} diff --git a/spa/lib/format.h b/spa/lib/pod.h index 35a08f62..aa6f6d10 100644 --- a/spa/lib/format.h +++ b/spa/lib/pod.h @@ -1,5 +1,5 @@ /* Simple Plugin API - * Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com> + * Copyright (C) 2017 Wim Taymans <wim.taymans@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -17,24 +17,25 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __SPA_LIBFORMAT_H__ -#define __SPA_LIBFORMAT_H__ +#ifndef __SPA_LIBPOD_H__ +#define __SPA_LIBPOD_H__ #ifdef __cplusplus extern "C" { #endif #include <spa/props.h> +#include <spa/pod-builder.h> -int spa_pod_object_filter(const struct spa_pod_object *obj, - const struct spa_pod_object *filter, - struct spa_pod_builder *result); +int spa_pod_filter(struct spa_pod_builder *b, + const struct spa_pod *pod, + const struct spa_pod *filter); -int spa_pod_object_compare(const struct spa_pod_object *obj1, - const struct spa_pod_object *obj2); +int spa_pod_compare(const struct spa_pod *pod1, + const struct spa_pod *pod2); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* __SPA_LIBFORMAT_H__ */ +#endif /* __SPA_LIBPOD_H__ */ diff --git a/spa/lib/props.c b/spa/lib/props.c deleted file mode 100644 index 40494edf..00000000 --- a/spa/lib/props.c +++ /dev/null @@ -1,364 +0,0 @@ -/* Simple Plugin API - * Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com> - * - * 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 <stdint.h> -#include <stddef.h> -#include <stdio.h> -#include <string.h> - -#include <spa/props.h> -#include <spa/pod-builder.h> - -static int compare_value(enum spa_pod_type type, const void *r1, const void *r2) -{ - switch (type) { - case SPA_POD_TYPE_INVALID: - return 0; - case SPA_POD_TYPE_BOOL: - case SPA_POD_TYPE_ID: - return *(int32_t *) r1 == *(uint32_t *) r2 ? 0 : 1; - case SPA_POD_TYPE_INT: - return *(int32_t *) r1 - *(int32_t *) r2; - case SPA_POD_TYPE_LONG: - return *(int64_t *) r1 - *(int64_t *) r2; - case SPA_POD_TYPE_FLOAT: - return *(float *) r1 - *(float *) r2; - case SPA_POD_TYPE_DOUBLE: - return *(double *) r1 - *(double *) r2; - case SPA_POD_TYPE_STRING: - return strcmp(r1, r2); - case SPA_POD_TYPE_RECTANGLE: - { - const struct spa_rectangle *rec1 = (struct spa_rectangle *) r1, - *rec2 = (struct spa_rectangle *) r2; - if (rec1->width == rec2->width && rec1->height == rec2->height) - return 0; - else if (rec1->width < rec2->width || rec1->height < rec2->height) - return -1; - else - return 1; - } - case SPA_POD_TYPE_FRACTION: - { - const struct spa_fraction *f1 = (struct spa_fraction *) r1, - *f2 = (struct spa_fraction *) r2; - int64_t n1, n2; - n1 = ((int64_t) f1->num) * f2->denom; - n2 = ((int64_t) f2->num) * f1->denom; - if (n1 < n2) - return -1; - else if (n1 > n2) - return 1; - else - return 0; - } - default: - break; - } - return 0; -} - -static void fix_default(struct spa_pod_prop *prop) -{ - void *val = SPA_MEMBER(prop, sizeof(struct spa_pod_prop), void), - *alt = SPA_MEMBER(val, prop->body.value.size, void); - int i, nalt = SPA_POD_PROP_N_VALUES(prop) - 1; - - switch (prop->body.flags & SPA_POD_PROP_RANGE_MASK) { - case SPA_POD_PROP_RANGE_NONE: - break; - case SPA_POD_PROP_RANGE_MIN_MAX: - case SPA_POD_PROP_RANGE_STEP: - if (compare_value(prop->body.value.type, val, alt) < 0) - memcpy(val, alt, prop->body.value.size); - alt = SPA_MEMBER(alt, prop->body.value.size, void); - if (compare_value(prop->body.value.type, val, alt) > 0) - memcpy(val, alt, prop->body.value.size); - break; - case SPA_POD_PROP_RANGE_ENUM: - { - void *best = NULL; - - for (i = 0; i < nalt; i++) { - if (compare_value(prop->body.value.type, val, alt) == 0) { - best = alt; - break; - } - if (best == NULL) - best = alt; - alt = SPA_MEMBER(alt, prop->body.value.size, void); - } - if (best) - memcpy(val, best, prop->body.value.size); - - if (nalt == 1) { - prop->body.flags &= ~SPA_POD_PROP_FLAG_UNSET; - prop->body.flags &= ~SPA_POD_PROP_RANGE_MASK; - prop->body.flags |= SPA_POD_PROP_RANGE_NONE; - } - break; - } - case SPA_POD_PROP_RANGE_FLAGS: - break; - } -} - -static inline struct spa_pod_prop *find_prop(const struct spa_pod *pod, uint32_t size, uint32_t key) -{ - const struct spa_pod *res; - SPA_POD_FOREACH(pod, size, res) { - if (res->type == SPA_POD_TYPE_PROP - && ((struct spa_pod_prop *) res)->body.key == key) - return (struct spa_pod_prop *) res; - } - return NULL; -} - -int -spa_props_filter(struct spa_pod_builder *b, - const struct spa_pod *props, - uint32_t props_size, - const struct spa_pod *filter, - uint32_t filter_size) -{ - int j, k; - const struct spa_pod *pp, *pf; - - pf = filter; - - SPA_POD_FOREACH(props, props_size, pp) { - struct spa_pod_prop *p1, *p2, *np; - int nalt1, nalt2; - void *alt1, *alt2, *a1, *a2; - uint32_t rt1, rt2; - - if (pp->type != SPA_POD_TYPE_PROP) { - if (pf != NULL) { - if (SPA_POD_SIZE(pp) != SPA_POD_SIZE(pf)) - return SPA_RESULT_INCOMPATIBLE_PROPS; - - if (memcmp(pf, pp, SPA_POD_SIZE(pp)) != 0) - return SPA_RESULT_INCOMPATIBLE_PROPS; - - if (spa_pod_has_next(filter, filter_size, pf)) - pf = spa_pod_next(pf); - else - pf = NULL; - } - spa_pod_builder_raw_padded(b, pp, SPA_POD_SIZE(pp)); - continue; - } - - p1 = (struct spa_pod_prop *) pp; - - if (filter == NULL || (p2 = find_prop(filter, filter_size, p1->body.key)) == NULL) { - /* no filter, copy the complete property */ - spa_pod_builder_raw_padded(b, p1, SPA_POD_SIZE(p1)); - continue; - } - - /* incompatible property types */ - if (p1->body.value.type != p2->body.value.type) - return SPA_RESULT_INCOMPATIBLE_PROPS; - - rt1 = p1->body.flags & SPA_POD_PROP_RANGE_MASK; - rt2 = p2->body.flags & SPA_POD_PROP_RANGE_MASK; - - /* else we filter. start with copying the property */ - np = spa_pod_builder_deref(b, - spa_pod_builder_push_prop(b, p1->body.key, 0)); - - /* default value */ - spa_pod_builder_raw(b, &p1->body.value, - sizeof(p1->body.value) + p1->body.value.size); - - alt1 = SPA_MEMBER(p1, sizeof(struct spa_pod_prop), void); - nalt1 = SPA_POD_PROP_N_VALUES(p1); - alt2 = SPA_MEMBER(p2, sizeof(struct spa_pod_prop), void); - nalt2 = SPA_POD_PROP_N_VALUES(p2); - - if (p1->body.flags & SPA_POD_PROP_FLAG_UNSET) { - alt1 = SPA_MEMBER(alt1, p1->body.value.size, void); - nalt1--; - } else { - nalt1 = 1; - rt1 = SPA_POD_PROP_RANGE_NONE; - } - - if (p2->body.flags & SPA_POD_PROP_FLAG_UNSET) { - alt2 = SPA_MEMBER(alt2, p2->body.value.size, void); - nalt2--; - } else { - nalt2 = 1; - rt2 = SPA_POD_PROP_RANGE_NONE; - } - - if ((rt1 == SPA_POD_PROP_RANGE_NONE && rt2 == SPA_POD_PROP_RANGE_NONE) || - (rt1 == SPA_POD_PROP_RANGE_NONE && rt2 == SPA_POD_PROP_RANGE_ENUM) || - (rt1 == SPA_POD_PROP_RANGE_ENUM && rt2 == SPA_POD_PROP_RANGE_NONE) || - (rt1 == SPA_POD_PROP_RANGE_ENUM && rt2 == SPA_POD_PROP_RANGE_ENUM)) { - int n_copied = 0; - /* copy all equal values */ - for (j = 0, a1 = alt1; j < nalt1; j++, a1 += p1->body.value.size) { - for (k = 0, a2 = alt2; k < nalt2; k++, a2 += p2->body.value.size) { - if (compare_value(p1->body.value.type, a1, a2) == 0) { - spa_pod_builder_raw(b, a1, p1->body.value.size); - n_copied++; - } - } - } - if (n_copied == 0) - return SPA_RESULT_INCOMPATIBLE_PROPS; - np->body.flags |= SPA_POD_PROP_RANGE_ENUM | SPA_POD_PROP_FLAG_UNSET; - } - - if ((rt1 == SPA_POD_PROP_RANGE_NONE && rt2 == SPA_POD_PROP_RANGE_MIN_MAX) || - (rt1 == SPA_POD_PROP_RANGE_ENUM && rt2 == SPA_POD_PROP_RANGE_MIN_MAX)) { - int n_copied = 0; - /* copy all values inside the range */ - for (j = 0, a1 = alt1, a2 = alt2; j < nalt1; j++, a1 += p1->body.value.size) { - if (compare_value(p1->body.value.type, a1, a2) < 0) - continue; - if (compare_value(p1->body.value.type, a1, a2 + p2->body.value.size) - > 0) - continue; - spa_pod_builder_raw(b, a1, p1->body.value.size); - n_copied++; - } - if (n_copied == 0) - return SPA_RESULT_INCOMPATIBLE_PROPS; - np->body.flags |= SPA_POD_PROP_RANGE_ENUM | SPA_POD_PROP_FLAG_UNSET; - } - - if ((rt1 == SPA_POD_PROP_RANGE_NONE && rt2 == SPA_POD_PROP_RANGE_STEP) || - (rt1 == SPA_POD_PROP_RANGE_ENUM && rt2 == SPA_POD_PROP_RANGE_STEP)) { - return SPA_RESULT_NOT_IMPLEMENTED; - } - - if ((rt1 == SPA_POD_PROP_RANGE_MIN_MAX && rt2 == SPA_POD_PROP_RANGE_NONE) || - (rt1 == SPA_POD_PROP_RANGE_MIN_MAX && rt2 == SPA_POD_PROP_RANGE_ENUM)) { - int n_copied = 0; - /* copy all values inside the range */ - for (k = 0, a1 = alt1, a2 = alt2; k < nalt2; k++, a2 += p2->body.value.size) { - if (compare_value(p1->body.value.type, a2, a1) < 0) - continue; - if (compare_value(p1->body.value.type, a2, a1 + p1->body.value.size) - > 0) - continue; - spa_pod_builder_raw(b, a2, p2->body.value.size); - n_copied++; - } - if (n_copied == 0) - return SPA_RESULT_INCOMPATIBLE_PROPS; - np->body.flags |= SPA_POD_PROP_RANGE_ENUM | SPA_POD_PROP_FLAG_UNSET; - } - - if (rt1 == SPA_POD_PROP_RANGE_MIN_MAX && rt2 == SPA_POD_PROP_RANGE_MIN_MAX) { - if (compare_value(p1->body.value.type, alt1, alt2) < 0) - spa_pod_builder_raw(b, alt2, p2->body.value.size); - else - spa_pod_builder_raw(b, alt1, p1->body.value.size); - - alt1 += p1->body.value.size; - alt2 += p2->body.value.size; - - if (compare_value(p1->body.value.type, alt1, alt2) < 0) - spa_pod_builder_raw(b, alt1, p1->body.value.size); - else - spa_pod_builder_raw(b, alt2, p2->body.value.size); - - np->body.flags |= SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET; - } - - if (rt1 == SPA_POD_PROP_RANGE_NONE && rt2 == SPA_POD_PROP_RANGE_FLAGS) - return SPA_RESULT_NOT_IMPLEMENTED; - - if (rt1 == SPA_POD_PROP_RANGE_MIN_MAX && rt2 == SPA_POD_PROP_RANGE_STEP) - return SPA_RESULT_NOT_IMPLEMENTED; - - if (rt1 == SPA_POD_PROP_RANGE_MIN_MAX && rt2 == SPA_POD_PROP_RANGE_FLAGS) - return SPA_RESULT_NOT_IMPLEMENTED; - - if (rt1 == SPA_POD_PROP_RANGE_ENUM && rt2 == SPA_POD_PROP_RANGE_FLAGS) - return SPA_RESULT_NOT_IMPLEMENTED; - - if (rt1 == SPA_POD_PROP_RANGE_STEP && rt2 == SPA_POD_PROP_RANGE_NONE) - return SPA_RESULT_NOT_IMPLEMENTED; - if (rt1 == SPA_POD_PROP_RANGE_STEP && rt2 == SPA_POD_PROP_RANGE_MIN_MAX) - return SPA_RESULT_NOT_IMPLEMENTED; - - if (rt1 == SPA_POD_PROP_RANGE_STEP && rt2 == SPA_POD_PROP_RANGE_STEP) - return SPA_RESULT_NOT_IMPLEMENTED; - if (rt1 == SPA_POD_PROP_RANGE_STEP && rt2 == SPA_POD_PROP_RANGE_ENUM) - return SPA_RESULT_NOT_IMPLEMENTED; - if (rt1 == SPA_POD_PROP_RANGE_STEP && rt2 == SPA_POD_PROP_RANGE_FLAGS) - return SPA_RESULT_NOT_IMPLEMENTED; - - if (rt1 == SPA_POD_PROP_RANGE_FLAGS && rt2 == SPA_POD_PROP_RANGE_NONE) - return SPA_RESULT_NOT_IMPLEMENTED; - if (rt1 == SPA_POD_PROP_RANGE_FLAGS && rt2 == SPA_POD_PROP_RANGE_MIN_MAX) - return SPA_RESULT_NOT_IMPLEMENTED; - if (rt1 == SPA_POD_PROP_RANGE_FLAGS && rt2 == SPA_POD_PROP_RANGE_STEP) - return SPA_RESULT_NOT_IMPLEMENTED; - if (rt1 == SPA_POD_PROP_RANGE_FLAGS && rt2 == SPA_POD_PROP_RANGE_ENUM) - return SPA_RESULT_NOT_IMPLEMENTED; - if (rt1 == SPA_POD_PROP_RANGE_FLAGS && rt2 == SPA_POD_PROP_RANGE_FLAGS) - return SPA_RESULT_NOT_IMPLEMENTED; - - spa_pod_builder_pop(b); - fix_default(np); - } - return SPA_RESULT_OK; -} - -int spa_props_compare(const struct spa_pod *props1, - uint32_t props1_size, - const struct spa_pod *props2, - uint32_t props2_size) -{ - const struct spa_pod *pr; - - SPA_POD_FOREACH(props1, props1_size, pr) { - struct spa_pod_prop *p1, *p2; - void *a1, *a2; - - if (pr->type != SPA_POD_TYPE_PROP) - continue; - - p1 = (struct spa_pod_prop *) pr; - - if ((p2 = find_prop(props2, props2_size, p1->body.key)) == NULL) - return SPA_RESULT_INCOMPATIBLE_PROPS; - - /* incompatible property types */ - if (p1->body.value.type != p2->body.value.type) - return SPA_RESULT_INCOMPATIBLE_PROPS; - - if (p1->body.flags & SPA_POD_PROP_FLAG_UNSET || - p2->body.flags & SPA_POD_PROP_FLAG_UNSET) - return SPA_RESULT_INCOMPATIBLE_PROPS; - - a1 = SPA_MEMBER(p1, sizeof(struct spa_pod_prop), void); - a2 = SPA_MEMBER(p2, sizeof(struct spa_pod_prop), void); - - if (compare_value(p1->body.value.type, a1, a2) != 0) - return SPA_RESULT_INCOMPATIBLE_PROPS; - } - return SPA_RESULT_OK; -} diff --git a/spa/lib/props.h b/spa/lib/props.h deleted file mode 100644 index ec31b7ca..00000000 --- a/spa/lib/props.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Simple Plugin API - * Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com> - * - * 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_LIBPROPS_H__ -#define __SPA_LIBPROPS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include <spa/props.h> -#include <spa/pod-builder.h> - -int spa_props_filter(struct spa_pod_builder *b, - const struct spa_pod *props, - uint32_t props_size, - const struct spa_pod *filter, - uint32_t filter_size); - -int spa_props_compare(const struct spa_pod *props1, - uint32_t props1_size, - const struct spa_pod *props2, - uint32_t props2_size); -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* __SPA_LIBPROPS_H__ */ diff --git a/spa/plugins/alsa/alsa-sink.c b/spa/plugins/alsa/alsa-sink.c index 5c1430ba..5e319c06 100644 --- a/spa/plugins/alsa/alsa-sink.c +++ b/spa/plugins/alsa/alsa-sink.c @@ -23,7 +23,7 @@ #include <spa/node.h> #include <spa/audio/format.h> -#include <lib/props.h> +#include <lib/pod.h> #define NAME "alsa-sink" @@ -49,6 +49,8 @@ static int impl_node_enum_params(struct spa_node *node, { struct state *this; struct type *t; + struct spa_pod *param; + uint32_t offset; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -57,11 +59,14 @@ static int impl_node_enum_params(struct spa_node *node, this = SPA_CONTAINER_OF(node, struct state, node); t = &this->type; + offset = builder->offset; + + next: if (id == t->param.idList) { if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", t->param.idProps); } @@ -71,21 +76,25 @@ static int impl_node_enum_params(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, - id, t->props, - ":", t->prop_device, "S", p->device, sizeof(p->device), - ":", t->prop_device_name, "S-r", p->device_name, sizeof(p->device_name), - ":", t->prop_card_name, "S-r", p->card_name, sizeof(p->card_name), - ":", t->prop_min_latency, "ir", p->min_latency, - 2, 1, INT32_MAX, - ":", t->prop_max_latency, "ir", p->max_latency, - 2, 1, INT32_MAX); + param = spa_pod_builder_object(builder, + id, t->props, + ":", t->prop_device, "S", p->device, sizeof(p->device), + ":", t->prop_device_name, "S-r", p->device_name, sizeof(p->device_name), + ":", t->prop_card_name, "S-r", p->card_name, sizeof(p->card_name), + ":", t->prop_min_latency, "ir", p->min_latency, + 2, 1, INT32_MAX, + ":", t->prop_max_latency, "ir", p->max_latency, + 2, 1, INT32_MAX); } else return SPA_RESULT_UNKNOWN_PARAM; (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } @@ -261,31 +270,6 @@ impl_node_port_get_info(struct spa_node *node, return SPA_RESULT_OK; } -static int port_get_format(struct spa_node *node, - enum spa_direction direction, uint32_t port_id, - uint32_t *index, - const struct spa_pod_object *filter, - struct spa_pod_builder *builder) -{ - struct state *this = SPA_CONTAINER_OF(node, struct state, node); - struct type *t = &this->type; - - if (!this->have_format) - return SPA_RESULT_NO_FORMAT; - if (*index > 0) - return SPA_RESULT_ENUM_END; - - spa_pod_builder_object(builder, - t->param.idFormat, t->format, - "I", t->media_type.audio, - "I", t->media_subtype.raw, - ":", t->format_audio.format, "I", this->current_format.info.raw.format, - ":", t->format_audio.rate, "i", this->current_format.info.raw.rate, - ":", t->format_audio.channels, "i", this->current_format.info.raw.channels); - - return SPA_RESULT_OK; -} - static int impl_node_port_enum_params(struct spa_node *node, enum spa_direction direction, uint32_t port_id, @@ -296,6 +280,8 @@ impl_node_port_enum_params(struct spa_node *node, struct state *this; struct type *t; + struct spa_pod *param; + uint32_t offset; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -306,6 +292,9 @@ impl_node_port_enum_params(struct spa_node *node, spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + offset = builder->offset; + + next: if (id == t->param.idList) { uint32_t list[] = { t->param.idEnumFormat, t->param.idFormat, @@ -313,7 +302,7 @@ impl_node_port_enum_params(struct spa_node *node, t->param.idMeta }; if (*index < SPA_N_ELEMENTS(list)) - spa_pod_builder_object(builder, id, t->param.List, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", list[*index]); else return SPA_RESULT_ENUM_END; @@ -322,7 +311,18 @@ impl_node_port_enum_params(struct spa_node *node, return spa_alsa_enum_format(this, index, filter, builder); } else if (id == t->param.idFormat) { - return port_get_format(node, direction, port_id, index, filter, builder); + if (!this->have_format) + return SPA_RESULT_NO_FORMAT; + if (*index > 0) + return SPA_RESULT_ENUM_END; + + param = spa_pod_builder_object(builder, + t->param.idFormat, t->format, + "I", t->media_type.audio, + "I", t->media_subtype.raw, + ":", t->format_audio.format, "I", this->current_format.info.raw.format, + ":", t->format_audio.rate, "i", this->current_format.info.raw.rate, + ":", t->format_audio.channels, "i", this->current_format.info.raw.channels); } else if (id == t->param.idBuffers) { if (!this->have_format) @@ -330,7 +330,7 @@ impl_node_port_enum_params(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_buffers.Buffers, ":", t->param_alloc_buffers.size, "iru", this->props.min_latency * this->frame_size, 2, this->props.min_latency * this->frame_size, @@ -346,13 +346,13 @@ impl_node_port_enum_params(struct spa_node *node, switch (*index) { case 0: - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_meta_enable.MetaEnable, ":", t->param_alloc_meta_enable.type, "I", t->meta.Header, ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header)); break; case 1: - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_meta_enable.MetaEnable, ":", t->param_alloc_meta_enable.type, "I", t->meta.Ringbuffer, ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_ringbuffer), @@ -373,6 +373,10 @@ impl_node_port_enum_params(struct spa_node *node, (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } diff --git a/spa/plugins/alsa/alsa-source.c b/spa/plugins/alsa/alsa-source.c index 8ff5c59c..a1bcb228 100644 --- a/spa/plugins/alsa/alsa-source.c +++ b/spa/plugins/alsa/alsa-source.c @@ -24,7 +24,8 @@ #include <spa/node.h> #include <spa/list.h> #include <spa/audio/format.h> -#include <lib/props.h> + +#include <lib/pod.h> #define NAME "alsa-source" @@ -48,6 +49,8 @@ static int impl_node_enum_params(struct spa_node *node, { struct state *this; struct type *t; + struct spa_pod *param; + uint32_t offset; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -56,11 +59,14 @@ static int impl_node_enum_params(struct spa_node *node, this = SPA_CONTAINER_OF(node, struct state, node); t = &this->type; + offset = builder->offset; + + next: if (id == t->param.idList) { if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", t->param.idProps); } @@ -70,7 +76,7 @@ static int impl_node_enum_params(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->props, ":", t->prop_device, "S", p->device, sizeof(p->device), ":", t->prop_device_name, "S-r", p->device_name, sizeof(p->device_name), @@ -83,6 +89,10 @@ static int impl_node_enum_params(struct spa_node *node, (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } @@ -290,7 +300,7 @@ static void recycle_buffer(struct state *this, uint32_t buffer_id) static int port_get_format(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, - const struct spa_pod_object *filter, + struct spa_pod **param, struct spa_pod_builder *builder) { struct state *this = SPA_CONTAINER_OF(node, struct state, node); @@ -301,7 +311,7 @@ static int port_get_format(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + *param = spa_pod_builder_object(builder, t->param.idFormat, t->format, "I", t->media_type.audio, "I", t->media_subtype.raw, @@ -321,6 +331,9 @@ impl_node_port_enum_params(struct spa_node *node, { struct state *this; struct type *t; + struct spa_pod *param; + uint32_t offset; + int res; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -331,6 +344,9 @@ impl_node_port_enum_params(struct spa_node *node, spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + offset = builder->offset; + + next: if (id == t->param.idList) { uint32_t list[] = { t->param.idEnumFormat, t->param.idFormat, @@ -338,7 +354,7 @@ impl_node_port_enum_params(struct spa_node *node, t->param.idMeta }; if (*index < SPA_N_ELEMENTS(list)) - spa_pod_builder_object(builder, id, t->param.List, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", list[*index]); else return SPA_RESULT_ENUM_END; @@ -347,7 +363,8 @@ impl_node_port_enum_params(struct spa_node *node, return spa_alsa_enum_format(this, index, filter, builder); } else if (id == t->param.idFormat) { - return port_get_format(node, direction, port_id, index, filter, builder); + if ((res = port_get_format(node, direction, port_id, index, ¶m, builder)) < 0) + return res; } else if (id == t->param.idBuffers) { if (!this->have_format) @@ -355,7 +372,7 @@ impl_node_port_enum_params(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_buffers.Buffers, ":", t->param_alloc_buffers.size, "i", this->props.min_latency * this->frame_size, ":", t->param_alloc_buffers.stride, "i", 0, @@ -369,7 +386,7 @@ impl_node_port_enum_params(struct spa_node *node, switch (*index) { case 0: - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_meta_enable.MetaEnable, ":", t->param_alloc_meta_enable.type, "I", t->meta.Header, ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header)); @@ -383,6 +400,10 @@ impl_node_port_enum_params(struct spa_node *node, (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } diff --git a/spa/plugins/alsa/alsa-utils.c b/spa/plugins/alsa/alsa-utils.c index 191ced23..c78f1917 100644 --- a/spa/plugins/alsa/alsa-utils.c +++ b/spa/plugins/alsa/alsa-utils.c @@ -10,7 +10,7 @@ #include <sys/timerfd.h> #include <lib/debug.h> -#include <lib/format.h> +#include <lib/pod.h> #include "alsa-utils.h" @@ -202,7 +202,7 @@ spa_alsa_enum_format(struct state *state, uint32_t *index, (*index)++; - if ((res = spa_pod_object_filter(fmt, filter, builder)) < 0) + if ((res = spa_pod_filter(builder, (struct spa_pod*)fmt, (struct spa_pod*)filter)) < 0) goto next; if (!opened) diff --git a/spa/plugins/audiomixer/audiomixer.c b/spa/plugins/audiomixer/audiomixer.c index 01e99900..c51d12c6 100644 --- a/spa/plugins/audiomixer/audiomixer.c +++ b/spa/plugins/audiomixer/audiomixer.c @@ -25,10 +25,10 @@ #include <spa/type-map.h> #include <spa/node.h> #include <spa/audio/format-utils.h> -#include <lib/format.h> -#include <lib/props.h> #include <spa/param-alloc.h> +#include <lib/pod.h> + #include "conv.h" #define NAME "audiomixer" @@ -323,22 +323,15 @@ impl_node_port_get_info(struct spa_node *node, static int port_enum_formats(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, - const struct spa_pod_object *filter, + struct spa_pod **param, struct spa_pod_builder *builder) { struct impl *this = SPA_CONTAINER_OF(node, struct impl, node); - struct spa_pod_object *fmt; - uint8_t buffer[256]; - struct spa_pod_builder b = { NULL, }; struct type *t = &this->type; - int res; - - next: - spa_pod_builder_init(&b, buffer, sizeof(buffer)); switch (*index) { case 0: - fmt = spa_pod_builder_object(&b, + *param = spa_pod_builder_object(builder, t->param.idEnumFormat, t->format, "I", t->media_type.audio, "I", t->media_subtype.raw, @@ -353,19 +346,13 @@ static int port_enum_formats(struct spa_node *node, default: return SPA_RESULT_ENUM_END; } - - (*index)++; - - if ((res = spa_pod_object_filter(fmt, filter, builder)) != SPA_RESULT_OK) - goto next; - return SPA_RESULT_OK; } static int port_get_format(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, - const struct spa_pod_object *filter, + struct spa_pod **param, struct spa_pod_builder *builder) { struct impl *this = SPA_CONTAINER_OF(node, struct impl, node); @@ -377,7 +364,7 @@ static int port_get_format(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + *param = spa_pod_builder_object(builder, t->param.idFormat, t->format, "I", t->media_type.audio, "I", t->media_subtype.raw, @@ -398,6 +385,9 @@ impl_node_port_enum_params(struct spa_node *node, struct impl *this; struct type *t; struct port *port; + struct spa_pod *param; + uint32_t offset; + int res; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -410,6 +400,9 @@ impl_node_port_enum_params(struct spa_node *node, port = GET_PORT(this, direction, port_id); + offset = builder->offset; + + next: if (id == t->param.idList) { uint32_t list[] = { t->param.idEnumFormat, t->param.idFormat, @@ -417,16 +410,18 @@ impl_node_port_enum_params(struct spa_node *node, t->param.idMeta }; if (*index < SPA_N_ELEMENTS(list)) - spa_pod_builder_object(builder, id, t->param.List, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", list[*index]); else return SPA_RESULT_ENUM_END; } else if (id == t->param.idEnumFormat) { - return port_enum_formats(node, direction, port_id, index, filter, builder); + if ((res = port_enum_formats(node, direction, port_id, index, ¶m, builder)) < 0) + return res; } else if (id == t->param.idFormat) { - return port_get_format(node, direction, port_id, index, filter, builder); + if ((res = port_get_format(node, direction, port_id, index, ¶m, builder)) < 0) + return res; } else if (id == t->param.idBuffers) { if (!port->have_format) @@ -434,7 +429,7 @@ impl_node_port_enum_params(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_buffers.Buffers, ":", t->param_alloc_buffers.size, "iru", 1024 * this->bpf, 2, 16 * this->bpf, @@ -450,13 +445,13 @@ impl_node_port_enum_params(struct spa_node *node, switch (*index) { case 0: - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_meta_enable.MetaEnable, ":", t->param_alloc_meta_enable.type, "I", t->meta.Header, ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header)); break; case 1: - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_meta_enable.MetaEnable, ":", t->param_alloc_meta_enable.type, "I", t->meta.Ringbuffer, ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_ringbuffer), @@ -475,6 +470,10 @@ impl_node_port_enum_params(struct spa_node *node, (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } diff --git a/spa/plugins/audiotestsrc/audiotestsrc.c b/spa/plugins/audiotestsrc/audiotestsrc.c index 1ca581f4..e2a58561 100644 --- a/spa/plugins/audiotestsrc/audiotestsrc.c +++ b/spa/plugins/audiotestsrc/audiotestsrc.c @@ -32,8 +32,7 @@ #include <spa/list.h> #include <spa/audio/format-utils.h> -#include <lib/format.h> -#include <lib/props.h> +#include <lib/pod.h> #define NAME "audiotestsrc" @@ -173,6 +172,8 @@ static int impl_node_enum_params(struct spa_node *node, { struct impl *this; struct type *t; + uint32_t offset; + struct spa_pod *param; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -181,11 +182,14 @@ static int impl_node_enum_params(struct spa_node *node, this = SPA_CONTAINER_OF(node, struct impl, node); t = &this->type; + offset = builder->offset; + + next: if (id == t->param.idList) { if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", t->param.idProps); } @@ -195,7 +199,7 @@ static int impl_node_enum_params(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->props, ":", t->prop_live, "b", p->live, ":", t->prop_wave, "Ie", p->wave, @@ -211,6 +215,10 @@ static int impl_node_enum_params(struct spa_node *node, (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } @@ -507,21 +515,14 @@ static int port_enum_formats(struct impl *this, enum spa_direction direction, uint32_t port_id, uint32_t *index, - const struct spa_pod_object *filter, + struct spa_pod **param, struct spa_pod_builder *builder) { - struct spa_pod_object *fmt; struct type *t = &this->type; - uint8_t buffer[1024]; - struct spa_pod_builder b = { 0 }; - int res; - - next: - spa_pod_builder_init(&b, buffer, sizeof(buffer)); switch (*index) { case 0: - fmt = spa_pod_builder_object(&b, + *param = spa_pod_builder_object(builder, t->param.idEnumFormat, t->format, "I", t->media_type.audio, "I", t->media_subtype.raw, @@ -538,12 +539,6 @@ port_enum_formats(struct impl *this, default: return SPA_RESULT_ENUM_END; } - - (*index)++; - - if ((res = spa_pod_object_filter(fmt, filter, builder)) != SPA_RESULT_OK) - goto next; - return SPA_RESULT_OK; } @@ -552,7 +547,7 @@ port_get_format(struct impl *this, enum spa_direction direction, uint32_t port_id, uint32_t *index, - const struct spa_pod_object *filter, + struct spa_pod **param, struct spa_pod_builder *builder) { struct type *t = &this->type; @@ -563,7 +558,7 @@ port_get_format(struct impl *this, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + *param = spa_pod_builder_object(builder, t->param.idFormat, t->format, "I", t->media_type.audio, "I", t->media_subtype.raw, @@ -583,6 +578,9 @@ impl_node_port_enum_params(struct spa_node *node, { struct impl *this; struct type *t; + uint32_t offset; + struct spa_pod *param; + int res; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -593,6 +591,9 @@ impl_node_port_enum_params(struct spa_node *node, spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + offset = builder->offset; + + next: if (id == t->param.idList) { uint32_t list[] = { t->param.idEnumFormat, t->param.idFormat, @@ -600,16 +601,18 @@ impl_node_port_enum_params(struct spa_node *node, t->param.idMeta }; if (*index < SPA_N_ELEMENTS(list)) - spa_pod_builder_object(builder, id, t->param.List, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", list[*index]); else return SPA_RESULT_ENUM_END; } else if (id == t->param.idEnumFormat) { - return port_enum_formats(this, direction, port_id, index, filter, builder); + if ((res = port_enum_formats(this, direction, port_id, index, ¶m, builder)) < 0) + return res; } else if (id == t->param.idFormat) { - return port_get_format(this, direction, port_id, index, filter, builder); + if ((res = port_get_format(this, direction, port_id, index, ¶m, builder)) < 0) + return res; } else if (id == t->param.idBuffers) { if (!this->have_format) @@ -617,7 +620,7 @@ impl_node_port_enum_params(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_buffers.Buffers, ":", t->param_alloc_buffers.size, "iru", 1024 * this->bpf, 2, 16 * this->bpf, @@ -633,13 +636,13 @@ impl_node_port_enum_params(struct spa_node *node, switch (*index) { case 0: - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_meta_enable.MetaEnable, ":", t->param_alloc_meta_enable.type, "I", t->meta.Header, ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header)); break; case 1: - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_meta_enable.MetaEnable, ":", t->param_alloc_meta_enable.type, "I", t->meta.Ringbuffer, ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_ringbuffer), @@ -658,6 +661,10 @@ impl_node_port_enum_params(struct spa_node *node, (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } diff --git a/spa/plugins/ffmpeg/ffmpeg-dec.c b/spa/plugins/ffmpeg/ffmpeg-dec.c index 46891d7c..642dfd83 100644 --- a/spa/plugins/ffmpeg/ffmpeg-dec.c +++ b/spa/plugins/ffmpeg/ffmpeg-dec.c @@ -26,7 +26,7 @@ #include <spa/log.h> #include <spa/node.h> #include <spa/video/format-utils.h> -#include <lib/props.h> +#include <lib/pod.h> #define IS_VALID_PORT(this,d,id) ((id) == 0) #define MAX_BUFFERS 32 @@ -189,11 +189,36 @@ spa_ffmpeg_dec_node_remove_port(struct spa_node *node, return SPA_RESULT_NOT_IMPLEMENTED; } +static int +spa_ffmpeg_dec_node_port_get_info(struct spa_node *node, + enum spa_direction direction, + uint32_t port_id, + const struct spa_port_info **info) +{ + struct impl *this; + struct port *port; + + if (node == NULL || info == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = SPA_CONTAINER_OF(node, struct impl, node); + + if (!IS_VALID_PORT(this, direction, port_id)) + return SPA_RESULT_INVALID_PORT; + + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + *info = &port->info; + + return SPA_RESULT_OK; +} + static int port_enum_formats(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, const struct spa_pod_object *filter, - struct spa_pod_builder *builder) + struct spa_pod_builder *builder, + struct spa_pod **param) { //struct impl *this; @@ -207,55 +232,13 @@ static int port_enum_formats(struct spa_node *node, switch (*index) { case 0: + *param = NULL; break; default: return SPA_RESULT_ENUM_END; } - return SPA_RESULT_OK; -} - -static int port_set_format(struct spa_node *node, - enum spa_direction direction, uint32_t port_id, - uint32_t flags, - const struct spa_pod_object *format) -{ - struct impl *this; - struct port *port; - - if (node == NULL || format == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - this = SPA_CONTAINER_OF(node, struct impl, node); - - if (!IS_VALID_PORT(this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; - - port = - direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - - if (format == NULL) { - port->have_format = false; - return SPA_RESULT_OK; - } else { - struct spa_video_info info = { 0 }; - - spa_pod_object_parse(format, - "I", &info.media_type, - "I", &info.media_subtype); - if (info.media_type != this->type.media_type.video && - info.media_subtype != this->type.media_subtype.raw) - return SPA_RESULT_INVALID_MEDIA_TYPE; - - if (spa_format_video_raw_parse(format, &info.info.raw, &this->type.format_video) < 0) - return SPA_RESULT_INVALID_MEDIA_TYPE; - - if (!(flags & SPA_NODE_PARAM_FLAG_TEST_ONLY)) { - port->current_format = info; - port->have_format = true; - } - } return SPA_RESULT_OK; } @@ -263,7 +246,8 @@ static int port_get_format(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, const struct spa_pod_object *filter, - struct spa_pod_builder *builder) + struct spa_pod_builder *builder, + struct spa_pod **param) { struct impl *this = SPA_CONTAINER_OF(node, struct impl, node); struct port *port; @@ -277,29 +261,7 @@ static int port_get_format(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - return SPA_RESULT_OK; -} - -static int -spa_ffmpeg_dec_node_port_get_info(struct spa_node *node, - enum spa_direction direction, - uint32_t port_id, - const struct spa_port_info **info) -{ - struct impl *this; - struct port *port; - - if (node == NULL || info == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - this = SPA_CONTAINER_OF(node, struct impl, node); - - if (!IS_VALID_PORT(this, direction, port_id)) - return SPA_RESULT_INVALID_PORT; - - port = - direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - *info = &port->info; + *param = NULL; return SPA_RESULT_OK; } @@ -313,28 +275,84 @@ spa_ffmpeg_dec_node_port_enum_params(struct spa_node *node, { struct impl *this = SPA_CONTAINER_OF(node, struct impl, node); struct type *t = &this->type; + uint32_t offset; + struct spa_pod *param; + int res; + offset = builder->offset; + + next: if (id == t->param.idList) { uint32_t list[] = { t->param.idEnumFormat, t->param.idFormat }; if (*index < SPA_N_ELEMENTS(list)) - spa_pod_builder_object(builder, id, t->param.List, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", list[*index]); else return SPA_RESULT_ENUM_END; } else if (id == t->param.idEnumFormat) { - return port_enum_formats(node, direction, port_id, index, filter, builder); + if ((res = port_enum_formats(node, direction, port_id, index, filter, builder, ¶m)) < 0) + return res; } else if (id == t->param.idFormat) { - return port_get_format(node, direction, port_id, index, filter, builder); + if ((res = port_get_format(node, direction, port_id, index, filter, builder, ¶m)) < 0) + return res; } else return SPA_RESULT_UNKNOWN_PARAM; (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + + return SPA_RESULT_OK; +} + +static int port_set_format(struct spa_node *node, + enum spa_direction direction, uint32_t port_id, + uint32_t flags, + const struct spa_pod_object *format) +{ + struct impl *this; + struct port *port; + + if (node == NULL || format == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = SPA_CONTAINER_OF(node, struct impl, node); + + if (!IS_VALID_PORT(this, direction, port_id)) + return SPA_RESULT_INVALID_PORT; + + port = + direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + + if (format == NULL) { + port->have_format = false; + return SPA_RESULT_OK; + } else { + struct spa_video_info info = { 0 }; + + spa_pod_object_parse(format, + "I", &info.media_type, + "I", &info.media_subtype); + + if (info.media_type != this->type.media_type.video && + info.media_subtype != this->type.media_subtype.raw) + return SPA_RESULT_INVALID_MEDIA_TYPE; + + if (spa_format_video_raw_parse(format, &info.info.raw, &this->type.format_video) < 0) + return SPA_RESULT_INVALID_MEDIA_TYPE; + + if (!(flags & SPA_NODE_PARAM_FLAG_TEST_ONLY)) { + port->current_format = info; + port->have_format = true; + } + } return SPA_RESULT_OK; } diff --git a/spa/plugins/ffmpeg/ffmpeg-enc.c b/spa/plugins/ffmpeg/ffmpeg-enc.c index 829cec02..7fb7aed9 100644 --- a/spa/plugins/ffmpeg/ffmpeg-enc.c +++ b/spa/plugins/ffmpeg/ffmpeg-enc.c @@ -26,7 +26,8 @@ #include <spa/type-map.h> #include <spa/node.h> #include <spa/video/format-utils.h> -#include <lib/props.h> + +#include <lib/pod.h> #define IS_VALID_PORT(this,d,id) ((id) == 0) #define MAX_BUFFERS 32 @@ -218,7 +219,8 @@ static int port_enum_formats(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, const struct spa_pod_object *filter, - struct spa_pod_builder *builder) + struct spa_pod_builder *builder, + struct spa_pod **param) { //struct impl *this = SPA_CONTAINER_OF (node, struct impl, node); //struct port *port; @@ -227,6 +229,7 @@ static int port_enum_formats(struct spa_node *node, switch (*index) { case 0: + *param = NULL; break; default: return SPA_RESULT_ENUM_END; @@ -238,7 +241,8 @@ static int port_get_format(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, const struct spa_pod_object *filter, - struct spa_pod_builder *builder) + struct spa_pod_builder *builder, + struct spa_pod **param) { struct impl *this = SPA_CONTAINER_OF(node, struct impl, node); struct port *port; @@ -252,6 +256,8 @@ static int port_get_format(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; + *param = NULL; + return SPA_RESULT_OK; } @@ -264,28 +270,40 @@ spa_ffmpeg_enc_node_port_enum_params(struct spa_node *node, { struct impl *this = SPA_CONTAINER_OF(node, struct impl, node); struct type *t = &this->type; + uint32_t offset; + struct spa_pod *param; + int res; + offset = builder->offset; + + next: if (id == t->param.idList) { uint32_t list[] = { t->param.idEnumFormat, t->param.idFormat }; if (*index < SPA_N_ELEMENTS(list)) - spa_pod_builder_object(builder, id, t->param.List, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", list[*index]); else return SPA_RESULT_ENUM_END; } else if (id == t->param.idEnumFormat) { - return port_enum_formats(node, direction, port_id, index, filter, builder); + if ((res = port_enum_formats(node, direction, port_id, index, filter, builder, ¶m)) < 0) + return res; } else if (id == t->param.idFormat) { - return port_get_format(node, direction, port_id, index, filter, builder); + if ((res = port_get_format(node, direction, port_id, index, filter, builder, ¶m)) < 0) + return res; } else return SPA_RESULT_UNKNOWN_PARAM; (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } diff --git a/spa/plugins/support/logger.c b/spa/plugins/support/logger.c index f181f9a5..bc7bd6a9 100644 --- a/spa/plugins/support/logger.c +++ b/spa/plugins/support/logger.c @@ -31,7 +31,7 @@ #include <spa/node.h> #include <spa/param-alloc.h> #include <spa/list.h> -#include <lib/props.h> +#include <lib/pod.h> #define NAME "logger" diff --git a/spa/plugins/support/mapper.c b/spa/plugins/support/mapper.c index 9c4ff2a0..2b1807c1 100644 --- a/spa/plugins/support/mapper.c +++ b/spa/plugins/support/mapper.c @@ -31,7 +31,6 @@ #include <spa/node.h> #include <spa/param-alloc.h> #include <spa/list.h> -#include <lib/props.h> #define NAME "mapper" diff --git a/spa/plugins/test/fakesink.c b/spa/plugins/test/fakesink.c index e4ce4ba9..2556f389 100644 --- a/spa/plugins/test/fakesink.c +++ b/spa/plugins/test/fakesink.c @@ -30,7 +30,7 @@ #include <spa/node.h> #include <spa/param-alloc.h> #include <spa/list.h> -#include <lib/props.h> +#include <lib/pod.h> #define NAME "fakesink" @@ -130,6 +130,8 @@ static int impl_node_enum_params(struct spa_node *node, { struct impl *this; struct type *t; + uint32_t offset; + struct spa_pod *param; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(builder != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -137,11 +139,14 @@ static int impl_node_enum_params(struct spa_node *node, this = SPA_CONTAINER_OF(node, struct impl, node); t = &this->type; + offset = builder->offset; + + next: if (id == t->param.idList) { if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", t->param.idProps); } @@ -149,7 +154,7 @@ static int impl_node_enum_params(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->props, ":", t->prop_live, "b", this->props.live); } @@ -158,6 +163,10 @@ static int impl_node_enum_params(struct spa_node *node, (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } @@ -421,7 +430,8 @@ static int port_enum_formats(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, const struct spa_pod_object *filter, - struct spa_pod_builder *builder) + struct spa_pod_builder *builder, + struct spa_pod **param) { return SPA_RESULT_ENUM_END; } @@ -430,7 +440,8 @@ static int port_get_format(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, const struct spa_pod_object *filter, - struct spa_pod_builder *builder) + struct spa_pod_builder *builder, + struct spa_pod **param) { struct impl *this = SPA_CONTAINER_OF(node, struct impl, node); @@ -440,7 +451,7 @@ static int port_get_format(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_primitive(builder, SPA_MEMBER(this->format_buffer, 0, struct spa_pod)); + *param = SPA_MEMBER(this->format_buffer, 0, struct spa_pod); return SPA_RESULT_OK; } @@ -454,6 +465,9 @@ impl_node_port_enum_params(struct spa_node *node, { struct impl *this; struct type *t; + uint32_t offset; + struct spa_pod *param; + int res; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -464,6 +478,9 @@ impl_node_port_enum_params(struct spa_node *node, spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + offset = builder->offset; + + next: if (id == t->param.idList) { uint32_t list[] = { t->param.idEnumFormat, t->param.idFormat, @@ -471,22 +488,24 @@ impl_node_port_enum_params(struct spa_node *node, t->param.idMeta }; if (*index < SPA_N_ELEMENTS(list)) - spa_pod_builder_object(builder, id, t->param.List, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", list[*index]); else return SPA_RESULT_ENUM_END; } else if (id == t->param.idEnumFormat) { - return port_enum_formats(node, direction, port_id, index, filter, builder); + if ((res = port_enum_formats(node, direction, port_id, index, filter, builder, ¶m)) < 0) + return res; } else if (id == t->param.idFormat) { - return port_get_format(node, direction, port_id, index, filter, builder); + if ((res = port_get_format(node, direction, port_id, index, filter, builder, ¶m)) < 0) + return res; } else if (id == t->param.idBuffers) { if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_buffers.Buffers, ":", t->param_alloc_buffers.size, "i", 128, ":", t->param_alloc_buffers.stride, "i", 1, @@ -497,7 +516,7 @@ impl_node_port_enum_params(struct spa_node *node, else if (id == t->param.idMeta) { switch (*index) { case 0: - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_meta_enable.MetaEnable, ":", t->param_alloc_meta_enable.type, "I", t->meta.Header, ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header)); @@ -511,6 +530,10 @@ impl_node_port_enum_params(struct spa_node *node, (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } diff --git a/spa/plugins/test/fakesrc.c b/spa/plugins/test/fakesrc.c index 8fa752f5..47a03fe0 100644 --- a/spa/plugins/test/fakesrc.c +++ b/spa/plugins/test/fakesrc.c @@ -30,7 +30,8 @@ #include <spa/node.h> #include <spa/param-alloc.h> #include <spa/list.h> -#include <lib/props.h> + +#include <lib/pod.h> #define NAME "fakesrc" @@ -136,6 +137,8 @@ static int impl_node_enum_params(struct spa_node *node, { struct impl *this; struct type *t; + uint32_t offset; + struct spa_pod *param; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -144,21 +147,24 @@ static int impl_node_enum_params(struct spa_node *node, this = SPA_CONTAINER_OF(node, struct impl, node); t = &this->type; + offset = builder->offset; + + next: if (id == t->param.idList) { if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", t->param.idProps); } - if (id == t->param.idProps) { + else if (id == t->param.idProps) { struct props *p = &this->props; if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->props, ":", t->prop_live, "b", p->live, ":", t->prop_pattern, "Ie", p->pattern, @@ -169,6 +175,10 @@ static int impl_node_enum_params(struct spa_node *node, (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } @@ -436,7 +446,8 @@ static int port_enum_formats(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, const struct spa_pod_object *filter, - struct spa_pod_builder *builder) + struct spa_pod_builder *builder, + struct spa_pod **param) { return SPA_RESULT_ENUM_END; } @@ -445,7 +456,8 @@ static int port_get_format(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, const struct spa_pod_object *filter, - struct spa_pod_builder *builder) + struct spa_pod_builder *builder, + struct spa_pod **param) { struct impl *this = SPA_CONTAINER_OF(node, struct impl, node); @@ -454,7 +466,7 @@ static int port_get_format(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_primitive(builder, SPA_MEMBER(this->format_buffer, 0, struct spa_pod)); + *param = SPA_MEMBER(this->format_buffer, 0, struct spa_pod); return SPA_RESULT_OK; } @@ -468,6 +480,9 @@ impl_node_port_enum_params(struct spa_node *node, { struct impl *this; struct type *t; + uint32_t offset; + struct spa_pod *param; + int res; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -478,6 +493,9 @@ impl_node_port_enum_params(struct spa_node *node, spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + offset = builder->offset; + + next: if (id == t->param.idList) { uint32_t list[] = { t->param.idEnumFormat, t->param.idFormat, @@ -485,22 +503,24 @@ impl_node_port_enum_params(struct spa_node *node, t->param.idMeta }; if (*index < SPA_N_ELEMENTS(list)) - spa_pod_builder_object(builder, id, t->param.List, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", list[*index]); else return SPA_RESULT_ENUM_END; } else if (id == t->param.idEnumFormat) { - return port_enum_formats(node, direction, port_id, index, filter, builder); + if ((res = port_enum_formats(node, direction, port_id, index, filter, builder, ¶m)) < 0) + return res; } else if (id == t->param.idFormat) { - return port_get_format(node, direction, port_id, index, filter, builder); + if ((res = port_get_format(node, direction, port_id, index, filter, builder, ¶m)) < 0) + return res; } else if (id == t->param.idBuffers) { if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_buffers.Buffers, ":", t->param_alloc_buffers.size, "i", 128, ":", t->param_alloc_buffers.stride, "i", 1, @@ -511,7 +531,7 @@ impl_node_port_enum_params(struct spa_node *node, else if (id == t->param.idMeta) { switch (*index) { case 0: - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_meta_enable.MetaEnable, ":", t->param_alloc_meta_enable.type, "I", t->meta.Header, ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header)); @@ -525,6 +545,10 @@ impl_node_port_enum_params(struct spa_node *node, (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index 5a76fb60..3a331ed3 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -32,8 +32,9 @@ #include <spa/loop.h> #include <spa/param-alloc.h> #include <spa/type-map.h> + #include <lib/debug.h> -#include <lib/props.h> +#include <lib/pod.h> #define NAME "v4l2-source" @@ -173,6 +174,8 @@ static int impl_node_enum_params(struct spa_node *node, { struct impl *this; struct type *t; + struct spa_pod *param; + uint32_t offset; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -181,11 +184,14 @@ static int impl_node_enum_params(struct spa_node *node, this = SPA_CONTAINER_OF(node, struct impl, node); t = &this->type; + offset = builder->offset; + + next: if (id == t->param.idList) { if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", t->param.idProps); } @@ -195,16 +201,20 @@ static int impl_node_enum_params(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, t->param.idProps, t->props, - ":", t->prop_device, "S", p->device, sizeof(p->device), - ":", t->prop_device_name, "S-r", p->device_name, sizeof(p->device_name), - ":", t->prop_device_fd, "i-r", p->device_fd); + param = spa_pod_builder_object(builder, t->param.idProps, t->props, + ":", t->prop_device, "S", p->device, sizeof(p->device), + ":", t->prop_device_name, "S-r", p->device_name, sizeof(p->device_name), + ":", t->prop_device_fd, "i-r", p->device_fd); } else return SPA_RESULT_UNKNOWN_PARAM; (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } @@ -459,7 +469,8 @@ static int port_get_format(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, const struct spa_pod_object *filter, - struct spa_pod_builder *builder) + struct spa_pod_builder *builder, + struct spa_pod **param) { struct impl *this = SPA_CONTAINER_OF(node, struct impl, node); struct type *t = &this->type; @@ -493,7 +504,7 @@ static int port_get_format(struct spa_node *node, } else return SPA_RESULT_NO_FORMAT; - spa_pod_builder_pop(builder); + *param = spa_pod_builder_pop_deref(builder); return SPA_RESULT_OK; } @@ -509,6 +520,9 @@ static int impl_node_port_enum_params(struct spa_node *node, struct impl *this; struct port *port; struct type *t; + struct spa_pod *param; + uint32_t offset; + int res; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -521,6 +535,9 @@ static int impl_node_port_enum_params(struct spa_node *node, port = &this->out_ports[port_id]; + offset = builder->offset; + + next: if (id == t->param.idList) { uint32_t list[] = { t->param.idEnumFormat, t->param.idFormat, @@ -528,7 +545,7 @@ static int impl_node_port_enum_params(struct spa_node *node, t->param.idMeta }; if (*index < SPA_N_ELEMENTS(list)) - spa_pod_builder_object(builder, id, t->param.List, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", list[*index]); else return SPA_RESULT_ENUM_END; @@ -537,7 +554,8 @@ static int impl_node_port_enum_params(struct spa_node *node, return spa_v4l2_enum_format(this, index, filter, builder); } else if (id == t->param.idFormat) { - return port_get_format(node, direction, port_id, index, filter, builder); + if((res = port_get_format(node, direction, port_id, index, filter, builder, ¶m)) < 0) + return res; } else if (id == t->param.idBuffers) { if (!port->have_format) @@ -545,7 +563,7 @@ static int impl_node_port_enum_params(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_buffers.Buffers, ":", t->param_alloc_buffers.size, "i", port->fmt.fmt.pix.sizeimage, ":", t->param_alloc_buffers.stride, "i", port->fmt.fmt.pix.bytesperline, @@ -556,7 +574,7 @@ static int impl_node_port_enum_params(struct spa_node *node, else if (id == t->param.idMeta) { switch (*index) { case 0: - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_meta_enable.MetaEnable, ":", t->param_alloc_meta_enable.type, "I", t->meta.Header, ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header)); @@ -570,6 +588,10 @@ static int impl_node_port_enum_params(struct spa_node *node, (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } diff --git a/spa/plugins/videotestsrc/videotestsrc.c b/spa/plugins/videotestsrc/videotestsrc.c index c8d88952..9089a4e5 100644 --- a/spa/plugins/videotestsrc/videotestsrc.c +++ b/spa/plugins/videotestsrc/videotestsrc.c @@ -33,8 +33,7 @@ #include <spa/list.h> #include <spa/video/format-utils.h> -#include <lib/format.h> -#include <lib/props.h> +#include <lib/pod.h> #define NAME "videotestsrc" @@ -157,6 +156,8 @@ static int impl_node_enum_params(struct spa_node *node, { struct impl *this; struct type *t; + uint32_t offset; + struct spa_pod *param; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(builder != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -164,11 +165,14 @@ static int impl_node_enum_params(struct spa_node *node, this = SPA_CONTAINER_OF(node, struct impl, node); t = &this->type; + offset = builder->offset; + + next: if (id == t->param.idList) { if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", t->param.idProps); } @@ -178,7 +182,7 @@ static int impl_node_enum_params(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->props, ":", t->prop_live, "b", p->live, ":", t->prop_pattern, "Ie", p->pattern, @@ -190,6 +194,10 @@ static int impl_node_enum_params(struct spa_node *node, (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } @@ -451,21 +459,15 @@ static int port_enum_formats(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, const struct spa_pod_object *filter, - struct spa_pod_builder *builder) + struct spa_pod_builder *builder, + struct spa_pod **param) { struct impl *this = SPA_CONTAINER_OF(node, struct impl, node); - struct spa_pod_object *fmt; - uint8_t buffer[256]; - struct spa_pod_builder b = { NULL, }; struct type *t = &this->type; - int res; - - next: - spa_pod_builder_init(&b, buffer, sizeof(buffer)); switch (*index) { case 0: - fmt = spa_pod_builder_object(&b, + *param = spa_pod_builder_object(builder, t->param.idEnumFormat, t->format, "I", t->media_type.video, "I", t->media_subtype.raw, @@ -482,11 +484,6 @@ static int port_enum_formats(struct spa_node *node, default: return SPA_RESULT_ENUM_END; } - (*index)++; - - if ((res = spa_pod_object_filter(fmt, filter, builder)) != SPA_RESULT_OK) - goto next; - return SPA_RESULT_OK; } @@ -494,18 +491,18 @@ static int port_get_format(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, const struct spa_pod_object *filter, - struct spa_pod_builder *builder) + struct spa_pod_builder *builder, + struct spa_pod **param) { struct impl *this = SPA_CONTAINER_OF(node, struct impl, node); struct type *t = &this->type; if (!this->have_format) return SPA_RESULT_NO_FORMAT; - if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + *param = spa_pod_builder_object(builder, t->param.idFormat, t->format, "I", t->media_type.video, "I", t->media_subtype.raw, @@ -525,6 +522,9 @@ impl_node_port_enum_params(struct spa_node *node, { struct impl *this; struct type *t; + uint32_t offset; + struct spa_pod *param; + int res; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -535,6 +535,9 @@ impl_node_port_enum_params(struct spa_node *node, spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); + offset = builder->offset; + + next: if (id == t->param.idList) { uint32_t list[] = { t->param.idEnumFormat, t->param.idFormat, @@ -542,16 +545,18 @@ impl_node_port_enum_params(struct spa_node *node, t->param.idMeta }; if (*index < SPA_N_ELEMENTS(list)) - spa_pod_builder_object(builder, id, t->param.List, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", list[*index]); else return SPA_RESULT_ENUM_END; } else if (id == t->param.idEnumFormat) { - return port_enum_formats(node, direction, port_id, index, filter, builder); + if ((res = port_enum_formats(node, direction, port_id, index, filter, builder, ¶m)) < 0) + return res; } else if (id == t->param.idFormat) { - return port_get_format(node, direction, port_id, index, filter, builder); + if ((res = port_get_format(node, direction, port_id, index, filter, builder, ¶m)) < 0) + return res; } else if (id == t->param.idBuffers) { struct spa_video_info_raw *raw_info = &this->current_format.info.raw; @@ -561,7 +566,7 @@ impl_node_port_enum_params(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_buffers.Buffers, ":", t->param_alloc_buffers.size, "i", this->stride * raw_info->size.height, ":", t->param_alloc_buffers.stride, "i", this->stride, @@ -575,7 +580,7 @@ impl_node_port_enum_params(struct spa_node *node, switch (*index) { case 0: - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_meta_enable.MetaEnable, ":", t->param_alloc_meta_enable.type, "I", t->meta.Header, ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header)); @@ -585,8 +590,15 @@ impl_node_port_enum_params(struct spa_node *node, return SPA_RESULT_ENUM_END; } } + else + return SPA_RESULT_UNKNOWN_PARAM; + (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } diff --git a/spa/plugins/volume/volume.c b/spa/plugins/volume/volume.c index 17d8aafc..0eae0b30 100644 --- a/spa/plugins/volume/volume.c +++ b/spa/plugins/volume/volume.c @@ -26,8 +26,8 @@ #include <spa/list.h> #include <spa/audio/format-utils.h> #include <spa/param-alloc.h> -#include <lib/props.h> -#include <lib/format.h> + +#include <lib/pod.h> #define NAME "volume" @@ -143,6 +143,8 @@ static int impl_node_enum_params(struct spa_node *node, { struct impl *this; struct type *t; + uint32_t offset; + struct spa_pod *param; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -151,11 +153,14 @@ static int impl_node_enum_params(struct spa_node *node, this = SPA_CONTAINER_OF(node, struct impl, node); t = &this->type; + offset = builder->offset; + + next: if (id == t->param.idList) { if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", t->param.idProps); } @@ -165,7 +170,7 @@ static int impl_node_enum_params(struct spa_node *node, if(*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->props, ":", t->prop_volume, "dr", p->volume, 2, 0.0, 10.0, ":", t->prop_mute, "b", p->mute); @@ -175,6 +180,10 @@ static int impl_node_enum_params(struct spa_node *node, (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } @@ -318,21 +327,15 @@ static int port_enum_formats(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, const struct spa_pod_object *filter, - struct spa_pod_builder *builder) + struct spa_pod_builder *builder, + struct spa_pod **param) { struct impl *this = SPA_CONTAINER_OF(node, struct impl, node); - int res; - struct spa_pod_object *fmt; - uint8_t buffer[1024]; - struct spa_pod_builder b = { NULL, }; struct type *t = &this->type; - next: - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - switch (*index) { case 0: - fmt = spa_pod_builder_object(&b, + *param = spa_pod_builder_object(builder, t->param.idEnumFormat, t->format, "I", t->media_type.audio, "I", t->media_subtype.raw, @@ -345,11 +348,6 @@ static int port_enum_formats(struct spa_node *node, default: return SPA_RESULT_ENUM_END; } - (*index)++; - - if ((res = spa_pod_object_filter(fmt, filter, builder)) != SPA_RESULT_OK) - goto next; - return SPA_RESULT_OK; } @@ -357,7 +355,8 @@ static int port_get_format(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, const struct spa_pod_object *filter, - struct spa_pod_builder *builder) + struct spa_pod_builder *builder, + struct spa_pod **param) { struct impl *this = SPA_CONTAINER_OF(node, struct impl, node); struct port *port; @@ -370,7 +369,7 @@ static int port_get_format(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + *param = spa_pod_builder_object(builder, t->param.idFormat, t->format, "I", t->media_type.audio, "I", t->media_subtype.raw, @@ -391,6 +390,9 @@ impl_node_port_enum_params(struct spa_node *node, struct impl *this; struct type *t; struct port *port; + uint32_t offset; + struct spa_pod *param; + int res; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -403,6 +405,9 @@ impl_node_port_enum_params(struct spa_node *node, port = GET_PORT(this, direction, port_id); + offset = builder->offset; + + next: if (id == t->param.idList) { uint32_t list[] = { t->param.idEnumFormat, t->param.idFormat, @@ -410,16 +415,18 @@ impl_node_port_enum_params(struct spa_node *node, t->param.idMeta }; if (*index < SPA_N_ELEMENTS(list)) - spa_pod_builder_object(builder, id, t->param.List, + param = spa_pod_builder_object(builder, id, t->param.List, ":", t->param.listId, "I", list[*index]); else return SPA_RESULT_ENUM_END; } else if (id == t->param.idEnumFormat) { - return port_enum_formats(node, direction, port_id, index, filter, builder); + if ((res = port_enum_formats(node, direction, port_id, index, filter, builder, ¶m)) < 0) + return res; } else if (id == t->param.idFormat) { - return port_get_format(node, direction, port_id, index, filter, builder); + if ((res = port_get_format(node, direction, port_id, index, filter, builder, ¶m)) < 0) + return res; } else if (id == t->param.idBuffers) { if (!port->have_format) @@ -427,7 +434,7 @@ impl_node_port_enum_params(struct spa_node *node, if (*index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_buffers.Buffers, ":", t->param_alloc_buffers.size, "iru", 1024 * this->bpf, 2, 16 * this->bpf, @@ -440,7 +447,7 @@ impl_node_port_enum_params(struct spa_node *node, else if (id == t->param.idMeta) { switch (*index) { case 0: - spa_pod_builder_object(builder, + param = spa_pod_builder_object(builder, id, t->param_alloc_meta_enable.MetaEnable, ":", t->param_alloc_meta_enable.type, "I", t->meta.Header, ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header)); @@ -454,6 +461,10 @@ impl_node_port_enum_params(struct spa_node *node, (*index)++; + spa_pod_builder_reset(builder, offset); + if (spa_pod_filter(builder, param, (struct spa_pod*)filter) < 0) + goto next; + return SPA_RESULT_OK; } diff --git a/spa/tests/test-ringbuffer.c b/spa/tests/test-ringbuffer.c index 38b9e00b..f3322c69 100644 --- a/spa/tests/test-ringbuffer.c +++ b/spa/tests/test-ringbuffer.c @@ -34,7 +34,6 @@ #include <spa/format-utils.h> #include <lib/debug.h> -#include <lib/props.h> static SPA_TYPE_MAP_IMPL(default_map, 4096); static SPA_LOG_IMPL(default_log); diff --git a/spa/tests/test-v4l2.c b/spa/tests/test-v4l2.c index 032b1fc7..5e495269 100644 --- a/spa/tests/test-v4l2.c +++ b/spa/tests/test-v4l2.c @@ -33,8 +33,8 @@ #include <spa/node.h> #include <spa/loop.h> #include <spa/video/format-utils.h> + #include <lib/debug.h> -#include <lib/props.h> static SPA_TYPE_MAP_IMPL(default_map, 4096); static SPA_LOG_IMPL(default_log); diff --git a/src/examples/video-play.c b/src/examples/video-play.c index 478e2382..e8f2c89b 100644 --- a/src/examples/video-play.c +++ b/src/examples/video-play.c @@ -82,7 +82,6 @@ struct data { struct spa_video_info_raw format; int32_t stride; - uint8_t params_buffer[1024]; int counter; }; @@ -240,7 +239,8 @@ on_stream_format_changed(void *_data, struct spa_pod_object *format) struct data *data = _data; struct pw_stream *stream = data->stream; struct pw_type *t = data->t; - struct spa_pod_builder b = { NULL }; + uint8_t params_buffer[1024]; + struct spa_pod_builder b = SPA_POD_BUILDER_INIT(params_buffer, sizeof(params_buffer)); struct spa_pod_object *params[2]; Uint32 sdl_format; void *d; @@ -266,7 +266,6 @@ on_stream_format_changed(void *_data, struct spa_pod_object *format) SDL_LockTexture(data->texture, NULL, &d, &data->stride); SDL_UnlockTexture(data->texture); - spa_pod_builder_init(&b, data->params_buffer, sizeof(data->params_buffer)); params[0] = spa_pod_builder_object(&b, t->param.idBuffers, t->param_alloc_buffers.Buffers, ":", t->param_alloc_buffers.size, "i", data->stride * data->format.size.height, diff --git a/src/examples/video-src.c b/src/examples/video-src.c index 7d13e861..101f814c 100644 --- a/src/examples/video-src.c +++ b/src/examples/video-src.c @@ -75,7 +75,6 @@ struct data { struct spa_video_info_raw format; int32_t stride; - uint8_t params_buffer[1024]; int counter; uint32_t seq; }; @@ -172,7 +171,8 @@ on_stream_format_changed(void *_data, struct spa_pod_object *format) struct data *data = _data; struct pw_stream *stream = data->stream; struct pw_type *t = data->t; - struct spa_pod_builder b = { NULL }; + uint8_t params_buffer[1024]; + struct spa_pod_builder b = SPA_POD_BUILDER_INIT(params_buffer, sizeof(params_buffer)); struct spa_pod_object *params[2]; if (format == NULL) { @@ -183,7 +183,6 @@ on_stream_format_changed(void *_data, struct spa_pod_object *format) data->stride = SPA_ROUND_UP_N(data->format.size.width * BPP, 4); - spa_pod_builder_init(&b, data->params_buffer, sizeof(data->params_buffer)); params[0] = spa_pod_builder_object(&b, t->param.idBuffers, t->param_alloc_buffers.Buffers, ":", t->param_alloc_buffers.size, "i", data->stride * data->format.size.height, diff --git a/src/gst/gstpipewireformat.c b/src/gst/gstpipewireformat.c index 54a8329a..65192e56 100644 --- a/src/gst/gstpipewireformat.c +++ b/src/gst/gstpipewireformat.c @@ -529,10 +529,9 @@ handle_audio_fields (ConvertData *d) } static uint32_t -write_pod (struct spa_pod_builder *b, uint32_t ref, const void *data, uint32_t size) +write_pod (struct spa_pod_builder *b, const void *data, uint32_t size) { - if (ref == -1) - ref = b->offset; + uint32_t ref = b->offset; if (b->size <= b->offset) { b->size = SPA_ROUND_UP_N (b->offset + size, 512); diff --git a/src/modules/module-client-node/client-node.c b/src/modules/module-client-node/client-node.c index 0f0f82c6..3f1d8099 100644 --- a/src/modules/module-client-node/client-node.c +++ b/src/modules/module-client-node/client-node.c @@ -29,7 +29,7 @@ #include <sys/eventfd.h> #include "spa/node.h" -#include "spa/lib/format.h" +#include "spa/lib/pod.h" #include "pipewire/pipewire.h" #include "pipewire/interfaces.h" @@ -57,6 +57,10 @@ #define CHECK_OUT_PORT(this,d,p) (CHECK_OUT_PORT_ID(this,d,p) && (this)->out_ports[p].valid) #define CHECK_PORT(this,d,p) (CHECK_IN_PORT (this,d,p) || CHECK_OUT_PORT (this,d,p)) +#define GET_IN_PORT(this,p) (&this->in_ports[p]) +#define GET_OUT_PORT(this,p) (&this->out_ports[p]) +#define GET_PORT(this,d,p) (d == SPA_DIRECTION_INPUT ? GET_IN_PORT(this,p) : GET_OUT_PORT(this,p)) + #define CHECK_PORT_BUFFER(this,b,p) (b < p->n_buffers) struct proxy_buffer { @@ -152,6 +156,7 @@ static int spa_proxy_node_enum_params(struct spa_node *node, struct spa_pod_builder *builder) { struct proxy *this; + uint32_t offset; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -159,6 +164,8 @@ static int spa_proxy_node_enum_params(struct spa_node *node, this = SPA_CONTAINER_OF(node, struct proxy, node); + offset = builder->offset; + while (true) { struct spa_pod_object *param; @@ -167,10 +174,13 @@ static int spa_proxy_node_enum_params(struct spa_node *node, param = this->params[(*index)++]; - if (param->body.id == id) { - spa_pod_builder_primitive(builder, ¶m->pod); + if (param->body.id != id) + continue; + + if (spa_pod_filter(builder, ¶m->pod, &filter->pod) == SPA_RESULT_OK) break; - } + + spa_pod_builder_reset(builder, offset); } return SPA_RESULT_OK; } @@ -312,11 +322,7 @@ do_update_port(struct proxy *this, struct proxy_port *port; struct pw_type *t = this->impl->t; - if (direction == SPA_DIRECTION_INPUT) { - port = &this->in_ports[port_id]; - } else { - port = &this->out_ports[port_id]; - } + port = GET_PORT(this, direction, port_id); if (change_mask & PW_CLIENT_NODE_PORT_UPDATE_PARAMS) { int i; @@ -369,11 +375,12 @@ static void do_uninit_port(struct proxy *this, enum spa_direction direction, uin struct proxy_port *port; spa_log_info(this->log, "proxy %p: removing port %d", this, port_id); + if (direction == SPA_DIRECTION_INPUT) { - port = &this->in_ports[port_id]; + port = GET_IN_PORT(this, port_id); this->n_inputs--; } else { - port = &this->out_ports[port_id]; + port = GET_OUT_PORT(this, port_id); this->n_outputs--; } clear_port(this, port, direction, port_id); @@ -394,8 +401,7 @@ spa_proxy_node_add_port(struct spa_node *node, enum spa_direction direction, uin if (!CHECK_FREE_PORT(this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - port = - direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + port = GET_PORT(this, direction, port_id); clear_port(this, port, direction, port_id); return SPA_RESULT_OK; @@ -435,9 +441,7 @@ spa_proxy_node_port_get_info(struct spa_node *node, if (!CHECK_PORT(this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - port = - direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; - + port = GET_PORT(this, direction, port_id); *info = &port->info; return SPA_RESULT_OK; @@ -452,6 +456,7 @@ spa_proxy_node_port_enum_params(struct spa_node *node, { struct proxy *this; struct proxy_port *port; + uint32_t offset; spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS); spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS); @@ -461,9 +466,9 @@ spa_proxy_node_port_enum_params(struct spa_node *node, spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT); - port = - direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + port = GET_PORT(this, direction, port_id); + offset = builder->offset; while (true) { struct spa_pod_object *param; @@ -472,10 +477,13 @@ spa_proxy_node_port_enum_params(struct spa_node *node, param = port->params[(*index)++]; - if (param->body.id == id) { - spa_pod_builder_primitive(builder, ¶m->pod); + if (param->body.id != id) + continue; + + if (spa_pod_filter(builder, ¶m->pod, &filter->pod) == SPA_RESULT_OK) break; - } + + spa_pod_builder_reset(builder, offset); } return SPA_RESULT_OK; } @@ -523,8 +531,7 @@ spa_proxy_node_port_set_io(struct spa_node *node, if (!CHECK_PORT(this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - port = - direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + port = GET_PORT(this, direction, port_id); port->io = io; return SPA_RESULT_OK; @@ -555,8 +562,7 @@ spa_proxy_node_port_use_buffers(struct spa_node *node, if (!CHECK_PORT(this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - port = - direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + port = GET_PORT(this, direction, port_id); if (!port->have_format) return SPA_RESULT_NO_FORMAT; @@ -661,8 +667,7 @@ spa_proxy_node_port_alloc_buffers(struct spa_node *node, if (!CHECK_PORT(this, direction, port_id)) return SPA_RESULT_INVALID_PORT; - port = - direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id]; + port = GET_PORT(this, direction, port_id); if (!port->have_format) return SPA_RESULT_NO_FORMAT; diff --git a/src/modules/module-jack/jack-node.c b/src/modules/module-jack/jack-node.c index 24c50e81..0bd9e46b 100644 --- a/src/modules/module-jack/jack-node.c +++ b/src/modules/module-jack/jack-node.c @@ -30,9 +30,10 @@ #include <spa/node.h> #include <spa/hook.h> -#include <spa/lib/format.h> #include <spa/audio/format-utils.h> +#include <spa/lib/pod.h> + #include "pipewire/pipewire.h" #include "pipewire/core.h" #include "pipewire/private.h" @@ -374,29 +375,41 @@ static int port_set_io(struct spa_node *node, enum spa_direction direction, uint return SPA_RESULT_OK; } +static int port_get_info(struct spa_node *node, enum spa_direction direction, uint32_t port_id, + const struct spa_port_info **info) +{ + struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); + struct port_data *pd = nd->port_data[direction][port_id]; + struct pw_jack_port *port = &pd->port; + + pd->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | SPA_PORT_INFO_FLAG_LIVE; + if (port->direction == PW_DIRECTION_OUTPUT && port->jack_port != NULL) + pd->info.flags |= SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS; + + pd->info.rate = pd->node->node.server->engine_control->sample_rate; + *info = &pd->info; + + return SPA_RESULT_OK; +} + static int port_enum_formats(struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t *index, const struct spa_pod_object *filter, - struct spa_pod_builder *builder) + struct spa_pod_builder *builder, + struct spa_pod **param) { struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); struct port_data *pd = nd->port_data[direction][port_id]; struct type *t = &pd->node->type; - struct spa_pod_builder b = { NULL, }; - struct spa_pod_object *fmt; - uint8_t buffer[4096]; - int res; struct jack_engine_control *ctrl = pd->node->node.server->engine_control; if (index > 0) return SPA_RESULT_ENUM_END; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - if (pd->port.jack_port) { if (pd->port.jack_port->type_id == 0) { - fmt = spa_pod_builder_object(&b, + *param = spa_pod_builder_object(builder, t->param.idEnumFormat, t->format, "I", t->media_type.audio, "I", t->media_subtype.raw, @@ -405,7 +418,7 @@ static int port_enum_formats(struct spa_node *node, ":", t->format_audio.channels, "i", 1); } else if (pd->port.jack_port->type_id == 1) { - fmt = spa_pod_builder_object(&b, + *param = spa_pod_builder_object(builder, t->param.idEnumFormat, t->format, "I", t->media_type.audio, "I", t->media_subtype_audio.midi); @@ -414,7 +427,7 @@ static int port_enum_formats(struct spa_node *node, return SPA_RESULT_ENUM_END; } else { - fmt = spa_pod_builder_object(&b, + *param = spa_pod_builder_object(builder, t->param.idEnumFormat, t->format, "I", t->media_type.audio, "I", t->media_subtype.raw, @@ -422,27 +435,6 @@ static int port_enum_formats(struct spa_node *node, ":", t->format_audio.rate, "i", ctrl->sample_rate, ":", t->format_audio.channels, "i", 2); } - - if ((res = spa_pod_object_filter(fmt, filter, builder)) < 0) - return res; - - return SPA_RESULT_OK; -} - -static int port_get_info(struct spa_node *node, enum spa_direction direction, uint32_t port_id, - const struct spa_port_info **info) -{ - struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); - struct port_data *pd = nd->port_data[direction][port_id]; - struct pw_jack_port *port = &pd->port; - - pd->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | SPA_PORT_INFO_FLAG_LIVE; - if (port->direction == PW_DIRECTION_OUTPUT && port->jack_port != NULL) - pd->info.flags |= SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS; - - pd->info.rate = pd->node->node.server->engine_control->sample_rate; - *info = &pd->info; - return SPA_RESULT_OK; } @@ -454,16 +446,30 @@ static int port_enum_params(struct spa_node *node, { struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); struct type *t = &nd->type; + struct spa_pod *param; + uint32_t offset; + int res; + + offset = builder->offset; + next: if (id == t->param.idEnumFormat) { - return port_enum_formats(node, direction, port_id, index, filter, builder); + if ((res = port_enum_formats(node, direction, port_id, index, filter, builder, ¶m)) < 0) + return res; } else if (id == t->param.idFormat) { - return port_enum_formats(node, direction, port_id, index, filter, builder); + if ((res = port_enum_formats(node, direction, port_id, index, filter, builder, ¶m)) < 0) + return res; } else return SPA_RESULT_UNKNOWN_PARAM; + (*index)++; + + spa_pod_builder_reset(builder, offset); + if ((res = spa_pod_filter(builder, param, (struct spa_pod*)filter)) < 0) + goto next; + return SPA_RESULT_ENUM_END; } diff --git a/src/modules/module-protocol-native/connection.c b/src/modules/module-protocol-native/connection.c index 73b8b4bd..93dc3977 100644 --- a/src/modules/module-protocol-native/connection.c +++ b/src/modules/module-protocol-native/connection.c @@ -338,12 +338,12 @@ 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, uint32_t ref, const void *data, uint32_t size) +static uint32_t write_pod(struct spa_pod_builder *b, const void *data, uint32_t size) { struct impl *impl = SPA_CONTAINER_OF(b, struct impl, builder); + uint32_t ref = b->offset; - if (ref == -1) - ref = b->offset; + ref = b->offset; if (b->size <= b->offset) { b->size = SPA_ROUND_UP_N(b->offset + size, 4096); diff --git a/src/modules/spa/module-monitor.c b/src/modules/spa/module-monitor.c index 720fd2dd..58573947 100644 --- a/src/modules/spa/module-monitor.c +++ b/src/modules/spa/module-monitor.c @@ -25,8 +25,6 @@ #include <getopt.h> #include <limits.h> -#include <spa/lib/props.h> - #include <pipewire/utils.h> #include <pipewire/log.h> #include <pipewire/core.h> diff --git a/src/modules/spa/module-node.c b/src/modules/spa/module-node.c index 8583134c..2d9bd931 100644 --- a/src/modules/spa/module-node.c +++ b/src/modules/spa/module-node.c @@ -25,8 +25,6 @@ #include <getopt.h> #include <limits.h> -#include <spa/lib/props.h> - #include <pipewire/core.h> #include <pipewire/log.h> #include <pipewire/module.h> diff --git a/src/pipewire/core.c b/src/pipewire/core.c index b0efd931..6f534890 100644 --- a/src/pipewire/core.c +++ b/src/pipewire/core.c @@ -787,7 +787,7 @@ int pw_core_find_format(struct pw_core *core, asprintf(error, "error output enum formats: %d", res); goto error; } - format = spa_pod_builder_deref(&fb, 0); + format = spa_pod_builder_deref(builder, 0); pw_log_debug("Got filtered:"); if (pw_log_level_enabled(SPA_LOG_LEVEL_DEBUG)) diff --git a/src/pipewire/link.c b/src/pipewire/link.c index e7bc3a80..b754b2db 100644 --- a/src/pipewire/link.c +++ b/src/pipewire/link.c @@ -24,8 +24,7 @@ #include <spa/video/format.h> #include <spa/pod-utils.h> -#include <spa/lib/format.h> -#include <spa/lib/props.h> +#include <spa/lib/pod.h> #include "pipewire.h" #include "private.h" @@ -148,7 +147,7 @@ static int do_negotiate(struct pw_link *this, uint32_t in_state, uint32_t out_st goto error; } current = spa_pod_builder_deref(&b, 0); - if (spa_pod_object_compare(current, format) < 0) { + if (spa_pod_compare((struct spa_pod*)current, (struct spa_pod*)format) != 0) { pw_log_debug("link %p: output format change, renegotiate", this); pw_node_set_state(output->node, PW_NODE_STATE_SUSPENDED); out_state = PW_PORT_STATE_CONFIGURE; @@ -167,7 +166,7 @@ static int do_negotiate(struct pw_link *this, uint32_t in_state, uint32_t out_st goto error; } current = spa_pod_builder_deref(&b, 0); - if (spa_pod_object_compare(current, format) < 0) { + if (spa_pod_compare((struct spa_pod*)current, (struct spa_pod*)format) != 0) { pw_log_debug("link %p: input format change, renegotiate", this); pw_node_set_state(input->node, PW_NODE_STATE_SUSPENDED); in_state = PW_PORT_STATE_CONFIGURE; @@ -399,7 +398,6 @@ param_filter(struct pw_link *this, uint32_t id, struct spa_pod_builder *result) { - int res; uint8_t ibuf[2048], obuf[2048]; struct spa_pod_builder ib = { 0 }, ob = { 0 }; struct spa_pod_object *oparam, *iparam; @@ -407,44 +405,37 @@ param_filter(struct pw_link *this, for (iidx = 0;;) { spa_pod_builder_init(&ib, ibuf, sizeof(ibuf)); + pw_log_debug("iparam %d", iidx); if (spa_node_port_enum_params(in_port->node->node, in_port->direction, in_port->port_id, id, &iidx, NULL, &ib) < 0) break; iparam = spa_pod_builder_deref(&ib, 0); + pw_log_debug("iparam %d", iidx); + if (pw_log_level_enabled(SPA_LOG_LEVEL_DEBUG)) + spa_debug_pod(&iparam->pod, 0); + for (oidx = 0;;) { uint32_t offset; spa_pod_builder_init(&ob, obuf, sizeof(obuf)); + + offset = result->offset; + + pw_log_debug("oparam %d %d", oidx, offset); if (spa_node_port_enum_params(out_port->node->node, out_port->direction, out_port->port_id, id, &oidx, - NULL, &ob) < 0) + iparam, result) < 0) { break; - oparam = spa_pod_builder_deref(&ob, 0); + } + oparam = spa_pod_builder_deref(result, offset); - if (iidx == 1 && pw_log_level_enabled(SPA_LOG_LEVEL_DEBUG)) + pw_log_debug("oparam %d", oidx); + if (pw_log_level_enabled(SPA_LOG_LEVEL_DEBUG)) spa_debug_pod(&oparam->pod, 0); - if (iparam->body.type != oparam->body.type) - continue; - - offset = result->offset; - spa_pod_builder_push_object(result, id, iparam->body.type); - if ((res = spa_props_filter(result, - SPA_POD_CONTENTS(struct spa_pod_object, iparam), - SPA_POD_CONTENTS_SIZE(struct spa_pod_object, iparam), - SPA_POD_CONTENTS(struct spa_pod_object, oparam), - SPA_POD_CONTENTS_SIZE(struct spa_pod_object, oparam))) < 0) { - result->offset = offset; - result->depth = 0; - continue; - } - spa_pod_builder_pop(result); num++; } - if (pw_log_level_enabled(SPA_LOG_LEVEL_DEBUG)) - spa_debug_pod(&iparam->pod, 0); - } return num; } |