PipeWire  0.3.59
builder.h
Go to the documentation of this file.
1 /* Simple Plugin API
2  *
3  * Copyright © 2018 Wim Taymans
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #ifndef SPA_POD_BUILDER_H
26 #define SPA_POD_BUILDER_H
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
41 #include <stdarg.h>
42 
43 #include <spa/utils/hook.h>
44 #include <spa/pod/iter.h>
45 #include <spa/pod/vararg.h>
46 
47 struct spa_pod_builder_state {
48  uint32_t offset;
49 #define SPA_POD_BUILDER_FLAG_BODY (1<<0)
50 #define SPA_POD_BUILDER_FLAG_FIRST (1<<1)
51  uint32_t flags;
53 };
54 
56 
58 #define SPA_VERSION_POD_BUILDER_CALLBACKS 0
59  uint32_t version;
60 
61  int (*overflow) (void *data, uint32_t size);
62 };
63 
64 struct spa_pod_builder {
65  void *data;
66  uint32_t size;
67  uint32_t _padding;
69  struct spa_callbacks callbacks;
70 };
71 
72 #define SPA_POD_BUILDER_INIT(buffer,size) ((struct spa_pod_builder){ (buffer), (size), 0, {}, {} })
73 
74 static inline void
76 {
77  *state = builder->state;
78 }
79 
80 static inline void
82  const struct spa_pod_builder_callbacks *callbacks, void *data)
83 {
84  builder->callbacks = SPA_CALLBACKS_INIT(callbacks, data);
85 }
86 
87 static inline void
88 spa_pod_builder_reset(struct spa_pod_builder *builder, struct spa_pod_builder_state *state)
89 {
90  struct spa_pod_frame *f;
91  uint32_t size = builder->state.offset - state->offset;
92  builder->state = *state;
93  for (f = builder->state.frame; f ; f = f->parent)
94  f->pod.size -= size;
95 }
96 
97 static inline void spa_pod_builder_init(struct spa_pod_builder *builder, void *data, uint32_t size)
98 {
99  *builder = SPA_POD_BUILDER_INIT(data, size);
100 }
101 
102 static inline struct spa_pod *
103 spa_pod_builder_deref(struct spa_pod_builder *builder, uint32_t offset)
104 {
105  uint32_t size = builder->size;
106  if (offset + 8 <= size) {
107  struct spa_pod *pod = SPA_PTROFF(builder->data, offset, struct spa_pod);
108  if (offset + SPA_POD_SIZE(pod) <= size)
109  return pod;
110  }
111  return NULL;
112 }
113 
114 static inline struct spa_pod *
115 spa_pod_builder_frame(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
116 {
117  if (frame->offset + SPA_POD_SIZE(&frame->pod) <= builder->size)
118  return SPA_PTROFF(builder->data, frame->offset, struct spa_pod);
119  return NULL;
120 }
121 
122 static inline void
123 spa_pod_builder_push(struct spa_pod_builder *builder,
124  struct spa_pod_frame *frame,
125  const struct spa_pod *pod,
126  uint32_t offset)
127 {
128  frame->pod = *pod;
129  frame->offset = offset;
130  frame->parent = builder->state.frame;
131  frame->flags = builder->state.flags;
132  builder->state.frame = frame;
133 
134  if (frame->pod.type == SPA_TYPE_Array || frame->pod.type == SPA_TYPE_Choice)
136 }
137 
138 static inline int spa_pod_builder_raw(struct spa_pod_builder *builder, const void *data, uint32_t size)
139 {
140  int res = 0;
141  struct spa_pod_frame *f;
142  uint32_t offset = builder->state.offset;
143 
144  if (offset + size > builder->size) {
145  res = -ENOSPC;
146  if (offset <= builder->size)
149  overflow, 0, offset + size);
150  }
151  if (res == 0 && data)
152  memcpy(SPA_PTROFF(builder->data, offset, void), data, size);
153 
154  builder->state.offset += size;
155 
156  for (f = builder->state.frame; f ; f = f->parent)
157  f->pod.size += size;
158 
159  return res;
160 }
161 
162 static inline int spa_pod_builder_pad(struct spa_pod_builder *builder, uint32_t size)
163 {
164  uint64_t zeroes = 0;
165  size = SPA_ROUND_UP_N(size, 8) - size;
166  return size ? spa_pod_builder_raw(builder, &zeroes, size) : 0;
167 }
168 
169 static inline int
170 spa_pod_builder_raw_padded(struct spa_pod_builder *builder, const void *data, uint32_t size)
171 {
172  int r, res = spa_pod_builder_raw(builder, data, size);
173  if ((r = spa_pod_builder_pad(builder, size)) < 0)
174  res = r;
175  return res;
176 }
177 
178 static inline void *spa_pod_builder_pop(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
179 {
180  struct spa_pod *pod;
181 
183  const struct spa_pod p = { 0, SPA_TYPE_None };
184  spa_pod_builder_raw(builder, &p, sizeof(p));
185  }
186  if ((pod = (struct spa_pod*)spa_pod_builder_frame(builder, frame)) != NULL)
187  *pod = frame->pod;
188 
189  builder->state.frame = frame->parent;
190  builder->state.flags = frame->flags;
191  spa_pod_builder_pad(builder, builder->state.offset);
192  return pod;
193 }
194 
195 static inline int
196 spa_pod_builder_primitive(struct spa_pod_builder *builder, const struct spa_pod *p)
197 {
198  const void *data;
199  uint32_t size;
200  int r, res;
201 
202  if (builder->state.flags == SPA_POD_BUILDER_FLAG_BODY) {
203  data = SPA_POD_BODY_CONST(p);
204  size = SPA_POD_BODY_SIZE(p);
205  } else {
206  data = p;
207  size = SPA_POD_SIZE(p);
209  }
210  res = spa_pod_builder_raw(builder, data, size);
211  if (builder->state.flags != SPA_POD_BUILDER_FLAG_BODY)
212  if ((r = spa_pod_builder_pad(builder, size)) < 0)
213  res = r;
214  return res;
215 }
216 
217 #define SPA_POD_INIT(size,type) ((struct spa_pod) { (size), (type) })
218 
219 #define SPA_POD_INIT_None() SPA_POD_INIT(0, SPA_TYPE_None)
220 
221 static inline int spa_pod_builder_none(struct spa_pod_builder *builder)
222 {
223  const struct spa_pod p = SPA_POD_INIT_None();
224  return spa_pod_builder_primitive(builder, &p);
225 }
226 
227 static inline int spa_pod_builder_child(struct spa_pod_builder *builder, uint32_t size, uint32_t type)
228 {
229  const struct spa_pod p = SPA_POD_INIT(size,type);
231  return spa_pod_builder_raw(builder, &p, sizeof(p));
232 }
233 
234 #define SPA_POD_INIT_Bool(val) ((struct spa_pod_bool){ { sizeof(uint32_t), SPA_TYPE_Bool }, (val) ? 1 : 0, 0 })
235 
236 static inline int spa_pod_builder_bool(struct spa_pod_builder *builder, bool val)
237 {
238  const struct spa_pod_bool p = SPA_POD_INIT_Bool(val);
239  return spa_pod_builder_primitive(builder, &p.pod);
240 }
241 
242 #define SPA_POD_INIT_Id(val) ((struct spa_pod_id){ { sizeof(uint32_t), SPA_TYPE_Id }, (val), 0 })
243 
244 static inline int spa_pod_builder_id(struct spa_pod_builder *builder, uint32_t val)
245 {
246  const struct spa_pod_id p = SPA_POD_INIT_Id(val);
247  return spa_pod_builder_primitive(builder, &p.pod);
248 }
249 
250 #define SPA_POD_INIT_Int(val) ((struct spa_pod_int){ { sizeof(int32_t), SPA_TYPE_Int }, (val), 0 })
251 
252 static inline int spa_pod_builder_int(struct spa_pod_builder *builder, int32_t val)
253 {
254  const struct spa_pod_int p = SPA_POD_INIT_Int(val);
255  return spa_pod_builder_primitive(builder, &p.pod);
256 }
257 
258 #define SPA_POD_INIT_Long(val) ((struct spa_pod_long){ { sizeof(int64_t), SPA_TYPE_Long }, (val) })
259 
260 static inline int spa_pod_builder_long(struct spa_pod_builder *builder, int64_t val)
261 {
262  const struct spa_pod_long p = SPA_POD_INIT_Long(val);
263  return spa_pod_builder_primitive(builder, &p.pod);
264 }
265 
266 #define SPA_POD_INIT_Float(val) ((struct spa_pod_float){ { sizeof(float), SPA_TYPE_Float }, (val), 0 })
267 
268 static inline int spa_pod_builder_float(struct spa_pod_builder *builder, float val)
269 {
270  const struct spa_pod_float p = SPA_POD_INIT_Float(val);
271  return spa_pod_builder_primitive(builder, &p.pod);
272 }
273 
274 #define SPA_POD_INIT_Double(val) ((struct spa_pod_double){ { sizeof(double), SPA_TYPE_Double }, (val) })
275 
276 static inline int spa_pod_builder_double(struct spa_pod_builder *builder, double val)
277 {
278  const struct spa_pod_double p = SPA_POD_INIT_Double(val);
279  return spa_pod_builder_primitive(builder, &p.pod);
280 }
281 
282 #define SPA_POD_INIT_String(len) ((struct spa_pod_string){ { (len), SPA_TYPE_String } })
283 
284 static inline int
285 spa_pod_builder_write_string(struct spa_pod_builder *builder, const char *str, uint32_t len)
286 {
287  int r, res;
288  res = spa_pod_builder_raw(builder, str, len);
289  if ((r = spa_pod_builder_raw(builder, "", 1)) < 0)
290  res = r;
291  if ((r = spa_pod_builder_pad(builder, builder->state.offset)) < 0)
292  res = r;
293  return res;
294 }
295 
296 static inline int
297 spa_pod_builder_string_len(struct spa_pod_builder *builder, const char *str, uint32_t len)
298 {
299  const struct spa_pod_string p = SPA_POD_INIT_String(len+1);
300  int r, res = spa_pod_builder_raw(builder, &p, sizeof(p));
301  if ((r = spa_pod_builder_write_string(builder, str, len)) < 0)
302  res = r;
303  return res;
304 }
305 
306 static inline int spa_pod_builder_string(struct spa_pod_builder *builder, const char *str)
307 {
308  uint32_t len = str ? strlen(str) : 0;
309  return spa_pod_builder_string_len(builder, str ? str : "", len);
310 }
311 
312 #define SPA_POD_INIT_Bytes(len) ((struct spa_pod_bytes){ { (len), SPA_TYPE_Bytes } })
313 
314 static inline int
315 spa_pod_builder_bytes(struct spa_pod_builder *builder, const void *bytes, uint32_t len)
316 {
317  const struct spa_pod_bytes p = SPA_POD_INIT_Bytes(len);
318  int r, res = spa_pod_builder_raw(builder, &p, sizeof(p));
319  if ((r = spa_pod_builder_raw_padded(builder, bytes, len)) < 0)
320  res = r;
321  return res;
322 }
323 static inline void *
324 spa_pod_builder_reserve_bytes(struct spa_pod_builder *builder, uint32_t len)
325 {
326  uint32_t offset = builder->state.offset;
327  if (spa_pod_builder_bytes(builder, NULL, len) < 0)
328  return NULL;
329  return SPA_POD_BODY(spa_pod_builder_deref(builder, offset));
330 }
331 
332 #define SPA_POD_INIT_Pointer(type,value) ((struct spa_pod_pointer){ { sizeof(struct spa_pod_pointer_body), SPA_TYPE_Pointer }, { (type), 0, (value) } })
333 
334 static inline int
335 spa_pod_builder_pointer(struct spa_pod_builder *builder, uint32_t type, const void *val)
336 {
337  const struct spa_pod_pointer p = SPA_POD_INIT_Pointer(type, val);
338  return spa_pod_builder_primitive(builder, &p.pod);
339 }
340 
341 #define SPA_POD_INIT_Fd(fd) ((struct spa_pod_fd){ { sizeof(int64_t), SPA_TYPE_Fd }, (fd) })
342 
343 static inline int spa_pod_builder_fd(struct spa_pod_builder *builder, int64_t fd)
344 {
345  const struct spa_pod_fd p = SPA_POD_INIT_Fd(fd);
346  return spa_pod_builder_primitive(builder, &p.pod);
347 }
348 
349 #define SPA_POD_INIT_Rectangle(val) ((struct spa_pod_rectangle){ { sizeof(struct spa_rectangle), SPA_TYPE_Rectangle }, (val) })
350 
351 static inline int
352 spa_pod_builder_rectangle(struct spa_pod_builder *builder, uint32_t width, uint32_t height)
353 {
354  const struct spa_pod_rectangle p = SPA_POD_INIT_Rectangle(SPA_RECTANGLE(width, height));
355  return spa_pod_builder_primitive(builder, &p.pod);
356 }
357 
358 #define SPA_POD_INIT_Fraction(val) ((struct spa_pod_fraction){ { sizeof(struct spa_fraction), SPA_TYPE_Fraction }, (val) })
359 
360 static inline int
361 spa_pod_builder_fraction(struct spa_pod_builder *builder, uint32_t num, uint32_t denom)
362 {
363  const struct spa_pod_fraction p = SPA_POD_INIT_Fraction(SPA_FRACTION(num, denom));
364  return spa_pod_builder_primitive(builder, &p.pod);
365 }
366 
367 static inline int
368 spa_pod_builder_push_array(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
369 {
370  const struct spa_pod_array p =
371  { {sizeof(struct spa_pod_array_body) - sizeof(struct spa_pod), SPA_TYPE_Array},
372  {{0, 0}} };
373  uint32_t offset = builder->state.offset;
374  int res = spa_pod_builder_raw(builder, &p, sizeof(p) - sizeof(struct spa_pod));
375  spa_pod_builder_push(builder, frame, &p.pod, offset);
376  return res;
377 }
378 
379 static inline int
380 spa_pod_builder_array(struct spa_pod_builder *builder,
381  uint32_t child_size, uint32_t child_type, uint32_t n_elems, const void *elems)
382 {
383  const struct spa_pod_array p = {
384  {(uint32_t)(sizeof(struct spa_pod_array_body) + n_elems * child_size), SPA_TYPE_Array},
385  {{child_size, child_type}}
386  };
387  int r, res = spa_pod_builder_raw(builder, &p, sizeof(p));
388  if ((r = spa_pod_builder_raw_padded(builder, elems, child_size * n_elems)) < 0)
389  res = r;
390  return res;
391 }
392 
393 #define SPA_POD_INIT_CHOICE_BODY(type, flags, child_size, child_type) \
394  ((struct spa_pod_choice_body) { (type), (flags), { (child_size), (child_type) }})
395 
396 #define SPA_POD_INIT_Choice(type, ctype, child_type, n_vals, ...) \
397  ((struct { struct spa_pod_choice choice; ctype vals[(n_vals)];}) \
398  { { { (n_vals) * sizeof(ctype) + sizeof(struct spa_pod_choice_body), SPA_TYPE_Choice }, \
399  { (type), 0, { sizeof(ctype), (child_type) } } }, { __VA_ARGS__ } })
400 
401 static inline int
402 spa_pod_builder_push_choice(struct spa_pod_builder *builder, struct spa_pod_frame *frame,
403  uint32_t type, uint32_t flags)
404 {
405  const struct spa_pod_choice p =
406  { {sizeof(struct spa_pod_choice_body) - sizeof(struct spa_pod), SPA_TYPE_Choice},
407  { type, flags, {0, 0}} };
408  uint32_t offset = builder->state.offset;
409  int res = spa_pod_builder_raw(builder, &p, sizeof(p) - sizeof(struct spa_pod));
410  spa_pod_builder_push(builder, frame, &p.pod, offset);
411  return res;
412 }
413 
414 #define SPA_POD_INIT_Struct(size) ((struct spa_pod_struct){ { (size), SPA_TYPE_Struct } })
415 
416 static inline int
418 {
419  const struct spa_pod_struct p = SPA_POD_INIT_Struct(0);
420  uint32_t offset = builder->state.offset;
421  int res = spa_pod_builder_raw(builder, &p, sizeof(p));
422  spa_pod_builder_push(builder, frame, &p.pod, offset);
423  return res;
424 }
425 
426 #define SPA_POD_INIT_Object(size,type,id,...) ((struct spa_pod_object){ { (size), SPA_TYPE_Object }, { (type), (id) }, ##__VA_ARGS__ })
427 
428 static inline int
429 spa_pod_builder_push_object(struct spa_pod_builder *builder, struct spa_pod_frame *frame,
430  uint32_t type, uint32_t id)
431 {
432  const struct spa_pod_object p =
433  SPA_POD_INIT_Object(sizeof(struct spa_pod_object_body), type, id);
434  uint32_t offset = builder->state.offset;
435  int res = spa_pod_builder_raw(builder, &p, sizeof(p));
436  spa_pod_builder_push(builder, frame, &p.pod, offset);
437  return res;
438 }
439 
440 #define SPA_POD_INIT_Prop(key,flags,size,type) \
441  ((struct spa_pod_prop){ (key), (flags), { (size), (type) } })
442 
443 static inline int
444 spa_pod_builder_prop(struct spa_pod_builder *builder, uint32_t key, uint32_t flags)
445 {
446  const struct { uint32_t key; uint32_t flags; } p = { key, flags };
447  return spa_pod_builder_raw(builder, &p, sizeof(p));
448 }
449 
450 #define SPA_POD_INIT_Sequence(size,unit) \
451  ((struct spa_pod_sequence){ { (size), SPA_TYPE_Sequence}, {(unit), 0 } })
452 
453 static inline int
454 spa_pod_builder_push_sequence(struct spa_pod_builder *builder, struct spa_pod_frame *frame, uint32_t unit)
455 {
456  const struct spa_pod_sequence p =
457  SPA_POD_INIT_Sequence(sizeof(struct spa_pod_sequence_body), unit);
458  uint32_t offset = builder->state.offset;
459  int res = spa_pod_builder_raw(builder, &p, sizeof(p));
460  spa_pod_builder_push(builder, frame, &p.pod, offset);
461  return res;
462 }
463 
464 static inline uint32_t
465 spa_pod_builder_control(struct spa_pod_builder *builder, uint32_t offset, uint32_t type)
466 {
467  const struct { uint32_t offset; uint32_t type; } p = { offset, type };
468  return spa_pod_builder_raw(builder, &p, sizeof(p));
469 }
470 
471 static inline uint32_t spa_choice_from_id(char id)
472 {
473  switch (id) {
474  case 'r':
475  return SPA_CHOICE_Range;
476  case 's':
477  return SPA_CHOICE_Step;
478  case 'e':
479  return SPA_CHOICE_Enum;
480  case 'f':
481  return SPA_CHOICE_Flags;
482  case 'n':
483  default:
484  return SPA_CHOICE_None;
485  }
486 }
487 
488 #define SPA_POD_BUILDER_COLLECT(builder,type,args) \
489 do { \
490  switch (type) { \
491  case 'b': \
492  spa_pod_builder_bool(builder, !!va_arg(args, int)); \
493  break; \
494  case 'I': \
495  spa_pod_builder_id(builder, va_arg(args, uint32_t)); \
496  break; \
497  case 'i': \
498  spa_pod_builder_int(builder, va_arg(args, int)); \
499  break; \
500  case 'l': \
501  spa_pod_builder_long(builder, va_arg(args, int64_t)); \
502  break; \
503  case 'f': \
504  spa_pod_builder_float(builder, va_arg(args, double)); \
505  break; \
506  case 'd': \
507  spa_pod_builder_double(builder, va_arg(args, double)); \
508  break; \
509  case 's': \
510  { \
511  char *strval = va_arg(args, char *); \
512  if (strval != NULL) { \
513  size_t len = strlen(strval); \
514  spa_pod_builder_string_len(builder, strval, len); \
515  } \
516  else \
517  spa_pod_builder_none(builder); \
518  break; \
519  } \
520  case 'S': \
521  { \
522  char *strval = va_arg(args, char *); \
523  size_t len = va_arg(args, int); \
524  spa_pod_builder_string_len(builder, strval, len); \
525  break; \
526  } \
527  case 'y': \
528  { \
529  void *ptr = va_arg(args, void *); \
530  int len = va_arg(args, int); \
531  spa_pod_builder_bytes(builder, ptr, len); \
532  break; \
533  } \
534  case 'R': \
535  { \
536  struct spa_rectangle *rectval = \
537  va_arg(args, struct spa_rectangle *); \
538  spa_pod_builder_rectangle(builder, \
539  rectval->width, rectval->height); \
540  break; \
541  } \
542  case 'F': \
543  { \
544  struct spa_fraction *fracval = \
545  va_arg(args, struct spa_fraction *); \
546  spa_pod_builder_fraction(builder, fracval->num, fracval->denom);\
547  break; \
548  } \
549  case 'a': \
550  { \
551  int child_size = va_arg(args, int); \
552  int child_type = va_arg(args, int); \
553  int n_elems = va_arg(args, int); \
554  void *elems = va_arg(args, void *); \
555  spa_pod_builder_array(builder, child_size, \
556  child_type, n_elems, elems); \
557  break; \
558  } \
559  case 'p': \
560  { \
561  int t = va_arg(args, uint32_t); \
562  spa_pod_builder_pointer(builder, t, va_arg(args, void *)); \
563  break; \
564  } \
565  case 'h': \
566  spa_pod_builder_fd(builder, va_arg(args, int)); \
567  break; \
568  case 'P': \
569  case 'O': \
570  case 'T': \
571  case 'V': \
572  { \
573  struct spa_pod *pod = va_arg(args, struct spa_pod *); \
574  if (pod == NULL) \
575  spa_pod_builder_none(builder); \
576  else \
577  spa_pod_builder_primitive(builder, pod); \
578  break; \
579  } \
580  } \
581 } while(false)
582 
583 static inline int
584 spa_pod_builder_addv(struct spa_pod_builder *builder, va_list args)
585 {
586  int res = 0;
587  struct spa_pod_frame *frame = builder->state.frame;
588  uint32_t ftype = frame ? frame->pod.type : (uint32_t)SPA_TYPE_None;
589 
590  do {
591  const char *format;
592  int n_values = 1;
593  struct spa_pod_frame f;
594  bool choice;
595 
596  switch (ftype) {
597  case SPA_TYPE_Object:
598  {
599  uint32_t key = va_arg(args, uint32_t);
600  if (key == 0)
601  goto exit;
602  spa_pod_builder_prop(builder, key, 0);
603  break;
604  }
605  case SPA_TYPE_Sequence:
606  {
607  uint32_t offset = va_arg(args, uint32_t);
608  uint32_t type = va_arg(args, uint32_t);
609  if (type == 0)
610  goto exit;
611  spa_pod_builder_control(builder, offset, type);
613  }
614  default:
615  break;
616  }
617  if ((format = va_arg(args, const char *)) == NULL)
618  break;
619 
620  choice = *format == '?';
621  if (choice) {
622  uint32_t type = spa_choice_from_id(*++format);
623  if (*format != '\0')
624  format++;
625 
626  spa_pod_builder_push_choice(builder, &f, type, 0);
627 
628  n_values = va_arg(args, int);
629  }
630  while (n_values-- > 0)
631  SPA_POD_BUILDER_COLLECT(builder, *format, args);
632 
633  if (choice)
634  spa_pod_builder_pop(builder, &f);
635  } while (true);
636 
637  exit:
638  return res;
639 }
640 
641 static inline int spa_pod_builder_add(struct spa_pod_builder *builder, ...)
642 {
643  int res;
644  va_list args;
645 
646  va_start(args, builder);
647  res = spa_pod_builder_addv(builder, args);
648  va_end(args);
649 
650  return res;
651 }
652 
653 #define spa_pod_builder_add_object(b,type,id,...) \
654 ({ \
655  struct spa_pod_builder *_b = (b); \
656  struct spa_pod_frame _f; \
657  spa_pod_builder_push_object(_b, &_f, type, id); \
658  spa_pod_builder_add(_b, ##__VA_ARGS__, 0); \
659  spa_pod_builder_pop(_b, &_f); \
660 })
661 
662 #define spa_pod_builder_add_struct(b,...) \
663 ({ \
664  struct spa_pod_builder *_b = (b); \
665  struct spa_pod_frame _f; \
666  spa_pod_builder_push_struct(_b, &_f); \
667  spa_pod_builder_add(_b, ##__VA_ARGS__, NULL); \
668  spa_pod_builder_pop(_b, &_f); \
669 })
670 
671 #define spa_pod_builder_add_sequence(b,unit,...) \
672 ({ \
673  struct spa_pod_builder *_b = (b); \
674  struct spa_pod_frame _f; \
675  spa_pod_builder_push_sequence(_b, &_f, unit); \
676  spa_pod_builder_add(_b, ##__VA_ARGS__, 0, 0); \
677  spa_pod_builder_pop(_b, &_f); \
678 })
679 
681 static inline struct spa_pod *
682 spa_pod_copy(const struct spa_pod *pod)
683 {
684  size_t size;
685  struct spa_pod *c;
686 
687  size = SPA_POD_SIZE(pod);
688  if ((c = (struct spa_pod *) malloc(size)) == NULL)
689  return NULL;
690  return (struct spa_pod *) memcpy(c, pod, size);
691 }
692 
697 #ifdef __cplusplus
698 } /* extern "C" */
699 #endif
700 
701 #endif /* SPA_POD_BUILDER_H */
#define SPA_CALLBACKS_INIT(_funcs, _data)
Initialize the set of functions funcs as a spa_callbacks, together with _data.
Definition: hook.h:154
#define spa_callbacks_call_res(callbacks, type, res, method, vers,...)
Invoke method named method in the callbacks.
Definition: hook.h:219
#define SPA_POD_INIT_Double(val)
Definition: builder.h:292
static int spa_pod_builder_prop(struct spa_pod_builder *builder, uint32_t key, uint32_t flags)
Definition: builder.h:470
#define SPA_POD_INIT_None()
Definition: builder.h:231
#define SPA_POD_INIT(size, type)
Definition: builder.h:228
static int spa_pod_builder_string(struct spa_pod_builder *builder, const char *str)
Definition: builder.h:325
static int spa_pod_builder_child(struct spa_pod_builder *builder, uint32_t size, uint32_t type)
Definition: builder.h:239
static int spa_pod_builder_fraction(struct spa_pod_builder *builder, uint32_t num, uint32_t denom)
Definition: builder.h:385
static int spa_pod_builder_rectangle(struct spa_pod_builder *builder, uint32_t width, uint32_t height)
Definition: builder.h:375
static int spa_pod_builder_float(struct spa_pod_builder *builder, float val)
Definition: builder.h:285
#define SPA_POD_BODY_CONST(pod)
Definition: pod.h:61
static void * spa_pod_builder_pop(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
Definition: builder.h:188
#define SPA_POD_INIT_Object(size, type, id,...)
Definition: builder.h:452
#define SPA_POD_BUILDER_FLAG_BODY
Definition: builder.h:55
static void spa_pod_builder_push(struct spa_pod_builder *builder, struct spa_pod_frame *frame, const struct spa_pod *pod, uint32_t offset)
Definition: builder.h:133
static int spa_pod_builder_double(struct spa_pod_builder *builder, double val)
Definition: builder.h:294
static int spa_pod_builder_write_string(struct spa_pod_builder *builder, const char *str, uint32_t len)
Definition: builder.h:304
#define SPA_POD_INIT_Sequence(size, unit)
Definition: builder.h:476
#define SPA_POD_INIT_Rectangle(val)
Definition: builder.h:372
static void spa_pod_builder_set_callbacks(struct spa_pod_builder *builder, const struct spa_pod_builder_callbacks *callbacks, void *data)
Definition: builder.h:91
#define SPA_POD_INIT_Bool(val)
Definition: builder.h:247
static int spa_pod_builder_id(struct spa_pod_builder *builder, uint32_t val)
Definition: builder.h:258
static int spa_pod_builder_add(struct spa_pod_builder *builder,...)
Definition: builder.h:667
#define SPA_POD_INIT_String(len)
Definition: builder.h:301
static int spa_pod_builder_fd(struct spa_pod_builder *builder, int64_t fd)
Definition: builder.h:365
#define SPA_POD_BODY(pod)
Definition: pod.h:59
static void spa_pod_builder_reset(struct spa_pod_builder *builder, struct spa_pod_builder_state *state)
Definition: builder.h:98
static int spa_pod_builder_none(struct spa_pod_builder *builder)
Definition: builder.h:233
static struct spa_pod * spa_pod_copy(const struct spa_pod *pod)
Copy a pod structure.
Definition: builder.h:708
#define SPA_POD_INIT_Id(val)
Definition: builder.h:256
static int spa_pod_builder_push_sequence(struct spa_pod_builder *builder, struct spa_pod_frame *frame, uint32_t unit)
Definition: builder.h:480
static int spa_pod_builder_raw_padded(struct spa_pod_builder *builder, const void *data, uint32_t size)
Definition: builder.h:180
#define SPA_POD_BODY_SIZE(pod)
Definition: pod.h:46
#define SPA_POD_BUILDER_INIT(buffer, size)
Definition: builder.h:82
static int spa_pod_builder_pad(struct spa_pod_builder *builder, uint32_t size)
Definition: builder.h:172
static int spa_pod_builder_string_len(struct spa_pod_builder *builder, const char *str, uint32_t len)
Definition: builder.h:316
#define SPA_POD_INIT_Struct(size)
Definition: builder.h:439
static int spa_pod_builder_push_array(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
Definition: builder.h:392
static int spa_pod_builder_primitive(struct spa_pod_builder *builder, const struct spa_pod *p)
Definition: builder.h:206
static uint32_t spa_choice_from_id(char id)
Definition: builder.h:497
static int spa_pod_builder_push_struct(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
Definition: builder.h:442
static uint32_t spa_pod_builder_control(struct spa_pod_builder *builder, uint32_t offset, uint32_t type)
Definition: builder.h:491
static void spa_pod_builder_get_state(struct spa_pod_builder *builder, struct spa_pod_builder_state *state)
Definition: builder.h:85
static int spa_pod_builder_bool(struct spa_pod_builder *builder, bool val)
Definition: builder.h:249
#define SPA_POD_BUILDER_COLLECT(builder, type, args)
Definition: builder.h:514
static struct spa_pod * spa_pod_builder_frame(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
Definition: builder.h:125
static int spa_pod_builder_raw(struct spa_pod_builder *builder, const void *data, uint32_t size)
Definition: builder.h:148
#define SPA_POD_INIT_Int(val)
Definition: builder.h:265
static int spa_pod_builder_bytes(struct spa_pod_builder *builder, const void *bytes, uint32_t len)
Definition: builder.h:335
static int spa_pod_builder_push_choice(struct spa_pod_builder *builder, struct spa_pod_frame *frame, uint32_t type, uint32_t flags)
Definition: builder.h:426
static int spa_pod_builder_int(struct spa_pod_builder *builder, int32_t val)
Definition: builder.h:267
static void spa_pod_builder_init(struct spa_pod_builder *builder, void *data, uint32_t size)
Definition: builder.h:107
static int spa_pod_builder_push_object(struct spa_pod_builder *builder, struct spa_pod_frame *frame, uint32_t type, uint32_t id)
Definition: builder.h:455
#define SPA_POD_INIT_Float(val)
Definition: builder.h:283
static int spa_pod_builder_long(struct spa_pod_builder *builder, int64_t val)
Definition: builder.h:276
#define SPA_POD_INIT_Bytes(len)
Definition: builder.h:332
#define SPA_POD_INIT_Fd(fd)
Definition: builder.h:363
static int spa_pod_builder_array(struct spa_pod_builder *builder, uint32_t child_size, uint32_t child_type, uint32_t n_elems, const void *elems)
Definition: builder.h:404
#define SPA_POD_INIT_Long(val)
Definition: builder.h:274
static void * spa_pod_builder_reserve_bytes(struct spa_pod_builder *builder, uint32_t len)
Definition: builder.h:344
#define SPA_POD_INIT_Pointer(type, value)
Definition: builder.h:353
#define SPA_POD_INIT_Fraction(val)
Definition: builder.h:382
#define SPA_POD_BUILDER_FLAG_FIRST
Definition: builder.h:57
#define SPA_POD_SIZE(pod)
Definition: pod.h:50
static int spa_pod_builder_addv(struct spa_pod_builder *builder, va_list args)
Definition: builder.h:610
static int spa_pod_builder_pointer(struct spa_pod_builder *builder, uint32_t type, const void *val)
Definition: builder.h:356
static struct spa_pod * spa_pod_builder_deref(struct spa_pod_builder *builder, uint32_t offset)
Definition: builder.h:113
@ SPA_CHOICE_Step
range with step: default, min, max, step
Definition: pod.h:169
@ SPA_CHOICE_None
no choice, first value is current
Definition: pod.h:167
@ SPA_CHOICE_Flags
flags: default, possible flags,...
Definition: pod.h:171
@ SPA_CHOICE_Range
range: default, min, max
Definition: pod.h:168
@ SPA_CHOICE_Enum
list: default, alternative,...
Definition: pod.h:170
@ SPA_TYPE_Object
Definition: type.h:65
@ SPA_TYPE_None
Definition: type.h:51
@ SPA_TYPE_Sequence
Definition: type.h:66
@ SPA_TYPE_Choice
Definition: type.h:69
@ SPA_TYPE_Array
Definition: type.h:63
#define SPA_ROUND_UP_N(num, align)
Definition: defs.h:336
#define SPA_FRACTION(num, denom)
Definition: defs.h:138
#define SPA_FLAG_IS_SET(field, flag)
Definition: defs.h:92
#define SPA_FALLTHROUGH
SPA_FALLTHROUGH is an annotation to suppress compiler warnings about switch cases that fall through w...
Definition: defs.h:86
#define SPA_FLAG_CLEAR(field, flag)
Definition: defs.h:96
#define SPA_PTROFF(ptr_, offset_, type_)
Return the address (buffer + offset) as pointer of type.
Definition: defs.h:210
#define SPA_RECTANGLE(width, height)
Definition: defs.h:117
spa/utils/hook.h
spa/pod/iter.h
Callbacks, contains the structure with functions and the data passed to the functions.
Definition: hook.h:136
void * data
Definition: hook.h:138
Definition: pod.h:141
Definition: pod.h:146
struct spa_pod pod
Definition: pod.h:147
Definition: pod.h:71
struct spa_pod pod
Definition: pod.h:72
Definition: builder.h:65
int(* overflow)(void *data, uint32_t size)
Definition: builder.h:70
uint32_t version
Definition: builder.h:68
Definition: builder.h:52
uint32_t flags
Definition: builder.h:58
uint32_t offset
Definition: builder.h:53
struct spa_pod_frame * frame
Definition: builder.h:59
Definition: builder.h:73
uint32_t _padding
Definition: builder.h:76
struct spa_callbacks callbacks
Definition: builder.h:78
void * data
Definition: builder.h:74
struct spa_pod_builder_state state
Definition: builder.h:77
uint32_t size
Definition: builder.h:75
Definition: pod.h:110
Definition: pod.h:174
uint32_t type
type of choice, one of enum spa_choice_type
Definition: pod.h:175
uint32_t flags
extra flags
Definition: pod.h:176
Definition: pod.h:182
struct spa_pod pod
Definition: pod.h:183
Definition: pod.h:100
struct spa_pod pod
Definition: pod.h:101
Definition: pod.h:219
struct spa_pod pod
Definition: pod.h:220
Definition: pod.h:94
struct spa_pod pod
Definition: pod.h:95
Definition: pod.h:120
struct spa_pod pod
Definition: pod.h:121
Definition: iter.h:47
struct spa_pod pod
Definition: iter.h:48
uint32_t offset
Definition: iter.h:50
struct spa_pod_frame * parent
Definition: iter.h:49
uint32_t flags
Definition: iter.h:51
Definition: pod.h:77
struct spa_pod pod
Definition: pod.h:78
Definition: pod.h:83
struct spa_pod pod
Definition: pod.h:84
Definition: pod.h:89
struct spa_pod pod
Definition: pod.h:90
Definition: pod.h:197
Definition: pod.h:203
struct spa_pod pod
Definition: pod.h:204
Definition: pod.h:214
struct spa_pod pod
Definition: pod.h:215
Definition: pod.h:115
struct spa_pod pod
Definition: pod.h:116
Definition: pod.h:261
a sequence of timed controls
Definition: pod.h:268
struct spa_pod pod
Definition: pod.h:269
Definition: pod.h:105
Definition: pod.h:187
struct spa_pod pod
Definition: pod.h:188
Definition: pod.h:63
uint32_t type
Definition: pod.h:65
uint32_t size
Definition: pod.h:64
spa/pod/vararg.h