]>
code.delx.au - pulseaudio/blob - src/pulsecore/tagstruct.c
556fe80676dc8a836ac2c02c03a68b1ca3293afe
4 This file is part of PulseAudio.
6 Copyright 2004-2006 Lennart Poettering
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of the
11 License, or (at your option) any later version.
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
34 #ifdef HAVE_NETINET_IN_H
35 #include <netinet/in.h>
38 #include <pulse/xmalloc.h>
40 #include <pulsecore/winsock.h>
41 #include <pulsecore/macro.h>
43 #include "tagstruct.h"
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
;
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
, int b
) {
168 t
->data
[t
->length
] = 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(tv
->tv_sec
);
179 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
180 tmp
= htonl(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
) {
231 extend(t
, 2 + map
->channels
);
233 t
->data
[t
->length
++] = PA_TAG_CHANNEL_MAP
;
234 t
->data
[t
->length
++] = map
->channels
;
236 for (i
= 0; i
< map
->channels
; i
++)
237 t
->data
[t
->length
++] = (uint8_t) map
->map
[i
];
240 void pa_tagstruct_put_cvolume(pa_tagstruct
*t
, const pa_cvolume
*cvolume
) {
245 extend(t
, 2 + cvolume
->channels
* sizeof(pa_volume_t
));
247 t
->data
[t
->length
++] = PA_TAG_CVOLUME
;
248 t
->data
[t
->length
++] = cvolume
->channels
;
250 for (i
= 0; i
< cvolume
->channels
; i
++) {
251 vol
= htonl(cvolume
->values
[i
]);
252 memcpy(t
->data
+ t
->length
, &vol
, sizeof(pa_volume_t
));
253 t
->length
+= sizeof(pa_volume_t
);
257 int pa_tagstruct_gets(pa_tagstruct
*t
, const char **s
) {
265 if (t
->rindex
+1 > t
->length
)
268 if (t
->data
[t
->rindex
] == PA_TAG_STRING_NULL
) {
274 if (t
->rindex
+2 > t
->length
)
277 if (t
->data
[t
->rindex
] != PA_TAG_STRING
)
281 for (n
= 0, c
= (char*) (t
->data
+t
->rindex
+1); t
->rindex
+1+n
< t
->length
; n
++, c
++)
290 *s
= (char*) (t
->data
+t
->rindex
+1);
296 int pa_tagstruct_getu32(pa_tagstruct
*t
, uint32_t *i
) {
300 if (t
->rindex
+5 > t
->length
)
303 if (t
->data
[t
->rindex
] != PA_TAG_U32
)
306 memcpy(i
, t
->data
+t
->rindex
+1, 4);
312 int pa_tagstruct_getu8(pa_tagstruct
*t
, uint8_t *c
) {
316 if (t
->rindex
+2 > t
->length
)
319 if (t
->data
[t
->rindex
] != PA_TAG_U8
)
322 *c
= t
->data
[t
->rindex
+1];
327 int pa_tagstruct_get_sample_spec(pa_tagstruct
*t
, pa_sample_spec
*ss
) {
331 if (t
->rindex
+7 > t
->length
)
334 if (t
->data
[t
->rindex
] != PA_TAG_SAMPLE_SPEC
)
337 ss
->format
= t
->data
[t
->rindex
+1];
338 ss
->channels
= t
->data
[t
->rindex
+2];
339 memcpy(&ss
->rate
, t
->data
+t
->rindex
+3, 4);
340 ss
->rate
= ntohl(ss
->rate
);
346 int pa_tagstruct_get_arbitrary(pa_tagstruct
*t
, const void **p
, size_t length
) {
352 if (t
->rindex
+5+length
> t
->length
)
355 if (t
->data
[t
->rindex
] != PA_TAG_ARBITRARY
)
358 memcpy(&len
, t
->data
+t
->rindex
+1, 4);
359 if (ntohl(len
) != length
)
362 *p
= t
->data
+t
->rindex
+5;
363 t
->rindex
+= 5+length
;
367 int pa_tagstruct_eof(pa_tagstruct
*t
) {
370 return t
->rindex
>= t
->length
;
373 const uint8_t* pa_tagstruct_data(pa_tagstruct
*t
, size_t *l
) {
375 pa_assert(t
->dynamic
);
382 int pa_tagstruct_get_boolean(pa_tagstruct
*t
, int *b
) {
386 if (t
->rindex
+1 > t
->length
)
389 if (t
->data
[t
->rindex
] == PA_TAG_BOOLEAN_TRUE
)
391 else if (t
->data
[t
->rindex
] == PA_TAG_BOOLEAN_FALSE
)
400 int pa_tagstruct_get_timeval(pa_tagstruct
*t
, struct timeval
*tv
) {
405 if (t
->rindex
+9 > t
->length
)
408 if (t
->data
[t
->rindex
] != PA_TAG_TIMEVAL
)
411 memcpy(&tv
->tv_sec
, t
->data
+t
->rindex
+1, 4);
412 tv
->tv_sec
= ntohl(tv
->tv_sec
);
413 memcpy(&tv
->tv_usec
, t
->data
+t
->rindex
+5, 4);
414 tv
->tv_usec
= ntohl(tv
->tv_usec
);
419 int pa_tagstruct_get_usec(pa_tagstruct
*t
, pa_usec_t
*u
) {
425 if (t
->rindex
+9 > t
->length
)
428 if (t
->data
[t
->rindex
] != PA_TAG_USEC
)
431 memcpy(&tmp
, t
->data
+t
->rindex
+1, 4);
432 *u
= (pa_usec_t
) ntohl(tmp
) << 32;
433 memcpy(&tmp
, t
->data
+t
->rindex
+5, 4);
434 *u
|= (pa_usec_t
) ntohl(tmp
);
439 int pa_tagstruct_getu64(pa_tagstruct
*t
, uint64_t *u
) {
445 if (t
->rindex
+9 > t
->length
)
448 if (t
->data
[t
->rindex
] != PA_TAG_U64
)
451 memcpy(&tmp
, t
->data
+t
->rindex
+1, 4);
452 *u
= (uint64_t) ntohl(tmp
) << 32;
453 memcpy(&tmp
, t
->data
+t
->rindex
+5, 4);
454 *u
|= (uint64_t) ntohl(tmp
);
459 int pa_tagstruct_gets64(pa_tagstruct
*t
, int64_t *u
) {
465 if (t
->rindex
+9 > t
->length
)
468 if (t
->data
[t
->rindex
] != PA_TAG_S64
)
471 memcpy(&tmp
, t
->data
+t
->rindex
+1, 4);
472 *u
= (int64_t) ((uint64_t) ntohl(tmp
) << 32);
473 memcpy(&tmp
, t
->data
+t
->rindex
+5, 4);
474 *u
|= (int64_t) ntohl(tmp
);
479 int pa_tagstruct_get_channel_map(pa_tagstruct
*t
, pa_channel_map
*map
) {
485 if (t
->rindex
+2 > t
->length
)
488 if (t
->data
[t
->rindex
] != PA_TAG_CHANNEL_MAP
)
491 if ((map
->channels
= t
->data
[t
->rindex
+1]) > PA_CHANNELS_MAX
)
494 if (t
->rindex
+2+map
->channels
> t
->length
)
497 for (i
= 0; i
< map
->channels
; i
++)
498 map
->map
[i
] = (int8_t) t
->data
[t
->rindex
+ 2 + i
];
500 t
->rindex
+= 2 + map
->channels
;
504 int pa_tagstruct_get_cvolume(pa_tagstruct
*t
, pa_cvolume
*cvolume
) {
511 if (t
->rindex
+2 > t
->length
)
514 if (t
->data
[t
->rindex
] != PA_TAG_CVOLUME
)
517 if ((cvolume
->channels
= t
->data
[t
->rindex
+1]) > PA_CHANNELS_MAX
)
520 if (t
->rindex
+2+cvolume
->channels
*sizeof(pa_volume_t
) > t
->length
)
523 for (i
= 0; i
< cvolume
->channels
; i
++) {
524 memcpy(&vol
, t
->data
+ t
->rindex
+ 2 + i
* sizeof(pa_volume_t
), sizeof(pa_volume_t
));
525 cvolume
->values
[i
] = (pa_volume_t
) ntohl(vol
);
528 t
->rindex
+= 2 + cvolume
->channels
* sizeof(pa_volume_t
);
532 void pa_tagstruct_put(pa_tagstruct
*t
, ...) {
539 int tag
= va_arg(va
, int);
541 if (tag
== PA_TAG_INVALID
)
546 case PA_TAG_STRING_NULL
:
547 pa_tagstruct_puts(t
, va_arg(va
, char*));
551 pa_tagstruct_putu32(t
, va_arg(va
, uint32_t));
555 pa_tagstruct_putu8(t
, (uint8_t) va_arg(va
, int));
559 pa_tagstruct_putu64(t
, va_arg(va
, uint64_t));
562 case PA_TAG_SAMPLE_SPEC
:
563 pa_tagstruct_put_sample_spec(t
, va_arg(va
, pa_sample_spec
*));
566 case PA_TAG_ARBITRARY
: {
567 void *p
= va_arg(va
, void*);
568 size_t size
= va_arg(va
, size_t);
569 pa_tagstruct_put_arbitrary(t
, p
, size
);
573 case PA_TAG_BOOLEAN_TRUE
:
574 case PA_TAG_BOOLEAN_FALSE
:
575 pa_tagstruct_put_boolean(t
, va_arg(va
, int));
579 pa_tagstruct_put_timeval(t
, va_arg(va
, struct timeval
*));
583 pa_tagstruct_put_usec(t
, va_arg(va
, pa_usec_t
));
586 case PA_TAG_CHANNEL_MAP
:
587 pa_tagstruct_put_channel_map(t
, va_arg(va
, pa_channel_map
*));
591 pa_tagstruct_put_cvolume(t
, va_arg(va
, pa_cvolume
*));
595 pa_assert_not_reached();
602 int pa_tagstruct_get(pa_tagstruct
*t
, ...) {
610 int tag
= va_arg(va
, int);
612 if (tag
== PA_TAG_INVALID
)
617 case PA_TAG_STRING_NULL
:
618 ret
= pa_tagstruct_gets(t
, va_arg(va
, const char**));
622 ret
= pa_tagstruct_getu32(t
, va_arg(va
, uint32_t*));
626 ret
= pa_tagstruct_getu8(t
, va_arg(va
, uint8_t*));
630 ret
= pa_tagstruct_getu64(t
, va_arg(va
, uint64_t*));
633 case PA_TAG_SAMPLE_SPEC
:
634 ret
= pa_tagstruct_get_sample_spec(t
, va_arg(va
, pa_sample_spec
*));
637 case PA_TAG_ARBITRARY
: {
638 const void **p
= va_arg(va
, const void**);
639 size_t size
= va_arg(va
, size_t);
640 ret
= pa_tagstruct_get_arbitrary(t
, p
, size
);
644 case PA_TAG_BOOLEAN_TRUE
:
645 case PA_TAG_BOOLEAN_FALSE
:
646 ret
= pa_tagstruct_get_boolean(t
, va_arg(va
, int*));
650 ret
= pa_tagstruct_get_timeval(t
, va_arg(va
, struct timeval
*));
654 ret
= pa_tagstruct_get_usec(t
, va_arg(va
, pa_usec_t
*));
657 case PA_TAG_CHANNEL_MAP
:
658 ret
= pa_tagstruct_get_channel_map(t
, va_arg(va
, pa_channel_map
*));
662 ret
= pa_tagstruct_get_cvolume(t
, va_arg(va
, pa_cvolume
*));
666 pa_assert_not_reached();