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>
39
#include "tagstruct.h"
41
#define MAX_TAG_SIZE (64*1024)
45
size_t length, allocated;
51
pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) {
54
pa_assert(!data || (data && length));
56
t = pa_xnew(pa_tagstruct, 1);
57
t->data = (uint8_t*) data;
58
t->allocated = t->length = data ? length : 0;
65
void pa_tagstruct_free(pa_tagstruct*t) {
73
uint8_t* pa_tagstruct_free_data(pa_tagstruct*t, size_t *l) {
77
pa_assert(t->dynamic);
86
static inline void extend(pa_tagstruct*t, size_t l) {
88
pa_assert(t->dynamic);
90
if (t->length+l <= t->allocated)
93
t->data = pa_xrealloc(t->data, t->allocated = t->length+l+100);
96
static void write_u8(pa_tagstruct *t, uint8_t u) {
98
t->data[t->length++] = u;
101
static int read_u8(pa_tagstruct *t, uint8_t *u) {
102
if (t->rindex + 1 > t->length)
105
*u = t->data[t->rindex++];
109
static void write_u32(pa_tagstruct *t, uint32_t u) {
112
memcpy(t->data + t->length, &u, 4);
116
static int read_u32(pa_tagstruct *t, uint32_t *u) {
117
if (t->rindex + 4 > t->length)
120
memcpy(u, t->data + t->rindex, 4);
127
static void write_u64(pa_tagstruct *t, uint64_t u) {
128
write_u32(t, u >> 32);
132
static int read_u64(pa_tagstruct *t, uint64_t *u) {
135
if (read_u32(t, &tmp) < 0)
138
*u = ((uint64_t) tmp) << 32;
140
if (read_u32(t, &tmp) < 0)
147
static int read_s64(pa_tagstruct *t, int64_t *u) {
150
if (read_u32(t, &tmp) < 0)
153
*u = (int64_t) (((uint64_t) tmp) << 32);
155
if (read_u32(t, &tmp) < 0)
162
static void write_arbitrary(pa_tagstruct *t, const void *p, size_t len) {
166
memcpy(t->data + t->length, p, len);
171
static int read_arbitrary(pa_tagstruct *t, const void **p, size_t length) {
172
if (t->rindex + length > t->length)
175
*p = t->data + t->rindex;
180
void pa_tagstruct_puts(pa_tagstruct*t, const char *s) {
185
write_u8(t, PA_TAG_STRING);
187
write_arbitrary(t, s, l);
189
write_u8(t, PA_TAG_STRING_NULL);
192
void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i) {
195
write_u8(t, PA_TAG_U32);
199
void pa_tagstruct_putu8(pa_tagstruct*t, uint8_t c) {
202
write_u8(t, PA_TAG_U8);
206
void pa_tagstruct_put_sample_spec(pa_tagstruct *t, const pa_sample_spec *ss) {
210
write_u8(t, PA_TAG_SAMPLE_SPEC);
211
write_u8(t, ss->format);
212
write_u8(t, ss->channels);
213
write_u32(t, ss->rate);
216
void pa_tagstruct_put_arbitrary(pa_tagstruct *t, const void *p, size_t length) {
220
write_u8(t, PA_TAG_ARBITRARY);
221
write_u32(t, length);
222
write_arbitrary(t, p, length);
225
void pa_tagstruct_put_boolean(pa_tagstruct*t, bool b) {
228
write_u8(t, b ? PA_TAG_BOOLEAN_TRUE : PA_TAG_BOOLEAN_FALSE);
231
void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv) {
234
write_u8(t, PA_TAG_TIMEVAL);
235
write_u32(t, tv->tv_sec);
236
write_u32(t, tv->tv_usec);
239
void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u) {
242
write_u8(t, PA_TAG_USEC);
246
void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t u) {
249
write_u8(t, PA_TAG_U64);
253
void pa_tagstruct_puts64(pa_tagstruct*t, int64_t u) {
256
write_u8(t, PA_TAG_S64);
260
void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map) {
266
write_u8(t, PA_TAG_CHANNEL_MAP);
267
write_u8(t, map->channels);
269
for (i = 0; i < map->channels; i ++)
270
write_u8(t, map->map[i]);
273
void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) {
279
write_u8(t, PA_TAG_CVOLUME);
280
write_u8(t, cvolume->channels);
282
for (i = 0; i < cvolume->channels; i ++)
283
write_u32(t, cvolume->values[i]);
286
void pa_tagstruct_put_volume(pa_tagstruct *t, pa_volume_t vol) {
289
write_u8(t, PA_TAG_VOLUME);
293
void pa_tagstruct_put_proplist(pa_tagstruct *t, pa_proplist *p) {
298
write_u8(t, PA_TAG_PROPLIST);
305
if (!(k = pa_proplist_iterate(p, &state)))
308
pa_tagstruct_puts(t, k);
309
pa_assert_se(pa_proplist_get(p, k, &d, &l) >= 0);
310
pa_tagstruct_putu32(t, (uint32_t) l);
311
pa_tagstruct_put_arbitrary(t, d, l);
314
pa_tagstruct_puts(t, NULL);
317
void pa_tagstruct_put_format_info(pa_tagstruct *t, pa_format_info *f) {
321
write_u8(t, PA_TAG_FORMAT_INFO);
322
pa_tagstruct_putu8(t, (uint8_t) f->encoding);
323
pa_tagstruct_put_proplist(t, f->plist);
326
static int read_tag(pa_tagstruct *t, uint8_t type) {
327
if (t->rindex + 1 > t->length)
330
if (t->data[t->rindex] != type)
338
int pa_tagstruct_gets(pa_tagstruct*t, const char **s) {
346
if (t->rindex+1 > t->length)
349
if (t->data[t->rindex] == PA_TAG_STRING_NULL) {
355
if (read_tag(t, PA_TAG_STRING) < 0)
358
if (t->rindex + 1 > t->length)
362
for (n = 0, c = (char*) (t->data + t->rindex); t->rindex + n < t->length; n++, c++)
371
*s = (char*) (t->data + t->rindex);
377
int pa_tagstruct_getu32(pa_tagstruct*t, uint32_t *i) {
381
if (read_tag(t, PA_TAG_U32) < 0)
384
return read_u32(t, i);
387
int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c) {
391
if (read_tag(t, PA_TAG_U8) < 0)
394
return read_u8(t, c);
397
int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss) {
403
if (read_tag(t, PA_TAG_SAMPLE_SPEC) < 0)
406
if (read_u8(t, &tmp) < 0)
411
if (read_u8(t, &ss->channels) < 0)
414
return read_u32(t, &ss->rate);
417
int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length) {
423
if (read_tag(t, PA_TAG_ARBITRARY) < 0)
426
if (read_u32(t, &len) < 0 || len != length)
429
return read_arbitrary(t, p, length);
432
int pa_tagstruct_eof(pa_tagstruct*t) {
435
return t->rindex >= t->length;
438
const uint8_t* pa_tagstruct_data(pa_tagstruct*t, size_t *l) {
440
pa_assert(t->dynamic);
447
int pa_tagstruct_get_boolean(pa_tagstruct*t, bool *b) {
451
if (t->rindex+1 > t->length)
454
if (t->data[t->rindex] == PA_TAG_BOOLEAN_TRUE)
456
else if (t->data[t->rindex] == PA_TAG_BOOLEAN_FALSE)
465
int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv) {
471
if (read_tag(t, PA_TAG_TIMEVAL) < 0)
474
if (read_u32(t, &tmp) < 0)
479
if (read_u32(t, &tmp) < 0)
487
int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u) {
491
if (read_tag(t, PA_TAG_USEC) < 0)
494
return read_u64(t, u);
497
int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *u) {
501
if (read_tag(t, PA_TAG_U64) < 0)
504
return read_u64(t, u);
507
int pa_tagstruct_gets64(pa_tagstruct*t, int64_t *u) {
511
if (read_tag(t, PA_TAG_S64) < 0)
514
return read_s64(t, u);
517
int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) {
523
if (read_tag(t, PA_TAG_CHANNEL_MAP) < 0)
526
if (read_u8(t, &map->channels) < 0 || map->channels > PA_CHANNELS_MAX)
529
for (i = 0; i < map->channels; i ++) {
532
if (read_u8(t, &tmp) < 0)
541
int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) {
547
if (read_tag(t, PA_TAG_CVOLUME) < 0)
550
if (read_u8(t, &cvolume->channels) < 0 || cvolume->channels > PA_CHANNELS_MAX)
553
for (i = 0; i < cvolume->channels; i ++) {
554
if (read_u32(t, &cvolume->values[i]) < 0)
561
int pa_tagstruct_get_volume(pa_tagstruct*t, pa_volume_t *vol) {
565
if (read_tag(t, PA_TAG_VOLUME) < 0)
568
return read_u32(t, vol);
571
int pa_tagstruct_get_proplist(pa_tagstruct *t, pa_proplist *p) {
574
if (read_tag(t, PA_TAG_PROPLIST) < 0)
582
if (pa_tagstruct_gets(t, &k) < 0)
588
if (!pa_proplist_key_valid(k))
591
if (pa_tagstruct_getu32(t, &length) < 0)
594
if (length > MAX_TAG_SIZE)
597
if (pa_tagstruct_get_arbitrary(t, &d, length) < 0)
601
pa_assert_se(pa_proplist_set(p, k, d, length) >= 0);
607
int pa_tagstruct_get_format_info(pa_tagstruct *t, pa_format_info *f) {
613
if (read_tag(t, PA_TAG_FORMAT_INFO) < 0)
616
if (pa_tagstruct_getu8(t, &encoding) < 0)
619
f->encoding = encoding;
621
return pa_tagstruct_get_proplist(t, f->plist);
624
void pa_tagstruct_put(pa_tagstruct *t, ...) {
631
int tag = va_arg(va, int);
633
if (tag == PA_TAG_INVALID)
638
case PA_TAG_STRING_NULL:
639
pa_tagstruct_puts(t, va_arg(va, char*));
643
pa_tagstruct_putu32(t, va_arg(va, uint32_t));
647
pa_tagstruct_putu8(t, (uint8_t) va_arg(va, int));
651
pa_tagstruct_putu64(t, va_arg(va, uint64_t));
654
case PA_TAG_SAMPLE_SPEC:
655
pa_tagstruct_put_sample_spec(t, va_arg(va, pa_sample_spec*));
658
case PA_TAG_ARBITRARY: {
659
void *p = va_arg(va, void*);
660
size_t size = va_arg(va, size_t);
661
pa_tagstruct_put_arbitrary(t, p, size);
665
case PA_TAG_BOOLEAN_TRUE:
666
case PA_TAG_BOOLEAN_FALSE:
667
pa_tagstruct_put_boolean(t, va_arg(va, int));
671
pa_tagstruct_put_timeval(t, va_arg(va, struct timeval*));
675
pa_tagstruct_put_usec(t, va_arg(va, pa_usec_t));
678
case PA_TAG_CHANNEL_MAP:
679
pa_tagstruct_put_channel_map(t, va_arg(va, pa_channel_map *));
683
pa_tagstruct_put_cvolume(t, va_arg(va, pa_cvolume *));
687
pa_tagstruct_put_volume(t, va_arg(va, pa_volume_t));
690
case PA_TAG_PROPLIST:
691
pa_tagstruct_put_proplist(t, va_arg(va, pa_proplist *));
695
pa_assert_not_reached();
702
int pa_tagstruct_get(pa_tagstruct *t, ...) {
710
int tag = va_arg(va, int);
712
if (tag == PA_TAG_INVALID)
717
case PA_TAG_STRING_NULL:
718
ret = pa_tagstruct_gets(t, va_arg(va, const char**));
722
ret = pa_tagstruct_getu32(t, va_arg(va, uint32_t*));
726
ret = pa_tagstruct_getu8(t, va_arg(va, uint8_t*));
730
ret = pa_tagstruct_getu64(t, va_arg(va, uint64_t*));
733
case PA_TAG_SAMPLE_SPEC:
734
ret = pa_tagstruct_get_sample_spec(t, va_arg(va, pa_sample_spec*));
737
case PA_TAG_ARBITRARY: {
738
const void **p = va_arg(va, const void**);
739
size_t size = va_arg(va, size_t);
740
ret = pa_tagstruct_get_arbitrary(t, p, size);
744
case PA_TAG_BOOLEAN_TRUE:
745
case PA_TAG_BOOLEAN_FALSE:
746
ret = pa_tagstruct_get_boolean(t, va_arg(va, bool*));
750
ret = pa_tagstruct_get_timeval(t, va_arg(va, struct timeval*));
754
ret = pa_tagstruct_get_usec(t, va_arg(va, pa_usec_t*));
757
case PA_TAG_CHANNEL_MAP:
758
ret = pa_tagstruct_get_channel_map(t, va_arg(va, pa_channel_map *));
762
ret = pa_tagstruct_get_cvolume(t, va_arg(va, pa_cvolume *));
766
ret = pa_tagstruct_get_volume(t, va_arg(va, pa_volume_t *));
769
case PA_TAG_PROPLIST:
770
ret = pa_tagstruct_get_proplist(t, va_arg(va, pa_proplist *));
774
pa_assert_not_reached();