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.
This commit is contained in:
Wim Taymans 2020-03-09 12:47:33 +01:00
parent 6c911993fb
commit 387fcfdc8a
2 changed files with 40 additions and 10 deletions

View file

@ -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);

View file

@ -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__)