summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2004-09-04 00:27:36 +0000
committerLennart Poettering <lennart@poettering.net>2004-09-04 00:27:36 +0000
commit57e473b61cf373f8d9befb03d359b999eca4262b (patch)
tree0c4d0798db9c4ecf4804aaaff60e9fe8b30ac0f6
parentfb962b67dbeb54d1cdd453c6f902b7c679b9197f (diff)
add support for automatic termination of the daemon after the last client quit
remove all gcc warnings add boolean types for tagstruct and modargs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@178 fefdeb5f-60dc-0310-8127-8f9354f1896f
-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);