]>
code.delx.au - pulseaudio/blob - src/pulsecore/tagstruct.c
ac7ae1ab8b514634f1fce5305b53da33498d105d
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
35 #ifdef HAVE_NETINET_IN_H
36 #include <netinet/in.h>
41 #include <pulse/xmalloc.h>
43 #include "tagstruct.h"
48 size_t length
, allocated
;
54 pa_tagstruct
*pa_tagstruct_new(const uint8_t* data
, size_t length
) {
57 assert(!data
|| (data
&& length
));
59 t
= pa_xmalloc(sizeof(pa_tagstruct
));
60 t
->data
= (uint8_t*) data
;
61 t
->allocated
= t
->length
= data
? length
: 0;
67 void pa_tagstruct_free(pa_tagstruct
*t
) {
74 uint8_t* pa_tagstruct_free_data(pa_tagstruct
*t
, size_t *l
) {
76 assert(t
&& t
->dynamic
&& l
);
83 static void extend(pa_tagstruct
*t
, size_t l
) {
87 if (t
->length
+l
<= t
->allocated
)
90 t
->data
= pa_xrealloc(t
->data
, t
->allocated
= t
->length
+l
+100);
93 void pa_tagstruct_puts(pa_tagstruct
*t
, const char *s
) {
99 t
->data
[t
->length
] = PA_TAG_STRING
;
100 strcpy((char*) (t
->data
+t
->length
+1), s
);
104 t
->data
[t
->length
] = PA_TAG_STRING_NULL
;
109 void pa_tagstruct_putu32(pa_tagstruct
*t
, uint32_t i
) {
112 t
->data
[t
->length
] = PA_TAG_U32
;
114 memcpy(t
->data
+t
->length
+1, &i
, 4);
118 void pa_tagstruct_putu8(pa_tagstruct
*t
, uint8_t c
) {
121 t
->data
[t
->length
] = PA_TAG_U8
;
122 *(t
->data
+t
->length
+1) = c
;
126 void pa_tagstruct_put_sample_spec(pa_tagstruct
*t
, const pa_sample_spec
*ss
) {
130 t
->data
[t
->length
] = PA_TAG_SAMPLE_SPEC
;
131 t
->data
[t
->length
+1] = (uint8_t) ss
->format
;
132 t
->data
[t
->length
+2] = ss
->channels
;
133 rate
= htonl(ss
->rate
);
134 memcpy(t
->data
+t
->length
+3, &rate
, 4);
138 void pa_tagstruct_put_arbitrary(pa_tagstruct
*t
, const void *p
, size_t length
) {
143 t
->data
[t
->length
] = PA_TAG_ARBITRARY
;
145 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
147 memcpy(t
->data
+t
->length
+5, p
, length
);
148 t
->length
+= 5+length
;
151 void pa_tagstruct_put_boolean(pa_tagstruct
*t
, int b
) {
154 t
->data
[t
->length
] = b
? PA_TAG_BOOLEAN_TRUE
: PA_TAG_BOOLEAN_FALSE
;
158 void pa_tagstruct_put_timeval(pa_tagstruct
*t
, const struct timeval
*tv
) {
162 t
->data
[t
->length
] = PA_TAG_TIMEVAL
;
163 tmp
= htonl(tv
->tv_sec
);
164 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
165 tmp
= htonl(tv
->tv_usec
);
166 memcpy(t
->data
+t
->length
+5, &tmp
, 4);
170 void pa_tagstruct_put_usec(pa_tagstruct
*t
, pa_usec_t u
) {
174 t
->data
[t
->length
] = PA_TAG_USEC
;
175 tmp
= htonl((uint32_t) (u
>> 32));
176 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
177 tmp
= htonl((uint32_t) u
);
178 memcpy(t
->data
+t
->length
+5, &tmp
, 4);
182 void pa_tagstruct_putu64(pa_tagstruct
*t
, uint64_t u
) {
186 t
->data
[t
->length
] = PA_TAG_U64
;
187 tmp
= htonl((uint32_t) (u
>> 32));
188 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
189 tmp
= htonl((uint32_t) u
);
190 memcpy(t
->data
+t
->length
+5, &tmp
, 4);
194 void pa_tagstruct_puts64(pa_tagstruct
*t
, int64_t u
) {
198 t
->data
[t
->length
] = PA_TAG_S64
;
199 tmp
= htonl((uint32_t) ((uint64_t) u
>> 32));
200 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
201 tmp
= htonl((uint32_t) ((uint64_t) u
));
202 memcpy(t
->data
+t
->length
+5, &tmp
, 4);
206 void pa_tagstruct_put_channel_map(pa_tagstruct
*t
, const pa_channel_map
*map
) {
210 extend(t
, 2 + map
->channels
);
212 t
->data
[t
->length
++] = PA_TAG_CHANNEL_MAP
;
213 t
->data
[t
->length
++] = map
->channels
;
215 for (i
= 0; i
< map
->channels
; i
++)
216 t
->data
[t
->length
++] = (uint8_t) map
->map
[i
];
219 void pa_tagstruct_put_cvolume(pa_tagstruct
*t
, const pa_cvolume
*cvolume
) {
224 extend(t
, 2 + cvolume
->channels
* sizeof(pa_volume_t
));
226 t
->data
[t
->length
++] = PA_TAG_CVOLUME
;
227 t
->data
[t
->length
++] = cvolume
->channels
;
229 for (i
= 0; i
< cvolume
->channels
; i
++) {
230 vol
= htonl(cvolume
->values
[i
]);
231 memcpy(t
->data
+ t
->length
, &vol
, sizeof(pa_volume_t
));
232 t
->length
+= sizeof(pa_volume_t
);
236 int pa_tagstruct_gets(pa_tagstruct
*t
, const char **s
) {
242 if (t
->rindex
+1 > t
->length
)
245 if (t
->data
[t
->rindex
] == PA_TAG_STRING_NULL
) {
251 if (t
->rindex
+2 > t
->length
)
254 if (t
->data
[t
->rindex
] != PA_TAG_STRING
)
258 for (n
= 0, c
= (char*) (t
->data
+t
->rindex
+1); t
->rindex
+1+n
< t
->length
; n
++, c
++)
267 *s
= (char*) (t
->data
+t
->rindex
+1);
273 int pa_tagstruct_getu32(pa_tagstruct
*t
, uint32_t *i
) {
276 if (t
->rindex
+5 > t
->length
)
279 if (t
->data
[t
->rindex
] != PA_TAG_U32
)
282 memcpy(i
, t
->data
+t
->rindex
+1, 4);
288 int pa_tagstruct_getu8(pa_tagstruct
*t
, uint8_t *c
) {
291 if (t
->rindex
+2 > t
->length
)
294 if (t
->data
[t
->rindex
] != PA_TAG_U8
)
297 *c
= t
->data
[t
->rindex
+1];
302 int pa_tagstruct_get_sample_spec(pa_tagstruct
*t
, pa_sample_spec
*ss
) {
305 if (t
->rindex
+7 > t
->length
)
308 if (t
->data
[t
->rindex
] != PA_TAG_SAMPLE_SPEC
)
311 ss
->format
= t
->data
[t
->rindex
+1];
312 ss
->channels
= t
->data
[t
->rindex
+2];
313 memcpy(&ss
->rate
, t
->data
+t
->rindex
+3, 4);
314 ss
->rate
= ntohl(ss
->rate
);
320 int pa_tagstruct_get_arbitrary(pa_tagstruct
*t
, const void **p
, size_t length
) {
324 if (t
->rindex
+5+length
> t
->length
)
327 if (t
->data
[t
->rindex
] != PA_TAG_ARBITRARY
)
330 memcpy(&len
, t
->data
+t
->rindex
+1, 4);
331 if (ntohl(len
) != length
)
334 *p
= t
->data
+t
->rindex
+5;
335 t
->rindex
+= 5+length
;
339 int pa_tagstruct_eof(pa_tagstruct
*t
) {
341 return t
->rindex
>= t
->length
;
344 const uint8_t* pa_tagstruct_data(pa_tagstruct
*t
, size_t *l
) {
345 assert(t
&& t
->dynamic
&& l
);
350 int pa_tagstruct_get_boolean(pa_tagstruct
*t
, int *b
) {
353 if (t
->rindex
+1 > t
->length
)
356 if (t
->data
[t
->rindex
] == PA_TAG_BOOLEAN_TRUE
)
358 else if (t
->data
[t
->rindex
] == PA_TAG_BOOLEAN_FALSE
)
367 int pa_tagstruct_get_timeval(pa_tagstruct
*t
, struct timeval
*tv
) {
369 if (t
->rindex
+9 > t
->length
)
372 if (t
->data
[t
->rindex
] != PA_TAG_TIMEVAL
)
375 memcpy(&tv
->tv_sec
, t
->data
+t
->rindex
+1, 4);
376 tv
->tv_sec
= ntohl(tv
->tv_sec
);
377 memcpy(&tv
->tv_usec
, t
->data
+t
->rindex
+5, 4);
378 tv
->tv_usec
= ntohl(tv
->tv_usec
);
383 int pa_tagstruct_get_usec(pa_tagstruct
*t
, pa_usec_t
*u
) {
387 if (t
->rindex
+9 > t
->length
)
390 if (t
->data
[t
->rindex
] != PA_TAG_USEC
)
393 memcpy(&tmp
, t
->data
+t
->rindex
+1, 4);
394 *u
= (pa_usec_t
) ntohl(tmp
) << 32;
395 memcpy(&tmp
, t
->data
+t
->rindex
+5, 4);
396 *u
|= (pa_usec_t
) ntohl(tmp
);
401 int pa_tagstruct_getu64(pa_tagstruct
*t
, uint64_t *u
) {
405 if (t
->rindex
+9 > t
->length
)
408 if (t
->data
[t
->rindex
] != PA_TAG_U64
)
411 memcpy(&tmp
, t
->data
+t
->rindex
+1, 4);
412 *u
= (uint64_t) ntohl(tmp
) << 32;
413 memcpy(&tmp
, t
->data
+t
->rindex
+5, 4);
414 *u
|= (uint64_t) ntohl(tmp
);
419 int pa_tagstruct_gets64(pa_tagstruct
*t
, int64_t *u
) {
423 if (t
->rindex
+9 > t
->length
)
426 if (t
->data
[t
->rindex
] != PA_TAG_S64
)
429 memcpy(&tmp
, t
->data
+t
->rindex
+1, 4);
430 *u
= (int64_t) ((uint64_t) ntohl(tmp
) << 32);
431 memcpy(&tmp
, t
->data
+t
->rindex
+5, 4);
432 *u
|= (int64_t) ntohl(tmp
);
437 int pa_tagstruct_get_channel_map(pa_tagstruct
*t
, pa_channel_map
*map
) {
443 if (t
->rindex
+2 > t
->length
)
446 if (t
->data
[t
->rindex
] != PA_TAG_CHANNEL_MAP
)
449 if ((map
->channels
= t
->data
[t
->rindex
+1]) > PA_CHANNELS_MAX
)
452 if (t
->rindex
+2+map
->channels
> t
->length
)
455 for (i
= 0; i
< map
->channels
; i
++)
456 map
->map
[i
] = (int8_t) t
->data
[t
->rindex
+ 2 + i
];
458 t
->rindex
+= 2 + map
->channels
;
462 int pa_tagstruct_get_cvolume(pa_tagstruct
*t
, pa_cvolume
*cvolume
) {
469 if (t
->rindex
+2 > t
->length
)
472 if (t
->data
[t
->rindex
] != PA_TAG_CVOLUME
)
475 if ((cvolume
->channels
= t
->data
[t
->rindex
+1]) > PA_CHANNELS_MAX
)
478 if (t
->rindex
+2+cvolume
->channels
*sizeof(pa_volume_t
) > t
->length
)
481 for (i
= 0; i
< cvolume
->channels
; i
++) {
482 memcpy(&vol
, t
->data
+ t
->rindex
+ 2 + i
* sizeof(pa_volume_t
), sizeof(pa_volume_t
));
483 cvolume
->values
[i
] = (pa_volume_t
) ntohl(vol
);
486 t
->rindex
+= 2 + cvolume
->channels
* sizeof(pa_volume_t
);
490 void pa_tagstruct_put(pa_tagstruct
*t
, ...) {
497 int tag
= va_arg(va
, int);
499 if (tag
== PA_TAG_INVALID
)
504 case PA_TAG_STRING_NULL
:
505 pa_tagstruct_puts(t
, va_arg(va
, char*));
509 pa_tagstruct_putu32(t
, va_arg(va
, uint32_t));
513 pa_tagstruct_putu8(t
, (uint8_t) va_arg(va
, int));
517 pa_tagstruct_putu64(t
, va_arg(va
, uint64_t));
520 case PA_TAG_SAMPLE_SPEC
:
521 pa_tagstruct_put_sample_spec(t
, va_arg(va
, pa_sample_spec
*));
524 case PA_TAG_ARBITRARY
: {
525 void *p
= va_arg(va
, void*);
526 size_t size
= va_arg(va
, size_t);
527 pa_tagstruct_put_arbitrary(t
, p
, size
);
531 case PA_TAG_BOOLEAN_TRUE
:
532 case PA_TAG_BOOLEAN_FALSE
:
533 pa_tagstruct_put_boolean(t
, va_arg(va
, int));
537 pa_tagstruct_put_timeval(t
, va_arg(va
, struct timeval
*));
541 pa_tagstruct_put_usec(t
, va_arg(va
, pa_usec_t
));
544 case PA_TAG_CHANNEL_MAP
:
545 pa_tagstruct_put_channel_map(t
, va_arg(va
, pa_channel_map
*));
549 pa_tagstruct_put_cvolume(t
, va_arg(va
, pa_cvolume
*));
560 int pa_tagstruct_get(pa_tagstruct
*t
, ...) {
568 int tag
= va_arg(va
, int);
570 if (tag
== PA_TAG_INVALID
)
575 case PA_TAG_STRING_NULL
:
576 ret
= pa_tagstruct_gets(t
, va_arg(va
, const char**));
580 ret
= pa_tagstruct_getu32(t
, va_arg(va
, uint32_t*));
584 ret
= pa_tagstruct_getu8(t
, va_arg(va
, uint8_t*));
588 ret
= pa_tagstruct_getu64(t
, va_arg(va
, uint64_t*));
591 case PA_TAG_SAMPLE_SPEC
:
592 ret
= pa_tagstruct_get_sample_spec(t
, va_arg(va
, pa_sample_spec
*));
595 case PA_TAG_ARBITRARY
: {
596 const void **p
= va_arg(va
, const void**);
597 size_t size
= va_arg(va
, size_t);
598 ret
= pa_tagstruct_get_arbitrary(t
, p
, size
);
602 case PA_TAG_BOOLEAN_TRUE
:
603 case PA_TAG_BOOLEAN_FALSE
:
604 ret
= pa_tagstruct_get_boolean(t
, va_arg(va
, int*));
608 ret
= pa_tagstruct_get_timeval(t
, va_arg(va
, struct timeval
*));
612 ret
= pa_tagstruct_get_usec(t
, va_arg(va
, pa_usec_t
*));
615 case PA_TAG_CHANNEL_MAP
:
616 ret
= pa_tagstruct_get_channel_map(t
, va_arg(va
, pa_channel_map
*));
620 ret
= pa_tagstruct_get_cvolume(t
, va_arg(va
, pa_cvolume
*));