]>
code.delx.au - pulseaudio/blob - src/pulsecore/tagstruct.c
2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
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.
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.
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
32 #ifdef HAVE_NETINET_IN_H
33 #include <netinet/in.h>
36 #include <pulse/xmalloc.h>
38 #include <pulsecore/socket.h>
39 #include <pulsecore/macro.h>
41 #include "tagstruct.h"
43 #define MAX_TAG_SIZE (64*1024)
47 size_t length
, allocated
;
53 pa_tagstruct
*pa_tagstruct_new(const uint8_t* data
, size_t length
) {
56 pa_assert(!data
|| (data
&& length
));
58 t
= pa_xnew(pa_tagstruct
, 1);
59 t
->data
= (uint8_t*) data
;
60 t
->allocated
= t
->length
= data
? length
: 0;
67 void pa_tagstruct_free(pa_tagstruct
*t
) {
75 uint8_t* pa_tagstruct_free_data(pa_tagstruct
*t
, size_t *l
) {
79 pa_assert(t
->dynamic
);
88 static void extend(pa_tagstruct
*t
, size_t l
) {
90 pa_assert(t
->dynamic
);
92 if (t
->length
+l
<= t
->allocated
)
95 t
->data
= pa_xrealloc(t
->data
, t
->allocated
= t
->length
+l
+100);
98 void pa_tagstruct_puts(pa_tagstruct
*t
, const char *s
) {
105 t
->data
[t
->length
] = PA_TAG_STRING
;
106 strcpy((char*) (t
->data
+t
->length
+1), s
);
110 t
->data
[t
->length
] = PA_TAG_STRING_NULL
;
115 void pa_tagstruct_putu32(pa_tagstruct
*t
, uint32_t i
) {
119 t
->data
[t
->length
] = PA_TAG_U32
;
121 memcpy(t
->data
+t
->length
+1, &i
, 4);
125 void pa_tagstruct_putu8(pa_tagstruct
*t
, uint8_t c
) {
129 t
->data
[t
->length
] = PA_TAG_U8
;
130 *(t
->data
+t
->length
+1) = c
;
134 void pa_tagstruct_put_sample_spec(pa_tagstruct
*t
, const pa_sample_spec
*ss
) {
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);
149 void pa_tagstruct_put_arbitrary(pa_tagstruct
*t
, const void *p
, size_t length
) {
156 t
->data
[t
->length
] = PA_TAG_ARBITRARY
;
157 tmp
= htonl((uint32_t) length
);
158 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
160 memcpy(t
->data
+t
->length
+5, p
, length
);
161 t
->length
+= 5+length
;
164 void pa_tagstruct_put_boolean(pa_tagstruct
*t
, pa_bool_t b
) {
168 t
->data
[t
->length
] = (uint8_t) (b
? PA_TAG_BOOLEAN_TRUE
: PA_TAG_BOOLEAN_FALSE
);
172 void pa_tagstruct_put_timeval(pa_tagstruct
*t
, const struct timeval
*tv
) {
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);
185 void pa_tagstruct_put_usec(pa_tagstruct
*t
, pa_usec_t u
) {
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);
199 void pa_tagstruct_putu64(pa_tagstruct
*t
, uint64_t u
) {
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);
213 void pa_tagstruct_puts64(pa_tagstruct
*t
, int64_t u
) {
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);
227 void pa_tagstruct_put_channel_map(pa_tagstruct
*t
, const pa_channel_map
*map
) {
232 extend(t
, 2 + (size_t) map
->channels
);
234 t
->data
[t
->length
++] = PA_TAG_CHANNEL_MAP
;
235 t
->data
[t
->length
++] = map
->channels
;
237 for (i
= 0; i
< map
->channels
; i
++)
238 t
->data
[t
->length
++] = (uint8_t) map
->map
[i
];
241 void pa_tagstruct_put_cvolume(pa_tagstruct
*t
, const pa_cvolume
*cvolume
) {
247 extend(t
, 2 + cvolume
->channels
* sizeof(pa_volume_t
));
249 t
->data
[t
->length
++] = PA_TAG_CVOLUME
;
250 t
->data
[t
->length
++] = cvolume
->channels
;
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
);
259 void pa_tagstruct_put_volume(pa_tagstruct
*t
, pa_volume_t vol
) {
264 t
->data
[t
->length
] = PA_TAG_VOLUME
;
265 u
= htonl((uint32_t) vol
);
266 memcpy(t
->data
+t
->length
+1, &u
, 4);
270 void pa_tagstruct_put_proplist(pa_tagstruct
*t
, pa_proplist
*p
) {
277 t
->data
[t
->length
++] = PA_TAG_PROPLIST
;
284 if (!(k
= pa_proplist_iterate(p
, &state
)))
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
);
293 pa_tagstruct_puts(t
, NULL
);
296 void pa_tagstruct_put_format_info(pa_tagstruct
*t
, pa_format_info
*f
) {
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
);
307 int pa_tagstruct_gets(pa_tagstruct
*t
, const char **s
) {
315 if (t
->rindex
+1 > t
->length
)
318 if (t
->data
[t
->rindex
] == PA_TAG_STRING_NULL
) {
324 if (t
->rindex
+2 > t
->length
)
327 if (t
->data
[t
->rindex
] != PA_TAG_STRING
)
331 for (n
= 0, c
= (char*) (t
->data
+t
->rindex
+1); t
->rindex
+1+n
< t
->length
; n
++, c
++)
340 *s
= (char*) (t
->data
+t
->rindex
+1);
346 int pa_tagstruct_getu32(pa_tagstruct
*t
, uint32_t *i
) {
350 if (t
->rindex
+5 > t
->length
)
353 if (t
->data
[t
->rindex
] != PA_TAG_U32
)
356 memcpy(i
, t
->data
+t
->rindex
+1, 4);
362 int pa_tagstruct_getu8(pa_tagstruct
*t
, uint8_t *c
) {
366 if (t
->rindex
+2 > t
->length
)
369 if (t
->data
[t
->rindex
] != PA_TAG_U8
)
372 *c
= t
->data
[t
->rindex
+1];
377 int pa_tagstruct_get_sample_spec(pa_tagstruct
*t
, pa_sample_spec
*ss
) {
381 if (t
->rindex
+7 > t
->length
)
384 if (t
->data
[t
->rindex
] != PA_TAG_SAMPLE_SPEC
)
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
);
396 int pa_tagstruct_get_arbitrary(pa_tagstruct
*t
, const void **p
, size_t length
) {
402 if (t
->rindex
+5+length
> t
->length
)
405 if (t
->data
[t
->rindex
] != PA_TAG_ARBITRARY
)
408 memcpy(&len
, t
->data
+t
->rindex
+1, 4);
409 if (ntohl(len
) != length
)
412 *p
= t
->data
+t
->rindex
+5;
413 t
->rindex
+= 5+length
;
417 int pa_tagstruct_eof(pa_tagstruct
*t
) {
420 return t
->rindex
>= t
->length
;
423 const uint8_t* pa_tagstruct_data(pa_tagstruct
*t
, size_t *l
) {
425 pa_assert(t
->dynamic
);
432 int pa_tagstruct_get_boolean(pa_tagstruct
*t
, pa_bool_t
*b
) {
436 if (t
->rindex
+1 > t
->length
)
439 if (t
->data
[t
->rindex
] == PA_TAG_BOOLEAN_TRUE
)
441 else if (t
->data
[t
->rindex
] == PA_TAG_BOOLEAN_FALSE
)
450 int pa_tagstruct_get_timeval(pa_tagstruct
*t
, struct timeval
*tv
) {
455 if (t
->rindex
+9 > t
->length
)
458 if (t
->data
[t
->rindex
] != PA_TAG_TIMEVAL
)
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
);
469 int pa_tagstruct_get_usec(pa_tagstruct
*t
, pa_usec_t
*u
) {
475 if (t
->rindex
+9 > t
->length
)
478 if (t
->data
[t
->rindex
] != PA_TAG_USEC
)
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
);
489 int pa_tagstruct_getu64(pa_tagstruct
*t
, uint64_t *u
) {
495 if (t
->rindex
+9 > t
->length
)
498 if (t
->data
[t
->rindex
] != PA_TAG_U64
)
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
);
509 int pa_tagstruct_gets64(pa_tagstruct
*t
, int64_t *u
) {
515 if (t
->rindex
+9 > t
->length
)
518 if (t
->data
[t
->rindex
] != PA_TAG_S64
)
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
);
529 int pa_tagstruct_get_channel_map(pa_tagstruct
*t
, pa_channel_map
*map
) {
535 if (t
->rindex
+2 > t
->length
)
538 if (t
->data
[t
->rindex
] != PA_TAG_CHANNEL_MAP
)
541 if ((map
->channels
= t
->data
[t
->rindex
+1]) > PA_CHANNELS_MAX
)
544 if (t
->rindex
+2+map
->channels
> t
->length
)
547 for (i
= 0; i
< map
->channels
; i
++)
548 map
->map
[i
] = (int8_t) t
->data
[t
->rindex
+ 2 + i
];
550 t
->rindex
+= 2 + (size_t) map
->channels
;
554 int pa_tagstruct_get_cvolume(pa_tagstruct
*t
, pa_cvolume
*cvolume
) {
561 if (t
->rindex
+2 > t
->length
)
564 if (t
->data
[t
->rindex
] != PA_TAG_CVOLUME
)
567 if ((cvolume
->channels
= t
->data
[t
->rindex
+1]) > PA_CHANNELS_MAX
)
570 if (t
->rindex
+2+cvolume
->channels
*sizeof(pa_volume_t
) > t
->length
)
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
);
578 t
->rindex
+= 2 + cvolume
->channels
* sizeof(pa_volume_t
);
582 int pa_tagstruct_get_volume(pa_tagstruct
*t
, pa_volume_t
*vol
) {
588 if (t
->rindex
+5 > t
->length
)
591 if (t
->data
[t
->rindex
] != PA_TAG_VOLUME
)
594 memcpy(&u
, t
->data
+t
->rindex
+1, 4);
595 *vol
= (pa_volume_t
) ntohl(u
);
601 int pa_tagstruct_get_proplist(pa_tagstruct
*t
, pa_proplist
*p
) {
607 if (t
->rindex
+1 > t
->length
)
610 if (t
->data
[t
->rindex
] != PA_TAG_PROPLIST
)
613 saved_rindex
= t
->rindex
;
621 if (pa_tagstruct_gets(t
, &k
) < 0)
627 if (pa_tagstruct_getu32(t
, &length
) < 0)
630 if (length
> MAX_TAG_SIZE
)
633 if (pa_tagstruct_get_arbitrary(t
, &d
, length
) < 0)
636 if (pa_proplist_set(p
, k
, d
, length
) < 0)
643 t
->rindex
= saved_rindex
;
647 int pa_tagstruct_get_format_info(pa_tagstruct
*t
, pa_format_info
*f
) {
654 if (t
->rindex
+1 > t
->length
)
657 if (t
->data
[t
->rindex
] != PA_TAG_FORMAT_INFO
)
660 saved_rindex
= t
->rindex
;
663 if (pa_tagstruct_getu8(t
, &encoding
) < 0)
666 f
->encoding
= encoding
;
668 if (pa_tagstruct_get_proplist(t
, f
->plist
) < 0)
674 t
->rindex
= saved_rindex
;
678 void pa_tagstruct_put(pa_tagstruct
*t
, ...) {
685 int tag
= va_arg(va
, int);
687 if (tag
== PA_TAG_INVALID
)
692 case PA_TAG_STRING_NULL
:
693 pa_tagstruct_puts(t
, va_arg(va
, char*));
697 pa_tagstruct_putu32(t
, va_arg(va
, uint32_t));
701 pa_tagstruct_putu8(t
, (uint8_t) va_arg(va
, int));
705 pa_tagstruct_putu64(t
, va_arg(va
, uint64_t));
708 case PA_TAG_SAMPLE_SPEC
:
709 pa_tagstruct_put_sample_spec(t
, va_arg(va
, pa_sample_spec
*));
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
);
719 case PA_TAG_BOOLEAN_TRUE
:
720 case PA_TAG_BOOLEAN_FALSE
:
721 pa_tagstruct_put_boolean(t
, va_arg(va
, int));
725 pa_tagstruct_put_timeval(t
, va_arg(va
, struct timeval
*));
729 pa_tagstruct_put_usec(t
, va_arg(va
, pa_usec_t
));
732 case PA_TAG_CHANNEL_MAP
:
733 pa_tagstruct_put_channel_map(t
, va_arg(va
, pa_channel_map
*));
737 pa_tagstruct_put_cvolume(t
, va_arg(va
, pa_cvolume
*));
741 pa_tagstruct_put_volume(t
, va_arg(va
, pa_volume_t
));
744 case PA_TAG_PROPLIST
:
745 pa_tagstruct_put_proplist(t
, va_arg(va
, pa_proplist
*));
749 pa_assert_not_reached();
756 int pa_tagstruct_get(pa_tagstruct
*t
, ...) {
764 int tag
= va_arg(va
, int);
766 if (tag
== PA_TAG_INVALID
)
771 case PA_TAG_STRING_NULL
:
772 ret
= pa_tagstruct_gets(t
, va_arg(va
, const char**));
776 ret
= pa_tagstruct_getu32(t
, va_arg(va
, uint32_t*));
780 ret
= pa_tagstruct_getu8(t
, va_arg(va
, uint8_t*));
784 ret
= pa_tagstruct_getu64(t
, va_arg(va
, uint64_t*));
787 case PA_TAG_SAMPLE_SPEC
:
788 ret
= pa_tagstruct_get_sample_spec(t
, va_arg(va
, pa_sample_spec
*));
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
);
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
*));
804 ret
= pa_tagstruct_get_timeval(t
, va_arg(va
, struct timeval
*));
808 ret
= pa_tagstruct_get_usec(t
, va_arg(va
, pa_usec_t
*));
811 case PA_TAG_CHANNEL_MAP
:
812 ret
= pa_tagstruct_get_channel_map(t
, va_arg(va
, pa_channel_map
*));
816 ret
= pa_tagstruct_get_cvolume(t
, va_arg(va
, pa_cvolume
*));
820 ret
= pa_tagstruct_get_volume(t
, va_arg(va
, pa_volume_t
*));
823 case PA_TAG_PROPLIST
:
824 ret
= pa_tagstruct_get_proplist(t
, va_arg(va
, pa_proplist
*));
828 pa_assert_not_reached();