spa-pod.dox 15.2 KB
 Peter Hutterer committed May 26, 2021 1 /** \page page_spa_pod SPA POD  Wim Taymans committed Jun 09, 2020 2   P V committed Oct 03, 2021 3 \ref spa_pod (plain old data) is a sort of data container. It is comparable to  Wim Taymans committed Jun 09, 2020 4 DBus Variant or LV2 Atom.  Wim Taymans committed Jun 09, 2020 5   jasker5183 committed May 08, 2022 6 7 A POD can express nested structures of objects (with properties), vectors, arrays, sequences and various primitives types. All information in the POD  Link Mauve committed Aug 17, 2020 8 is laid out sequentially in memory and can be written directly to  Wim Taymans committed Jun 09, 2020 9 storage or exchanged between processes or threads without additional  iss committed Mar 13, 2021 10 marshalling.  Wim Taymans committed Jun 09, 2020 11 12  Each POD is made of a 32 bits size followed by a 32 bits type field,  jasker5183 committed May 08, 2022 13 followed by the POD contents. This makes it possible to skip over unknown  Peter Hutterer committed May 07, 2021 14 POD types. The POD start is always aligned to 8 bytes.  Wim Taymans committed Jun 09, 2020 15   jasker5183 committed May 08, 2022 16 POD's can be efficiently constructed and parsed in real-time threads without  Peter Hutterer committed May 07, 2021 17 requiring memory allocations.  Wim Taymans committed Jun 09, 2020 18   jasker5183 committed May 08, 2022 19 POD's use the SPA type system for the basic types and containers. See  Wim Taymans committed Jun 09, 2020 20 21 22 the SPA types for more info.  jasker5183 committed May 08, 2022 23 # Types  Wim Taymans committed Jun 09, 2020 24   jasker5183 committed May 08, 2022 25 POD's can contain a number of basic SPA types:  Wim Taymans committed Jun 09, 2020 26   jasker5183 committed May 08, 2022 27 28 29 30 31 32 33 34 35 36 - SPA_TYPE_None: No value or a NULL pointer. - SPA_TYPE_Bool: A boolean value. - SPA_TYPE_Id: An enumerated value. - SPA_TYPE_Int, SPA_TYPE_Long, SPA_TYPE_Float, SPA_TYPE_Double: various numeral types, 32 and 64 bits. - SPA_TYPE_String: A string. - SPA_TYPE_Bytes: A byte array. - SPA_TYPE_Rectangle: A rectangle with width and height. - SPA_TYPE_Fraction: A fraction with numerator and denominator. - SPA_TYPE_Bitmap: An array of bits.  Wim Taymans committed Jun 09, 2020 37   jasker5183 committed May 08, 2022 38 POD's can be grouped together in these container types:  Wim Taymans committed Jun 09, 2020 39   jasker5183 committed May 08, 2022 40 41 42 43 - SPA_TYPE_Array: An array of equal sized objects. - SPA_TYPE_Struct: A collection of types and objects. - SPA_TYPE_Object: An object with properties. - SPA_TYPE_Sequence: A timed sequence of POD's.  Wim Taymans committed Jun 09, 2020 44   jasker5183 committed May 08, 2022 45 POD's can also contain some extra types:  Wim Taymans committed Jun 09, 2020 46   jasker5183 committed May 08, 2022 47 48 49 50 51 52 53 - SPA_TYPE_Pointer: A typed pointer in memory. - SPA_TYPE_Fd: A file descriptor. - SPA_TYPE_Choice: A choice of values. - SPA_TYPE_Pod: A generic type for the POD itself. # Constructing A POD  Wim Taymans committed Jun 09, 2020 54 55 56 57 58 59 60  A POD is usually constructed with a struct spa_pod_builder. The builder needs to be initialized with a memory region to write into. It is also possible to dynamically grow the memory as needed. The most common way to construct a POD is on the stack. This does not require any memory allocations. The size of the POD can be  Wim Taymans committed Nov 27, 2020 61 estimated pretty easily and if the buffer is not large enough, an  Wim Taymans committed Jun 09, 2020 62 63 appropriate error will be generated.  jasker5183 committed May 08, 2022 64 The code fragment below initializes a POD builder to write into  Wim Taymans committed Jun 09, 2020 65 66 the stack allocated buffer.  Peter Hutterer committed May 26, 2021 67 \code{.c}  Wim Taymans committed Jun 09, 2020 68 69 uint8_t buffer[4096]; struct spa_pod_builder b;  Peter Hutterer committed May 07, 2021 70 spa_pod_builder_init(&b, buffer, sizeof(buffer));  Peter Hutterer committed May 26, 2021 71 \endcode  Wim Taymans committed Jun 09, 2020 72 73 74 75 76  Next we need to write some object into the builder. Let's write a simple struct with an Int and Float in it. Structs are comparable to JSON arrays.  Peter Hutterer committed May 26, 2021 77 \code{.c}  Wim Taymans committed Jun 09, 2020 78 79 struct spa_pod_frame f; spa_pod_builder_push_struct(&b, &f);  Peter Hutterer committed May 26, 2021 80 \endcode  Wim Taymans committed Jun 09, 2020 81 82 83 84 85  First we open the struct container, the struct spa_pod_frame keeps track of the container context. Next we add some values to the container like this:  Peter Hutterer committed May 26, 2021 86 \code{.c}  Wim Taymans committed Jun 09, 2020 87 88 spa_pod_builder_int(&b, 5); spa_pod_builder_float(&b, 3.1415f);  Peter Hutterer committed May 26, 2021 89 \endcode  Wim Taymans committed Jun 09, 2020 90   iss committed Mar 13, 2021 91 Then we close the container by popping the frame again:  Wim Taymans committed Jun 09, 2020 92   Peter Hutterer committed May 26, 2021 93 \code{.c}  Wim Taymans committed Jun 09, 2020 94 95 struct spa_pod *pod; pod = spa_pod_builder_pop(&b, &f);  Peter Hutterer committed May 26, 2021 96 \endcode  Wim Taymans committed Jun 09, 2020 97 98 99 100  spa_pod_builder_pop() returns a reference to the object we completed on the stack.  jasker5183 committed May 08, 2022 101 ## Using varargs Builder  Wim Taymans committed Jun 09, 2020 102 103 104  We can also use the following construct to make POD objects:  Peter Hutterer committed May 26, 2021 105 \code{.c}  Wim Taymans committed Jun 09, 2020 106 107 108 109 110 spa_pod_builder_push_struct(&b, &f); spa_pod_builder_add(&b, SPA_POD_Int(5), SPA_POD_Float(3.1415f)); pod = spa_pod_builder_pop(&b, &f);  Peter Hutterer committed May 26, 2021 111 \endcode  Wim Taymans committed Jun 09, 2020 112 113 114  Or even shorter:  Peter Hutterer committed May 26, 2021 115 \code{.c}  Wim Taymans committed Jun 09, 2020 116 117 118 pod = spa_pod_builder_add_struct(&b, SPA_POD_Int(5), SPA_POD_Float(3.1415f));  Peter Hutterer committed May 26, 2021 119 \endcode  Wim Taymans committed Jun 09, 2020 120   jasker5183 committed May 08, 2022 121 122 It's not possible to use the varargs builder to make a sequence or array, use the normal builder methods for that.  Wim Taymans committed Jun 09, 2020 123   jasker5183 committed May 08, 2022 124 ## Making Objects  Wim Taymans committed Jun 09, 2020 125 126 127 128 129 130  POD objects are containers for properties and are comparable to JSON objects. Start by pushing an object:  Peter Hutterer committed May 26, 2021 131 \code{.c}  Wim Taymans committed Jun 09, 2020 132 spa_pod_builder_push_object(&b, &f, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props);  Peter Hutterer committed May 26, 2021 133 \endcode  Wim Taymans committed Jun 09, 2020 134 135  An object requires an object type (SPA_TYPE_OBJECT_Props) and a context  jasker5183 committed May 08, 2022 136 ID (SPA_PARAM_Props). The object type defines the properties that can be  Wim Taymans committed Jun 09, 2020 137 138 139 140 141 added to the object and their meaning. The SPA type system allows you to make this connection (See the type system). Next we can push some properties in the object:  Peter Hutterer committed May 26, 2021 142 \code{.c}  Wim Taymans committed Jun 09, 2020 143 144 145 146 spa_pod_builder_prop(&b, SPA_PROP_device, 0); spa_pod_builder_string(&b, "hw:0"); spa_pod_builder_prop(&b, SPA_PROP_frequency, 0); spa_pod_builder_float(&b, 440.0);  Peter Hutterer committed May 26, 2021 147 \endcode  Wim Taymans committed Jun 09, 2020 148 149 150 151 152 153 154  As can be seen, we always need to push a prop (with key and flags) and then the associated value. For performance reasons it is a good idea to always push (and parse) the object keys in ascending order. Don't forget to pop the result when the object is finished:  Peter Hutterer committed May 26, 2021 155 \code{.c}  Wim Taymans committed Jun 09, 2020 156 pod = spa_pod_builder_pop(&b, &f);  Peter Hutterer committed May 26, 2021 157 \endcode  Wim Taymans committed Jun 09, 2020 158 159 160  There is a shortcut for making objects:  Peter Hutterer committed May 26, 2021 161 \code{.c}  Wim Taymans committed Jun 09, 2020 162 163 164 165 pod = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props, SPA_PROP_device, SPA_POD_String("hw:0"), SPA_PROP_frequency, SPA_POD_Float(440.0f));  Peter Hutterer committed May 26, 2021 166 \endcode  Wim Taymans committed Jun 09, 2020 167   jasker5183 committed May 08, 2022 168 ## Choice Values  Wim Taymans committed Jun 09, 2020 169 170 171  It is possible to express ranges or enumerations of possible values for properties (and to some extend structs). This is achieved  jasker5183 committed May 08, 2022 172 with choice values.  Wim Taymans committed Jun 09, 2020 173 174 175 176 177  Choice values are really just a choice type and an array of choice values (of the same type). Depending on the choice type, the array values are interpreted in different ways:  jasker5183 committed May 08, 2022 178 179 180 181 182 - SPA_CHOICE_None: No choice, first value is current. - SPA_CHOICE_Range: Range: default, min, max. - SPA_CHOICE_Step: Range with step: default, min, max, step. - SPA_CHOICE_Enum: Enum: default, alternative,... - SPA_CHOICE_Flags: Bitmask of flags.  Wim Taymans committed Jun 09, 2020 183   jasker5183 committed May 08, 2022 184 Let's illustrate this with a props object that specifies a range of  Wim Taymans committed Jun 09, 2020 185 186 possible values for the frequency:  Peter Hutterer committed May 26, 2021 187 \code{.c}  Wim Taymans committed Jun 09, 2020 188 189 190 191 192 struct spa_pod_frame f2; spa_pod_builder_push_object(&b, &f, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props); spa_pod_builder_prop(&b, SPA_PROP_frequency, 0); spa_pod_builder_push_choice(&b, &f2, SPA_CHOICE_Range, 0);  Peter Hutterer committed May 26, 2021 193 194 195 spa_pod_builder_float(&b, 440.0); // default spa_pod_builder_float(&b, 110.0); // min spa_pod_builder_float(&b, 880.0); // min  Wim Taymans committed Jun 09, 2020 196 197 pod = spa_pod_builder_pop(&b, &f2); pod = spa_pod_builder_pop(&b, &f);  Peter Hutterer committed May 26, 2021 198 \endcode  Wim Taymans committed Jun 09, 2020 199   jasker5183 committed May 08, 2022 200 201 As you can see, first push the choice as a range, then the values. A range choice expects at least three values, the default value, minimum and maximum  Link Mauve committed Aug 17, 2020 202 values. There is a shortcut for this as well using varargs:  Wim Taymans committed Jun 09, 2020 203   Peter Hutterer committed May 26, 2021 204 \code{.c}  Wim Taymans committed Jun 09, 2020 205 206 207 pod = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props, SPA_PROP_frequency, SPA_POD_CHOICE_RANGE_Float(440.0f, 110.0f, 880.0f));  Peter Hutterer committed May 26, 2021 208 \endcode  Wim Taymans committed Jun 09, 2020 209   jasker5183 committed May 08, 2022 210 ## Choice Examples  Wim Taymans committed Jun 09, 2020 211 212 213 214  This is a description of a possible SPA_TYPE_OBJECT_Format as used when enumerating allowed formats (SPA_PARAM_EnumFormat) in SPA objects:  Peter Hutterer committed May 26, 2021 215 \code{.c}  Wim Taymans committed Jun 09, 2020 216 217 pod = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,  Peter Hutterer committed May 26, 2021 218  // specify the media type and subtype  Wim Taymans committed Jun 09, 2020 219 220  SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),  Peter Hutterer committed May 26, 2021 221  // audio/raw properties  Wim Taymans committed Jun 09, 2020 222  SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(  Peter Hutterer committed May 26, 2021 223 224 225 226  SPA_AUDIO_FORMAT_S16, // default SPA_AUDIO_FORMAT_S16, // alternative1 SPA_AUDIO_FORMAT_S32, // alternative2 SPA_AUDIO_FORMAT_f32 // alternative3  Wim Taymans committed Jun 09, 2020 227 228  ), SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(  Peter Hutterer committed May 26, 2021 229 230 231  44100, // default 8000, // min 192000 // max  Wim Taymans committed Jun 09, 2020 232 233  ), SPA_FORMAT_AUDIO_channels, SPA_POD_Int(2));  Peter Hutterer committed May 26, 2021 234 \endcode  Wim Taymans committed Jun 09, 2020 235 236 237  ## Fixate  Peter Hutterer committed May 07, 2021 238 We can remove all choice values from the object with the  Wim Taymans committed Jun 09, 2020 239 240 241 242 243 244 245 spa_pod_object_fixate() method. This modifies the pod in-place and sets all choice properties to SPA_CHOICE_None, forcing the default value as the only available value in the choice. Running fixate on our previous example would result in an object equivalent to:  Peter Hutterer committed May 26, 2021 246 \code{.c}  Wim Taymans committed Jun 09, 2020 247 248 pod = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,  Peter Hutterer committed May 26, 2021 249  // specify the media type and subtype  Wim Taymans committed Jun 09, 2020 250 251  SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),  Peter Hutterer committed May 26, 2021 252  // audio/raw properties  Wim Taymans committed Jun 09, 2020 253 254 255  SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_S16), SPA_FORMAT_AUDIO_rate, SPA_POD_Int(44100), SPA_FORMAT_AUDIO_channels, SPA_POD_Int(2));  Peter Hutterer committed May 26, 2021 256 \endcode  Wim Taymans committed Jun 09, 2020 257 258   jasker5183 committed May 08, 2022 259 # Parsing A POD  Wim Taymans committed Jun 09, 2020 260   jasker5183 committed May 08, 2022 261 Parsing a POD usually consists of:  Wim Taymans committed Jun 09, 2020 262   jasker5183 committed May 08, 2022 263 264 265 266 267 268 - Validating if raw bytes + size can contain a valid POD. - Inspecting the type of a POD. - Looping over the items in an object or struct. - Getting data out of POD's. ## Validating Bytes  Wim Taymans committed Jun 09, 2020 269 270 271 272 273  Use spa_pod_from_data() to check if maxsize of bytes in data contain a POD at the size bytes starting at offset. This function checks that the POD size will fit and not overflow.  Peter Hutterer committed May 26, 2021 274 \code{.c}  Wim Taymans committed Jun 09, 2020 275 276 struct spa_pod *pod; pod = spa_pod_from_data(data, maxsize, offset, size);  Peter Hutterer committed May 26, 2021 277 \endcode  Wim Taymans committed Jun 09, 2020 278   jasker5183 committed May 08, 2022 279 ## Checking The Type Of POD  Wim Taymans committed Jun 09, 2020 280 281 282 283 284 285 286 287 288  Use one of spa_pod_is_bool(), spa_pod_is_int(), etc to check for the type of the pod. For simple (non-container) types, spa_pod_get_bool(), spa_pod_get_int() etc can be used to extract the value of the pod. spa_pod_is_object_type() can be used to check if the POD contains an object of the expected type.  jasker5183 committed May 08, 2022 289 ## Struct Fields  Wim Taymans committed Jun 09, 2020 290   jasker5183 committed May 08, 2022 291 To iterate over the fields of a struct use:  Wim Taymans committed Jun 09, 2020 292   Peter Hutterer committed May 26, 2021 293 \code{.c}  Wim Taymans committed Jun 09, 2020 294 295 296 297 struct spa_pod *pod, *obj; SPA_POD_STRUCT_FOREACH(obj, pod) { printf("field type:%d\n", pod->type); }  Peter Hutterer committed May 26, 2021 298 \endcode  Wim Taymans committed Jun 09, 2020 299   jasker5183 committed May 08, 2022 300 For parsing structs it is usually much easier to use the parser  Wim Taymans committed Jun 09, 2020 301 302 303 304 below. ## Object Properties  Link Mauve committed Aug 17, 2020 305 To iterate over the properties in an object you can do:  Wim Taymans committed Jun 09, 2020 306   Peter Hutterer committed May 26, 2021 307 \code{.c}  Wim Taymans committed Jun 09, 2020 308 309 310 311 312 struct spa_pod_prop *prop; struct spa_pod_object *obj = (struct spa_pod_object*)pod; SPA_POD_OBJECT_FOREACH(pod, prop) { printf("prop key:%d\n", prop->key); }  Peter Hutterer committed May 26, 2021 313 \endcode  Wim Taymans committed Jun 09, 2020 314 315 316 317 318  There is a function to retrieve the property for a certain key in the object. If the properties of the object are in ascending order, you can start searching from the previous key.  Peter Hutterer committed May 26, 2021 319 \code{.c}  Wim Taymans committed Jun 09, 2020 320 321 struct spa_pod_prop *prop; prop = spa_pod_find_prop(obj, NULL, SPA_FORMAT_AUDIO_format);  Peter Hutterer committed May 26, 2021 322  // .. use first prop  Wim Taymans committed Jun 09, 2020 323 prop = spa_pod_find_prop(obj, prop, SPA_FORMAT_AUDIO_rate);  Peter Hutterer committed May 26, 2021 324 325  // .. use next prop \endcode  Wim Taymans committed Jun 09, 2020 326 327 328 329 330  ## Parser Similar to the builder, there is a parser object as well.  Wim Taymans committed Nov 27, 2020 331 332 If the fields in a struct are known, it is much easier to use the parser. Similarly, if the object type (and thus its keys) are known,  Wim Taymans committed Jun 09, 2020 333 334 335 336 the parser is easier. First initialize a struct spa_pod_parser:  Peter Hutterer committed May 26, 2021 337 \code{.c}  Wim Taymans committed Jun 09, 2020 338 339 struct spa_pod_parser p; spa_pod_parser_pod(&p, obj);  Peter Hutterer committed May 26, 2021 340 \endcode  Wim Taymans committed Jun 09, 2020 341 342 343 344  You can then enter containers such as objects or structs with a push operation:  Peter Hutterer committed May 26, 2021 345 \code{.c}  Wim Taymans committed Jun 09, 2020 346 347 struct spa_pod_frame f; spa_pod_parser_push_struct(&p, &f);  Peter Hutterer committed May 26, 2021 348 \endcode  Wim Taymans committed Jun 09, 2020 349 350  You need to store the context in a struct spa_pod_frame to be able  Peter Hutterer committed May 07, 2021 351 to exit the container again later.  Wim Taymans committed Jun 09, 2020 352 353 354 355  You can then parse each field. The parser takes care of moving to the next field.  Peter Hutterer committed May 26, 2021 356 \code{.c}  Wim Taymans committed Jun 09, 2020 357 358 359 360 uint32_t id, val; spa_pod_parser_get_id(&p, &id); spa_pod_parser_get_int(&p, &val); ...  Peter Hutterer committed May 26, 2021 361 \endcode  Wim Taymans committed Jun 09, 2020 362 363 364  And finally exit the container again:  Peter Hutterer committed May 26, 2021 365 \code{.c}  Wim Taymans committed Jun 09, 2020 366 spa_pod_parser_pop(&p, &f);  Peter Hutterer committed May 26, 2021 367 \endcode  Wim Taymans committed Jun 09, 2020 368   jasker5183 committed May 08, 2022 369 ## Parser With Variable Arguments  Wim Taymans committed Jun 09, 2020 370 371 372 373 374 375 376  In most cases, parsing objects is easier with the variable argument functions. The parse function look like the mirror image of the builder functions. To parse a struct:  Peter Hutterer committed May 26, 2021 377 \code{.c}  Wim Taymans committed Jun 09, 2020 378 379 380 spa_pod_parser_get_struct(&p, SPA_POD_Id(&id), SPA_POD_Int(&val));  Peter Hutterer committed May 26, 2021 381 \endcode  Wim Taymans committed Jun 09, 2020 382 383 384  To parse properties in an object:  Peter Hutterer committed May 26, 2021 385 \code{.c}  Wim Taymans committed Jun 09, 2020 386 387 388 389 390 391 392 393 uint32_t type, subtype, format, rate, channels; spa_pod_parser_get_object(&p, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, SPA_FORMAT_mediaType, SPA_POD_Id(&type), SPA_FORMAT_mediaSubtype, SPA_POD_Id(&subtype), SPA_FORMAT_AUDIO_format, SPA_POD_Id(&format), SPA_FORMAT_AUDIO_rate, SPA_POD_Int(&rate), SPA_FORMAT_AUDIO_channels, SPA_POD_Int(&channels));  Peter Hutterer committed May 26, 2021 394 \endcode  Wim Taymans committed Jun 09, 2020 395 396 397 398 399 400 401 402  When parsing objects it is possible to have optional fields. You can make a field optional be parsing it with the SPA_POD_OPT_ prefix for the type. In the next example, the rate and channels fields are optional and when they are not present, the variables will not be changed.  Peter Hutterer committed May 26, 2021 403 \code{.c}  Wim Taymans committed Jun 09, 2020 404 405 406 407 408 409 410 411 uint32_t type, subtype, format, rate = 0, channels = 0; spa_pod_parser_get_object(&p, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, SPA_FORMAT_mediaType, SPA_POD_Id(&type), SPA_FORMAT_mediaSubtype, SPA_POD_Id(&subtype), SPA_FORMAT_AUDIO_format, SPA_POD_Id(&format), SPA_FORMAT_AUDIO_rate, SPA_POD_OPT_Int(&rate), SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&channels));  Peter Hutterer committed May 26, 2021 412 \endcode  Wim Taymans committed Jun 09, 2020 413   jasker5183 committed May 08, 2022 414 It is not possible to parse a sequence or array with the parser.  Wim Taymans committed Jun 09, 2020 415 416 Use the iterator for this.  jasker5183 committed May 08, 2022 417 ## Choice Values  Wim Taymans committed Jun 09, 2020 418   jasker5183 committed May 08, 2022 419 420 The parser will handle choice values as long as they are of type none. It will then parse the single value from the choice. When  Peter Hutterer committed May 07, 2021 421 dealing with other choice values, it's possible to parse the  jasker5183 committed May 08, 2022 422 property values into a struct spa_pod and then inspect the choice  Wim Taymans committed Jun 09, 2020 423 424 425 426 manually, if needed. Here is an example of parsing the format values as a POD:  Peter Hutterer committed May 26, 2021 427 \code{.c}  Wim Taymans committed Jun 09, 2020 428 429 430 431 432 433 434 uint32_t type, subtype; struct spa_pod *format; spa_pod_parser_get_object(&p, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, SPA_FORMAT_mediaType, SPA_POD_Id(&type), SPA_FORMAT_mediaSubtype, SPA_POD_Id(&subtype), SPA_FORMAT_AUDIO_format, SPA_POD_Pod(&format));  Peter Hutterer committed May 26, 2021 435 \endcode  Wim Taymans committed Jun 09, 2020 436 437  spa_pod_get_values() is a useful function. It returns a  jasker5183 committed May 08, 2022 438 439 440 struct spa_pod* with and array of values. For normal POD's and choice none values, it simply returns the POD and one value. For other choice values it returns the choice type and an array  Wim Taymans committed Jun 09, 2020 441 442 of values:  Peter Hutterer committed May 26, 2021 443 \code{.c}  Wim Taymans committed Jun 09, 2020 444 445 446 447 448 449 450 struct spa_pod *value; uint32_t n_vals, choice; value = spa_pod_get_values(pod, &n_vals, &choice); switch (choice) { case SPA_CHOICE_None:  Peter Hutterer committed May 26, 2021 451  // one single value  Wim Taymans committed Jun 09, 2020 452 453  break; case SPA_CHOICE_Range:  Peter Hutterer committed May 26, 2021 454 455  // array of values of type of pod, cast to right type // to iterate.  Wim Taymans committed Jun 09, 2020 456 457 458 459 460 461 462 463  uint32_t *v = SPA_POD_BODY(values); if (n_vals < 3) break; printf("default value: %u\n", v[0]); printf("min value: %u\n", v[1]); printf("max value: %u\n", v[2]); break;  Peter Hutterer committed May 26, 2021 464  // ...  Wim Taymans committed Jun 09, 2020 465 466 467 default: break; }  Peter Hutterer committed May 26, 2021 468 \endcode  Wim Taymans committed Jun 09, 2020 469   jasker5183 committed May 08, 2022 470   Wim Taymans committed Jun 09, 2020 471 472 # Filter  jasker5183 committed May 08, 2022 473 474 475 Given two POD objects of the same type (object, struct, ..) one can run a filter and generate a new POD that only contains values that are compatible with both input POD's.  Wim Taymans committed Jun 09, 2020 476   Wim Taymans committed Jun 09, 2020 477 This is, for example, used to find a compatible format between two ports.  Wim Taymans committed Jun 09, 2020 478   jasker5183 committed May 08, 2022 479 As an example we can run a filter on two simple POD's:  Wim Taymans committed Jun 09, 2020 480   Peter Hutterer committed May 26, 2021 481 \code{.c}  Wim Taymans committed Jun 09, 2020 482 483 484 485 486 pod = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(  Peter Hutterer committed May 26, 2021 487 488 489 490  SPA_AUDIO_FORMAT_S16, // default SPA_AUDIO_FORMAT_S16, // alternative1 SPA_AUDIO_FORMAT_S32, // alternative2 SPA_AUDIO_FORMAT_f32 // alternative3  Wim Taymans committed Jun 09, 2020 491 492 493 494 495 496 497  )); filter = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(  Peter Hutterer committed May 26, 2021 498 499 500  SPA_AUDIO_FORMAT_S16, // default SPA_AUDIO_FORMAT_S16, // alternative1 SPA_AUDIO_FORMAT_f64 // alternative2  Wim Taymans committed Jun 09, 2020 501 502 503 504 505  )); struct spa_pod *result; if (spa_pod_filter(&b, &result, pod, filter) < 0) goto exit_error;  Peter Hutterer committed May 26, 2021 506 \endcode  Wim Taymans committed Jun 09, 2020 507 508 509  Filter will contain a POD equivalent to:  Peter Hutterer committed May 26, 2021 510 \code{.c}  Wim Taymans committed Jun 09, 2020 511 512 513 514 515 result = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), SPA_FORMAT_AUDIO_format, SPA_AUDIO_FORMAT_S16);  Peter Hutterer committed May 26, 2021 516 \endcode  Wim Taymans committed Jun 09, 2020 517   jasker5183 committed May 08, 2022 518 # POD Layout  Wim Taymans committed Jun 09, 2020 519 520 521 522 523 524 525  Each POD has a 32 bits size field, followed by a 32 bits type field. The size field specifies the size following the type field. Each POD is aligned to an 8 byte boundary.  P V committed Oct 03, 2021 526 527 528 529 \addtogroup spa_pod See: \ref page_spa_pod  Peter Hutterer committed May 26, 2021 530 */