]> code.delx.au - pulseaudio/commitdiff
basic cli interface
authorLennart Poettering <lennart@poettering.net>
Fri, 18 Jun 2004 00:22:37 +0000 (00:22 +0000)
committerLennart Poettering <lennart@poettering.net>
Fri, 18 Jun 2004 00:22:37 +0000 (00:22 +0000)
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@22 fefdeb5f-60dc-0310-8127-8f9354f1896f

21 files changed:
src/Makefile.am
src/cli.c [new file with mode: 0644]
src/cli.h [new file with mode: 0644]
src/client.c
src/client.h
src/core.c
src/core.h
src/ioline.c [new file with mode: 0644]
src/ioline.h [new file with mode: 0644]
src/main.c
src/main.h [new file with mode: 0644]
src/module-cli.c [new file with mode: 0644]
src/module.c
src/module.h
src/protocol-simple.c
src/sink.c
src/sink.h
src/source.c
src/source.h
src/strbuf.c
src/strbuf.h

index 8ce5202dce88af5426806b3c579cd67b590531fa..5afc5bc08d6b638f7a66fdf2e3dbbe4e52d33720 100644 (file)
@@ -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 (file)
index 0000000..9aad7f5
--- /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 (file)
index 0000000..f1b7439
--- /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
index 1b84c6bf59c452210a888ee9196a859ee3eec6b5..4c8a04910b9964f16a4483afd664bb1a48fbabff 100644 (file)
@@ -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);
+}
+
index 556b5fb3dfa1d7cb59900a70a5dbff65dc9f34a6..4817205188d914fc31af8b45de02591758410acf 100644 (file)
@@ -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
index 0bc13a5b9a8a77671fa6ce7f0e335b0517cca3ba..50248501a7c571b10fa36a7d576d62fb265bf195 100644 (file)
@@ -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;
-}
index a8a140b8939a9cfa07a092a725c66d341737d203..f6f794b99eb12bc736e51bcef09e4e0f18433960 100644 (file)
@@ -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 (file)
index 0000000..c37737a
--- /dev/null
@@ -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 (file)
index 0000000..55d7d4a
--- /dev/null
@@ -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
index bce0782315971bbad97261d2872501fdeedca28f..f35505ecbad65a64e2b13f705e5732a4807f5a70 100644 (file)
@@ -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 (file)
index 0000000..c4bea04
--- /dev/null
@@ -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 (file)
index 0000000..4af37f6
--- /dev/null
@@ -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;
+}
index 7f2bc218e4cb42217661a41de592fea0f4ca5d6e..0be7f5ed3c3aadbb013f1b33ad8824a26f8af2bf 100644 (file)
@@ -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);
+}
index 980821945be9e41e7f8dc33f29df3499053bbeb6..709c7f55c3114cc497ed661854e93b35955b42d6 100644 (file)
@@ -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
index f779a56a0e78d9353a65b831f136d3ec903ae924..3563419eaddf31d708cf6e6353dd608d0471797b 100644 (file)
@@ -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;
         }
index 4d3206d82682baf21280a29c3e9543afc12fb23d..89f5e0880bca709df24b0b863440ca8d43fa746d 100644 (file)
@@ -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);
+}
index 1a9fb8caa1c30582ac31d50fe992526090a0a071..394abb5bab230f25e068c62a98238bc8c844c170 100644 (file)
@@ -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
index c950b54d58638a0fe69f004aa9e10bc8e7709155..44d775327e01aa7cd6fb863c0d767f318575de6c 100644 (file)
@@ -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);
+}
+
index 1442b9f01fa8c6958877336fb62f049941c1c626..078fb1c9a4d1ecb510b7dbbf439c3a6415684c34 100644 (file)
@@ -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
index 7c8b965dea740fb4d17a4b50b35bad9056085a2c..97c451c170510669301eb4e8509074b8e765718e 100644 (file)
@@ -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
index 6ad582a31fde93cffdfd5b9d748b1bb5e91a792a..f530a0dcfeaf4f7c64b26903fbb901a41a68bc5e 100644 (file)
@@ -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);