2
This file is part of PulseAudio.
4
Copyright 2004-2006 Lennart Poettering
6
PulseAudio 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
PulseAudio 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 PulseAudio; if not, see <http://www.gnu.org/licenses/>.
30
#ifdef HAVE_NETINET_IN_H
31
#include <netinet/in.h>
34
#include <pulse/xmalloc.h>
36
#include <pulsecore/socket.h>
37
#include <pulsecore/macro.h>
38
#include <pulsecore/flist.h>
40
#include "tagstruct.h"
42
#define MAX_TAG_SIZE (64*1024)
43
#define MAX_APPENDED_SIZE 128
44
#define GROW_TAG_SIZE 100
48
size_t length, allocated;
52
PA_TAGSTRUCT_FIXED, /* The tagstruct does not own the data, buffer was provided by caller. */
53
PA_TAGSTRUCT_DYNAMIC, /* Buffer owned by tagstruct, data must be freed. */
54
PA_TAGSTRUCT_APPENDED, /* Data points to appended buffer, used for small tagstructs. Will change to dynamic if needed. */
57
uint8_t appended[MAX_APPENDED_SIZE];
61
PA_STATIC_FLIST_DECLARE(tagstructs, 0, pa_xfree);
63
pa_tagstruct *pa_tagstruct_new(void) {
66
if (!(t = pa_flist_pop(PA_STATIC_FLIST_GET(tagstructs))))
67
t = pa_xnew(pa_tagstruct, 1);
68
t->data = t->per_type.appended;
69
t->allocated = MAX_APPENDED_SIZE;
70
t->length = t->rindex = 0;
71
t->type = PA_TAGSTRUCT_APPENDED;
76
pa_tagstruct *pa_tagstruct_new_fixed(const uint8_t* data, size_t length) {
79
pa_assert(data && length);
81
if (!(t = pa_flist_pop(PA_STATIC_FLIST_GET(tagstructs))))
82
t = pa_xnew(pa_tagstruct, 1);
83
t->data = (uint8_t*) data;
84
t->allocated = t->length = length;
86
t->type = PA_TAGSTRUCT_FIXED;
91
void pa_tagstruct_free(pa_tagstruct*t) {
94
if (t->type == PA_TAGSTRUCT_DYNAMIC)
96
if (pa_flist_push(PA_STATIC_FLIST_GET(tagstructs), t) < 0)
100
static inline void extend(pa_tagstruct*t, size_t l) {
102
pa_assert(t->type != PA_TAGSTRUCT_FIXED);
104
if (t->length+l <= t->allocated)
107
if (t->type == PA_TAGSTRUCT_DYNAMIC)
108
t->data = pa_xrealloc(t->data, t->allocated = t->length + l + GROW_TAG_SIZE);
109
else if (t->type == PA_TAGSTRUCT_APPENDED) {
110
t->type = PA_TAGSTRUCT_DYNAMIC;
111
t->data = pa_xmalloc(t->allocated = t->length + l + GROW_TAG_SIZE);
112
memcpy(t->data, t->per_type.appended, t->length);
116
static void write_u8(pa_tagstruct *t, uint8_t u) {
118
t->data[t->length++] = u;
121
static int read_u8(pa_tagstruct *t, uint8_t *u) {
122
if (t->rindex + 1 > t->length)
125
*u = t->data[t->rindex++];
129
static void write_u32(pa_tagstruct *t, uint32_t u) {
132
memcpy(t->data + t->length, &u, 4);
136
static int read_u32(pa_tagstruct *t, uint32_t *u) {
137
if (t->rindex + 4 > t->length)
140
memcpy(u, t->data + t->rindex, 4);
147
static void write_u64(pa_tagstruct *t, uint64_t u) {
148
write_u32(t, u >> 32);
152
static int read_u64(pa_tagstruct *t, uint64_t *u) {
155
if (read_u32(t, &tmp) < 0)
158
*u = ((uint64_t) tmp) << 32;
160
if (read_u32(t, &tmp) < 0)
167
static int read_s64(pa_tagstruct *t, int64_t *u) {
170
if (read_u32(t, &tmp) < 0)
173
*u = (int64_t) (((uint64_t) tmp) << 32);
175
if (read_u32(t, &tmp) < 0)
182
static void write_arbitrary(pa_tagstruct *t, const void *p, size_t len) {
186
memcpy(t->data + t->length, p, len);
191
static int read_arbitrary(pa_tagstruct *t, const void **p, size_t length) {
192
if (t->rindex + length > t->length)
195
*p = t->data + t->rindex;
200
void pa_tagstruct_puts(pa_tagstruct*t, const char *s) {
205
write_u8(t, PA_TAG_STRING);
207
write_arbitrary(t, s, l);
209
write_u8(t, PA_TAG_STRING_NULL);
212
void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i) {
215
write_u8(t, PA_TAG_U32);
219
void pa_tagstruct_putu8(pa_tagstruct*t, uint8_t c) {
222
write_u8(t, PA_TAG_U8);
226
void pa_tagstruct_put_sample_spec(pa_tagstruct *t, const pa_sample_spec *ss) {
230
write_u8(t, PA_TAG_SAMPLE_SPEC);
231
write_u8(t, ss->format);
232
write_u8(t, ss->channels);
233
write_u32(t, ss->rate);
236
void pa_tagstruct_put_arbitrary(pa_tagstruct *t, const void *p, size_t length) {
240
write_u8(t, PA_TAG_ARBITRARY);
241
write_u32(t, length);
242
write_arbitrary(t, p, length);
245
void pa_tagstruct_put_boolean(pa_tagstruct*t, bool b) {
248
write_u8(t, b ? PA_TAG_BOOLEAN_TRUE : PA_TAG_BOOLEAN_FALSE);
251
void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv) {
254
write_u8(t, PA_TAG_TIMEVAL);
255
write_u32(t, tv->tv_sec);
256
write_u32(t, tv->tv_usec);
259
void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u) {
262
write_u8(t, PA_TAG_USEC);
266
void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t u) {
269
write_u8(t, PA_TAG_U64);
273
void pa_tagstruct_puts64(pa_tagstruct*t, int64_t u) {
276
write_u8(t, PA_TAG_S64);
280
void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map) {
286
write_u8(t, PA_TAG_CHANNEL_MAP);
287
write_u8(t, map->channels);
289
for (i = 0; i < map->channels; i ++)
290
write_u8(t, map->map[i]);
293
void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) {
299
write_u8(t, PA_TAG_CVOLUME);
300
write_u8(t, cvolume->channels);
302
for (i = 0; i < cvolume->channels; i ++)
303
write_u32(t, cvolume->values[i]);
306
void pa_tagstruct_put_volume(pa_tagstruct *t, pa_volume_t vol) {
309
write_u8(t, PA_TAG_VOLUME);
313
void pa_tagstruct_put_proplist(pa_tagstruct *t, pa_proplist *p) {
318
write_u8(t, PA_TAG_PROPLIST);
325
if (!(k = pa_proplist_iterate(p, &state)))
328
pa_tagstruct_puts(t, k);
329
pa_assert_se(pa_proplist_get(p, k, &d, &l) >= 0);
330
pa_tagstruct_putu32(t, (uint32_t) l);
331
pa_tagstruct_put_arbitrary(t, d, l);
334
pa_tagstruct_puts(t, NULL);
337
void pa_tagstruct_put_format_info(pa_tagstruct *t, pa_format_info *f) {
341
write_u8(t, PA_TAG_FORMAT_INFO);
342
pa_tagstruct_putu8(t, (uint8_t) f->encoding);
343
pa_tagstruct_put_proplist(t, f->plist);
346
static int read_tag(pa_tagstruct *t, uint8_t type) {
347
if (t->rindex + 1 > t->length)
350
if (t->data[t->rindex] != type)
358
int pa_tagstruct_gets(pa_tagstruct*t, const char **s) {
366
if (t->rindex+1 > t->length)
369
if (t->data[t->rindex] == PA_TAG_STRING_NULL) {
375
if (read_tag(t, PA_TAG_STRING) < 0)
378
if (t->rindex + 1 > t->length)
382
for (n = 0, c = (char*) (t->data + t->rindex); t->rindex + n < t->length; n++, c++)
391
*s = (char*) (t->data + t->rindex);
397
int pa_tagstruct_getu32(pa_tagstruct*t, uint32_t *i) {
401
if (read_tag(t, PA_TAG_U32) < 0)
404
return read_u32(t, i);
407
int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c) {
411
if (read_tag(t, PA_TAG_U8) < 0)
414
return read_u8(t, c);
417
int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss) {
423
if (read_tag(t, PA_TAG_SAMPLE_SPEC) < 0)
426
if (read_u8(t, &tmp) < 0)
431
if (read_u8(t, &ss->channels) < 0)
434
return read_u32(t, &ss->rate);
437
int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length) {
443
if (read_tag(t, PA_TAG_ARBITRARY) < 0)
446
if (read_u32(t, &len) < 0 || len != length)
449
return read_arbitrary(t, p, length);
452
int pa_tagstruct_eof(pa_tagstruct*t) {
455
return t->rindex >= t->length;
458
const uint8_t* pa_tagstruct_data(pa_tagstruct*t, size_t *l) {
466
int pa_tagstruct_get_boolean(pa_tagstruct*t, bool *b) {
470
if (t->rindex+1 > t->length)
473
if (t->data[t->rindex] == PA_TAG_BOOLEAN_TRUE)
475
else if (t->data[t->rindex] == PA_TAG_BOOLEAN_FALSE)
484
int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv) {
490
if (read_tag(t, PA_TAG_TIMEVAL) < 0)
493
if (read_u32(t, &tmp) < 0)
498
if (read_u32(t, &tmp) < 0)
506
int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u) {
510
if (read_tag(t, PA_TAG_USEC) < 0)
513
return read_u64(t, u);
516
int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *u) {
520
if (read_tag(t, PA_TAG_U64) < 0)
523
return read_u64(t, u);
526
int pa_tagstruct_gets64(pa_tagstruct*t, int64_t *u) {
530
if (read_tag(t, PA_TAG_S64) < 0)
533
return read_s64(t, u);
536
int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) {
542
if (read_tag(t, PA_TAG_CHANNEL_MAP) < 0)
545
if (read_u8(t, &map->channels) < 0 || map->channels > PA_CHANNELS_MAX)
548
for (i = 0; i < map->channels; i ++) {
551
if (read_u8(t, &tmp) < 0)
560
int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) {
566
if (read_tag(t, PA_TAG_CVOLUME) < 0)
569
if (read_u8(t, &cvolume->channels) < 0 || cvolume->channels > PA_CHANNELS_MAX)
572
for (i = 0; i < cvolume->channels; i ++) {
573
if (read_u32(t, &cvolume->values[i]) < 0)
580
int pa_tagstruct_get_volume(pa_tagstruct*t, pa_volume_t *vol) {
584
if (read_tag(t, PA_TAG_VOLUME) < 0)
587
return read_u32(t, vol);
590
int pa_tagstruct_get_proplist(pa_tagstruct *t, pa_proplist *p) {
593
if (read_tag(t, PA_TAG_PROPLIST) < 0)
601
if (pa_tagstruct_gets(t, &k) < 0)
607
if (!pa_proplist_key_valid(k))
610
if (pa_tagstruct_getu32(t, &length) < 0)
613
if (length > MAX_TAG_SIZE)
616
if (pa_tagstruct_get_arbitrary(t, &d, length) < 0)
620
pa_assert_se(pa_proplist_set(p, k, d, length) >= 0);
626
int pa_tagstruct_get_format_info(pa_tagstruct *t, pa_format_info *f) {
632
if (read_tag(t, PA_TAG_FORMAT_INFO) < 0)
635
if (pa_tagstruct_getu8(t, &encoding) < 0)
638
f->encoding = encoding;
640
return pa_tagstruct_get_proplist(t, f->plist);
643
void pa_tagstruct_put(pa_tagstruct *t, ...) {
650
int tag = va_arg(va, int);
652
if (tag == PA_TAG_INVALID)
657
case PA_TAG_STRING_NULL:
658
pa_tagstruct_puts(t, va_arg(va, char*));
662
pa_tagstruct_putu32(t, va_arg(va, uint32_t));
666
pa_tagstruct_putu8(t, (uint8_t) va_arg(va, int));
670
pa_tagstruct_putu64(t, va_arg(va, uint64_t));
673
case PA_TAG_SAMPLE_SPEC:
674
pa_tagstruct_put_sample_spec(t, va_arg(va, pa_sample_spec*));
677
case PA_TAG_ARBITRARY: {
678
void *p = va_arg(va, void*);
679
size_t size = va_arg(va, size_t);
680
pa_tagstruct_put_arbitrary(t, p, size);
684
case PA_TAG_BOOLEAN_TRUE:
685
case PA_TAG_BOOLEAN_FALSE:
686
pa_tagstruct_put_boolean(t, va_arg(va, int));
690
pa_tagstruct_put_timeval(t, va_arg(va, struct timeval*));
694
pa_tagstruct_put_usec(t, va_arg(va, pa_usec_t));
697
case PA_TAG_CHANNEL_MAP:
698
pa_tagstruct_put_channel_map(t, va_arg(va, pa_channel_map *));
702
pa_tagstruct_put_cvolume(t, va_arg(va, pa_cvolume *));
706
pa_tagstruct_put_volume(t, va_arg(va, pa_volume_t));
709
case PA_TAG_PROPLIST:
710
pa_tagstruct_put_proplist(t, va_arg(va, pa_proplist *));
714
pa_assert_not_reached();
721
int pa_tagstruct_get(pa_tagstruct *t, ...) {
729
int tag = va_arg(va, int);
731
if (tag == PA_TAG_INVALID)
736
case PA_TAG_STRING_NULL:
737
ret = pa_tagstruct_gets(t, va_arg(va, const char**));
741
ret = pa_tagstruct_getu32(t, va_arg(va, uint32_t*));
745
ret = pa_tagstruct_getu8(t, va_arg(va, uint8_t*));
749
ret = pa_tagstruct_getu64(t, va_arg(va, uint64_t*));
752
case PA_TAG_SAMPLE_SPEC:
753
ret = pa_tagstruct_get_sample_spec(t, va_arg(va, pa_sample_spec*));
756
case PA_TAG_ARBITRARY: {
757
const void **p = va_arg(va, const void**);
758
size_t size = va_arg(va, size_t);
759
ret = pa_tagstruct_get_arbitrary(t, p, size);
763
case PA_TAG_BOOLEAN_TRUE:
764
case PA_TAG_BOOLEAN_FALSE:
765
ret = pa_tagstruct_get_boolean(t, va_arg(va, bool*));
769
ret = pa_tagstruct_get_timeval(t, va_arg(va, struct timeval*));
773
ret = pa_tagstruct_get_usec(t, va_arg(va, pa_usec_t*));
776
case PA_TAG_CHANNEL_MAP:
777
ret = pa_tagstruct_get_channel_map(t, va_arg(va, pa_channel_map *));
781
ret = pa_tagstruct_get_cvolume(t, va_arg(va, pa_cvolume *));
785
ret = pa_tagstruct_get_volume(t, va_arg(va, pa_volume_t *));
788
case PA_TAG_PROPLIST:
789
ret = pa_tagstruct_get_proplist(t, va_arg(va, pa_proplist *));
793
pa_assert_not_reached();