]>
code.delx.au - pulseaudio/blob - src/polypcore/tagstruct.c
27582cae174cb110a78b73c7cce9999313aa51b8
4 This file is part of polypaudio.
6 polypaudio 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 polypaudio 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 polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
33 #ifdef HAVE_NETINET_IN_H
34 #include <netinet/in.h>
39 #include <polyp/xmalloc.h>
41 #include "tagstruct.h"
46 size_t length
, allocated
;
52 pa_tagstruct
*pa_tagstruct_new(const uint8_t* data
, size_t length
) {
55 assert(!data
|| (data
&& length
));
57 t
= pa_xmalloc(sizeof(pa_tagstruct
));
58 t
->data
= (uint8_t*) data
;
59 t
->allocated
= t
->length
= data
? length
: 0;
65 void pa_tagstruct_free(pa_tagstruct
*t
) {
72 uint8_t* pa_tagstruct_free_data(pa_tagstruct
*t
, size_t *l
) {
74 assert(t
&& t
->dynamic
&& l
);
81 static void extend(pa_tagstruct
*t
, size_t l
) {
82 assert(t
&& t
->dynamic
);
84 if (t
->length
+l
<= t
->allocated
)
87 t
->data
= pa_xrealloc(t
->data
, t
->allocated
= t
->length
+l
+100);
91 void pa_tagstruct_puts(pa_tagstruct
*t
, const char *s
) {
97 t
->data
[t
->length
] = PA_TAG_STRING
;
98 strcpy((char*) (t
->data
+t
->length
+1), s
);
102 t
->data
[t
->length
] = PA_TAG_STRING_NULL
;
107 void pa_tagstruct_putu32(pa_tagstruct
*t
, uint32_t i
) {
110 t
->data
[t
->length
] = PA_TAG_U32
;
112 memcpy(t
->data
+t
->length
+1, &i
, 4);
116 void pa_tagstruct_putu8(pa_tagstruct
*t
, uint8_t c
) {
119 t
->data
[t
->length
] = PA_TAG_U8
;
120 *(t
->data
+t
->length
+1) = c
;
124 void pa_tagstruct_put_sample_spec(pa_tagstruct
*t
, const pa_sample_spec
*ss
) {
128 t
->data
[t
->length
] = PA_TAG_SAMPLE_SPEC
;
129 t
->data
[t
->length
+1] = (uint8_t) ss
->format
;
130 t
->data
[t
->length
+2] = ss
->channels
;
131 rate
= htonl(ss
->rate
);
132 memcpy(t
->data
+t
->length
+3, &rate
, 4);
136 void pa_tagstruct_put_arbitrary(pa_tagstruct
*t
, const void *p
, size_t length
) {
141 t
->data
[t
->length
] = PA_TAG_ARBITRARY
;
143 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
145 memcpy(t
->data
+t
->length
+5, p
, length
);
146 t
->length
+= 5+length
;
149 void pa_tagstruct_put_boolean(pa_tagstruct
*t
, int b
) {
152 t
->data
[t
->length
] = b
? PA_TAG_BOOLEAN_TRUE
: PA_TAG_BOOLEAN_FALSE
;
156 void pa_tagstruct_put_timeval(pa_tagstruct
*t
, const struct timeval
*tv
) {
160 t
->data
[t
->length
] = PA_TAG_TIMEVAL
;
161 tmp
= htonl(tv
->tv_sec
);
162 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
163 tmp
= htonl(tv
->tv_usec
);
164 memcpy(t
->data
+t
->length
+5, &tmp
, 4);
168 void pa_tagstruct_put_usec(pa_tagstruct
*t
, pa_usec_t u
) {
172 t
->data
[t
->length
] = PA_TAG_USEC
;
173 tmp
= htonl((uint32_t) (u
>> 32));
174 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
175 tmp
= htonl((uint32_t) u
);
176 memcpy(t
->data
+t
->length
+5, &tmp
, 4);
180 void pa_tagstruct_putu64(pa_tagstruct
*t
, uint64_t u
) {
184 t
->data
[t
->length
] = PA_TAG_U64
;
185 tmp
= htonl((uint32_t) (u
>> 32));
186 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
187 tmp
= htonl((uint32_t) u
);
188 memcpy(t
->data
+t
->length
+5, &tmp
, 4);
192 void pa_tagstruct_puts64(pa_tagstruct
*t
, int64_t u
) {
196 t
->data
[t
->length
] = PA_TAG_S64
;
197 tmp
= htonl((uint32_t) ((uint64_t) u
>> 32));
198 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
199 tmp
= htonl((uint32_t) ((uint64_t) u
));
200 memcpy(t
->data
+t
->length
+5, &tmp
, 4);
204 void pa_tagstruct_put_channel_map(pa_tagstruct
*t
, const pa_channel_map
*map
) {
208 extend(t
, 2 + map
->channels
);
210 t
->data
[t
->length
++] = PA_TAG_CHANNEL_MAP
;
211 t
->data
[t
->length
++] = map
->channels
;
213 for (i
= 0; i
< map
->channels
; i
++)
214 t
->data
[t
->length
++] = (uint8_t) map
->map
[i
];
217 void pa_tagstruct_put_cvolume(pa_tagstruct
*t
, const pa_cvolume
*cvolume
) {
222 extend(t
, 2 + cvolume
->channels
* sizeof(pa_volume_t
));
224 t
->data
[t
->length
++] = PA_TAG_CVOLUME
;
225 t
->data
[t
->length
++] = cvolume
->channels
;
227 for (i
= 0; i
< cvolume
->channels
; i
++) {
228 vol
= htonl(cvolume
->values
[i
]);
229 memcpy(t
->data
+ t
->length
, &vol
, sizeof(pa_volume_t
));
230 t
->length
+= sizeof(pa_volume_t
);
234 int pa_tagstruct_gets(pa_tagstruct
*t
, const char **s
) {
240 if (t
->rindex
+1 > t
->length
)
243 if (t
->data
[t
->rindex
] == PA_TAG_STRING_NULL
) {
249 if (t
->rindex
+2 > t
->length
)
252 if (t
->data
[t
->rindex
] != PA_TAG_STRING
)
256 for (n
= 0, c
= (char*) (t
->data
+t
->rindex
+1); t
->rindex
+1+n
< t
->length
; n
++, c
++)
265 *s
= (char*) (t
->data
+t
->rindex
+1);
271 int pa_tagstruct_getu32(pa_tagstruct
*t
, uint32_t *i
) {
274 if (t
->rindex
+5 > t
->length
)
277 if (t
->data
[t
->rindex
] != PA_TAG_U32
)
280 memcpy(i
, t
->data
+t
->rindex
+1, 4);
286 int pa_tagstruct_getu8(pa_tagstruct
*t
, uint8_t *c
) {
289 if (t
->rindex
+2 > t
->length
)
292 if (t
->data
[t
->rindex
] != PA_TAG_U8
)
295 *c
= t
->data
[t
->rindex
+1];
300 int pa_tagstruct_get_sample_spec(pa_tagstruct
*t
, pa_sample_spec
*ss
) {
303 if (t
->rindex
+7 > t
->length
)
306 if (t
->data
[t
->rindex
] != PA_TAG_SAMPLE_SPEC
)
309 ss
->format
= t
->data
[t
->rindex
+1];
310 ss
->channels
= t
->data
[t
->rindex
+2];
311 memcpy(&ss
->rate
, t
->data
+t
->rindex
+3, 4);
312 ss
->rate
= ntohl(ss
->rate
);
318 int pa_tagstruct_get_arbitrary(pa_tagstruct
*t
, const void **p
, size_t length
) {
322 if (t
->rindex
+5+length
> t
->length
)
325 if (t
->data
[t
->rindex
] != PA_TAG_ARBITRARY
)
328 memcpy(&len
, t
->data
+t
->rindex
+1, 4);
329 if (ntohl(len
) != length
)
332 *p
= t
->data
+t
->rindex
+5;
333 t
->rindex
+= 5+length
;
337 int pa_tagstruct_eof(pa_tagstruct
*t
) {
339 return t
->rindex
>= t
->length
;
342 const uint8_t* pa_tagstruct_data(pa_tagstruct
*t
, size_t *l
) {
343 assert(t
&& t
->dynamic
&& l
);
348 int pa_tagstruct_get_boolean(pa_tagstruct
*t
, int *b
) {
351 if (t
->rindex
+1 > t
->length
)
354 if (t
->data
[t
->rindex
] == PA_TAG_BOOLEAN_TRUE
)
356 else if (t
->data
[t
->rindex
] == PA_TAG_BOOLEAN_FALSE
)
365 int pa_tagstruct_get_timeval(pa_tagstruct
*t
, struct timeval
*tv
) {
367 if (t
->rindex
+9 > t
->length
)
370 if (t
->data
[t
->rindex
] != PA_TAG_TIMEVAL
)
373 memcpy(&tv
->tv_sec
, t
->data
+t
->rindex
+1, 4);
374 tv
->tv_sec
= ntohl(tv
->tv_sec
);
375 memcpy(&tv
->tv_usec
, t
->data
+t
->rindex
+5, 4);
376 tv
->tv_usec
= ntohl(tv
->tv_usec
);
381 int pa_tagstruct_get_usec(pa_tagstruct
*t
, pa_usec_t
*u
) {
385 if (t
->rindex
+9 > t
->length
)
388 if (t
->data
[t
->rindex
] != PA_TAG_USEC
)
391 memcpy(&tmp
, t
->data
+t
->rindex
+1, 4);
392 *u
= (pa_usec_t
) ntohl(tmp
) << 32;
393 memcpy(&tmp
, t
->data
+t
->rindex
+5, 4);
394 *u
|= (pa_usec_t
) ntohl(tmp
);
399 int pa_tagstruct_getu64(pa_tagstruct
*t
, uint64_t *u
) {
403 if (t
->rindex
+9 > t
->length
)
406 if (t
->data
[t
->rindex
] != PA_TAG_U64
)
409 memcpy(&tmp
, t
->data
+t
->rindex
+1, 4);
410 *u
= (uint64_t) ntohl(tmp
) << 32;
411 memcpy(&tmp
, t
->data
+t
->rindex
+5, 4);
412 *u
|= (uint64_t) ntohl(tmp
);
417 int pa_tagstruct_gets64(pa_tagstruct
*t
, int64_t *u
) {
421 if (t
->rindex
+9 > t
->length
)
424 if (t
->data
[t
->rindex
] != PA_TAG_S64
)
427 memcpy(&tmp
, t
->data
+t
->rindex
+1, 4);
428 *u
= (int64_t) ((uint64_t) ntohl(tmp
) << 32);
429 memcpy(&tmp
, t
->data
+t
->rindex
+5, 4);
430 *u
|= (int64_t) ntohl(tmp
);
435 int pa_tagstruct_get_channel_map(pa_tagstruct
*t
, pa_channel_map
*map
) {
441 if (t
->rindex
+2 > t
->length
)
444 if (t
->data
[t
->rindex
] != PA_TAG_CHANNEL_MAP
)
447 if ((map
->channels
= t
->data
[t
->rindex
+1]) > PA_CHANNELS_MAX
)
450 if (t
->rindex
+2+map
->channels
> t
->length
)
453 for (i
= 0; i
< map
->channels
; i
++)
454 map
->map
[i
] = (int8_t) t
->data
[t
->rindex
+ 2 + i
];
456 t
->rindex
+= 2 + map
->channels
;
460 int pa_tagstruct_get_cvolume(pa_tagstruct
*t
, pa_cvolume
*cvolume
) {
467 if (t
->rindex
+2 > t
->length
)
470 if (t
->data
[t
->rindex
] != PA_TAG_CVOLUME
)
473 if ((cvolume
->channels
= t
->data
[t
->rindex
+1]) > PA_CHANNELS_MAX
)
476 if (t
->rindex
+2+cvolume
->channels
*sizeof(pa_volume_t
) > t
->length
)
479 for (i
= 0; i
< cvolume
->channels
; i
++) {
480 memcpy(&vol
, t
->data
+ t
->rindex
+ 2 + i
* sizeof(pa_volume_t
), sizeof(pa_volume_t
));
481 cvolume
->values
[i
] = (pa_volume_t
) ntohl(vol
);
484 t
->rindex
+= 2 + cvolume
->channels
* sizeof(pa_volume_t
);
488 void pa_tagstruct_put(pa_tagstruct
*t
, ...) {
495 int tag
= va_arg(va
, int);
497 if (tag
== PA_TAG_INVALID
)
502 case PA_TAG_STRING_NULL
:
503 pa_tagstruct_puts(t
, va_arg(va
, char*));
507 pa_tagstruct_putu32(t
, va_arg(va
, uint32_t));
511 pa_tagstruct_putu8(t
, (uint8_t) va_arg(va
, int));
515 pa_tagstruct_putu64(t
, va_arg(va
, uint64_t));
518 case PA_TAG_SAMPLE_SPEC
:
519 pa_tagstruct_put_sample_spec(t
, va_arg(va
, pa_sample_spec
*));
522 case PA_TAG_ARBITRARY
: {
523 void *p
= va_arg(va
, void*);
524 size_t size
= va_arg(va
, size_t);
525 pa_tagstruct_put_arbitrary(t
, p
, size
);
529 case PA_TAG_BOOLEAN_TRUE
:
530 case PA_TAG_BOOLEAN_FALSE
:
531 pa_tagstruct_put_boolean(t
, va_arg(va
, int));
535 pa_tagstruct_put_timeval(t
, va_arg(va
, struct timeval
*));
539 pa_tagstruct_put_usec(t
, va_arg(va
, pa_usec_t
));
542 case PA_TAG_CHANNEL_MAP
:
543 pa_tagstruct_put_channel_map(t
, va_arg(va
, pa_channel_map
*));
547 pa_tagstruct_put_cvolume(t
, va_arg(va
, pa_cvolume
*));
558 int pa_tagstruct_get(pa_tagstruct
*t
, ...) {
566 int tag
= va_arg(va
, int);
568 if (tag
== PA_TAG_INVALID
)
573 case PA_TAG_STRING_NULL
:
574 ret
= pa_tagstruct_gets(t
, va_arg(va
, const char**));
578 ret
= pa_tagstruct_getu32(t
, va_arg(va
, uint32_t*));
582 ret
= pa_tagstruct_getu8(t
, va_arg(va
, uint8_t*));
586 ret
= pa_tagstruct_getu64(t
, va_arg(va
, uint64_t*));
589 case PA_TAG_SAMPLE_SPEC
:
590 ret
= pa_tagstruct_get_sample_spec(t
, va_arg(va
, pa_sample_spec
*));
593 case PA_TAG_ARBITRARY
: {
594 const void **p
= va_arg(va
, const void**);
595 size_t size
= va_arg(va
, size_t);
596 ret
= pa_tagstruct_get_arbitrary(t
, p
, size
);
600 case PA_TAG_BOOLEAN_TRUE
:
601 case PA_TAG_BOOLEAN_FALSE
:
602 ret
= pa_tagstruct_get_boolean(t
, va_arg(va
, int*));
606 ret
= pa_tagstruct_get_timeval(t
, va_arg(va
, struct timeval
*));
610 ret
= pa_tagstruct_get_usec(t
, va_arg(va
, pa_usec_t
*));
613 case PA_TAG_CHANNEL_MAP
:
614 ret
= pa_tagstruct_get_channel_map(t
, va_arg(va
, pa_channel_map
*));
618 ret
= pa_tagstruct_get_cvolume(t
, va_arg(va
, pa_cvolume
*));