]>
code.delx.au - pulseaudio/blob - src/polypcore/tagstruct.c
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 <polypcore/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_put_channel_map(pa_tagstruct
*t
, const pa_channel_map
*map
) {
196 extend(t
, 2 + map
->channels
);
198 t
->data
[t
->length
++] = PA_TAG_CHANNEL_MAP
;
199 t
->data
[t
->length
++] = map
->channels
;
201 for (i
= 0; i
< map
->channels
; i
++)
202 t
->data
[t
->length
++] = (uint8_t) map
->map
[i
];
205 void pa_tagstruct_put_cvolume(pa_tagstruct
*t
, const pa_cvolume
*cvolume
) {
210 extend(t
, 2 + cvolume
->channels
* sizeof(pa_volume_t
));
212 t
->data
[t
->length
++] = PA_TAG_CVOLUME
;
213 t
->data
[t
->length
++] = cvolume
->channels
;
215 for (i
= 0; i
< cvolume
->channels
; i
++) {
216 vol
= htonl(cvolume
->values
[i
]);
217 memcpy(t
->data
+ t
->length
, &vol
, sizeof(pa_volume_t
));
218 t
->length
+= sizeof(pa_volume_t
);
222 int pa_tagstruct_gets(pa_tagstruct
*t
, const char **s
) {
228 if (t
->rindex
+1 > t
->length
)
231 if (t
->data
[t
->rindex
] == PA_TAG_STRING_NULL
) {
237 if (t
->rindex
+2 > t
->length
)
240 if (t
->data
[t
->rindex
] != PA_TAG_STRING
)
244 for (n
= 0, c
= (char*) (t
->data
+t
->rindex
+1); t
->rindex
+1+n
< t
->length
; n
++, c
++)
253 *s
= (char*) (t
->data
+t
->rindex
+1);
259 int pa_tagstruct_getu32(pa_tagstruct
*t
, uint32_t *i
) {
262 if (t
->rindex
+5 > t
->length
)
265 if (t
->data
[t
->rindex
] != PA_TAG_U32
)
268 memcpy(i
, t
->data
+t
->rindex
+1, 4);
274 int pa_tagstruct_getu8(pa_tagstruct
*t
, uint8_t *c
) {
277 if (t
->rindex
+2 > t
->length
)
280 if (t
->data
[t
->rindex
] != PA_TAG_U8
)
283 *c
= t
->data
[t
->rindex
+1];
288 int pa_tagstruct_get_sample_spec(pa_tagstruct
*t
, pa_sample_spec
*ss
) {
291 if (t
->rindex
+7 > t
->length
)
294 if (t
->data
[t
->rindex
] != PA_TAG_SAMPLE_SPEC
)
297 ss
->format
= t
->data
[t
->rindex
+1];
298 ss
->channels
= t
->data
[t
->rindex
+2];
299 memcpy(&ss
->rate
, t
->data
+t
->rindex
+3, 4);
300 ss
->rate
= ntohl(ss
->rate
);
302 if (!pa_sample_spec_valid(ss
))
309 int pa_tagstruct_get_arbitrary(pa_tagstruct
*t
, const void **p
, size_t length
) {
313 if (t
->rindex
+5+length
> t
->length
)
316 if (t
->data
[t
->rindex
] != PA_TAG_ARBITRARY
)
319 memcpy(&len
, t
->data
+t
->rindex
+1, 4);
320 if (ntohl(len
) != length
)
323 *p
= t
->data
+t
->rindex
+5;
324 t
->rindex
+= 5+length
;
328 int pa_tagstruct_eof(pa_tagstruct
*t
) {
330 return t
->rindex
>= t
->length
;
333 const uint8_t* pa_tagstruct_data(pa_tagstruct
*t
, size_t *l
) {
334 assert(t
&& t
->dynamic
&& l
);
339 int pa_tagstruct_get_boolean(pa_tagstruct
*t
, int *b
) {
342 if (t
->rindex
+1 > t
->length
)
345 if (t
->data
[t
->rindex
] == PA_TAG_BOOLEAN_TRUE
)
347 else if (t
->data
[t
->rindex
] == PA_TAG_BOOLEAN_FALSE
)
356 int pa_tagstruct_get_timeval(pa_tagstruct
*t
, struct timeval
*tv
) {
358 if (t
->rindex
+9 > t
->length
)
361 if (t
->data
[t
->rindex
] != PA_TAG_TIMEVAL
)
364 memcpy(&tv
->tv_sec
, t
->data
+t
->rindex
+1, 4);
365 tv
->tv_sec
= ntohl(tv
->tv_sec
);
366 memcpy(&tv
->tv_usec
, t
->data
+t
->rindex
+5, 4);
367 tv
->tv_usec
= ntohl(tv
->tv_usec
);
373 int pa_tagstruct_get_usec(pa_tagstruct
*t
, pa_usec_t
*u
) {
377 if (t
->rindex
+9 > t
->length
)
380 if (t
->data
[t
->rindex
] != PA_TAG_USEC
)
383 memcpy(&tmp
, t
->data
+t
->rindex
+1, 4);
384 *u
= (pa_usec_t
) ntohl(tmp
) << 32;
385 memcpy(&tmp
, t
->data
+t
->rindex
+5, 4);
386 *u
|= (pa_usec_t
) ntohl(tmp
);
391 int pa_tagstruct_getu64(pa_tagstruct
*t
, uint64_t *u
) {
395 if (t
->rindex
+9 > t
->length
)
398 if (t
->data
[t
->rindex
] != PA_TAG_U64
)
401 memcpy(&tmp
, t
->data
+t
->rindex
+1, 4);
402 *u
= (pa_usec_t
) ntohl(tmp
) << 32;
403 memcpy(&tmp
, t
->data
+t
->rindex
+5, 4);
404 *u
|= (pa_usec_t
) ntohl(tmp
);
409 int pa_tagstruct_get_channel_map(pa_tagstruct
*t
, pa_channel_map
*map
) {
415 if (t
->rindex
+2 > t
->length
)
418 if (t
->data
[t
->rindex
] != PA_TAG_CHANNEL_MAP
)
421 if ((map
->channels
= t
->data
[t
->rindex
+1]) > PA_CHANNELS_MAX
)
424 if (t
->rindex
+2+map
->channels
> t
->length
)
427 for (i
= 0; i
< map
->channels
; i
++)
428 map
->map
[i
] = (int8_t) t
->data
[t
->rindex
+ 2 + i
];
430 if (!pa_channel_map_valid(map
))
433 t
->rindex
+= 2 + map
->channels
;
437 int pa_tagstruct_get_cvolume(pa_tagstruct
*t
, pa_cvolume
*cvolume
) {
444 if (t
->rindex
+2 > t
->length
)
447 if (t
->data
[t
->rindex
] != PA_TAG_CVOLUME
)
450 if ((cvolume
->channels
= t
->data
[t
->rindex
+1]) > PA_CHANNELS_MAX
)
453 if (t
->rindex
+2+cvolume
->channels
*sizeof(pa_volume_t
) > t
->length
)
456 for (i
= 0; i
< cvolume
->channels
; i
++) {
457 memcpy(&vol
, t
->data
+ t
->rindex
+ 2 + i
* sizeof(pa_volume_t
), sizeof(pa_volume_t
));
458 cvolume
->values
[i
] = (pa_volume_t
) ntohl(vol
);
461 if (!pa_cvolume_valid(cvolume
))
464 t
->rindex
+= 2 + cvolume
->channels
* sizeof(pa_volume_t
);
468 void pa_tagstruct_put(pa_tagstruct
*t
, ...) {
475 int tag
= va_arg(va
, int);
477 if (tag
== PA_TAG_INVALID
)
482 case PA_TAG_STRING_NULL
:
483 pa_tagstruct_puts(t
, va_arg(va
, char*));
487 pa_tagstruct_putu32(t
, va_arg(va
, uint32_t));
491 pa_tagstruct_putu8(t
, (uint8_t) va_arg(va
, int));
495 pa_tagstruct_putu64(t
, va_arg(va
, uint64_t));
498 case PA_TAG_SAMPLE_SPEC
:
499 pa_tagstruct_put_sample_spec(t
, va_arg(va
, pa_sample_spec
*));
502 case PA_TAG_ARBITRARY
: {
503 void *p
= va_arg(va
, void*);
504 size_t size
= va_arg(va
, size_t);
505 pa_tagstruct_put_arbitrary(t
, p
, size
);
509 case PA_TAG_BOOLEAN_TRUE
:
510 case PA_TAG_BOOLEAN_FALSE
:
511 pa_tagstruct_put_boolean(t
, va_arg(va
, int));
515 pa_tagstruct_put_timeval(t
, va_arg(va
, struct timeval
*));
519 pa_tagstruct_put_usec(t
, va_arg(va
, pa_usec_t
));
522 case PA_TAG_CHANNEL_MAP
:
523 pa_tagstruct_put_channel_map(t
, va_arg(va
, pa_channel_map
*));
527 pa_tagstruct_put_cvolume(t
, va_arg(va
, pa_cvolume
*));
538 int pa_tagstruct_get(pa_tagstruct
*t
, ...) {
546 int tag
= va_arg(va
, int);
548 if (tag
== PA_TAG_INVALID
)
553 case PA_TAG_STRING_NULL
:
554 ret
= pa_tagstruct_gets(t
, va_arg(va
, const char**));
558 ret
= pa_tagstruct_getu32(t
, va_arg(va
, uint32_t*));
562 ret
= pa_tagstruct_getu8(t
, va_arg(va
, uint8_t*));
566 ret
= pa_tagstruct_getu64(t
, va_arg(va
, uint64_t*));
569 case PA_TAG_SAMPLE_SPEC
:
570 ret
= pa_tagstruct_get_sample_spec(t
, va_arg(va
, pa_sample_spec
*));
573 case PA_TAG_ARBITRARY
: {
574 const void **p
= va_arg(va
, const void**);
575 size_t size
= va_arg(va
, size_t);
576 ret
= pa_tagstruct_get_arbitrary(t
, p
, size
);
580 case PA_TAG_BOOLEAN_TRUE
:
581 case PA_TAG_BOOLEAN_FALSE
:
582 ret
= pa_tagstruct_get_boolean(t
, va_arg(va
, int*));
586 ret
= pa_tagstruct_get_timeval(t
, va_arg(va
, struct timeval
*));
590 ret
= pa_tagstruct_get_usec(t
, va_arg(va
, pa_usec_t
*));
593 case PA_TAG_CHANNEL_MAP
:
594 ret
= pa_tagstruct_get_channel_map(t
, va_arg(va
, pa_channel_map
*));
598 ret
= pa_tagstruct_get_cvolume(t
, va_arg(va
, pa_cvolume
*));