builder: add support for FEATURE choice

This is the same as the Flags choice but the property (if any) has the
DROP flag set.

This means that when filtering, the property is dropped when one side
is missing the property. Otherwise, the flags are AND-ed together with a
negotiation failure when the result if 0.

This can be used to make sure both sides present compatible feature bits.
The result of the filter is then:

  1. no property (one side didn't present bits). This is likely because
     the other side is old and doesn't know about the feature bits yet.
     Code can take a backwards compatibility codepath.
  2. a negotiation failure, both sides presented bits but the AND is 0,
     they don't have compatible features.
  3. a property with bits (features) that are compatible.

This is different from normal flags in that the flags are not dropped
when the other size is missing the property.
This commit is contained in:
Wim Taymans 2025-09-19 13:40:52 +02:00
parent b57c6d3729
commit a859c7a651
2 changed files with 30 additions and 16 deletions

View file

@ -486,7 +486,7 @@ spa_pod_builder_control(struct spa_pod_builder *builder, uint32_t offset, uint32
return spa_pod_builder_raw(builder, &p, sizeof(p));
}
SPA_API_POD_BUILDER uint32_t spa_choice_from_id(char id)
SPA_API_POD_BUILDER uint32_t spa_choice_from_id_flags(char id, uint32_t *flags)
{
switch (id) {
case 'r':
@ -495,6 +495,9 @@ SPA_API_POD_BUILDER uint32_t spa_choice_from_id(char id)
return SPA_CHOICE_Step;
case 'e':
return SPA_CHOICE_Enum;
case 'F':
*flags |= SPA_POD_PROP_FLAG_DROP;
SPA_FALLTHROUGH;
case 'f':
return SPA_CHOICE_Flags;
case 'n':
@ -502,6 +505,11 @@ SPA_API_POD_BUILDER uint32_t spa_choice_from_id(char id)
return SPA_CHOICE_None;
}
}
SPA_API_POD_BUILDER uint32_t spa_choice_from_id(char id)
{
uint32_t flags = 0;
return spa_choice_from_id_flags(id, &flags);
}
#define SPA_POD_BUILDER_COLLECT(builder,type,args) \
do { \
@ -621,43 +629,46 @@ spa_pod_builder_addv(struct spa_pod_builder *builder, va_list args)
int n_values = 1;
struct spa_pod_frame f;
bool choice;
uint32_t key = 0, flags = 0, offset = 0, type = 0, ctype = 0;
switch (ftype) {
case SPA_TYPE_Object:
{
uint32_t key = va_arg(args, uint32_t), flags = 0;
key = va_arg(args, uint32_t);
if (key == 0)
goto exit;
if (key == SPA_ID_INVALID) {
key = va_arg(args, uint32_t);
flags = va_arg(args, uint32_t);
}
spa_pod_builder_prop(builder, key, flags);
break;
}
case SPA_TYPE_Sequence:
{
uint32_t offset = va_arg(args, uint32_t);
uint32_t type = va_arg(args, uint32_t);
offset = va_arg(args, uint32_t);
type = va_arg(args, uint32_t);
if (type == 0)
goto exit;
spa_pod_builder_control(builder, offset, type);
SPA_FALLTHROUGH
}
default:
break;
}
if ((format = va_arg(args, const char *)) == NULL)
break;
choice = *format == '?';
if (choice) {
uint32_t type = spa_choice_from_id(*++format);
ctype = spa_choice_from_id_flags(*++format, &flags);
if (*format != '\0')
format++;
spa_pod_builder_push_choice(builder, &f, type, 0);
}
switch (ftype) {
case SPA_TYPE_Object:
spa_pod_builder_prop(builder, key, flags);
break;
case SPA_TYPE_Sequence:
spa_pod_builder_control(builder, offset, type);
break;
}
if (choice) {
spa_pod_builder_push_choice(builder, &f, ctype, 0);
n_values = va_arg(args, int);
}
while (n_values-- > 0)

View file

@ -30,6 +30,7 @@ extern "C" {
#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_FEATURES(features) 1, (features)
#define SPA_CHOICE_BOOL(def) 3,(def),(def),!(def)
#define SPA_POD_Bool(val) "b", val
@ -43,12 +44,14 @@ extern "C" {
#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_CHOICE_FEATURES_Int(features) "?Fi", SPA_CHOICE_FEATURES(features)
#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_CHOICE_FEATURES_LONG(features) "?Fl", SPA_CHOICE_FEATURES(features)
#define SPA_POD_Float(val) "f", val
#define SPA_POD_CHOICE_ENUM_Float(n_vals,...) "?ef", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__)