]>
code.delx.au - pulseaudio/blob - polyp/tagstruct.c
676f67ded6043fd607a6a5381b4bb19d9d629492
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 "tagstruct.h"
45 size_t length
, allocated
;
51 pa_tagstruct
*pa_tagstruct_new(const uint8_t* data
, size_t length
) {
54 assert(!data
|| (data
&& length
));
56 t
= pa_xmalloc(sizeof(pa_tagstruct
));
57 t
->data
= (uint8_t*) data
;
58 t
->allocated
= t
->length
= data
? length
: 0;
64 void pa_tagstruct_free(pa_tagstruct
*t
) {
71 uint8_t* pa_tagstruct_free_data(pa_tagstruct
*t
, size_t *l
) {
73 assert(t
&& t
->dynamic
&& l
);
80 static void extend(pa_tagstruct
*t
, size_t l
) {
81 assert(t
&& t
->dynamic
);
83 if (t
->length
+l
<= t
->allocated
)
86 t
->data
= pa_xrealloc(t
->data
, t
->allocated
= t
->length
+l
+100);
90 void pa_tagstruct_puts(pa_tagstruct
*t
, const char *s
) {
96 t
->data
[t
->length
] = PA_TAG_STRING
;
97 strcpy((char*) (t
->data
+t
->length
+1), s
);
101 t
->data
[t
->length
] = PA_TAG_STRING_NULL
;
106 void pa_tagstruct_putu32(pa_tagstruct
*t
, uint32_t i
) {
109 t
->data
[t
->length
] = PA_TAG_U32
;
111 memcpy(t
->data
+t
->length
+1, &i
, 4);
115 void pa_tagstruct_putu8(pa_tagstruct
*t
, uint8_t c
) {
118 t
->data
[t
->length
] = PA_TAG_U8
;
119 *(t
->data
+t
->length
+1) = c
;
123 void pa_tagstruct_put_sample_spec(pa_tagstruct
*t
, const pa_sample_spec
*ss
) {
127 t
->data
[t
->length
] = PA_TAG_SAMPLE_SPEC
;
128 t
->data
[t
->length
+1] = (uint8_t) ss
->format
;
129 t
->data
[t
->length
+2] = ss
->channels
;
130 rate
= htonl(ss
->rate
);
131 memcpy(t
->data
+t
->length
+3, &rate
, 4);
135 void pa_tagstruct_put_arbitrary(pa_tagstruct
*t
, const void *p
, size_t length
) {
140 t
->data
[t
->length
] = PA_TAG_ARBITRARY
;
142 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
144 memcpy(t
->data
+t
->length
+5, p
, length
);
145 t
->length
+= 5+length
;
148 void pa_tagstruct_put_boolean(pa_tagstruct
*t
, int b
) {
151 t
->data
[t
->length
] = b
? PA_TAG_BOOLEAN_TRUE
: PA_TAG_BOOLEAN_FALSE
;
155 void pa_tagstruct_put_timeval(pa_tagstruct
*t
, const struct timeval
*tv
) {
159 t
->data
[t
->length
] = PA_TAG_TIMEVAL
;
160 tmp
= htonl(tv
->tv_sec
);
161 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
162 tmp
= htonl(tv
->tv_usec
);
163 memcpy(t
->data
+t
->length
+5, &tmp
, 4);
167 void pa_tagstruct_put_usec(pa_tagstruct
*t
, pa_usec_t u
) {
171 t
->data
[t
->length
] = PA_TAG_USEC
;
172 tmp
= htonl((uint32_t) (u
>> 32));
173 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
174 tmp
= htonl((uint32_t) u
);
175 memcpy(t
->data
+t
->length
+5, &tmp
, 4);
179 void pa_tagstruct_putu64(pa_tagstruct
*t
, uint64_t u
) {
183 t
->data
[t
->length
] = PA_TAG_U64
;
184 tmp
= htonl((uint32_t) (u
>> 32));
185 memcpy(t
->data
+t
->length
+1, &tmp
, 4);
186 tmp
= htonl((uint32_t) u
);
187 memcpy(t
->data
+t
->length
+5, &tmp
, 4);
191 void pa_tagstruct_put_channel_map(pa_tagstruct
*t
, const pa_channel_map
*map
) {
195 extend(t
, 2 + map
->channels
);
197 t
->data
[t
->length
++] = PA_TAG_CHANNEL_MAP
;
198 t
->data
[t
->length
++] = map
->channels
;
200 for (i
= 0; i
< map
->channels
; i
++)
201 t
->data
[t
->length
++] = (uint8_t) map
->map
[i
];
204 void pa_tagstruct_put_cvolume(pa_tagstruct
*t
, const pa_cvolume
*cvolume
) {
209 extend(t
, 2 + cvolume
->channels
* sizeof(pa_volume_t
));
211 t
->data
[t
->length
++] = PA_TAG_CVOLUME
;
212 t
->data
[t
->length
++] = cvolume
->channels
;
214 for (i
= 0; i
< cvolume
->channels
; i
++) {
215 vol
= htonl(cvolume
->values
[i
]);
216 memcpy(t
->data
+ t
->length
, &vol
, sizeof(pa_volume_t
));
217 t
->length
+= sizeof(pa_volume_t
);
221 int pa_tagstruct_gets(pa_tagstruct
*t
, const char **s
) {
227 if (t
->rindex
+1 > t
->length
)
230 if (t
->data
[t
->rindex
] == PA_TAG_STRING_NULL
) {
236 if (t
->rindex
+2 > t
->length
)
239 if (t
->data
[t
->rindex
] != PA_TAG_STRING
)
243 for (n
= 0, c
= (char*) (t
->data
+t
->rindex
+1); t
->rindex
+1+n
< t
->length
; n
++, c
++)
252 *s
= (char*) (t
->data
+t
->rindex
+1);
258 int pa_tagstruct_getu32(pa_tagstruct
*t
, uint32_t *i
) {
261 if (t
->rindex
+5 > t
->length
)
264 if (t
->data
[t
->rindex
] != PA_TAG_U32
)
267 memcpy(i
, t
->data
+t
->rindex
+1, 4);
273 int pa_tagstruct_getu8(pa_tagstruct
*t
, uint8_t *c
) {
276 if (t
->rindex
+2 > t
->length
)
279 if (t
->data
[t
->rindex
] != PA_TAG_U8
)
282 *c
= t
->data
[t
->rindex
+1];
287 int pa_tagstruct_get_sample_spec(pa_tagstruct
*t
, pa_sample_spec
*ss
) {
290 if (t
->rindex
+7 > t
->length
)
293 if (t
->data
[t
->rindex
] != PA_TAG_SAMPLE_SPEC
)
296 ss
->format
= t
->data
[t
->rindex
+1];
297 ss
->channels
= t
->data
[t
->rindex
+2];
298 memcpy(&ss
->rate
, t
->data
+t
->rindex
+3, 4);
299 ss
->rate
= ntohl(ss
->rate
);
301 if (!pa_sample_spec_valid(ss
))
308 int pa_tagstruct_get_arbitrary(pa_tagstruct
*t
, const void **p
, size_t length
) {
312 if (t
->rindex
+5+length
> t
->length
)
315 if (t
->data
[t
->rindex
] != PA_TAG_ARBITRARY
)
318 memcpy(&len
, t
->data
+t
->rindex
+1, 4);
319 if (ntohl(len
) != length
)
322 *p
= t
->data
+t
->rindex
+5;
323 t
->rindex
+= 5+length
;
327 int pa_tagstruct_eof(pa_tagstruct
*t
) {
329 return t
->rindex
>= t
->length
;
332 const uint8_t* pa_tagstruct_data(pa_tagstruct
*t
, size_t *l
) {
333 assert(t
&& t
->dynamic
&& l
);
338 int pa_tagstruct_get_boolean(pa_tagstruct
*t
, int *b
) {
341 if (t
->rindex
+1 > t
->length
)
344 if (t
->data
[t
->rindex
] == PA_TAG_BOOLEAN_TRUE
)
346 else if (t
->data
[t
->rindex
] == PA_TAG_BOOLEAN_FALSE
)
355 int pa_tagstruct_get_timeval(pa_tagstruct
*t
, struct timeval
*tv
) {
357 if (t
->rindex
+9 > t
->length
)
360 if (t
->data
[t
->rindex
] != PA_TAG_TIMEVAL
)
363 memcpy(&tv
->tv_sec
, t
->data
+t
->rindex
+1, 4);
364 tv
->tv_sec
= ntohl(tv
->tv_sec
);
365 memcpy(&tv
->tv_usec
, t
->data
+t
->rindex
+5, 4);
366 tv
->tv_usec
= ntohl(tv
->tv_usec
);
372 int pa_tagstruct_get_usec(pa_tagstruct
*t
, pa_usec_t
*u
) {
376 if (t
->rindex
+9 > t
->length
)
379 if (t
->data
[t
->rindex
] != PA_TAG_USEC
)
382 memcpy(&tmp
, t
->data
+t
->rindex
+1, 4);
383 *u
= (pa_usec_t
) ntohl(tmp
) << 32;
384 memcpy(&tmp
, t
->data
+t
->rindex
+5, 4);
385 *u
|= (pa_usec_t
) ntohl(tmp
);
390 int pa_tagstruct_getu64(pa_tagstruct
*t
, uint64_t *u
) {
394 if (t
->rindex
+9 > t
->length
)
397 if (t
->data
[t
->rindex
] != PA_TAG_U64
)
400 memcpy(&tmp
, t
->data
+t
->rindex
+1, 4);
401 *u
= (pa_usec_t
) ntohl(tmp
) << 32;
402 memcpy(&tmp
, t
->data
+t
->rindex
+5, 4);
403 *u
|= (pa_usec_t
) ntohl(tmp
);
408 int pa_tagstruct_get_channel_map(pa_tagstruct
*t
, pa_channel_map
*map
) {
414 if (t
->rindex
+2 > t
->length
)
417 if (t
->data
[t
->rindex
] != PA_TAG_CHANNEL_MAP
)
420 if ((map
->channels
= t
->data
[t
->rindex
+1]) > PA_CHANNELS_MAX
)
423 if (t
->rindex
+2+map
->channels
> t
->length
)
426 for (i
= 0; i
< map
->channels
; i
++)
427 map
->map
[i
] = (int8_t) t
->data
[t
->rindex
+ 2 + i
];
429 if (!pa_channel_map_valid(map
))
432 t
->rindex
+= 2 + map
->channels
;
436 int pa_tagstruct_get_cvolume(pa_tagstruct
*t
, pa_cvolume
*cvolume
) {
443 if (t
->rindex
+2 > t
->length
)
446 if (t
->data
[t
->rindex
] != PA_TAG_CVOLUME
)
449 if ((cvolume
->channels
= t
->data
[t
->rindex
+1]) > PA_CHANNELS_MAX
)
452 if (t
->rindex
+2+cvolume
->channels
*sizeof(pa_volume_t
) > t
->length
)
455 for (i
= 0; i
< cvolume
->channels
; i
++) {
456 memcpy(&vol
, t
->data
+ t
->rindex
+ 2 + i
* sizeof(pa_volume_t
), sizeof(pa_volume_t
));
457 cvolume
->values
[i
] = (pa_volume_t
) ntohl(vol
);
460 if (!pa_cvolume_valid(cvolume
))
463 t
->rindex
+= 2 + cvolume
->channels
* sizeof(pa_volume_t
);
467 void pa_tagstruct_put(pa_tagstruct
*t
, ...) {
474 int tag
= va_arg(va
, int);
476 if (tag
== PA_TAG_INVALID
)
481 case PA_TAG_STRING_NULL
:
482 pa_tagstruct_puts(t
, va_arg(va
, char*));
486 pa_tagstruct_putu32(t
, va_arg(va
, uint32_t));
490 pa_tagstruct_putu8(t
, (uint8_t) va_arg(va
, int));
494 pa_tagstruct_putu64(t
, va_arg(va
, uint64_t));
497 case PA_TAG_SAMPLE_SPEC
:
498 pa_tagstruct_put_sample_spec(t
, va_arg(va
, pa_sample_spec
*));
501 case PA_TAG_ARBITRARY
: {
502 void *p
= va_arg(va
, void*);
503 size_t size
= va_arg(va
, size_t);
504 pa_tagstruct_put_arbitrary(t
, p
, size
);
508 case PA_TAG_BOOLEAN_TRUE
:
509 case PA_TAG_BOOLEAN_FALSE
:
510 pa_tagstruct_put_boolean(t
, va_arg(va
, int));
514 pa_tagstruct_put_timeval(t
, va_arg(va
, struct timeval
*));
518 pa_tagstruct_put_usec(t
, va_arg(va
, pa_usec_t
));
521 case PA_TAG_CHANNEL_MAP
:
522 pa_tagstruct_put_channel_map(t
, va_arg(va
, pa_channel_map
*));
526 pa_tagstruct_put_cvolume(t
, va_arg(va
, pa_cvolume
*));
537 int pa_tagstruct_get(pa_tagstruct
*t
, ...) {
545 int tag
= va_arg(va
, int);
547 if (tag
== PA_TAG_INVALID
)
552 case PA_TAG_STRING_NULL
:
553 ret
= pa_tagstruct_gets(t
, va_arg(va
, const char**));
557 ret
= pa_tagstruct_getu32(t
, va_arg(va
, uint32_t*));
561 ret
= pa_tagstruct_getu8(t
, va_arg(va
, uint8_t*));
565 ret
= pa_tagstruct_getu64(t
, va_arg(va
, uint64_t*));
568 case PA_TAG_SAMPLE_SPEC
:
569 ret
= pa_tagstruct_get_sample_spec(t
, va_arg(va
, pa_sample_spec
*));
572 case PA_TAG_ARBITRARY
: {
573 const void **p
= va_arg(va
, const void**);
574 size_t size
= va_arg(va
, size_t);
575 ret
= pa_tagstruct_get_arbitrary(t
, p
, size
);
579 case PA_TAG_BOOLEAN_TRUE
:
580 case PA_TAG_BOOLEAN_FALSE
:
581 ret
= pa_tagstruct_get_boolean(t
, va_arg(va
, int*));
585 ret
= pa_tagstruct_get_timeval(t
, va_arg(va
, struct timeval
*));
589 ret
= pa_tagstruct_get_usec(t
, va_arg(va
, pa_usec_t
*));
592 case PA_TAG_CHANNEL_MAP
:
593 ret
= pa_tagstruct_get_channel_map(t
, va_arg(va
, pa_channel_map
*));
597 ret
= pa_tagstruct_get_cvolume(t
, va_arg(va
, pa_cvolume
*));