From 387fcfdc8ab435d9669db10b9fb8f737252ba540 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 9 Mar 2020 12:47:33 +0100 Subject: [PATCH] pod: add support for flags filter Add macro to make flags choice from int and long. Implement the filter for flags by or-ing the flags. --- spa/include/spa/pod/filter.h | 47 ++++++++++++++++++++++++++++-------- spa/include/spa/pod/vararg.h | 3 +++ 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/spa/include/spa/pod/filter.h b/spa/include/spa/pod/filter.h index 6680037c0..92d49229e 100644 --- a/spa/include/spa/pod/filter.h +++ b/spa/include/spa/pod/filter.h @@ -60,6 +60,7 @@ static inline int spa_pod_choice_fix_default(struct spa_pod_choice *choice) memcpy(val, alt, size); } break; + case SPA_CHOICE_Flags: case SPA_CHOICE_Enum: { void *best = NULL; @@ -80,12 +81,37 @@ static inline int spa_pod_choice_fix_default(struct spa_pod_choice *choice) choice->body.type = SPA_CHOICE_None; break; } - case SPA_CHOICE_Flags: - break; } return 0; } +static inline int spa_pod_filter_flags_value(struct spa_pod_builder *b, + uint32_t type, const void *r1, const void *r2, uint32_t size) +{ + switch (type) { + case SPA_TYPE_Int: + { + int32_t val = (*(int32_t *) r1) & (*(int32_t *) r2); + if (val == 0) + return 0; + spa_pod_builder_int(b, val); + break; + } + case SPA_TYPE_Long: + { + int64_t val = (*(int64_t *) r1) & (*(int64_t *) r2); + if (val == 0) + return 0; + spa_pod_builder_long(b, val); + break; + } + default: + return -ENOTSUP; + } + return 1; +} + + static inline int spa_pod_filter_prop(struct spa_pod_builder *b, const struct spa_pod_prop *p1, @@ -110,14 +136,14 @@ spa_pod_filter_prop(struct spa_pod_builder *b, if (type != v2->type || size != v2->size || p1->key != p2->key) return -EINVAL; - if (p1c == SPA_CHOICE_None) { + if (p1c == SPA_CHOICE_None || p1c == SPA_CHOICE_Flags) { nalt1 = 1; } else { alt1 = SPA_MEMBER(alt1, size, void); nalt1--; } - if (p2c == SPA_CHOICE_None) { + if (p2c == SPA_CHOICE_None || p2c == SPA_CHOICE_Flags) { nalt2 = 1; } else { alt2 = SPA_MEMBER(alt2, size, void); @@ -211,8 +237,13 @@ spa_pod_filter_prop(struct spa_pod_builder *b, nc->body.type = SPA_CHOICE_Range; } - if (p1c == SPA_CHOICE_None && p2c == SPA_CHOICE_Flags) - return -ENOTSUP; + if ((p1c == SPA_CHOICE_None && p2c == SPA_CHOICE_Flags) || + (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_None) || + (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_Flags)) { + if (spa_pod_filter_flags_value(b, type, alt1, alt2, size) != 1) + return -EINVAL; + nc->body.type = SPA_CHOICE_Flags; + } if (p1c == SPA_CHOICE_Range && p2c == SPA_CHOICE_Flags) return -ENOTSUP; @@ -227,16 +258,12 @@ spa_pod_filter_prop(struct spa_pod_builder *b, if (p1c == SPA_CHOICE_Step && p2c == SPA_CHOICE_Flags) return -ENOTSUP; - if (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_None) - return -ENOTSUP; if (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_Range) return -ENOTSUP; if (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_Step) return -ENOTSUP; if (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_Enum) return -ENOTSUP; - if (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_Flags) - return -ENOTSUP; spa_pod_builder_pop(b, &f); spa_pod_choice_fix_default(nc); diff --git a/spa/include/spa/pod/vararg.h b/spa/include/spa/pod/vararg.h index 97473445c..b6dcdc7b7 100644 --- a/spa/include/spa/pod/vararg.h +++ b/spa/include/spa/pod/vararg.h @@ -42,6 +42,7 @@ extern "C" { #define SPA_CHOICE_RANGE(def,min,max) 3,(def),(min),(max) #define SPA_CHOICE_STEP(def,min,max,step) 4,(def),(min),(max),(step) #define SPA_CHOICE_ENUM(n_vals,...) (n_vals),##__VA_ARGS__ +#define SPA_CHOICE_FLAGS(flags) 1, (flags) #define SPA_CHOICE_BOOL(def) 3,(def),(def),!(def) #define SPA_POD_Bool(val) "b", val @@ -54,11 +55,13 @@ extern "C" { #define SPA_POD_CHOICE_ENUM_Int(n_vals,...) "?ei", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) #define SPA_POD_CHOICE_RANGE_Int(def,min,max) "?ri", SPA_CHOICE_RANGE(def, min, max) #define SPA_POD_CHOICE_STEP_Int(def,min,max,step) "?si", SPA_CHOICE_STEP(def, min, max, step) +#define SPA_POD_CHOICE_FLAGS_Int(flags) "?fi", SPA_CHOICE_FLAGS(flags) #define SPA_POD_Long(val) "l", val #define SPA_POD_CHOICE_ENUM_Long(n_vals,...) "?el", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) #define SPA_POD_CHOICE_RANGE_Long(def,min,max) "?rl", SPA_CHOICE_RANGE(def, min, max) #define SPA_POD_CHOICE_STEP_Long(def,min,max,step) "?sl", SPA_CHOICE_STEP(def, min, max, step) +#define SPA_POD_CHOICE_FLAGS_Long(flags) "?fl", SPA_CHOICE_FLAGS(flags) #define SPA_POD_Float(val) "f", val #define SPA_POD_CHOICE_ENUM_Float(n_vals,...) "?ef", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__)