summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2004-06-18 00:22:37 +0000
committerLennart Poettering <lennart@poettering.net>2004-06-18 00:22:37 +0000
commit993d1bce74f4cc5be2bfa69a467aae106e2194ab (patch)
treef281667fdbc6f643f4a799be75dcbd95102c0dc8
parenteb946dbdbeda66b95039b1e5ada3b9006dc33c8c (diff)
basic cli interface
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@22 fefdeb5f-60dc-0310-8127-8f9354f1896f
-rw-r--r--src/Makefile.am35
-rw-r--r--src/cli.c83
-rw-r--r--src/cli.h14
-rw-r--r--src/client.c18
-rw-r--r--src/client.h3
-rw-r--r--src/core.c27
-rw-r--r--src/core.h3
-rw-r--r--src/ioline.c190
-rw-r--r--src/ioline.h14
-rw-r--r--src/main.c4
-rw-r--r--src/main.h6
-rw-r--r--src/module-cli.c34
-rw-r--r--src/module.c17
-rw-r--r--src/module.h7
-rw-r--r--src/protocol-simple.c4
-rw-r--r--src/sink.c36
-rw-r--r--src/sink.h6
-rw-r--r--src/source.c35
-rw-r--r--src/source.h4
-rw-r--r--src/strbuf.c13
-rw-r--r--src/strbuf.h1
21 files changed, 505 insertions, 49 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 8ce5202d..5afc5bc0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,12 +22,25 @@ bin_PROGRAMS = polypaudio
pkglib_LTLIBRARIES=libprotocol-simple.la module-simple-protocol-tcp.la \
libsocket-server.la module-pipe-sink.la libpstream.la libiochannel.la \
- libpacket.la module-oss.la module-oss-mmap.la liboss.la
+ libpacket.la module-oss.la module-oss-mmap.la liboss.la libioline.la \
+ libcli.la module-cli.la
+
+polypaudio_SOURCES = idxset.c idxset.h \
+ queue.c queue.h \
+ strbuf.c strbuf.h \
+ mainloop.c mainloop.h \
+ memblock.c memblock.h \
+ sample.c sample.h \
+ memblockq.c memblockq.h \
+ client.c client.h \
+ core.c core.h \
+ main.c main.h \
+ sourceoutput.c sourceoutput.h \
+ sinkinput.c sinkinput.h \
+ source.c source.h \
+ sink.c sink.h \
+ module.c module.h
-polypaudio_SOURCES = idxset.c queue.c strbuf.c mainloop.c \
- memblock.c sample.c memblockq.c client.c \
- core.c main.c sourceoutput.c sinkinput.c source.c sink.c \
- module.c
polypaudio_INCLUDES = $(INCLTDL)
polypaudio_LDADD = $(LIBLTDL)
polypaudio_LDFLAGS=-export-dynamic
@@ -53,6 +66,14 @@ libpacket_la_LDFLAGS = -avoid-version
liboss_la_SOURCES = oss.c
liboss_la_LDFLAGS = -avoid-version
+libioline_la_SOURCES = ioline.c
+libioline_la_LDFLAGS = -avoid-version
+libioline_la_LIBADD = libiochannel.la
+
+libcli_la_SOURCES = cli.c
+libcli_la_LDFLAGS = -avoid-version
+libcli_la_LIBADD = libiochannel.la libioline.la
+
module_simple_protocol_tcp_la_SOURCES = module-simple-protocol-tcp.c
module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version
module_simple_protocol_tcp_la_LIBADD = libprotocol-simple.la libiochannel.la
@@ -68,3 +89,7 @@ module_oss_la_LIBADD = libiochannel.la liboss.la
module_oss_mmap_la_SOURCES = module-oss-mmap.c
module_oss_mmap_la_LDFLAGS = -module -avoid-version
module_oss_mmap_la_LIBADD = libiochannel.la liboss.la
+
+module_cli_la_SOURCES = module-cli.c
+module_cli_la_LDFLAGS = -module -avoid-version
+module_cli_la_LIBADD = libcli.la libiochannel.la
diff --git a/src/cli.c b/src/cli.c
new file mode 100644
index 00000000..9aad7f56
--- /dev/null
+++ b/src/cli.c
@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "ioline.h"
+#include "cli.h"
+#include "module.h"
+#include "sink.h"
+#include "source.h"
+#include "client.h"
+
+struct cli {
+ struct core *core;
+ struct ioline *line;
+
+ void (*eof_callback)(struct cli *c, void *userdata);
+ void *userdata;
+};
+
+static void line_callback(struct ioline *line, const char *s, void *userdata);
+
+struct cli* cli_new(struct core *core, struct iochannel *io) {
+ struct cli *c;
+ assert(io);
+
+ c = malloc(sizeof(struct cli));
+ assert(c);
+ c->core = core;
+ c->line = ioline_new(io);
+ assert(c->line);
+
+ c->userdata = NULL;
+ c->eof_callback = NULL;
+
+ ioline_set_callback(c->line, line_callback, c);
+ ioline_puts(c->line, "Welcome to polypaudio!\n> ");
+
+ return c;
+}
+
+void cli_free(struct cli *c) {
+ assert(c);
+ ioline_free(c->line);
+ free(c);
+}
+
+static void line_callback(struct ioline *line, const char *s, void *userdata) {
+ struct cli *c = userdata;
+ char *t = NULL;
+ assert(line && c);
+
+ if (!s) {
+ fprintf(stderr, "CLI client exited\n");
+ if (c->eof_callback)
+ c->eof_callback(c, c->userdata);
+
+ return;
+ }
+
+ if (!strcmp(s, "modules"))
+ ioline_puts(line, (t = module_list_to_string(c->core)));
+ else if (!strcmp(s, "sources"))
+ ioline_puts(line, (t = source_list_to_string(c->core)));
+ else if (!strcmp(s, "sinks"))
+ ioline_puts(line, (t = sink_list_to_string(c->core)));
+ else if (!strcmp(s, "clients"))
+ ioline_puts(line, (t = client_list_to_string(c->core)));
+ else if (!strcmp(s, "exit")) {
+ assert(c->core && c->core->mainloop);
+ mainloop_quit(c->core->mainloop, -1);
+ } else if (*s)
+ ioline_puts(line, "Unknown command\n");
+
+ free(t);
+ ioline_puts(line, "> ");
+}
+
+void cli_set_eof_callback(struct cli *c, void (*cb)(struct cli*c, void *userdata), void *userdata) {
+ assert(c && cb);
+ c->eof_callback = cb;
+ c->userdata = userdata;
+}
diff --git a/src/cli.h b/src/cli.h
new file mode 100644
index 00000000..f1b74397
--- /dev/null
+++ b/src/cli.h
@@ -0,0 +1,14 @@
+#ifndef fooclihfoo
+#define fooclihfoo
+
+#include "iochannel.h"
+#include "core.h"
+
+struct cli;
+
+struct cli* cli_new(struct core *core, struct iochannel *io);
+void cli_free(struct cli *cli);
+
+void cli_set_eof_callback(struct cli *cli, void (*cb)(struct cli*c, void *userdata), void *userdata);
+
+#endif
diff --git a/src/client.c b/src/client.c
index 1b84c6bf..4c8a0491 100644
--- a/src/client.c
+++ b/src/client.c
@@ -4,6 +4,7 @@
#include <string.h>
#include "client.h"
+#include "strbuf.h"
struct client *client_new(struct core *core, const char *protocol_name, char *name) {
struct client *c;
@@ -42,3 +43,20 @@ void client_kill(struct client *c) {
c->kill(c);
}
+char *client_list_to_string(struct core *c) {
+ struct strbuf *s;
+ struct client *client;
+ uint32_t index = IDXSET_INVALID;
+ assert(c);
+
+ s = strbuf_new();
+ assert(s);
+
+ strbuf_printf(s, "%u client(s).\n", idxset_ncontents(c->clients));
+
+ for (client = idxset_first(c->clients, &index); client; client = idxset_next(c->clients, &index))
+ strbuf_printf(s, " index: %u, name: <%s>, protocol_name: <%s>\n", client->index, client->name, client->protocol_name);
+
+ return strbuf_tostring_free(s);
+}
+
diff --git a/src/client.h b/src/client.h
index 556b5fb3..48172051 100644
--- a/src/client.h
+++ b/src/client.h
@@ -11,7 +11,6 @@ struct client {
const char *protocol_name;
void (*kill)(struct client *c);
-
void *userdata;
};
@@ -24,4 +23,6 @@ void client_free(struct client *c);
* request destruction of the client */
void client_kill(struct client *c);
+char *client_list_to_string(struct core *c);
+
#endif
diff --git a/src/core.c b/src/core.c
index 0bc13a5b..50248501 100644
--- a/src/core.c
+++ b/src/core.c
@@ -50,30 +50,3 @@ void core_free(struct core *c) {
free(c);
};
-struct sink* core_get_default_sink(struct core *c) {
- struct sink *sink;
- assert(c);
-
- if ((sink = idxset_get_by_index(c->sinks, c->default_sink_index)))
- return sink;
-
- if (!(sink = idxset_first(c->sinks, &c->default_sink_index)))
- return NULL;
-
- fprintf(stderr, "core: default sink vanished, setting to %u.\n", sink->index);
- return sink;
-}
-
-struct source* core_get_default_source(struct core *c) {
- struct source *source;
- assert(c);
-
- if ((source = idxset_get_by_index(c->sources, c->default_source_index)))
- return source;
-
- if (!(source = idxset_first(c->sources, &c->default_source_index)))
- return NULL;
-
- fprintf(stderr, "core: default source vanished, setting to %u.\n", source->index);
- return source;
-}
diff --git a/src/core.h b/src/core.h
index a8a140b8..f6f794b9 100644
--- a/src/core.h
+++ b/src/core.h
@@ -15,7 +15,4 @@ struct core {
struct core* core_new(struct mainloop *m);
void core_free(struct core*c);
-struct sink* core_get_default_sink(struct core *c);
-struct source* core_get_default_source(struct core *c);
-
#endif
diff --git a/src/ioline.c b/src/ioline.c
new file mode 100644
index 00000000..c37737a6
--- /dev/null
+++ b/src/ioline.c
@@ -0,0 +1,190 @@
+#include <errno.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ioline.h"
+
+#define BUFFER_LIMIT (64*1024)
+#define READ_SIZE (1024)
+
+struct ioline {
+ struct iochannel *io;
+ int dead;
+
+ char *wbuf;
+ size_t wbuf_length, wbuf_index, wbuf_valid_length;
+
+ char *rbuf;
+ size_t rbuf_length, rbuf_index, rbuf_valid_length;
+
+ void (*callback)(struct ioline*io, const char *s, void *userdata);
+ void *userdata;
+};
+
+static void io_callback(struct iochannel*io, void *userdata);
+static int do_write(struct ioline *l);
+
+struct ioline* ioline_new(struct iochannel *io) {
+ struct ioline *l;
+ assert(io);
+
+ l = malloc(sizeof(struct ioline));
+ assert(l);
+ l->io = io;
+ l->dead = 0;
+
+ l->wbuf = NULL;
+ l->wbuf_length = l->wbuf_index = l->wbuf_valid_length = 0;
+
+ l->rbuf = NULL;
+ l->rbuf_length = l->rbuf_index = l->rbuf_valid_length = 0;
+
+ l->callback = NULL;
+ l->userdata = NULL;
+
+ iochannel_set_callback(io, io_callback, l);
+
+ return l;
+}
+
+void ioline_free(struct ioline *l) {
+ assert(l);
+ iochannel_free(l->io);
+ free(l->wbuf);
+ free(l->rbuf);
+ free(l);
+}
+
+void ioline_puts(struct ioline *l, const char *c) {
+ size_t len;
+ assert(l && c);
+
+ len = strlen(c);
+ if (len > BUFFER_LIMIT - l->wbuf_valid_length)
+ len = BUFFER_LIMIT - l->wbuf_valid_length;
+
+ if (!len)
+ return;
+
+ if (len > l->wbuf_length - l->wbuf_valid_length) {
+ size_t n = l->wbuf_valid_length+len;
+ char *new = malloc(n);
+ if (l->wbuf) {
+ memcpy(new, l->wbuf+l->wbuf_index, l->wbuf_valid_length);
+ free(l->wbuf);
+ }
+ l->wbuf = new;
+ l->wbuf_length = n;
+ l->wbuf_index = 0;
+ } else if (len > l->wbuf_length - l->wbuf_valid_length - l->wbuf_index) {
+ memmove(l->wbuf, l->wbuf+l->wbuf_index, l->wbuf_valid_length);
+ l->wbuf_index = 0;
+ }
+
+ memcpy(l->wbuf+l->wbuf_index+l->wbuf_valid_length, c, len);
+ l->wbuf_valid_length += len;
+
+ do_write(l);
+}
+
+void ioline_set_callback(struct ioline*l, void (*callback)(struct ioline*io, const char *s, void *userdata), void *userdata) {
+ assert(l && callback);
+ l->callback = callback;
+ l->userdata = userdata;
+}
+
+static int do_read(struct ioline *l) {
+ ssize_t r;
+ size_t m, len;
+ char *p, *e;
+ assert(l);
+
+ if (!iochannel_is_readable(l->io))
+ return 0;
+
+ len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length;
+
+ if (len < READ_SIZE) {
+ size_t n = l->rbuf_valid_length+READ_SIZE;
+
+ if (n >= BUFFER_LIMIT)
+ n = BUFFER_LIMIT;
+
+ if (l->rbuf_length >= n) {
+ if (l->rbuf_valid_length)
+ memmove(l->rbuf, l->rbuf+l->rbuf_index, l->rbuf_valid_length);
+ } else {
+ char *new = malloc(n);
+ if (l->rbuf_valid_length)
+ memcpy(new, l->rbuf+l->rbuf_index, l->rbuf_valid_length);
+ free(l->rbuf);
+ l->rbuf = new;
+ l->rbuf_length = n;
+ }
+
+ l->rbuf_index = 0;
+ }
+
+ len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length;
+
+ if ((r = iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len)) <= 0)
+ return -1;
+
+ e = memchr(l->rbuf+l->rbuf_index+l->rbuf_valid_length, '\n', r);
+ l->rbuf_valid_length += r;
+
+ if (!e && l->rbuf_valid_length >= BUFFER_LIMIT)
+ e = l->rbuf+BUFFER_LIMIT-1;
+
+ *e = 0;
+ p = l->rbuf+l->rbuf_index;
+ m = strlen(p);
+
+ if (l->callback)
+ l->callback(l, p, l->userdata);
+
+ l->rbuf_index += m+1;
+ l->rbuf_valid_length -= m+1;
+
+ if (l->rbuf_valid_length == 0)
+ l->rbuf_index = 0;
+
+ return 0;
+}
+
+static int do_write(struct ioline *l) {
+ ssize_t r;
+ assert(l);
+
+ if (!l->wbuf_valid_length || !iochannel_is_writable(l->io))
+ return 0;
+
+ if ((r = iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0)
+ return -1;
+
+ l->wbuf_valid_length -= r;
+ if (l->wbuf_valid_length == 0)
+ l->wbuf_index = 0;
+
+ return 0;
+}
+
+static void io_callback(struct iochannel*io, void *userdata) {
+ struct ioline *l = userdata;
+ assert(io && l);
+
+ if (!l->dead && do_read(l) < 0)
+ goto fail;
+
+ if (!l->dead && do_write(l) < 0)
+ goto fail;
+
+ return;
+
+fail:
+ if (l->callback)
+ l->callback(l, NULL, l->userdata);
+ l->dead = 1;
+}
diff --git a/src/ioline.h b/src/ioline.h
new file mode 100644
index 00000000..55d7d4a3
--- /dev/null
+++ b/src/ioline.h
@@ -0,0 +1,14 @@
+#ifndef fooiolinehfoo
+#define fooiolinehfoo
+
+#include "iochannel.h"
+
+struct ioline;
+
+struct ioline* ioline_new(struct iochannel *io);
+void ioline_free(struct ioline *l);
+
+void ioline_puts(struct ioline *s, const char *c);
+void ioline_set_callback(struct ioline*io, void (*callback)(struct ioline*io, const char *s, void *userdata), void *userdata);
+
+#endif
diff --git a/src/main.c b/src/main.c
index bce07823..f35505ec 100644
--- a/src/main.c
+++ b/src/main.c
@@ -9,6 +9,8 @@
#include "mainloop.h"
#include "module.h"
+int stdin_inuse = 0, stdout_inuse = 0;
+
static void signal_callback(struct mainloop_source *m, int sig, void *userdata) {
mainloop_quit(mainloop_source_get_mainloop(m), -1);
fprintf(stderr, "main: got signal.\n");
@@ -33,12 +35,12 @@ int main(int argc, char *argv[]) {
module_load(c, "module-oss-mmap", "/dev/dsp1");
module_load(c, "module-pipe-sink", NULL);
module_load(c, "module-simple-protocol-tcp", NULL);
+ module_load(c, "module-cli", NULL);
fprintf(stderr, "main: mainloop entry.\n");
while (mainloop_iterate(m, 1) == 0);
/* fprintf(stderr, "main: %u blocks\n", n_blocks);*/
fprintf(stderr, "main: mainloop exit.\n");
-
mainloop_run(m);
diff --git a/src/main.h b/src/main.h
new file mode 100644
index 00000000..c4bea049
--- /dev/null
+++ b/src/main.h
@@ -0,0 +1,6 @@
+#ifndef foomainhfoo
+#define foomainhfoo
+
+extern int stdin_inuse, stdout_inuse;
+
+#endif
diff --git a/src/module-cli.c b/src/module-cli.c
new file mode 100644
index 00000000..4af37f67
--- /dev/null
+++ b/src/module-cli.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <assert.h>
+#include <unistd.h>
+
+#include "main.h"
+#include "module.h"
+#include "iochannel.h"
+#include "cli.h"
+
+int module_init(struct core *c, struct module*m) {
+ struct iochannel *io;
+ assert(c && m);
+
+ if (stdin_inuse || stdout_inuse) {
+ fprintf(stderr, "STDIN/STDUSE already used\n");
+ return -1;
+ }
+
+ stdin_inuse = stdout_inuse = 1;
+ io = iochannel_new(c->mainloop, STDIN_FILENO, STDOUT_FILENO);
+ assert(io);
+
+ m->userdata = cli_new(c, io);
+ assert(m->userdata);
+ return 0;
+}
+
+void module_done(struct core *c, struct module*m) {
+ assert(c && m);
+
+ cli_free(m->userdata);
+ assert(stdin_inuse && stdout_inuse);
+ stdin_inuse = stdout_inuse = 0;
+}
diff --git a/src/module.c b/src/module.c
index 7f2bc218..0be7f5ed 100644
--- a/src/module.c
+++ b/src/module.c
@@ -6,6 +6,7 @@
#include <errno.h>
#include "module.h"
+#include "strbuf.h"
struct module* module_load(struct core *c, const char *name, const char *argument) {
struct module *m = NULL;
@@ -110,3 +111,19 @@ void module_unload_all(struct core *c) {
c->modules = NULL;
}
+char *module_list_to_string(struct core *c) {
+ struct strbuf *s;
+ struct module *m;
+ uint32_t index = IDXSET_INVALID;
+ assert(c);
+
+ s = strbuf_new();
+ assert(s);
+
+ strbuf_printf(s, "%u module(s) loaded.\n", idxset_ncontents(c->modules));
+
+ for (m = idxset_first(c->modules, &index); m; m = idxset_next(c->modules, &index))
+ strbuf_printf(s, " index: %u, name: <%s>, argument: <%s>\n", m->index, m->name, m->argument);
+
+ return strbuf_tostring_free(s);
+}
diff --git a/src/module.h b/src/module.h
index 98082194..709c7f55 100644
--- a/src/module.h
+++ b/src/module.h
@@ -6,11 +6,6 @@
#include "core.h"
-struct dependency_module {
- lt_dlhandle dl;
- struct dependency_module *next;
-};
-
struct module {
struct core *core;
char *name, *argument;
@@ -30,4 +25,6 @@ void module_unload_by_index(struct core *c, uint32_t index);
void module_unload_all(struct core *c);
+char *module_list_to_string(struct core *c);
+
#endif
diff --git a/src/protocol-simple.c b/src/protocol-simple.c
index f779a56a..3563419e 100644
--- a/src/protocol-simple.c
+++ b/src/protocol-simple.c
@@ -205,7 +205,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us
struct source *source;
size_t l;
- if (!(source = core_get_default_source(p->core))) {
+ if (!(source = source_get_default(p->core))) {
fprintf(stderr, "Failed to get default source.\n");
goto fail;
}
@@ -224,7 +224,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us
struct sink *sink;
size_t l;
- if (!(sink = core_get_default_sink(p->core))) {
+ if (!(sink = sink_get_default(p->core))) {
fprintf(stderr, "Failed to get default sink.\n");
goto fail;
}
diff --git a/src/sink.c b/src/sink.c
index 4d3206d8..89f5e088 100644
--- a/src/sink.c
+++ b/src/sink.c
@@ -5,6 +5,7 @@
#include "sink.h"
#include "sinkinput.h"
+#include "strbuf.h"
#define MAX_MIX_CHANNELS 32
@@ -214,3 +215,38 @@ uint32_t sink_get_latency(struct sink *s) {
return s->get_latency(s);
}
+
+struct sink* sink_get_default(struct core *c) {
+ struct sink *sink;
+ assert(c);
+
+ if ((sink = idxset_get_by_index(c->sinks, c->default_sink_index)))
+ return sink;
+
+ if (!(sink = idxset_first(c->sinks, &c->default_sink_index)))
+ return NULL;
+
+ fprintf(stderr, "core: default sink vanished, setting to %u.\n", sink->index);
+ return sink;
+}
+
+char *sink_list_to_string(struct core *c) {
+ struct strbuf *s;
+ struct sink *sink, *default_sink;
+ uint32_t index = IDXSET_INVALID;
+ assert(c);
+
+ s = strbuf_new();
+ assert(s);
+
+ strbuf_printf(s, "%u sink(s) available.\n", idxset_ncontents(c->sinks));
+
+ default_sink = sink_get_default(c);
+
+ for (sink = idxset_first(c->sinks, &index); sink; sink = idxset_next(c->sinks, &index)) {
+ assert(sink->monitor_source);
+ strbuf_printf(s, " %c index: %u, name: <%s>, volume: <0x%02x>, latency: <%u usec>, monitor_source: <%u>\n", sink == default_sink ? '*' : ' ', sink->index, sink->name, (unsigned) sink->volume, sink_get_latency(sink), sink->monitor_source->index);
+ }
+
+ return strbuf_tostring_free(s);
+}
diff --git a/src/sink.h b/src/sink.h
index 1a9fb8ca..394abb5b 100644
--- a/src/sink.h
+++ b/src/sink.h
@@ -38,4 +38,10 @@ uint32_t sink_get_latency(struct sink *s);
void sink_notify(struct sink*s);
+char *sink_list_to_string(struct core *core);
+
+struct sink* sink_get_default(struct core *c);
+
+
+
#endif
diff --git a/src/source.c b/src/source.c
index c950b54d..44d77532 100644
--- a/src/source.c
+++ b/src/source.c
@@ -5,6 +5,7 @@
#include "source.h"
#include "sourceoutput.h"
+#include "strbuf.h"
struct source* source_new(struct core *core, const char *name, const struct sample_spec *spec) {
struct source *s;
@@ -70,3 +71,37 @@ void source_post(struct source*s, struct memchunk *chunk) {
idxset_foreach(s->outputs, do_post, chunk);
}
+
+struct source* source_get_default(struct core *c) {
+ struct source *source;
+ assert(c);
+
+ if ((source = idxset_get_by_index(c->sources, c->default_source_index)))
+ return source;
+
+ if (!(source = idxset_first(c->sources, &c->default_source_index)))
+ return NULL;
+
+ fprintf(stderr, "core: default source vanished, setting to %u.\n", source->index);
+ return source;
+}
+
+char *source_list_to_string(struct core *c) {
+ struct strbuf *s;
+ struct source *source, *default_source;
+ uint32_t index = IDXSET_INVALID;
+ assert(c);
+
+ s = strbuf_new();
+ assert(s);
+
+ strbuf_printf(s, "%u source(s) available.\n", idxset_ncontents(c->sources));
+
+ default_source = source_get_default(c);
+
+ for (source = idxset_first(c->sources, &index); source; source = idxset_next(c->sources, &index))
+ strbuf_printf(s, " %c index: %u, name: <%s>\n", source == default_source ? '*' : ' ', source->index, source->name);
+
+ return strbuf_tostring_free(s);
+}
+
diff --git a/src/source.h b/src/source.h
index 1442b9f0..078fb1c9 100644
--- a/src/source.h
+++ b/src/source.h
@@ -29,4 +29,8 @@ void source_post(struct source*s, struct memchunk *b);
void source_notify(struct source *s);
+char *source_list_to_string(struct core *c);
+
+struct source* source_get_default(struct core *c);
+
#endif
diff --git a/src/strbuf.c b/src/strbuf.c
index 7c8b965d..97c451c1 100644
--- a/src/strbuf.c
+++ b/src/strbuf.c
@@ -1,6 +1,3 @@
-#ifndef foostrbufhfoo
-#define foostrbufhfoo
-
#include <sys/types.h>
#include <stdlib.h>
#include <assert.h>
@@ -55,6 +52,14 @@ char *strbuf_tostring(struct strbuf *sb) {
return t;
}
+char *strbuf_tostring_free(struct strbuf *sb) {
+ char *t;
+ assert(sb);
+ t = strbuf_tostring(sb);
+ strbuf_free(sb);
+ return t;
+}
+
void strbuf_puts(struct strbuf *sb, const char *t) {
struct chunk *c;
size_t l;
@@ -118,5 +123,3 @@ int strbuf_printf(struct strbuf *sb, const char *format, ...) {
size *= 2;
}
}
-
-#endif
diff --git a/src/strbuf.h b/src/strbuf.h
index 6ad582a3..f530a0dc 100644
--- a/src/strbuf.h
+++ b/src/strbuf.h
@@ -6,6 +6,7 @@ struct strbuf;
struct strbuf *strbuf_new(void);
void strbuf_free(struct strbuf *sb);
char *strbuf_tostring(struct strbuf *sb);
+char *strbuf_tostring_free(struct strbuf *sb);
int strbuf_printf(struct strbuf *sb, const char *format, ...);
void strbuf_puts(struct strbuf *sb, const char *t);