dev = s->context->conf->default_source;
}
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_puts(t, s->name);
- pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_put_channel_map(t, &s->channel_map);
- pa_tagstruct_putu32(t, PA_INVALID_INDEX);
- pa_tagstruct_puts(t, dev);
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- pa_tagstruct_put_boolean(t, !!(flags & PA_STREAM_START_CORKED));
+ pa_tagstruct_put(t,
+ PA_TAG_U32, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM,
+ PA_TAG_U32, tag = s->context->ctag++,
+ PA_TAG_STRING, s->name,
+ PA_TAG_SAMPLE_SPEC, &s->sample_spec,
+ PA_TAG_CHANNEL_MAP, &s->channel_map,
+ PA_TAG_U32, PA_INVALID_INDEX,
+ PA_TAG_STRING, dev,
+ PA_TAG_U32, s->buffer_attr.maxlength,
+ PA_TAG_BOOLEAN, !!(flags & PA_STREAM_START_CORKED),
+ PA_TAG_INVALID);
+
if (s->direction == PA_STREAM_PLAYBACK) {
pa_cvolume cv;
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
+ pa_tagstruct_put(t,
+ PA_TAG_U32, s->buffer_attr.tlength,
+ PA_TAG_U32, s->buffer_attr.prebuf,
+ PA_TAG_U32, s->buffer_attr.minreq,
+ PA_TAG_INVALID);
if (!volume) {
pa_cvolume_reset(&cv, s->sample_spec.channels);
assert(c && t && c->protocol && c->protocol->core);
- if (pa_tagstruct_gets(t, &name) < 0 || !name ||
- pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
- pa_tagstruct_get_channel_map(t, &map) < 0 ||
- pa_tagstruct_getu32(t, &sink_index) < 0 ||
- pa_tagstruct_gets(t, &sink_name) < 0 ||
- pa_tagstruct_getu32(t, &maxlength) < 0 ||
- pa_tagstruct_get_boolean(t, &corked) < 0 ||
- pa_tagstruct_getu32(t, &tlength) < 0 ||
- pa_tagstruct_getu32(t, &prebuf) < 0 ||
- pa_tagstruct_getu32(t, &minreq) < 0 ||
- pa_tagstruct_get_cvolume(t, &volume) < 0 ||
- !pa_tagstruct_eof(t)) {
+ if (pa_tagstruct_get(
+ t,
+ PA_TAG_STRING, &name,
+ PA_TAG_SAMPLE_SPEC, &ss,
+ PA_TAG_CHANNEL_MAP, &map,
+ PA_TAG_U32, &sink_index,
+ PA_TAG_STRING, &sink_name,
+ PA_TAG_U32, &maxlength,
+ PA_TAG_BOOLEAN, &corked,
+ PA_TAG_U32, &tlength,
+ PA_TAG_U32, &prebuf,
+ PA_TAG_U32, &minreq,
+ PA_TAG_CVOLUME, &volume,
+ PA_TAG_INVALID) < 0 ||
+ !pa_tagstruct_eof(t) ||
+ !name) {
protocol_error(c);
return;
}
static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) {
assert(t && sink);
- pa_tagstruct_putu32(t, sink->index);
- pa_tagstruct_puts(t, sink->name);
- pa_tagstruct_puts(t, sink->description);
- pa_tagstruct_put_sample_spec(t, &sink->sample_spec);
- pa_tagstruct_put_channel_map(t, &sink->channel_map);
- pa_tagstruct_putu32(t, sink->owner ? sink->owner->index : (uint32_t) -1);
- pa_tagstruct_put_cvolume(t, pa_sink_get_volume(sink, PA_MIXER_HARDWARE));
- pa_tagstruct_putu32(t, sink->monitor_source->index);
- pa_tagstruct_puts(t, sink->monitor_source->name);
- pa_tagstruct_put_usec(t, pa_sink_get_latency(sink));
- pa_tagstruct_puts(t, sink->driver);
+ pa_tagstruct_put(
+ t,
+ PA_TAG_U32, sink->index,
+ PA_TAG_STRING, sink->name,
+ PA_TAG_STRING, sink->description,
+ PA_TAG_SAMPLE_SPEC, &sink->sample_spec,
+ PA_TAG_CHANNEL_MAP, &sink->channel_map,
+ PA_TAG_U32, sink->owner ? sink->owner->index : PA_INVALID_INDEX,
+ PA_TAG_CVOLUME, pa_sink_get_volume(sink, PA_MIXER_HARDWARE),
+ PA_TAG_U32, sink->monitor_source->index,
+ PA_TAG_STRING, sink->monitor_source->name,
+ PA_TAG_USEC, pa_sink_get_latency(sink),
+ PA_TAG_STRING, sink->driver,
+ PA_TAG_INVALID);
}
static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) {
#include <unistd.h>
#include <sys/time.h>
#include <assert.h>
+#include <stdarg.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#include "tagstruct.h"
#include "xmalloc.h"
-enum tags {
- TAG_STRING = 't',
- TAG_NULL_STRING = 'N',
- TAG_U32 = 'L',
- TAG_S32 = 'l',
- TAG_U16 = 'S',
- TAG_S16 = 's',
- TAG_U8 = 'B',
- TAG_S8 = 'b',
- TAG_U64 = 'R',
- TAG_S64 = 'r',
- TAG_SAMPLE_SPEC = 'a',
- TAG_ARBITRARY = 'x',
- TAG_BOOLEAN_TRUE = '1',
- TAG_BOOLEAN_FALSE = '0',
- TAG_TIMEVAL = 'T',
- TAG_USEC = 'U' /* 64bit unsigned */,
- TAG_CHANNEL_MAP = 'm',
- TAG_CVOLUME = 'v'
-};
struct pa_tagstruct {
uint8_t *data;
t->data = pa_xrealloc(t->data, t->allocated = t->length+l+100);
}
+
void pa_tagstruct_puts(pa_tagstruct*t, const char *s) {
size_t l;
assert(t);
if (s) {
l = strlen(s)+2;
extend(t, l);
- t->data[t->length] = TAG_STRING;
+ t->data[t->length] = PA_TAG_STRING;
strcpy((char*) (t->data+t->length+1), s);
t->length += l;
} else {
extend(t, 1);
- t->data[t->length] = TAG_NULL_STRING;
+ t->data[t->length] = PA_TAG_STRING_NULL;
t->length += 1;
}
}
void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i) {
assert(t);
extend(t, 5);
- t->data[t->length] = TAG_U32;
+ t->data[t->length] = PA_TAG_U32;
i = htonl(i);
memcpy(t->data+t->length+1, &i, 4);
t->length += 5;
void pa_tagstruct_putu8(pa_tagstruct*t, uint8_t c) {
assert(t);
extend(t, 2);
- t->data[t->length] = TAG_U8;
+ t->data[t->length] = PA_TAG_U8;
*(t->data+t->length+1) = c;
t->length += 2;
}
uint32_t rate;
assert(t && ss);
extend(t, 7);
- t->data[t->length] = TAG_SAMPLE_SPEC;
+ t->data[t->length] = PA_TAG_SAMPLE_SPEC;
t->data[t->length+1] = (uint8_t) ss->format;
t->data[t->length+2] = ss->channels;
rate = htonl(ss->rate);
assert(t && p);
extend(t, 5+length);
- t->data[t->length] = TAG_ARBITRARY;
+ t->data[t->length] = PA_TAG_ARBITRARY;
tmp = htonl(length);
memcpy(t->data+t->length+1, &tmp, 4);
if (length)
void pa_tagstruct_put_boolean(pa_tagstruct*t, int b) {
assert(t);
extend(t, 1);
- t->data[t->length] = b ? TAG_BOOLEAN_TRUE : TAG_BOOLEAN_FALSE;
+ t->data[t->length] = b ? PA_TAG_BOOLEAN_TRUE : PA_TAG_BOOLEAN_FALSE;
t->length += 1;
}
uint32_t tmp;
assert(t);
extend(t, 9);
- t->data[t->length] = TAG_TIMEVAL;
+ t->data[t->length] = PA_TAG_TIMEVAL;
tmp = htonl(tv->tv_sec);
memcpy(t->data+t->length+1, &tmp, 4);
tmp = htonl(tv->tv_usec);
uint32_t tmp;
assert(t);
extend(t, 9);
- t->data[t->length] = TAG_USEC;
+ t->data[t->length] = PA_TAG_USEC;
tmp = htonl((uint32_t) (u >> 32));
memcpy(t->data+t->length+1, &tmp, 4);
tmp = htonl((uint32_t) u);
uint32_t tmp;
assert(t);
extend(t, 9);
- t->data[t->length] = TAG_U64;
+ t->data[t->length] = PA_TAG_U64;
tmp = htonl((uint32_t) (u >> 32));
memcpy(t->data+t->length+1, &tmp, 4);
tmp = htonl((uint32_t) u);
assert(t);
extend(t, 2 + map->channels);
- t->data[t->length++] = TAG_CHANNEL_MAP;
+ t->data[t->length++] = PA_TAG_CHANNEL_MAP;
t->data[t->length++] = map->channels;
for (i = 0; i < map->channels; i ++)
assert(t);
extend(t, 2 + cvolume->channels * sizeof(pa_volume_t));
- t->data[t->length++] = TAG_CVOLUME;
+ t->data[t->length++] = PA_TAG_CVOLUME;
t->data[t->length++] = cvolume->channels;
for (i = 0; i < cvolume->channels; i ++) {
if (t->rindex+1 > t->length)
return -1;
- if (t->data[t->rindex] == TAG_NULL_STRING) {
+ if (t->data[t->rindex] == PA_TAG_STRING_NULL) {
t->rindex++;
*s = NULL;
return 0;
if (t->rindex+2 > t->length)
return -1;
- if (t->data[t->rindex] != TAG_STRING)
+ if (t->data[t->rindex] != PA_TAG_STRING)
return -1;
error = 1;
if (t->rindex+5 > t->length)
return -1;
- if (t->data[t->rindex] != TAG_U32)
+ if (t->data[t->rindex] != PA_TAG_U32)
return -1;
memcpy(i, t->data+t->rindex+1, 4);
if (t->rindex+2 > t->length)
return -1;
- if (t->data[t->rindex] != TAG_U8)
+ if (t->data[t->rindex] != PA_TAG_U8)
return -1;
*c = t->data[t->rindex+1];
if (t->rindex+7 > t->length)
return -1;
- if (t->data[t->rindex] != TAG_SAMPLE_SPEC)
+ if (t->data[t->rindex] != PA_TAG_SAMPLE_SPEC)
return -1;
ss->format = t->data[t->rindex+1];
if (t->rindex+5+length > t->length)
return -1;
- if (t->data[t->rindex] != TAG_ARBITRARY)
+ if (t->data[t->rindex] != PA_TAG_ARBITRARY)
return -1;
memcpy(&len, t->data+t->rindex+1, 4);
if (t->rindex+1 > t->length)
return -1;
- if (t->data[t->rindex] == TAG_BOOLEAN_TRUE)
+ if (t->data[t->rindex] == PA_TAG_BOOLEAN_TRUE)
*b = 1;
- else if (t->data[t->rindex] == TAG_BOOLEAN_FALSE)
+ else if (t->data[t->rindex] == PA_TAG_BOOLEAN_FALSE)
*b = 0;
else
return -1;
if (t->rindex+9 > t->length)
return -1;
- if (t->data[t->rindex] != TAG_TIMEVAL)
+ if (t->data[t->rindex] != PA_TAG_TIMEVAL)
return -1;
memcpy(&tv->tv_sec, t->data+t->rindex+1, 4);
if (t->rindex+9 > t->length)
return -1;
- if (t->data[t->rindex] != TAG_USEC)
+ if (t->data[t->rindex] != PA_TAG_USEC)
return -1;
memcpy(&tmp, t->data+t->rindex+1, 4);
if (t->rindex+9 > t->length)
return -1;
- if (t->data[t->rindex] != TAG_U64)
+ if (t->data[t->rindex] != PA_TAG_U64)
return -1;
memcpy(&tmp, t->data+t->rindex+1, 4);
if (t->rindex+2 > t->length)
return -1;
- if (t->data[t->rindex] != TAG_CHANNEL_MAP)
+ if (t->data[t->rindex] != PA_TAG_CHANNEL_MAP)
return -1;
if ((map->channels = t->data[t->rindex+1]) > PA_CHANNELS_MAX)
if (t->rindex+2 > t->length)
return -1;
- if (t->data[t->rindex] != TAG_CVOLUME)
+ if (t->data[t->rindex] != PA_TAG_CVOLUME)
return -1;
if ((cvolume->channels = t->data[t->rindex+1]) > PA_CHANNELS_MAX)
t->rindex += 2 + cvolume->channels * sizeof(pa_volume_t);
return 0;
}
+
+void pa_tagstruct_put(pa_tagstruct *t, ...) {
+ va_list va;
+ assert(t);
+
+ va_start(va, t);
+
+ for (;;) {
+ int tag = va_arg(va, int);
+
+ if (tag == PA_TAG_INVALID)
+ break;
+
+ switch (tag) {
+ case PA_TAG_STRING:
+ case PA_TAG_STRING_NULL:
+ pa_tagstruct_puts(t, va_arg(va, char*));
+ break;
+
+ case PA_TAG_U32:
+ pa_tagstruct_putu32(t, va_arg(va, uint32_t));
+ break;
+
+ case PA_TAG_U8:
+ pa_tagstruct_putu8(t, (uint8_t) va_arg(va, int));
+ break;
+
+ case PA_TAG_U64:
+ pa_tagstruct_putu64(t, va_arg(va, uint64_t));
+ break;
+
+ case PA_TAG_SAMPLE_SPEC:
+ pa_tagstruct_put_sample_spec(t, va_arg(va, pa_sample_spec*));
+ break;
+
+ case PA_TAG_ARBITRARY: {
+ void *p = va_arg(va, void*);
+ size_t size = va_arg(va, size_t);
+ pa_tagstruct_put_arbitrary(t, p, size);
+ break;
+ }
+
+ case PA_TAG_BOOLEAN_TRUE:
+ case PA_TAG_BOOLEAN_FALSE:
+ pa_tagstruct_put_boolean(t, va_arg(va, int));
+ break;
+
+ case PA_TAG_TIMEVAL:
+ pa_tagstruct_put_timeval(t, va_arg(va, struct timeval*));
+ break;
+
+ case PA_TAG_USEC:
+ pa_tagstruct_put_usec(t, va_arg(va, pa_usec_t));
+ break;
+
+ case PA_TAG_CHANNEL_MAP:
+ pa_tagstruct_put_channel_map(t, va_arg(va, pa_channel_map *));
+ break;
+
+ case PA_TAG_CVOLUME:
+ pa_tagstruct_put_cvolume(t, va_arg(va, pa_cvolume *));
+ break;
+
+ default:
+ abort();
+ }
+ }
+
+ va_end(va);
+}
+
+int pa_tagstruct_get(pa_tagstruct *t, ...) {
+ va_list va;
+ int ret = 0;
+
+ assert(t);
+
+ va_start(va, t);
+ while (ret == 0) {
+ int tag = va_arg(va, int);
+
+ if (tag == PA_TAG_INVALID)
+ break;
+
+ switch (tag) {
+ case PA_TAG_STRING:
+ case PA_TAG_STRING_NULL:
+ ret = pa_tagstruct_gets(t, va_arg(va, const char**));
+ break;
+
+ case PA_TAG_U32:
+ ret = pa_tagstruct_getu32(t, va_arg(va, uint32_t*));
+ break;
+
+ case PA_TAG_U8:
+ ret = pa_tagstruct_getu8(t, va_arg(va, uint8_t*));
+ break;
+
+ case PA_TAG_U64:
+ ret = pa_tagstruct_getu64(t, va_arg(va, uint64_t*));
+ break;
+
+ case PA_TAG_SAMPLE_SPEC:
+ ret = pa_tagstruct_get_sample_spec(t, va_arg(va, pa_sample_spec*));
+ break;
+
+ case PA_TAG_ARBITRARY: {
+ const void **p = va_arg(va, const void**);
+ size_t size = va_arg(va, size_t);
+ ret = pa_tagstruct_get_arbitrary(t, p, size);
+ break;
+ }
+
+ case PA_TAG_BOOLEAN_TRUE:
+ case PA_TAG_BOOLEAN_FALSE:
+ ret = pa_tagstruct_get_boolean(t, va_arg(va, int*));
+ break;
+
+ case PA_TAG_TIMEVAL:
+ ret = pa_tagstruct_get_timeval(t, va_arg(va, struct timeval*));
+ break;
+
+ case PA_TAG_USEC:
+ ret = pa_tagstruct_get_usec(t, va_arg(va, pa_usec_t*));
+ break;
+
+ case PA_TAG_CHANNEL_MAP:
+ ret = pa_tagstruct_get_channel_map(t, va_arg(va, pa_channel_map *));
+ break;
+
+ case PA_TAG_CVOLUME:
+ ret = pa_tagstruct_get_cvolume(t, va_arg(va, pa_cvolume *));
+ break;
+
+
+ default:
+ abort();
+ }
+
+ }
+
+ va_end(va);
+ return ret;
+}
typedef struct pa_tagstruct pa_tagstruct;
+enum {
+ PA_TAG_INVALID = 0,
+ PA_TAG_STRING = 't',
+ PA_TAG_STRING_NULL = 'N',
+ PA_TAG_U32 = 'L',
+ PA_TAG_U8 = 'B',
+ PA_TAG_U64 = 'R',
+ PA_TAG_SAMPLE_SPEC = 'a',
+ PA_TAG_ARBITRARY = 'x',
+ PA_TAG_BOOLEAN_TRUE = '1',
+ PA_TAG_BOOLEAN_FALSE = '0',
+ PA_TAG_BOOLEAN = PA_TAG_BOOLEAN_TRUE,
+ PA_TAG_TIMEVAL = 'T',
+ PA_TAG_USEC = 'U' /* 64bit unsigned */,
+ PA_TAG_CHANNEL_MAP = 'm',
+ PA_TAG_CVOLUME = 'v'
+};
+
+
+
pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length);
void pa_tagstruct_free(pa_tagstruct*t);
uint8_t* pa_tagstruct_free_data(pa_tagstruct*t, size_t *l);
+int pa_tagstruct_eof(pa_tagstruct*t);
+const uint8_t* pa_tagstruct_data(pa_tagstruct*t, size_t *l);
+
+void pa_tagstruct_put(pa_tagstruct *t, ...);
+
void pa_tagstruct_puts(pa_tagstruct*t, const char *s);
void pa_tagstruct_putu8(pa_tagstruct*t, uint8_t c);
void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i);
void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map);
void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume);
+int pa_tagstruct_get(pa_tagstruct *t, ...);
+
int pa_tagstruct_gets(pa_tagstruct*t, const char **s);
int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c);
int pa_tagstruct_getu32(pa_tagstruct*t, uint32_t *i);
int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map);
int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *v);
-int pa_tagstruct_eof(pa_tagstruct*t);
-const uint8_t* pa_tagstruct_data(pa_tagstruct*t, size_t *l);
#endif