]> code.delx.au - pulseaudio/blob - src/pulsecore/tagstruct.c
remap: Change remapping function argument type from void to int16_t / float as approp...
[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 bool 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, bool 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, bool *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
606 if (t->rindex+1 > t->length)
607 return -1;
608
609 if (t->data[t->rindex] != PA_TAG_PROPLIST)
610 return -1;
611
612 saved_rindex = t->rindex;
613 t->rindex++;
614
615 for (;;) {
616 const char *k;
617 const void *d;
618 uint32_t length;
619
620 if (pa_tagstruct_gets(t, &k) < 0)
621 goto fail;
622
623 if (!k)
624 break;
625
626 if (!pa_proplist_key_valid(k))
627 goto fail;
628
629 if (pa_tagstruct_getu32(t, &length) < 0)
630 goto fail;
631
632 if (length > MAX_TAG_SIZE)
633 goto fail;
634
635 if (pa_tagstruct_get_arbitrary(t, &d, length) < 0)
636 goto fail;
637
638 if (p)
639 pa_assert_se(pa_proplist_set(p, k, d, length) >= 0);
640 }
641
642 return 0;
643
644 fail:
645 t->rindex = saved_rindex;
646 return -1;
647 }
648
649 int pa_tagstruct_get_format_info(pa_tagstruct *t, pa_format_info *f) {
650 size_t saved_rindex;
651 uint8_t encoding;
652
653 pa_assert(t);
654 pa_assert(f);
655
656 if (t->rindex+1 > t->length)
657 return -1;
658
659 if (t->data[t->rindex] != PA_TAG_FORMAT_INFO)
660 return -1;
661
662 saved_rindex = t->rindex;
663 t->rindex++;
664
665 if (pa_tagstruct_getu8(t, &encoding) < 0)
666 goto fail;
667
668 f->encoding = encoding;
669
670 if (pa_tagstruct_get_proplist(t, f->plist) < 0)
671 goto fail;
672
673 return 0;
674
675 fail:
676 t->rindex = saved_rindex;
677 return -1;
678 }
679
680 void pa_tagstruct_put(pa_tagstruct *t, ...) {
681 va_list va;
682 pa_assert(t);
683
684 va_start(va, t);
685
686 for (;;) {
687 int tag = va_arg(va, int);
688
689 if (tag == PA_TAG_INVALID)
690 break;
691
692 switch (tag) {
693 case PA_TAG_STRING:
694 case PA_TAG_STRING_NULL:
695 pa_tagstruct_puts(t, va_arg(va, char*));
696 break;
697
698 case PA_TAG_U32:
699 pa_tagstruct_putu32(t, va_arg(va, uint32_t));
700 break;
701
702 case PA_TAG_U8:
703 pa_tagstruct_putu8(t, (uint8_t) va_arg(va, int));
704 break;
705
706 case PA_TAG_U64:
707 pa_tagstruct_putu64(t, va_arg(va, uint64_t));
708 break;
709
710 case PA_TAG_SAMPLE_SPEC:
711 pa_tagstruct_put_sample_spec(t, va_arg(va, pa_sample_spec*));
712 break;
713
714 case PA_TAG_ARBITRARY: {
715 void *p = va_arg(va, void*);
716 size_t size = va_arg(va, size_t);
717 pa_tagstruct_put_arbitrary(t, p, size);
718 break;
719 }
720
721 case PA_TAG_BOOLEAN_TRUE:
722 case PA_TAG_BOOLEAN_FALSE:
723 pa_tagstruct_put_boolean(t, va_arg(va, int));
724 break;
725
726 case PA_TAG_TIMEVAL:
727 pa_tagstruct_put_timeval(t, va_arg(va, struct timeval*));
728 break;
729
730 case PA_TAG_USEC:
731 pa_tagstruct_put_usec(t, va_arg(va, pa_usec_t));
732 break;
733
734 case PA_TAG_CHANNEL_MAP:
735 pa_tagstruct_put_channel_map(t, va_arg(va, pa_channel_map *));
736 break;
737
738 case PA_TAG_CVOLUME:
739 pa_tagstruct_put_cvolume(t, va_arg(va, pa_cvolume *));
740 break;
741
742 case PA_TAG_VOLUME:
743 pa_tagstruct_put_volume(t, va_arg(va, pa_volume_t));
744 break;
745
746 case PA_TAG_PROPLIST:
747 pa_tagstruct_put_proplist(t, va_arg(va, pa_proplist *));
748 break;
749
750 default:
751 pa_assert_not_reached();
752 }
753 }
754
755 va_end(va);
756 }
757
758 int pa_tagstruct_get(pa_tagstruct *t, ...) {
759 va_list va;
760 int ret = 0;
761
762 pa_assert(t);
763
764 va_start(va, t);
765 while (ret == 0) {
766 int tag = va_arg(va, int);
767
768 if (tag == PA_TAG_INVALID)
769 break;
770
771 switch (tag) {
772 case PA_TAG_STRING:
773 case PA_TAG_STRING_NULL:
774 ret = pa_tagstruct_gets(t, va_arg(va, const char**));
775 break;
776
777 case PA_TAG_U32:
778 ret = pa_tagstruct_getu32(t, va_arg(va, uint32_t*));
779 break;
780
781 case PA_TAG_U8:
782 ret = pa_tagstruct_getu8(t, va_arg(va, uint8_t*));
783 break;
784
785 case PA_TAG_U64:
786 ret = pa_tagstruct_getu64(t, va_arg(va, uint64_t*));
787 break;
788
789 case PA_TAG_SAMPLE_SPEC:
790 ret = pa_tagstruct_get_sample_spec(t, va_arg(va, pa_sample_spec*));
791 break;
792
793 case PA_TAG_ARBITRARY: {
794 const void **p = va_arg(va, const void**);
795 size_t size = va_arg(va, size_t);
796 ret = pa_tagstruct_get_arbitrary(t, p, size);
797 break;
798 }
799
800 case PA_TAG_BOOLEAN_TRUE:
801 case PA_TAG_BOOLEAN_FALSE:
802 ret = pa_tagstruct_get_boolean(t, va_arg(va, bool*));
803 break;
804
805 case PA_TAG_TIMEVAL:
806 ret = pa_tagstruct_get_timeval(t, va_arg(va, struct timeval*));
807 break;
808
809 case PA_TAG_USEC:
810 ret = pa_tagstruct_get_usec(t, va_arg(va, pa_usec_t*));
811 break;
812
813 case PA_TAG_CHANNEL_MAP:
814 ret = pa_tagstruct_get_channel_map(t, va_arg(va, pa_channel_map *));
815 break;
816
817 case PA_TAG_CVOLUME:
818 ret = pa_tagstruct_get_cvolume(t, va_arg(va, pa_cvolume *));
819 break;
820
821 case PA_TAG_VOLUME:
822 ret = pa_tagstruct_get_volume(t, va_arg(va, pa_volume_t *));
823 break;
824
825 case PA_TAG_PROPLIST:
826 ret = pa_tagstruct_get_proplist(t, va_arg(va, pa_proplist *));
827 break;
828
829 default:
830 pa_assert_not_reached();
831 }
832
833 }
834
835 va_end(va);
836 return ret;
837 }