some more work
authorLennart Poettering <lennart@poettering.net>
Fri, 18 Jun 2004 17:12:50 +0000 (17:12 +0000)
committerLennart Poettering <lennart@poettering.net>
Fri, 18 Jun 2004 17:12:50 +0000 (17:12 +0000)
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@23 fefdeb5f-60dc-0310-8127-8f9354f1896f

14 files changed:
src/cli.c
src/memblock.c
src/memblock.h
src/memblockq.c
src/memblockq.h
src/module-oss.c
src/protocol-simple.c
src/sample.c
src/sample.h
src/sink.c
src/sinkinput.c
src/sinkinput.h
src/sourceoutput.c
src/sourceoutput.h

index 9aad7f5..4a19814 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -9,6 +9,8 @@
 #include "sink.h"
 #include "source.h"
 #include "client.h"
+#include "sinkinput.h"
+#include "sourceoutput.h"
 
 struct cli {
     struct core *core;
@@ -34,7 +36,7 @@ struct cli* cli_new(struct core *core, struct iochannel *io) {
     c->eof_callback = NULL;
 
     ioline_set_callback(c->line, line_callback, c);
-    ioline_puts(c->line, "Welcome to polypaudio!\n> ");
+    ioline_puts(c->line, "Welcome to polypaudio! Use \"help\" for usage information.\n> ");
 
     return c;
 }
@@ -66,10 +68,30 @@ static void line_callback(struct ioline *line, const char *s, void *userdata) {
         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")) {
+    else if (!strcmp(s, "source_outputs"))
+        ioline_puts(line, (t = source_output_list_to_string(c->core)));
+    else if (!strcmp(s, "sink_inputs"))
+        ioline_puts(line, (t = sink_input_list_to_string(c->core)));
+    else if (!strcmp(s, "stat")) {
+        char txt[256];
+        snprintf(txt, sizeof(txt), "Memory blocks allocated: %u, total size: %u bytes.\n", memblock_count, memblock_total);
+        ioline_puts(line, txt);
+    } else if (!strcmp(s, "exit")) {
         assert(c->core && c->core->mainloop);
         mainloop_quit(c->core->mainloop, -1);
-    } else if (*s)
+    } else if (!strcmp(s, "help"))
+        ioline_puts(line,
+                    "Available commands:\n"
+                    "    modules\t\tlist modules\n"
+                    "    sinks\t\tlist sinks\n"
+                    "    sources\t\tlist sources\n"
+                    "    clients\t\tlist clients\n"
+                    "    source_outputs\tlist source outputs\n"
+                    "    sink_inputs\t\tlist sink inputs\n"
+                    "    stat\t\tshow memblock statistics\n"
+                    "    exit\t\tterminate the daemon\n"
+                    "    help\t\tshow this help\n");
+    else if (*s)
         ioline_puts(line, "Unknown command\n");
 
     free(t);
index 6f05918..067243c 100644 (file)
@@ -5,7 +5,7 @@
 
 #include "memblock.h"
 
-unsigned n_blocks = 0;
+unsigned memblock_count = 0, memblock_total = 0;
 
 struct memblock *memblock_new(size_t length) {
     struct memblock *b = malloc(sizeof(struct memblock)+length);
@@ -13,7 +13,8 @@ struct memblock *memblock_new(size_t length) {
     b->ref = 1;
     b->length = length;
     b->data = b+1;
-    n_blocks++;
+    memblock_count++;
+    memblock_total += length;
     return b;
 }
 
@@ -23,7 +24,8 @@ struct memblock *memblock_new_fixed(void *d, size_t length) {
     b->ref = 1;
     b->length = length;
     b->data = d;
-    n_blocks++;
+    memblock_count++;
+    memblock_total += length;
     return b;
 }
 
@@ -33,7 +35,8 @@ struct memblock *memblock_new_dynamic(void *d, size_t length) {
     b->ref = 1;
     b->length = length;
     b->data = d;
-    n_blocks++;
+    memblock_count++;
+    memblock_total += length;
     return b;
 }
 
@@ -50,8 +53,11 @@ void memblock_unref(struct memblock*b) {
     if (b->ref == 0) {
         if (b->type == MEMBLOCK_DYNAMIC)
             free(b->data);
+
+        memblock_count--;
+        memblock_total -= b->length;
+
         free(b);
-        n_blocks--;
     }
 }
 
index 52f1fe5..cba1110 100644 (file)
@@ -29,6 +29,6 @@ void memblock_unref_fixed(struct memblock*b);
 
 #define memblock_assert_exclusive(b) assert((b)->ref == 1)
 
-extern unsigned n_blocks;
+extern unsigned memblock_count, memblock_total;
 
 #endif
index 9e9c109..10c59e5 100644 (file)
@@ -16,8 +16,8 @@ struct memblockq {
     struct memblock_list *blocks, *blocks_tail;
     unsigned n_blocks;
     size_t total_length, maxlength, base, prebuf;
-    int measure_latency;
-    uint32_t latency;
+    int measure_delay;
+    uint32_t delay;
 };
 
 struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf) {
@@ -38,8 +38,8 @@ struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf) {
     
     assert(bq->maxlength >= base);
 
-    bq->measure_latency = 1;
-    bq->latency = 0;
+    bq->measure_delay = 0;
+    bq->delay = 0;
     
     return bq;
 }
@@ -64,7 +64,7 @@ void memblockq_push(struct memblockq* bq, struct memchunk *chunk, size_t delta)
     q = malloc(sizeof(struct memblock_list));
     assert(q);
 
-    if (bq->measure_latency)
+    if (bq->measure_delay)
         gettimeofday(&q->stamp, NULL);
     else
         timerclear(&q->stamp);
@@ -152,8 +152,8 @@ void memblockq_drop(struct memblockq *bq, size_t length) {
         if (l > bq->blocks->chunk.length)
             l = bq->blocks->chunk.length;
 
-        if (bq->measure_latency)
-            bq->latency = age(&bq->blocks->stamp);
+        if (bq->measure_delay)
+            bq->delay = age(&bq->blocks->stamp);
         
         bq->blocks->chunk.index += l;
         bq->blocks->chunk.length -= l;
@@ -211,6 +211,12 @@ int memblockq_is_writable(struct memblockq *bq, size_t length) {
     return bq->total_length + length <= bq->maxlength;
 }
 
-uint32_t memblockq_get_latency(struct memblockq *bq) {
-    return bq->latency;
+uint32_t memblockq_get_delay(struct memblockq *bq) {
+    assert(bq);
+    return bq->delay;
+}
+
+uint32_t memblockq_get_length(struct memblockq *bq) {
+    assert(bq);
+    return bq->total_length;
 }
index 9543b40..0a68dda 100644 (file)
@@ -22,6 +22,7 @@ void memblockq_empty(struct memblockq *bq);
 int memblockq_is_readable(struct memblockq *bq);
 int memblockq_is_writable(struct memblockq *bq, size_t length);
 
-uint32_t memblockq_get_latency(struct memblockq *bq);
+uint32_t memblockq_get_delay(struct memblockq *bq);
+uint32_t memblockq_get_length(struct memblockq *bq);
 
 #endif
index 170d864..fab5c8c 100644 (file)
@@ -25,7 +25,7 @@ struct userdata {
 
     struct memchunk memchunk, silence;
 
-    uint32_t in_fragment_size, out_fragment_size, sample_size, sample_usec;
+    uint32_t in_fragment_size, out_fragment_size, sample_size;
 
     int fd;
 };
@@ -99,7 +99,7 @@ static void io_callback(struct iochannel *io, void*userdata) {
 static uint32_t sink_get_latency_cb(struct sink *s) {
     int arg;
     struct userdata *u = s->userdata;
-    assert(s && u);
+    assert(s && u && u->sink);
 
     if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) {
         fprintf(stderr, "module-oss: device doesn't support SNDCTL_DSP_GETODELAY.\n");
@@ -107,7 +107,7 @@ static uint32_t sink_get_latency_cb(struct sink *s) {
         return 0;
     }
 
-    return arg/u->sample_size*u->sample_usec;
+    return samples_usec(arg, &s->sample_spec);
 }
 
 int module_init(struct core *c, struct module*m) {
@@ -204,7 +204,6 @@ int module_init(struct core *c, struct module*m) {
     u->memchunk.memblock = NULL;
     u->memchunk.length = 0;
     u->sample_size = sample_size(&ss);
-    u->sample_usec = 1000000/ss.rate;
 
     u->out_fragment_size = out_frag_size;
     u->in_fragment_size = in_frag_size;
index 3563419..a0a996c 100644 (file)
@@ -56,7 +56,6 @@ static void destroy_connection(struct connection *c) {
 static int do_read(struct connection *c) {
     struct memchunk chunk;
     ssize_t r;
-    uint32_t u1, u2;
 
     if (!iochannel_is_readable(c->io))
         return 0;
@@ -81,12 +80,6 @@ static int do_read(struct connection *c) {
     memblockq_push(c->input_memblockq, &chunk, 0);
     memblock_unref(chunk.memblock);
     sink_notify(c->sink_input->sink);
-
-
-    u1 = memblockq_get_latency(c->input_memblockq);
-    u2 = sink_get_latency(c->sink_input->sink);
-
-    fprintf(stderr, "latency: %u+%u=%u\r", u1, u2, u1+u2);
     
     return 0;
 }
@@ -120,14 +113,13 @@ static int do_write(struct connection *c) {
 
 /*** sink_input callbacks ***/
 
-static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk, uint8_t *volume) {
+static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk) {
     struct connection*c = i->userdata;
-    assert(i && c && chunk && volume);
+    assert(i && c && chunk);
 
     if (memblockq_peek(c->input_memblockq, chunk) < 0)
         return -1;
 
-    *volume = 0xFF;
     return 0;
 }
 
@@ -146,6 +138,13 @@ static void sink_input_kill_cb(struct sink_input *i) {
     destroy_connection((struct connection *) i->userdata);
 }
 
+
+static uint32_t sink_input_get_latency_cb(struct sink_input *i) {
+    struct connection*c = i->userdata;
+    assert(i && c);
+    return samples_usec(memblockq_get_length(c->input_memblockq), &DEFAULT_SAMPLE_SPEC);
+}
+
 /*** source_output callbacks ***/
 
 static void source_output_push_cb(struct source_output *o, struct memchunk *chunk) {
@@ -163,7 +162,6 @@ static void source_output_kill_cb(struct source_output *o) {
     destroy_connection((struct connection *) o->userdata);
 }
 
-
 /*** client callbacks ***/
 
 static void client_kill_cb(struct client *c) {
@@ -234,6 +232,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us
         c->sink_input->peek = sink_input_peek_cb;
         c->sink_input->drop = sink_input_drop_cb;
         c->sink_input->kill = sink_input_kill_cb;
+        c->sink_input->get_latency = sink_input_get_latency_cb;
         c->sink_input->userdata = c;
 
         l = bytes_per_second(&DEFAULT_SAMPLE_SPEC)/2; /* half a second */
index 81fe699..c270f25 100644 (file)
@@ -113,3 +113,9 @@ size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, si
         data += sizeof(int16_t);
     }
 }
+
+uint32_t samples_usec(size_t length, struct sample_spec *spec) {
+    assert(spec);
+
+    return (uint32_t) (((double) length /sample_size(spec))/spec->rate*1000000);
+}
index 23fc088..5ed740e 100644 (file)
@@ -40,5 +40,6 @@ size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, si
 
 size_t bytes_per_second(struct sample_spec *spec);
 size_t sample_size(struct sample_spec *spec);
+uint32_t samples_usec(size_t length, struct sample_spec *spec);
 
 #endif
index 89f5e08..cd12b46 100644 (file)
@@ -81,9 +81,11 @@ static unsigned fill_mix_info(struct sink *s, struct mix_info *info, unsigned ma
 
     for (i = idxset_first(s->inputs, &index); maxinfo > 0 && i; i = idxset_next(s->inputs, &index)) {
         assert(i->peek);
-        if (i->peek(i, &info->chunk, &info->volume) < 0)
+        if (i->peek(i, &info->chunk) < 0)
             continue;
 
+        info->volume = i->volume;
+        
         assert(info->chunk.memblock && info->chunk.memblock->data && info->chunk.length);
         info->userdata = i;
         
index ae7b27f..f589b4d 100644 (file)
@@ -3,6 +3,7 @@
 #include <string.h>
 
 #include "sinkinput.h"
+#include "strbuf.h"
 
 struct sink_input* sink_input_new(struct sink *s, struct sample_spec *spec, const char *name) {
     struct sink_input *i;
@@ -18,6 +19,7 @@ struct sink_input* sink_input_new(struct sink *s, struct sample_spec *spec, cons
     i->peek = NULL;
     i->drop = NULL;
     i->kill = NULL;
+    i->get_latency = NULL;
     i->userdata = NULL;
 
     assert(s->core);
@@ -46,3 +48,40 @@ void sink_input_kill(struct sink_input*i) {
     if (i->kill)
         i->kill(i);
 }
+
+char *sink_input_list_to_string(struct core *c) {
+    struct strbuf *s;
+    struct sink_input *i;
+    uint32_t index = IDXSET_INVALID;
+    assert(c);
+
+    s = strbuf_new();
+    assert(s);
+
+    strbuf_printf(s, "%u sink input(s) available.\n", idxset_ncontents(c->sink_inputs));
+
+    for (i = idxset_first(c->sink_inputs, &index); i; i = idxset_next(c->sink_inputs, &index)) {
+        assert(i->sink);
+        strbuf_printf(s, "    index: %u, name: <%s>, sink: <%u>; volume: <0x%02x>, latency: <%u usec>\n",
+                      i->index,
+                      i->name,
+                      i->sink->index,
+                      (unsigned) i->volume,
+                      sink_input_get_latency(i));
+    }
+    
+    return strbuf_tostring_free(s);
+}
+
+uint32_t sink_input_get_latency(struct sink_input *i) {
+    uint32_t l = 0;
+    
+    assert(i);
+    if (i->get_latency)
+        l += i->get_latency(i);
+
+    assert(i->sink);
+    l += sink_get_latency(i->sink);
+
+    return l;
+}
index 5e71d21..f62070c 100644 (file)
@@ -13,10 +13,13 @@ struct sink_input {
     char *name;
     struct sink *sink;
     struct sample_spec spec;
+    uint8_t volume;
     
-    int (*peek) (struct sink_input *i, struct memchunk *chunk, uint8_t *volume);
+    int (*peek) (struct sink_input *i, struct memchunk *chunk);
     void (*drop) (struct sink_input *i, size_t length);
     void (*kill) (struct sink_input *i);
+    uint32_t (*get_latency) (struct sink_input *i);
+    
 
     void *userdata;
 };
@@ -28,5 +31,7 @@ void sink_input_free(struct sink_input* i);
  * request destruction of it */
 void sink_input_kill(struct sink_input *i);
 
+uint32_t sink_input_get_latency(struct sink_input *i);
+char *sink_input_list_to_string(struct core *c);
 
 #endif
index d4e7a50..8021b52 100644 (file)
@@ -3,6 +3,7 @@
 #include <string.h>
 
 #include "sourceoutput.h"
+#include "strbuf.h"
 
 struct source_output* source_output_new(struct source *s, struct sample_spec *spec, const char *name) {
     struct source_output *o;
@@ -45,3 +46,25 @@ void source_output_kill(struct source_output*i) {
     if (i->kill)
         i->kill(i);
 }
+
+char *source_output_list_to_string(struct core *c) {
+    struct strbuf *s;
+    struct source_output *o;
+    uint32_t index = IDXSET_INVALID;
+    assert(c);
+
+    s = strbuf_new();
+    assert(s);
+
+    strbuf_printf(s, "%u source outputs(s) available.\n", idxset_ncontents(c->source_outputs));
+
+    for (o = idxset_first(c->source_outputs, &index); o; o = idxset_next(c->source_outputs, &index)) {
+        assert(o->source);
+        strbuf_printf(s, "  %c index: %u, name: <%s>, source: <%u>\n",
+                      o->index,
+                      o->name,
+                      o->source->index);
+    }
+    
+    return strbuf_tostring_free(s);
+}
index fecfea3..359ff15 100644 (file)
@@ -25,4 +25,6 @@ void source_output_free(struct source_output* o);
 
 void source_output_kill(struct source_output*o);
 
+char *source_output_list_to_string(struct core *c);
+
 #endif