summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/todo6
-rw-r--r--polyp/client.c6
-rw-r--r--polyp/cmdline.c7
-rw-r--r--polyp/cmdline.h2
-rw-r--r--polyp/core.c28
-rw-r--r--polyp/core.h6
-rw-r--r--polyp/main.c1
-rw-r--r--polyp/modargs.c40
-rw-r--r--polyp/modargs.h2
-rw-r--r--polyp/module-native-protocol-fd.c2
-rw-r--r--polyp/module-oss-mmap.c9
-rw-r--r--polyp/module-oss.c11
-rw-r--r--polyp/module-protocol-stub.c9
-rw-r--r--polyp/module.c5
-rw-r--r--polyp/polyplib-def.h2
-rw-r--r--polyp/polyplib-introspect.c2
-rw-r--r--polyp/polyplib-introspect.h4
-rw-r--r--polyp/polyplib-stream.c2
-rw-r--r--polyp/protocol-native.c8
-rw-r--r--polyp/protocol-simple.c6
-rw-r--r--polyp/scache.c2
-rw-r--r--polyp/tagstruct.c30
-rw-r--r--polyp/tagstruct.h2
23 files changed, 155 insertions, 37 deletions
diff --git a/doc/todo b/doc/todo
index bfc29fab..5a1a247c 100644
--- a/doc/todo
+++ b/doc/todo
@@ -9,17 +9,13 @@
kill client/...
autoload management
- more complete pactl
-- cleanup tagstruct and modargs (add s32, pa_volume_t, pa_usec_t)
-- remove all gcc warnings
-- make fragments settings runtime configurable
- logging
-- automatic termination of daemon if unused
- add sample directory
-- paman: show scache and sample size
- add timing parameter to write callback of stream in client API
** later ***
- xmlrpc/http
+- dbus
- slp/rendezvous
- modinfo
- make alsa modules use mmap
diff --git a/polyp/client.c b/polyp/client.c
index 0cb42466..c7fb1e07 100644
--- a/polyp/client.c
+++ b/polyp/client.c
@@ -51,6 +51,8 @@ struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name,
fprintf(stderr, "client: created %u \"%s\"\n", c->index, c->name);
pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index);
+
+ pa_core_check_quit(core);
return c;
}
@@ -59,10 +61,14 @@ void pa_client_free(struct pa_client *c) {
assert(c && c->core);
pa_idxset_remove_by_data(c->core->clients, c, NULL);
+
+ pa_core_check_quit(c->core);
+
fprintf(stderr, "client: freed %u \"%s\"\n", c->index, c->name);
pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index);
pa_xfree(c->name);
pa_xfree(c);
+
}
void pa_client_kill(struct pa_client *c) {
diff --git a/polyp/cmdline.c b/polyp/cmdline.c
index 265e0ec8..aba20af1 100644
--- a/polyp/cmdline.c
+++ b/polyp/cmdline.c
@@ -75,6 +75,7 @@ void pa_cmdline_help(const char *argv0) {
" -d Disallow module loading after startup\n"
" -f Dont quit when the startup fails\n"
" -v Verbose startup\n"
+ " -X SECS Terminate the daemon after the last client quit and this time passed\n"
" -h Show this help\n"
" -V Show version\n", e, cfg);
@@ -97,11 +98,12 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) {
cmdline->version =
cmdline->disallow_module_loading = 0;
cmdline->fail = 1;
+ cmdline->quit_after_last_client_time = -1;
buf = pa_strbuf_new();
assert(buf);
- while ((c = getopt(argc, argv, "L:F:CDhfvrRVnd")) != -1) {
+ while ((c = getopt(argc, argv, "L:F:CDhfvrRVndX:")) != -1) {
switch (c) {
case 'L':
pa_strbuf_printf(buf, "load %s\n", optarg);
@@ -139,6 +141,9 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) {
case 'd':
cmdline->disallow_module_loading = 1;
break;
+ case 'X':
+ cmdline->quit_after_last_client_time = atoi(optarg);
+ break;
default:
goto fail;
}
diff --git a/polyp/cmdline.h b/polyp/cmdline.h
index 7330a716..d1c438d1 100644
--- a/polyp/cmdline.h
+++ b/polyp/cmdline.h
@@ -24,7 +24,7 @@
struct pa_cmdline {
- int daemonize, help, fail, verbose, high_priority, stay_root, version, disallow_module_loading;
+ int daemonize, help, fail, verbose, high_priority, stay_root, version, disallow_module_loading, quit_after_last_client_time;
char *cli_commands;
};
diff --git a/polyp/core.c b/polyp/core.c
index da6ace6a..4362f0cb 100644
--- a/polyp/core.c
+++ b/polyp/core.c
@@ -71,6 +71,9 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) {
c->memblock_stat = pa_memblock_stat_new();
c->disallow_module_loading = 0;
+
+ c->quit_event = NULL;
+ c->quit_after_last_client_time = -1;
pa_check_for_sigpipe();
@@ -102,6 +105,11 @@ void pa_core_free(struct pa_core *c) {
pa_namereg_free(c);
pa_autoload_free(c);
pa_subscription_free_all(c);
+
+ if (c->quit_event) {
+ c->mainloop->time_free(c->quit_event);
+ c->quit_event = NULL;
+ }
pa_xfree(c->default_source_name);
pa_xfree(c->default_sink_name);
@@ -111,3 +119,23 @@ void pa_core_free(struct pa_core *c) {
pa_xfree(c);
}
+static void quit_callback(struct pa_mainloop_api*m, struct pa_time_event *e, const struct timeval *tv, void *userdata) {
+ struct pa_core *c = userdata;
+ assert(c->quit_event = e);
+
+ m->quit(m, 0);
+}
+
+void pa_core_check_quit(struct pa_core *c) {
+ assert(c);
+
+ if (!c->quit_event && c->quit_after_last_client_time >= 0 && pa_idxset_ncontents(c->clients) == 0) {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ tv.tv_sec+= c->quit_after_last_client_time;
+ c->quit_event = c->mainloop->time_new(c->mainloop, &tv, quit_callback, c);
+ } else if (c->quit_event && pa_idxset_ncontents(c->clients) > 0) {
+ c->mainloop->time_free(c->quit_event);
+ c->quit_event = NULL;
+ }
+}
diff --git a/polyp/core.h b/polyp/core.h
index ffcd018b..513d8172 100644
--- a/polyp/core.h
+++ b/polyp/core.h
@@ -48,9 +48,15 @@ struct pa_core {
struct pa_memblock_stat *memblock_stat;
int disallow_module_loading;
+ int quit_after_last_client_time;
+
+ struct pa_time_event *quit_event;
+
};
struct pa_core* pa_core_new(struct pa_mainloop_api *m);
void pa_core_free(struct pa_core*c);
+void pa_core_check_quit(struct pa_core *c);
+
#endif
diff --git a/polyp/main.c b/polyp/main.c
index 1c09276e..0f88a76e 100644
--- a/polyp/main.c
+++ b/polyp/main.c
@@ -213,6 +213,7 @@ int main(int argc, char *argv[]) {
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
c->disallow_module_loading = cmdline->disallow_module_loading;
+ c->quit_after_last_client_time = cmdline->quit_after_last_client_time;
fprintf(stderr, __FILE__": mainloop entry.\n");
if (pa_mainloop_run(mainloop, &retval) < 0)
diff --git a/polyp/modargs.c b/polyp/modargs.c
index 87d99ad2..4874d808 100644
--- a/polyp/modargs.c
+++ b/polyp/modargs.c
@@ -207,6 +207,46 @@ int pa_modargs_get_value_u32(struct pa_modargs *ma, const char *key, uint32_t *v
return 0;
}
+int pa_modargs_get_value_s32(struct pa_modargs *ma, const char *key, int32_t *value) {
+ const char *v;
+ char *e;
+ signed long l;
+ assert(ma && key && value);
+
+ if (!(v = pa_modargs_get_value(ma, key, NULL)))
+ return 0;
+
+ if (!*v)
+ return -1;
+
+ l = strtol(v, &e, 0);
+ if (*e)
+ return -1;
+
+ *value = (int32_t) l;
+ return 0;
+}
+
+int pa_modargs_get_value_boolean(struct pa_modargs *ma, const char *key, int *value) {
+ const char *v;
+ assert(ma && key && value);
+
+ if (!(v = pa_modargs_get_value(ma, key, NULL)))
+ return 0;
+
+ if (!*v)
+ return -1;
+
+ if (!strcmp(v, "1") || !strcasecmp(v, "yes") || !strcasecmp(v, "y") || !strcasecmp(v, "on"))
+ *value = 1;
+ else if (!strcmp(v, "0") || !strcasecmp(v, "no") || !strcasecmp(v, "n") || !strcasecmp(v, "off"))
+ *value = 0;
+ else
+ return -1;
+
+ return 0;
+}
+
int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *rss) {
const char *format;
uint32_t channels;
diff --git a/polyp/modargs.h b/polyp/modargs.h
index 872fb14f..705d9f43 100644
--- a/polyp/modargs.h
+++ b/polyp/modargs.h
@@ -33,6 +33,8 @@ void pa_modargs_free(struct pa_modargs*ma);
const char *pa_modargs_get_value(struct pa_modargs *ma, const char *key, const char *def);
int pa_modargs_get_value_u32(struct pa_modargs *ma, const char *key, uint32_t *value);
+int pa_modargs_get_value_s32(struct pa_modargs *ma, const char *key, int32_t *value);
+int pa_modargs_get_value_boolean(struct pa_modargs *ma, const char *key, int *value);
int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *ss);
diff --git a/polyp/module-native-protocol-fd.c b/polyp/module-native-protocol-fd.c
index 58d09ffe..213e291e 100644
--- a/polyp/module-native-protocol-fd.c
+++ b/polyp/module-native-protocol-fd.c
@@ -50,7 +50,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) {
goto finish;
}
- if (pa_modargs_get_value_u32(ma, "fd", &fd) < 0) {
+ if (pa_modargs_get_value_s32(ma, "fd", &fd) < 0) {
fprintf(stderr, __FILE__": invalid file descriptor.\n");
goto finish;
}
diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c
index 5c3be1ad..8a0dd9a4 100644
--- a/polyp/module-oss-mmap.c
+++ b/polyp/module-oss-mmap.c
@@ -234,20 +234,21 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) {
goto fail;
}
- if (pa_modargs_get_value_u32(ma, "record", &record) < 0 || pa_modargs_get_value_u32(ma, "playback", &playback) < 0) {
+ if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
fprintf(stderr, __FILE__": record= and playback= expect numeric arguments.\n");
goto fail;
}
- mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
- if (mode == 0) {
+ if (!playback && !record) {
fprintf(stderr, __FILE__": neither playback nor record enabled for device.\n");
goto fail;
}
+ mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
+
nfrags = 12;
frag_size = 1024;
- if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 || nfrags < 2 || pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0 || frag_size < 1) {
+ if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || nfrags < 2 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0 || frag_size < 1) {
fprintf(stderr, __FILE__": failed to parse fragments arguments\n");
goto fail;
}
diff --git a/polyp/module-oss.c b/polyp/module-oss.c
index 403716fd..4fd79624 100644
--- a/polyp/module-oss.c
+++ b/polyp/module-oss.c
@@ -177,7 +177,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) {
int fd = -1;
int nfrags, frag_size, in_frag_size, out_frag_size;
int mode;
- uint32_t record = 1, playback = 1;
+ int record = 1, playback = 1;
struct pa_sample_spec ss;
struct pa_modargs *ma = NULL;
assert(c && m);
@@ -187,20 +187,21 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) {
goto fail;
}
- if (pa_modargs_get_value_u32(ma, "record", &record) < 0 || pa_modargs_get_value_u32(ma, "playback", &playback) < 0) {
+ if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
fprintf(stderr, __FILE__": record= and playback= expect numeric argument.\n");
goto fail;
}
- mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
- if (mode == 0) {
+ if (!playback && !record) {
fprintf(stderr, __FILE__": neither playback nor record enabled for device.\n");
goto fail;
}
+ mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
+
nfrags = 12;
frag_size = 1024;
- if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 || nfrags < 2 || pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0 || frag_size < 1) {
+ if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || nfrags < 2 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0 || frag_size < 1) {
fprintf(stderr, __FILE__": failed to parse fragments arguments\n");
goto fail;
}
diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c
index e681732f..4d86c28e 100644
--- a/polyp/module-protocol-stub.c
+++ b/polyp/module-protocol-stub.c
@@ -83,15 +83,16 @@ static const char* const valid_modargs[] = {
static struct pa_socket_server *create_socket_server(struct pa_core *c, struct pa_modargs *ma) {
struct pa_socket_server *s;
#ifdef USE_TCP_SOCKETS
- uint32_t loopback = 1, port = IPV4_PORT;
+ int loopback = 1;
+ uint32_t port = IPV4_PORT;
- if (pa_modargs_get_value_u32(ma, "loopback", &loopback) < 0) {
+ if (pa_modargs_get_value_boolean(ma, "loopback", &loopback) < 0) {
fprintf(stderr, "loopback= expects a numerical argument.\n");
return NULL;
}
- if (pa_modargs_get_value_u32(ma, "port", &port) < 0) {
- fprintf(stderr, "port= expects a numerical argument.\n");
+ if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) {
+ fprintf(stderr, "port= expects a numerical argument between 1 and 65535.\n");
return NULL;
}
diff --git a/polyp/module.c b/polyp/module.c
index fc714953..a06b2754 100644
--- a/polyp/module.c
+++ b/polyp/module.c
@@ -117,6 +117,10 @@ fail:
static void pa_module_free(struct pa_module *m) {
assert(m && m->done && m->core);
+
+ if (m->core->disallow_module_loading)
+ return;
+
m->done(m->core, m);
lt_dlclose(m->dl);
@@ -130,7 +134,6 @@ static void pa_module_free(struct pa_module *m) {
pa_xfree(m);
}
-
void pa_module_unload(struct pa_core *c, struct pa_module *m) {
assert(c && m);
diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h
index 6c3cd825..f0ecc5c4 100644
--- a/polyp/polyplib-def.h
+++ b/polyp/polyplib-def.h
@@ -140,7 +140,7 @@ struct pa_latency_info {
pa_usec_t buffer_usec; /**< Time in usecs the current buffer takes to play */
pa_usec_t sink_usec; /**< Time in usecs a sample takes to be played on the sink. */
int playing; /**< Non-zero when the stream is currently playing */
- int queue_length; /**< Queue size in bytes. */
+ uint32_t queue_length; /**< Queue size in bytes. */
};
PA_C_DECL_END
diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c
index a4ecf5ee..b31a40c7 100644
--- a/polyp/polyplib-introspect.c
+++ b/polyp/polyplib-introspect.c
@@ -331,7 +331,7 @@ static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t c
pa_tagstruct_gets(t, &i.name) < 0 ||
pa_tagstruct_gets(t, &i.argument) < 0 ||
pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
+ pa_tagstruct_get_boolean(t, &i.auto_unload) < 0) {
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
goto finish;
}
diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h
index 1cc79d0f..0a14fad0 100644
--- a/polyp/polyplib-introspect.h
+++ b/polyp/polyplib-introspect.h
@@ -106,8 +106,8 @@ struct pa_module_info {
uint32_t index; /**< Index of the module */
const char*name, /**< Name of the module */
*argument; /**< Argument string of the module */
- uint32_t n_used, /**< Usage counter or PA_INVALID_INDEX */
- auto_unload; /**< Non-zero if this is an autoloaded module */
+ uint32_t n_used; /**< Usage counter or PA_INVALID_INDEX */
+ int auto_unload; /**< Non-zero if this is an autoloaded module */
};
/** Get some information about a module by its index */
diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c
index 220e4a14..7170a32e 100644
--- a/polyp/polyplib-stream.c
+++ b/polyp/polyplib-stream.c
@@ -329,7 +329,7 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman
} else if (pa_tagstruct_getu32(t, &i.buffer_usec) < 0 ||
pa_tagstruct_getu32(t, &i.sink_usec) < 0 ||
- pa_tagstruct_getu32(t, &i.playing) < 0 ||
+ pa_tagstruct_get_boolean(t, &i.playing) < 0 ||
pa_tagstruct_getu32(t, &i.queue_length) < 0 ||
!pa_tagstruct_eof(t)) {
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c
index cce6cc6c..2572810f 100644
--- a/polyp/protocol-native.c
+++ b/polyp/protocol-native.c
@@ -830,7 +830,7 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma
pa_tagstruct_putu32(reply, tag);
pa_tagstruct_putu32(reply, pa_sink_input_get_latency(s->sink_input));
pa_tagstruct_putu32(reply, pa_sink_get_latency(s->sink_input->sink));
- pa_tagstruct_putu32(reply, pa_memblockq_is_readable(s->memblockq));
+ pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq));
pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq));
pa_pstream_send_tagstruct(c->pstream, reply);
}
@@ -1012,7 +1012,7 @@ static void module_fill_tagstruct(struct pa_tagstruct *t, struct pa_module *modu
pa_tagstruct_puts(t, module->name);
pa_tagstruct_puts(t, module->argument ? module->argument : "");
pa_tagstruct_putu32(t, module->n_used);
- pa_tagstruct_putu32(t, module->auto_unload);
+ pa_tagstruct_put_boolean(t, module->auto_unload);
}
static void sink_input_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink_input *s) {
@@ -1505,10 +1505,10 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo
static struct pa_protocol_native* protocol_new_internal(struct pa_core *c, struct pa_module *m, struct pa_modargs *ma) {
struct pa_protocol_native *p;
- uint32_t public;
+ int public;
assert(c && ma);
- if (pa_modargs_get_value_u32(ma, "public", &public) < 0) {
+ if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) {
fprintf(stderr, __FILE__": public= expects numeric argument.\n");
return NULL;
}
diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c
index 41c1f484..3ccb3068 100644
--- a/polyp/protocol-simple.c
+++ b/polyp/protocol-simple.c
@@ -366,7 +366,7 @@ fail:
struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) {
struct pa_protocol_simple* p = NULL;
- uint32_t enable;
+ int enable;
assert(core && server && ma);
p = pa_xmalloc0(sizeof(struct pa_protocol_simple));
@@ -385,14 +385,14 @@ struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct p
p->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
enable = 0;
- if (pa_modargs_get_value_u32(ma, "record", &enable) < 0) {
+ if (pa_modargs_get_value_boolean(ma, "record", &enable) < 0) {
fprintf(stderr, __FILE__": record= expects a numeric argument.\n");
goto fail;
}
p->mode = enable ? RECORD : 0;
enable = 1;
- if (pa_modargs_get_value_u32(ma, "playback", &enable) < 0) {
+ if (pa_modargs_get_value_boolean(ma, "playback", &enable) < 0) {
fprintf(stderr, __FILE__": playback= expects a numeric argument.\n");
goto fail;
}
diff --git a/polyp/scache.c b/polyp/scache.c
index b7a8ff02..53e8a3fe 100644
--- a/polyp/scache.c
+++ b/polyp/scache.c
@@ -172,7 +172,7 @@ uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name) {
uint32_t pa_scache_total_size(struct pa_core *c) {
struct pa_scache_entry *e;
uint32_t index;
- uint32_t sum;
+ uint32_t sum = 0;
if (!c->scache)
return 0;
diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c
index 742f6b9c..5aa79e6c 100644
--- a/polyp/tagstruct.c
+++ b/polyp/tagstruct.c
@@ -40,7 +40,9 @@ enum tags {
TAG_U8 = 'B',
TAG_S8 = 'b',
TAG_SAMPLE_SPEC = 'a',
- TAG_ARBITRARY = 'x'
+ TAG_ARBITRARY = 'x',
+ TAG_BOOLEAN_TRUE = '1',
+ TAG_BOOLEAN_FALSE = '0',
};
struct pa_tagstruct {
@@ -125,7 +127,6 @@ void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample
t->length += 7;
}
-
void pa_tagstruct_put_arbitrary(struct pa_tagstruct *t, const void *p, size_t length) {
assert(t && p);
@@ -137,6 +138,13 @@ void pa_tagstruct_put_arbitrary(struct pa_tagstruct *t, const void *p, size_t le
t->length += 5+length;
}
+void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b) {
+ assert(t);
+ extend(t, 1);
+ t->data[t->length] = b ? TAG_BOOLEAN_TRUE : TAG_BOOLEAN_FALSE;
+ t->length += 1;
+}
+
int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s) {
int error = 0;
size_t n;
@@ -238,3 +246,21 @@ const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l) {
return t->data;
}
+int pa_tagstruct_get_boolean(struct pa_tagstruct*t, int *b) {
+ assert(t && b);
+
+ if (t->rindex+1 > t->length)
+ return -1;
+
+ if (t->data[t->rindex] == TAG_BOOLEAN_TRUE)
+ *b = 1;
+ else if (t->data[t->rindex] == TAG_BOOLEAN_FALSE)
+ *b = 0;
+ else
+ return -1;
+
+ t->rindex +=1;
+ return 0;
+}
+
+
diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h
index bcd7f456..9a91ee96 100644
--- a/polyp/tagstruct.h
+++ b/polyp/tagstruct.h
@@ -38,12 +38,14 @@ void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i);
void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c);
void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss);
void pa_tagstruct_put_arbitrary(struct pa_tagstruct*t, const void *p, size_t length);
+void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b);
int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s);
int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i);
int pa_tagstruct_getu8(struct pa_tagstruct*t, uint8_t *c);
int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec *ss);
int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length);
+int pa_tagstruct_get_boolean(struct pa_tagstruct *t, int *b);
int pa_tagstruct_eof(struct pa_tagstruct*t);
const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l);