]> code.delx.au - pulseaudio/blob - src/pulsecore/tagstruct.c
Remove unnecessary #includes
[pulseaudio] / src / pulsecore / tagstruct.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
10
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <sys/time.h>
30 #include <stdarg.h>
31
32 #ifdef HAVE_NETINET_IN_H
33 #include <netinet/in.h>
34 #endif
35
36 #include <pulse/xmalloc.h>
37
38 #include <pulsecore/socket.h>
39 #include <pulsecore/macro.h>
40
41 #include "tagstruct.h"
42
43 #define MAX_TAG_SIZE (64*1024)
44
45 struct pa_tagstruct {
46 uint8_t *data;
47 size_t length, allocated;
48 size_t rindex;
49
50 pa_bool_t dynamic;
51 };
52
53 pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) {
54 pa_tagstruct*t;
55
56 pa_assert(!data || (data && length));
57
58 t = pa_xnew(pa_tagstruct, 1);
59 t->data = (uint8_t*) data;
60 t->allocated = t->length = data ? length : 0;
61 t->rindex = 0;
62 t->dynamic = !data;
63
64 return t;
65 }
66
67 void pa_tagstruct_free(pa_tagstruct*t) {
68 pa_assert(t);
69
70 if (t->dynamic)
71 pa_xfree(t->data);
72 pa_xfree(t);
73 }
74
75 uint8_t* pa_tagstruct_free_data(pa_tagstruct*t, size_t *l) {
76 uint8_t *p;
77
78 pa_assert(t);
79 pa_assert(t->dynamic);
80 pa_assert(l);
81
82 p = t->data;
83 *l = t->length;
84 pa_xfree(t);
85 return p;
86 }
87
88 static void extend(pa_tagstruct*t, size_t l) {
89 pa_assert(t);
90 pa_assert(t->dynamic);
91
92 if (t->length+l <= t->allocated)
93 return;
94
95 t->data = pa_xrealloc(t->data, t->allocated = t->length+l+100);
96 }
97
98 void pa_tagstruct_puts(pa_tagstruct*t, const char *s) {
99 size_t l;
100 pa_assert(t);
101
102 if (s) {
103 l = strlen(s)+2;
104 extend(t, l);
105 t->data[t->length] = PA_TAG_STRING;
106 strcpy((char*) (t->data+t->length+1), s);
107 t->length += l;
108 } else {
109 extend(t, 1);
110 t->data[t->length] = PA_TAG_STRING_NULL;
111 t->length += 1;
112 }
113 }
114
115 void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i) {
116 pa_assert(t);
117
118 extend(t, 5);
119 t->data[t->length] = PA_TAG_U32;
120 i = htonl(i);
121 memcpy(t->data+t->length+1, &i, 4);
122 t->length += 5;
123 }
124
125 void pa_tagstruct_putu8(pa_tagstruct*t, uint8_t c) {
126 pa_assert(t);
127
128 extend(t, 2);
129 t->data[t->length] = PA_TAG_U8;
130 *(t->data+t->length+1) = c;
131 t->length += 2;
132 }
133
134 void pa_tagstruct_put_sample_spec(pa_tagstruct *t, const pa_sample_spec *ss) {
135 uint32_t rate;
136
137 pa_assert(t);
138 pa_assert(ss);
139
140 extend(t, 7);
141 t->data[t->length] = PA_TAG_SAMPLE_SPEC;
142 t->data[t->length+1] = (uint8_t) ss->format;
143 t->data[t->length+2] = ss->channels;
144 rate = htonl(ss->rate);
145 memcpy(t->data+t->length+3, &rate, 4);
146 t->length += 7;
147 }
148
149 void pa_tagstruct_put_arbitrary(pa_tagstruct *t, const void *p, size_t length) {
150 uint32_t tmp;
151
152 pa_assert(t);
153 pa_assert(p);
154
155 extend(t, 5+length);
156 t->data[t->length] = PA_TAG_ARBITRARY;
157 tmp = htonl((uint32_t) length);
158 memcpy(t->data+t->length+1, &tmp, 4);
159 if (length)
160 memcpy(t->data+t->length+5, p, length);
161 t->length += 5+length;
162 }
163
164 void pa_tagstruct_put_boolean(pa_tagstruct*t, pa_bool_t b) {
165 pa_assert(t);
166
167 extend(t, 1);
168 t->data[t->length] = (uint8_t) (b ? PA_TAG_BOOLEAN_TRUE : PA_TAG_BOOLEAN_FALSE);
169 t->length += 1;
170 }
171
172 void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv) {
173 uint32_t tmp;
174 pa_assert(t);
175
176 extend(t, 9);
177 t->data[t->length] = PA_TAG_TIMEVAL;
178 tmp = htonl((uint32_t) tv->tv_sec);
179 memcpy(t->data+t->length+1, &tmp, 4);
180 tmp = htonl((uint32_t) tv->tv_usec);
181 memcpy(t->data+t->length+5, &tmp, 4);
182 t->length += 9;
183 }
184
185 void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u) {
186 uint32_t tmp;
187
188 pa_assert(t);
189
190 extend(t, 9);
191 t->data[t->length] = PA_TAG_USEC;
192 tmp = htonl((uint32_t) (u >> 32));
193 memcpy(t->data+t->length+1, &tmp, 4);
194 tmp = htonl((uint32_t) u);
195 memcpy(t->data+t->length+5, &tmp, 4);
196 t->length += 9;
197 }
198
199 void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t u) {
200 uint32_t tmp;
201
202 pa_assert(t);
203
204 extend(t, 9);
205 t->data[t->length] = PA_TAG_U64;
206 tmp = htonl((uint32_t) (u >> 32));
207 memcpy(t->data+t->length+1, &tmp, 4);
208 tmp = htonl((uint32_t) u);
209 memcpy(t->data+t->length+5, &tmp, 4);
210 t->length += 9;
211 }
212
213 void pa_tagstruct_puts64(pa_tagstruct*t, int64_t u) {
214 uint32_t tmp;
215
216 pa_assert(t);
217
218 extend(t, 9);
219 t->data[t->length] = PA_TAG_S64;
220 tmp = htonl((uint32_t) ((uint64_t) u >> 32));
221 memcpy(t->data+t->length+1, &tmp, 4);
222 tmp = htonl((uint32_t) ((uint64_t) u));
223 memcpy(t->data+t->length+5, &tmp, 4);
224 t->length += 9;
225 }
226
227 void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map) {
228 unsigned i;
229
230 pa_assert(t);
231 pa_assert(map);
232 extend(t, 2 + (size_t) map->channels);
233
234 t->data[t->length++] = PA_TAG_CHANNEL_MAP;
235 t->data[t->length++] = map->channels;
236
237 for (i = 0; i < map->channels; i ++)
238 t->data[t->length++] = (uint8_t) map->map[i];
239 }
240
241 void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) {
242 unsigned i;
243 pa_volume_t vol;
244
245 pa_assert(t);
246 pa_assert(cvolume);
247 extend(t, 2 + cvolume->channels * sizeof(pa_volume_t));
248
249 t->data[t->length++] = PA_TAG_CVOLUME;
250 t->data[t->length++] = cvolume->channels;
251
252 for (i = 0; i < cvolume->channels; i ++) {
253 vol = htonl(cvolume->values[i]);
254 memcpy(t->data + t->length, &vol, sizeof(pa_volume_t));
255 t->length += sizeof(pa_volume_t);
256 }
257 }
258
259 void pa_tagstruct_put_volume(pa_tagstruct *t, pa_volume_t vol) {
260 uint32_t u;
261 pa_assert(t);
262
263 extend(t, 5);
264 t->data[t->length] = PA_TAG_VOLUME;
265 u = htonl((uint32_t) vol);
266 memcpy(t->data+t->length+1, &u, 4);
267 t->length += 5;
268 }
269
270 void pa_tagstruct_put_proplist(pa_tagstruct *t, pa_proplist *p) {
271 void *state = NULL;
272 pa_assert(t);
273 pa_assert(p);
274
275 extend(t, 1);
276
277 t->data[t->length++] = PA_TAG_PROPLIST;
278
279 for (;;) {
280 const char *k;
281 const void *d;
282 size_t l;
283
284 if (!(k = pa_proplist_iterate(p, &state)))
285 break;
286
287 pa_tagstruct_puts(t, k);
288 pa_assert_se(pa_proplist_get(p, k, &d, &l) >= 0);
289 pa_tagstruct_putu32(t, (uint32_t) l);
290 pa_tagstruct_put_arbitrary(t, d, l);
291 }
292
293 pa_tagstruct_puts(t, NULL);
294 }
295
296 void pa_tagstruct_put_format_info(pa_tagstruct *t, pa_format_info *f) {
297 pa_assert(t);
298 pa_assert(f);
299
300 extend(t, 1);
301
302 t->data[t->length++] = PA_TAG_FORMAT_INFO;
303 pa_tagstruct_putu8(t, (uint8_t) f->encoding);
304 pa_tagstruct_put_proplist(t, f->plist);
305 }
306
307 int pa_tagstruct_gets(pa_tagstruct*t, const char **s) {
308 int error = 0;
309 size_t n;
310 char *c;
311
312 pa_assert(t);
313 pa_assert(s);
314
315 if (t->rindex+1 > t->length)
316 return -1;
317
318 if (t->data[t->rindex] == PA_TAG_STRING_NULL) {
319 t->rindex++;
320 *s = NULL;
321 return 0;
322 }
323
324 if (t->rindex+2 > t->length)
325 return -1;
326
327 if (t->data[t->rindex] != PA_TAG_STRING)
328 return -1;
329
330 error = 1;
331 for (n = 0, c = (char*) (t->data+t->rindex+1); t->rindex+1+n < t->length; n++, c++)
332 if (!*c) {
333 error = 0;
334 break;
335 }
336
337 if (error)
338 return -1;
339
340 *s = (char*) (t->data+t->rindex+1);
341
342 t->rindex += n+2;
343 return 0;
344 }
345
346 int pa_tagstruct_getu32(pa_tagstruct*t, uint32_t *i) {
347 pa_assert(t);
348 pa_assert(i);
349
350 if (t->rindex+5 > t->length)
351 return -1;
352
353 if (t->data[t->rindex] != PA_TAG_U32)
354 return -1;
355
356 memcpy(i, t->data+t->rindex+1, 4);
357 *i = ntohl(*i);
358 t->rindex += 5;
359 return 0;
360 }
361
362 int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c) {
363 pa_assert(t);
364 pa_assert(c);
365
366 if (t->rindex+2 > t->length)
367 return -1;
368
369 if (t->data[t->rindex] != PA_TAG_U8)
370 return -1;
371
372 *c = t->data[t->rindex+1];
373 t->rindex +=2;
374 return 0;
375 }
376
377 int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss) {
378 pa_assert(t);
379 pa_assert(ss);
380
381 if (t->rindex+7 > t->length)
382 return -1;
383
384 if (t->data[t->rindex] != PA_TAG_SAMPLE_SPEC)
385 return -1;
386
387 ss->format = t->data[t->rindex+1];
388 ss->channels = t->data[t->rindex+2];
389 memcpy(&ss->rate, t->data+t->rindex+3, 4);
390 ss->rate = ntohl(ss->rate);
391
392 t->rindex += 7;
393 return 0;
394 }
395
396 int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length) {
397 uint32_t len;
398
399 pa_assert(t);
400 pa_assert(p);
401
402 if (t->rindex+5+length > t->length)
403 return -1;
404
405 if (t->data[t->rindex] != PA_TAG_ARBITRARY)
406 return -1;
407
408 memcpy(&len, t->data+t->rindex+1, 4);
409 if (ntohl(len) != length)
410 return -1;
411
412 *p = t->data+t->rindex+5;
413 t->rindex += 5+length;
414 return 0;
415 }
416
417 int pa_tagstruct_eof(pa_tagstruct*t) {
418 pa_assert(t);
419
420 return t->rindex >= t->length;
421 }
422
423 const uint8_t* pa_tagstruct_data(pa_tagstruct*t, size_t *l) {
424 pa_assert(t);
425 pa_assert(t->dynamic);
426 pa_assert(l);
427
428 *l = t->length;
429 return t->data;
430 }
431
432 int pa_tagstruct_get_boolean(pa_tagstruct*t, pa_bool_t *b) {
433 pa_assert(t);
434 pa_assert(b);
435
436 if (t->rindex+1 > t->length)
437 return -1;
438
439 if (t->data[t->rindex] == PA_TAG_BOOLEAN_TRUE)
440 *b = TRUE;
441 else if (t->data[t->rindex] == PA_TAG_BOOLEAN_FALSE)
442 *b = FALSE;
443 else
444 return -1;
445
446 t->rindex +=1;
447 return 0;
448 }
449
450 int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv) {
451
452 pa_assert(t);
453 pa_assert(tv);
454
455 if (t->rindex+9 > t->length)
456 return -1;
457
458 if (t->data[t->rindex] != PA_TAG_TIMEVAL)
459 return -1;
460
461 memcpy(&tv->tv_sec, t->data+t->rindex+1, 4);
462 tv->tv_sec = (time_t) ntohl((uint32_t) tv->tv_sec);
463 memcpy(&tv->tv_usec, t->data+t->rindex+5, 4);
464 tv->tv_usec = (suseconds_t) ntohl((uint32_t) tv->tv_usec);
465 t->rindex += 9;
466 return 0;
467 }
468
469 int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u) {
470 uint32_t tmp;
471
472 pa_assert(t);
473 pa_assert(u);
474
475 if (t->rindex+9 > t->length)
476 return -1;
477
478 if (t->data[t->rindex] != PA_TAG_USEC)
479 return -1;
480
481 memcpy(&tmp, t->data+t->rindex+1, 4);
482 *u = (pa_usec_t) ntohl(tmp) << 32;
483 memcpy(&tmp, t->data+t->rindex+5, 4);
484 *u |= (pa_usec_t) ntohl(tmp);
485 t->rindex +=9;
486 return 0;
487 }
488
489 int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *u) {
490 uint32_t tmp;
491
492 pa_assert(t);
493 pa_assert(u);
494
495 if (t->rindex+9 > t->length)
496 return -1;
497
498 if (t->data[t->rindex] != PA_TAG_U64)
499 return -1;
500
501 memcpy(&tmp, t->data+t->rindex+1, 4);
502 *u = (uint64_t) ntohl(tmp) << 32;
503 memcpy(&tmp, t->data+t->rindex+5, 4);
504 *u |= (uint64_t) ntohl(tmp);
505 t->rindex +=9;
506 return 0;
507 }
508
509 int pa_tagstruct_gets64(pa_tagstruct*t, int64_t *u) {
510 uint32_t tmp;
511
512 pa_assert(t);
513 pa_assert(u);
514
515 if (t->rindex+9 > t->length)
516 return -1;
517
518 if (t->data[t->rindex] != PA_TAG_S64)
519 return -1;
520
521 memcpy(&tmp, t->data+t->rindex+1, 4);
522 *u = (int64_t) ((uint64_t) ntohl(tmp) << 32);
523 memcpy(&tmp, t->data+t->rindex+5, 4);
524 *u |= (int64_t) ntohl(tmp);
525 t->rindex +=9;
526 return 0;
527 }
528
529 int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) {
530 unsigned i;
531
532 pa_assert(t);
533 pa_assert(map);
534
535 if (t->rindex+2 > t->length)
536 return -1;
537
538 if (t->data[t->rindex] != PA_TAG_CHANNEL_MAP)
539 return -1;
540
541 if ((map->channels = t->data[t->rindex+1]) > PA_CHANNELS_MAX)
542 return -1;
543
544 if (t->rindex+2+map->channels > t->length)
545 return -1;
546
547 for (i = 0; i < map->channels; i ++)
548 map->map[i] = (int8_t) t->data[t->rindex + 2 + i];
549
550 t->rindex += 2 + (size_t) map->channels;
551 return 0;
552 }
553
554 int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) {
555 unsigned i;
556 pa_volume_t vol;
557
558 pa_assert(t);
559 pa_assert(cvolume);
560
561 if (t->rindex+2 > t->length)
562 return -1;
563
564 if (t->data[t->rindex] != PA_TAG_CVOLUME)
565 return -1;
566
567 if ((cvolume->channels = t->data[t->rindex+1]) > PA_CHANNELS_MAX)
568 return -1;
569
570 if (t->rindex+2+cvolume->channels*sizeof(pa_volume_t) > t->length)
571 return -1;
572
573 for (i = 0; i < cvolume->channels; i ++) {
574 memcpy(&vol, t->data + t->rindex + 2 + i * sizeof(pa_volume_t), sizeof(pa_volume_t));
575 cvolume->values[i] = (pa_volume_t) ntohl(vol);
576 }
577
578 t->rindex += 2 + cvolume->channels * sizeof(pa_volume_t);
579 return 0;
580 }
581
582 int pa_tagstruct_get_volume(pa_tagstruct*t, pa_volume_t *vol) {
583 uint32_t u;
584
585 pa_assert(t);
586 pa_assert(vol);
587
588 if (t->rindex+5 > t->length)
589 return -1;
590
591 if (t->data[t->rindex] != PA_TAG_VOLUME)
592 return -1;
593
594 memcpy(&u, t->data+t->rindex+1, 4);
595 *vol = (pa_volume_t) ntohl(u);
596
597 t->rindex += 5;
598 return 0;
599 }
600
601 int pa_tagstruct_get_proplist(pa_tagstruct *t, pa_proplist *p) {
602 size_t saved_rindex;
603
604 pa_assert(t);
605 pa_assert(p);
606
607 if (t->rindex+1 > t->length)
608 return -1;
609
610 if (t->data[t->rindex] != PA_TAG_PROPLIST)
611 return -1;
612
613 saved_rindex = t->rindex;
614 t->rindex++;
615
616 for (;;) {
617 const char *k;
618 const void *d;
619 uint32_t length;
620
621 if (pa_tagstruct_gets(t, &k) < 0)
622 goto fail;
623
624 if (!k)
625 break;
626
627 if (pa_tagstruct_getu32(t, &length) < 0)
628 goto fail;
629
630 if (length > MAX_TAG_SIZE)
631 goto fail;
632
633 if (pa_tagstruct_get_arbitrary(t, &d, length) < 0)
634 goto fail;
635
636 if (pa_proplist_set(p, k, d, length) < 0)
637 goto fail;
638 }
639
640 return 0;
641
642 fail:
643 t->rindex = saved_rindex;
644 return -1;
645 }
646
647 int pa_tagstruct_get_format_info(pa_tagstruct *t, pa_format_info *f) {
648 size_t saved_rindex;
649 uint8_t encoding;
650
651 pa_assert(t);
652 pa_assert(f);
653
654 if (t->rindex+1 > t->length)
655 return -1;
656
657 if (t->data[t->rindex] != PA_TAG_FORMAT_INFO)
658 return -1;
659
660 saved_rindex = t->rindex;
661 t->rindex++;
662
663 if (pa_tagstruct_getu8(t, &encoding) < 0)
664 goto fail;
665
666 f->encoding = encoding;
667
668 if (pa_tagstruct_get_proplist(t, f->plist) < 0)
669 goto fail;
670
671 return 0;
672
673 fail:
674 t->rindex = saved_rindex;
675 return -1;
676 }
677
678 void pa_tagstruct_put(pa_tagstruct *t, ...) {
679 va_list va;
680 pa_assert(t);
681
682 va_start(va, t);
683
684 for (;;) {
685 int tag = va_arg(va, int);
686
687 if (tag == PA_TAG_INVALID)
688 break;
689
690 switch (tag) {
691 case PA_TAG_STRING:
692 case PA_TAG_STRING_NULL:
693 pa_tagstruct_puts(t, va_arg(va, char*));
694 break;
695
696 case PA_TAG_U32:
697 pa_tagstruct_putu32(t, va_arg(va, uint32_t));
698 break;
699
700 case PA_TAG_U8:
701 pa_tagstruct_putu8(t, (uint8_t) va_arg(va, int));
702 break;
703
704 case PA_TAG_U64:
705 pa_tagstruct_putu64(t, va_arg(va, uint64_t));
706 break;
707
708 case PA_TAG_SAMPLE_SPEC:
709 pa_tagstruct_put_sample_spec(t, va_arg(va, pa_sample_spec*));
710 break;
711
712 case PA_TAG_ARBITRARY: {
713 void *p = va_arg(va, void*);
714 size_t size = va_arg(va, size_t);
715 pa_tagstruct_put_arbitrary(t, p, size);
716 break;
717 }
718
719 case PA_TAG_BOOLEAN_TRUE:
720 case PA_TAG_BOOLEAN_FALSE:
721 pa_tagstruct_put_boolean(t, va_arg(va, int));
722 break;
723
724 case PA_TAG_TIMEVAL:
725 pa_tagstruct_put_timeval(t, va_arg(va, struct timeval*));
726 break;
727
728 case PA_TAG_USEC:
729 pa_tagstruct_put_usec(t, va_arg(va, pa_usec_t));
730 break;
731
732 case PA_TAG_CHANNEL_MAP:
733 pa_tagstruct_put_channel_map(t, va_arg(va, pa_channel_map *));
734 break;
735
736 case PA_TAG_CVOLUME:
737 pa_tagstruct_put_cvolume(t, va_arg(va, pa_cvolume *));
738 break;
739
740 case PA_TAG_VOLUME:
741 pa_tagstruct_put_volume(t, va_arg(va, pa_volume_t));
742 break;
743
744 case PA_TAG_PROPLIST:
745 pa_tagstruct_put_proplist(t, va_arg(va, pa_proplist *));
746 break;
747
748 default:
749 pa_assert_not_reached();
750 }
751 }
752
753 va_end(va);
754 }
755
756 int pa_tagstruct_get(pa_tagstruct *t, ...) {
757 va_list va;
758 int ret = 0;
759
760 pa_assert(t);
761
762 va_start(va, t);
763 while (ret == 0) {
764 int tag = va_arg(va, int);
765
766 if (tag == PA_TAG_INVALID)
767 break;
768
769 switch (tag) {
770 case PA_TAG_STRING:
771 case PA_TAG_STRING_NULL:
772 ret = pa_tagstruct_gets(t, va_arg(va, const char**));
773 break;
774
775 case PA_TAG_U32:
776 ret = pa_tagstruct_getu32(t, va_arg(va, uint32_t*));
777 break;
778
779 case PA_TAG_U8:
780 ret = pa_tagstruct_getu8(t, va_arg(va, uint8_t*));
781 break;
782
783 case PA_TAG_U64:
784 ret = pa_tagstruct_getu64(t, va_arg(va, uint64_t*));
785 break;
786
787 case PA_TAG_SAMPLE_SPEC:
788 ret = pa_tagstruct_get_sample_spec(t, va_arg(va, pa_sample_spec*));
789 break;
790
791 case PA_TAG_ARBITRARY: {
792 const void **p = va_arg(va, const void**);
793 size_t size = va_arg(va, size_t);
794 ret = pa_tagstruct_get_arbitrary(t, p, size);
795 break;
796 }
797
798 case PA_TAG_BOOLEAN_TRUE:
799 case PA_TAG_BOOLEAN_FALSE:
800 ret = pa_tagstruct_get_boolean(t, va_arg(va, pa_bool_t*));
801 break;
802
803 case PA_TAG_TIMEVAL:
804 ret = pa_tagstruct_get_timeval(t, va_arg(va, struct timeval*));
805 break;
806
807 case PA_TAG_USEC:
808 ret = pa_tagstruct_get_usec(t, va_arg(va, pa_usec_t*));
809 break;
810
811 case PA_TAG_CHANNEL_MAP:
812 ret = pa_tagstruct_get_channel_map(t, va_arg(va, pa_channel_map *));
813 break;
814
815 case PA_TAG_CVOLUME:
816 ret = pa_tagstruct_get_cvolume(t, va_arg(va, pa_cvolume *));
817 break;
818
819 case PA_TAG_VOLUME:
820 ret = pa_tagstruct_get_volume(t, va_arg(va, pa_volume_t *));
821 break;
822
823 case PA_TAG_PROPLIST:
824 ret = pa_tagstruct_get_proplist(t, va_arg(va, pa_proplist *));
825 break;
826
827 default:
828 pa_assert_not_reached();
829 }
830
831 }
832
833 va_end(va);
834 return ret;
835 }