* add variadic function pa_tagstruct_get() and pa_tagstruct_put() for parsing/constru...
authorLennart Poettering <lennart@poettering.net>
Sat, 28 Jan 2006 01:07:09 +0000 (01:07 +0000)
committerLennart Poettering <lennart@poettering.net>
Sat, 28 Jan 2006 01:07:09 +0000 (01:07 +0000)
* convert some of the tagstruct uses to this new API

git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@466 fefdeb5f-60dc-0310-8127-8f9354f1896f

polyp/Makefile.am
polyp/polyplib-stream.c
polyp/protocol-native.c
polyp/tagstruct.c
polyp/tagstruct.h

index ad9952a..b24d548 100644 (file)
@@ -46,8 +46,8 @@ AM_CFLAGS = -I$(top_srcdir)
 AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS
 AM_CFLAGS += $(LTDLINCL)
 AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS)
-AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\"
-#AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\"
+#AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\"
+AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\"
 AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\"
 AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(POLYPAUDIO_BINARY)\"
 
index 51ee6a2..7b9d686 100644 (file)
@@ -317,20 +317,25 @@ static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *a
             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);
index 0491dc4..b94903d 100644 (file)
@@ -588,18 +588,22 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
     
     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;
     }
@@ -1138,17 +1142,20 @@ static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED
 
 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) {
index d498041..64f00e4 100644 (file)
@@ -28,6 +28,7 @@
 #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;
@@ -105,18 +86,19 @@ static void extend(pa_tagstruct*t, size_t l) {
     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;
     }
 }
@@ -124,7 +106,7 @@ void pa_tagstruct_puts(pa_tagstruct*t, const char *s) {
 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;
@@ -133,7 +115,7 @@ void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i) {
 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;
 }
@@ -142,7 +124,7 @@ void pa_tagstruct_put_sample_spec(pa_tagstruct *t, const pa_sample_spec *ss) {
     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);
@@ -155,7 +137,7 @@ void pa_tagstruct_put_arbitrary(pa_tagstruct *t, const void *p, size_t length) {
     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)
@@ -166,7 +148,7 @@ void pa_tagstruct_put_arbitrary(pa_tagstruct *t, const void *p, size_t 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;
 }
 
@@ -174,7 +156,7 @@ void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv) {
     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);
@@ -186,7 +168,7 @@ void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u) {
     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);
@@ -198,7 +180,7 @@ void pa_tagstruct_putu64(pa_tagstruct*t, uint64_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);
@@ -212,7 +194,7 @@ void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map) {
     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 ++)
@@ -225,7 +207,7 @@ void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) {
     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 ++) {
@@ -243,7 +225,7 @@ int pa_tagstruct_gets(pa_tagstruct*t, const char **s) {
     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;
@@ -252,7 +234,7 @@ int pa_tagstruct_gets(pa_tagstruct*t, const char **s) {
     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;
@@ -277,7 +259,7 @@ int pa_tagstruct_getu32(pa_tagstruct*t, uint32_t *i) {
     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);
@@ -292,7 +274,7 @@ int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c) {
     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];
@@ -306,7 +288,7 @@ int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss) {
     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];
@@ -328,7 +310,7 @@ int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length) {
     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);
@@ -357,9 +339,9 @@ int pa_tagstruct_get_boolean(pa_tagstruct*t, int *b) {
     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;
@@ -373,7 +355,7 @@ int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv) {
     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);
@@ -392,7 +374,7 @@ int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u) {
     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);
@@ -410,7 +392,7 @@ int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *u) {
     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);
@@ -430,7 +412,7 @@ int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) {
     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)
@@ -458,7 +440,7 @@ int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) {
     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)
@@ -476,3 +458,147 @@ int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) {
     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;
+}
index cd6a8f9..b41936f 100644 (file)
 
 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);
@@ -49,6 +74,8 @@ void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u);
 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);
@@ -61,7 +88,5 @@ int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u);
 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