]> code.delx.au - pulseaudio/commitdiff
more work
authorLennart Poettering <lennart@poettering.net>
Tue, 15 Jun 2004 15:18:33 +0000 (15:18 +0000)
committerLennart Poettering <lennart@poettering.net>
Tue, 15 Jun 2004 15:18:33 +0000 (15:18 +0000)
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@17 fefdeb5f-60dc-0310-8127-8f9354f1896f

19 files changed:
src/client.c
src/core.c
src/main.c
src/memblock.c
src/memblock.h
src/memblockq.c
src/memblockq.h
src/module-oss.c
src/module.c
src/protocol-simple.c
src/sample.c
src/sample.h
src/sink.c
src/sink.h
src/sinkinput.c [moved from src/inputstream.c with 100% similarity]
src/sinkinput.h [moved from src/inputstream.h with 100% similarity]
src/source.c
src/sourceoutput.c [moved from src/outputstream.c with 100% similarity]
src/sourceoutput.h [moved from src/outputstream.h with 100% similarity]

index 3dd37668c441ec9d2e9bef47a26b7c012260b588..578d51c32539cabf536beff44f593760a9885c4f 100644 (file)
@@ -1,3 +1,4 @@
+#include <stdio.h>
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
@@ -19,6 +20,8 @@ struct client *client_new(struct core *core, const char *protocol_name, char *na
 
     r = idxset_put(core->clients, c, &c->index);
     assert(c->index != IDXSET_INVALID && r >= 0);
+
+    fprintf(stderr, "client: created %u \"%s\"\n", c->index, c->name);
     
     return c;
 }
@@ -27,6 +30,7 @@ void client_free(struct client *c) {
     assert(c && c->core);
 
     idxset_remove_by_data(c->core->clients, c, NULL);
+    fprintf(stderr, "client: freed %u \"%s\"\n", c->index, c->name);
     free(c->name);
     free(c);
 }
index 0457f4f3ef837f749ff47979a720ad81c82e0655..2e67118a9484a8d9f57a2bf14eb9cfd9d5c0717a 100644 (file)
@@ -60,7 +60,7 @@ struct sink* core_get_default_sink(struct core *c) {
     if (!(sink = idxset_first(c->sinks, &c->default_sink_index)))
         return NULL;
 
-    fprintf(stderr, "Default sink vanished, setting to %u\n", sink->index);
+    fprintf(stderr, "core: default sink vanished, setting to %u.\n", sink->index);
     return sink;
 }
 
@@ -74,6 +74,6 @@ struct source* core_get_default_source(struct core *c) {
     if (!(source = idxset_first(c->sources, &c->default_source_index)))
         return NULL;
 
-    fprintf(stderr, "Default source vanished, setting to %u\n", source->index);
+    fprintf(stderr, "core: default source vanished, setting to %u.\n", source->index);
     return source;
 }
index d54bee0a5437d91003e32c98f0d87780a7aea677..a42eaa828bf2f20f47695ebfe4e27d243d83076e 100644 (file)
@@ -3,6 +3,7 @@
 #include <stddef.h>
 #include <assert.h>
 #include <ltdl.h>
+#include <memblock.h>
 
 #include "core.h"
 #include "mainloop.h"
@@ -10,7 +11,7 @@
 
 static void signal_callback(struct mainloop_source *m, int sig, void *userdata) {
     mainloop_quit(mainloop_source_get_mainloop(m), -1);
-    fprintf(stderr, "Got signal.\n");
+    fprintf(stderr, "main: got signal.\n");
 }
 
 int main(int argc, char *argv[]) {
@@ -29,10 +30,17 @@ int main(int argc, char *argv[]) {
     mainloop_source_new_signal(m, SIGINT, signal_callback, NULL);
     signal(SIGPIPE, SIG_IGN);
 
-    module_load(c, "module-oss", NULL);
+    module_load(c, "module-oss", "/dev/dsp1");
     module_load(c, "module-pipe-sink", NULL);
     module_load(c, "module-simple-protocol-tcp", 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);
     
     core_free(c);
index 3bef4944f8ae22118dbb1c981bb2f9dcef9e2e3d..2d34676971b1bd4656a75ca3d9d52338020b851b 100644 (file)
@@ -1,15 +1,22 @@
+#include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
 #include <string.h>
+#include <sys/time.h>
+#include <time.h>
 
 #include "memblock.h"
 
+unsigned n_blocks = 0;
+
 struct memblock *memblock_new(size_t length) {
     struct memblock *b = malloc(sizeof(struct memblock)+length);
     b->type = MEMBLOCK_APPENDED;
     b->ref = 1;
     b->length = length;
     b->data = b+1;
+    n_blocks++;
+    timerclear(&b->stamp);
     return b;
 }
 
@@ -19,6 +26,8 @@ struct memblock *memblock_new_fixed(void *d, size_t length) {
     b->ref = 1;
     b->length = length;
     b->data = d;
+    n_blocks++;
+    timerclear(&b->stamp);
     return b;
 }
 
@@ -28,6 +37,8 @@ struct memblock *memblock_new_dynamic(void *d, size_t length) {
     b->ref = 1;
     b->length = length;
     b->data = d;
+    n_blocks++;
+    timerclear(&b->stamp);
     return b;
 }
 
@@ -45,6 +56,7 @@ void memblock_unref(struct memblock*b) {
         if (b->type == MEMBLOCK_DYNAMIC)
             free(b->data);
         free(b);
+        n_blocks--;
     }
 }
 
@@ -65,3 +77,29 @@ void memblock_unref_fixed(struct memblock *b) {
     b->type = MEMBLOCK_DYNAMIC;
 }
 
+void memblock_stamp(struct memblock*b) {
+    assert(b);
+    gettimeofday(&b->stamp, NULL);
+}
+
+uint32_t memblock_age(struct memblock*b) {
+    assert(b);
+    struct timeval tv;
+    uint32_t r;
+
+    if (b->stamp.tv_sec == 0)
+        return (suseconds_t) -1;
+
+    gettimeofday(&tv, NULL);
+
+    /*fprintf(stderr, "memblock: (%lu,%lu) -- (%lu,%lu)\r", b->stamp.tv_sec, b->stamp.tv_usec, tv.tv_sec, tv.tv_usec);*/
+    
+    r = (tv.tv_sec-b->stamp.tv_sec) * 1000000;
+
+    if (tv.tv_usec >= b->stamp.tv_usec)
+        r += tv.tv_usec - b->stamp.tv_usec;
+    else
+        r -= b->stamp.tv_usec - tv.tv_usec;
+
+    return r;
+}
index 48e87286d205565698b264e54c592ea960a07afe..c0fb6708ee029aa83fdc3e1c044ae98b5ef5d6fa 100644 (file)
@@ -2,6 +2,7 @@
 #define foomemblockhfoo
 
 #include <sys/types.h>
+#include <inttypes.h>
 
 enum memblock_type { MEMBLOCK_FIXED, MEMBLOCK_APPENDED, MEMBLOCK_DYNAMIC };
 
@@ -10,6 +11,7 @@ struct memblock {
     unsigned ref;
     size_t length;
     void *data;
+    struct timeval stamp;
 };
 
 struct memchunk {
@@ -26,6 +28,11 @@ struct memblock* memblock_ref(struct memblock*b);
 
 void memblock_unref_fixed(struct memblock*b);
 
+void memblock_stamp(struct memblock*b);
+uint32_t memblock_age(struct memblock*b);
+
 #define memblock_assert_exclusive(b) assert((b)->ref == 1)
 
+extern unsigned n_blocks;
+
 #endif
index b25adc65496a6e4371b9e4b0e1ec2132ba855eba..3c0d43267751d74b21deea7275ec712f86020d58 100644 (file)
@@ -18,6 +18,7 @@ struct memblockq {
     size_t prebuf;
 };
 
+
 struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf) {
     struct memblockq* bq;
     assert(maxlength && base);
@@ -35,6 +36,7 @@ struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf) {
         bq->prebuf = bq->maxlength;
     
     assert(bq->maxlength >= base);
+
     return bq;
 }
 
index 48050d49df1b944887957327687cafed993e4370..25c2f2d4041746c7a198a6727afb913eeb4aa18e 100644 (file)
@@ -22,4 +22,5 @@ void memblockq_empty(struct memblockq *bq);
 int memblockq_is_readable(struct memblockq *bq);
 int memblockq_is_writable(struct memblockq *bq, size_t length);
 
+
 #endif
index 7a1482e7f847e5a07c69015deaa42fbd998d1f6f..07a407d8e8574453c5ff61f67c18a611dd1ffdd3 100644 (file)
@@ -31,7 +31,7 @@ static void do_write(struct userdata *u) {
     ssize_t r;
     assert(u);
 
-    if (!iochannel_is_writable(u->io))
+    if (!u->sink || !iochannel_is_writable(u->io))
         return;
 
     if (!u->memchunk.length) {
@@ -66,7 +66,7 @@ static void do_read(struct userdata *u) {
     ssize_t r;
     assert(u);
     
-    if (!iochannel_is_readable(u->io))
+    if (!u->source || !iochannel_is_readable(u->io))
         return;
 
     memchunk.memblock = memblock_new(u->in_fragment_size);
@@ -103,7 +103,7 @@ int module_init(struct core *c, struct module*m) {
     assert(c && m);
 
     p = m->argument ? m->argument : "/dev/dsp";
-    if ((fd = open(p, mode = O_RDWR)) >= 0) {
+    if ((fd = open(p, (mode = O_RDWR)|O_NDELAY)) >= 0) {
         int caps;
 
         ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
@@ -120,15 +120,17 @@ int module_init(struct core *c, struct module*m) {
     }
 
     if (fd < 0) {
-        if ((fd = open(p, mode = O_WRONLY)) < 0) {
-            if ((fd = open(p, mode = O_RDONLY)) < 0) {
+        if ((fd = open(p, (mode = O_WRONLY)|O_NDELAY)) < 0) {
+            if ((fd = open(p, (mode = O_RDONLY)|O_NDELAY)) < 0) {
                 fprintf(stderr, "open('%s'): %s\n", p, strerror(errno));
                 goto fail;
             }
         }
     }
+
+    fprintf(stderr, "module-oss: device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR"));
     
-    frag_size = ((int) 0x7ffff << 4) | 10; /* nfrags = 4; frag_size = 2^10 */
+    frag_size = ((int) 4 << 16) | 10; /* nfrags = 4; frag_size = 2^10 */
     if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag_size) < 0) {
         fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT: %s\n", strerror(errno));
         goto fail;
@@ -174,12 +176,12 @@ int module_init(struct core *c, struct module*m) {
     in_frag_size = out_frag_size = frag_size;
 
     if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) {
-        fprintf(stderr, "INPUT: %u fragments of size %u.\n", info.fragstotal, info.fragsize);
+        fprintf(stderr, "module-oss: input -- %u fragments of size %u.\n", info.fragstotal, info.fragsize);
         in_frag_size = info.fragsize;
     }
 
     if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) {
-        fprintf(stderr, "OUTUT: %u fragments of size %u.\n", info.fragstotal, info.fragsize);
+        fprintf(stderr, "module-oss: output -- %u fragments of size %u.\n", info.fragstotal, info.fragsize);
         out_frag_size = info.fragsize;
     }
 
@@ -239,9 +241,11 @@ void module_done(struct core *c, struct module*m) {
         memblock_unref(u->memchunk.memblock);
     if (u->silence.memblock)
         memblock_unref(u->silence.memblock);
-        
-    sink_free(u->sink);
-    source_free(u->source);
+
+    if (u->sink)
+        sink_free(u->sink);
+    if (u->source)
+        source_free(u->source);
     iochannel_free(u->io);
     free(u);
 }
index 62204e4c27b01cc128dfa8b19ca0c768031f72c0..7f2bc218e4cb42217661a41de592fea0f4ca5d6e 100644 (file)
@@ -40,6 +40,9 @@ struct module* module_load(struct core *c, const char *name, const char *argumen
     assert(c->modules);
     r = idxset_put(c->modules, m, &m->index);
     assert(r >= 0 && m->index != IDXSET_INVALID);
+
+    fprintf(stderr, "module: loaded %u \"%s\" with argument \"%s\".\n", m->index, m->name, m->argument);
+    
     return m;
     
 fail:
@@ -61,6 +64,9 @@ static void module_free(struct module *m) {
     m->done(m->core, m);
 
     lt_dlclose(m->dl);
+    
+    fprintf(stderr, "module: unloaded %u \"%s\".\n", m->index, m->name);
+
     free(m->name);
     free(m->argument);
     free(m);
index 1c462b397bed2639dffdcd1a914b4e7536609abd..d34a5d021182f503fd1a1a16c8137e3484ed9edc 100644 (file)
@@ -78,13 +78,15 @@ static int do_read(struct connection *c) {
     
     chunk.memblock = memblock_new(BUFSIZE);
     assert(chunk.memblock);
+
+    memblock_stamp(chunk.memblock);
     
     if ((r = iochannel_read(c->io, chunk.memblock->data, BUFSIZE)) <= 0) {
         fprintf(stderr, "read(): %s\n", r == 0 ? "EOF" : strerror(errno));
         memblock_unref(chunk.memblock);
         return -1;
     }
-    
+
     chunk.memblock->length = r;
     chunk.length = r;
     chunk.index = 0;
index 2e46eac768d35b053bb9795b65ae02d63145ed30..6a00022822bf9dff09e0a351133a50366934d4aa 100644 (file)
@@ -33,24 +33,6 @@ struct memblock *silence(struct memblock* b, struct sample_spec *spec) {
     return b;
 }
 
-void add_clip(struct memchunk *target, struct memchunk *chunk, struct sample_spec *spec) {
-    int16_t *p, *d;
-    size_t i;
-    assert(target && target->memblock && chunk && chunk->memblock && spec);
-    assert(spec->format == SAMPLE_S16NE);
-    assert((target->length & 1) == 0);
-    
-    d = target->memblock->data + target->index;
-    p = chunk->memblock->data + chunk->index;
-
-    for (i = 0; i < target->length && i < chunk->length; i++) {
-        int32_t r = (int32_t) *d + (int32_t) *p;
-        if (r < -0x8000) r = 0x8000;
-        if (r > 0x7FFF) r = 0x7FFF;
-        *d = (int16_t) r;
-    }
-}
-
 size_t sample_size(struct sample_spec *spec) {
     assert(spec);
     size_t b = 1;
@@ -78,3 +60,38 @@ size_t bytes_per_second(struct sample_spec *spec) {
     return spec->rate*sample_size(spec);
 }
 
+size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct sample_spec *spec) {
+    unsigned c, d;
+    assert(chunks && target && spec);
+    assert(spec->format == SAMPLE_S16NE);
+
+    for (d = 0;; d += sizeof(int16_t)) {
+        int32_t sum = 0;
+
+        if (d >= length)
+            return d;
+        
+        for (c = 0; c < nchannels; c++) {
+            int32_t v;
+            uint8_t volume = channels[c].volume;
+            
+            if (d >= channels[c].chunk.length)
+                return d;
+
+            if (volume == 0)
+                v = 0;
+            else {
+                v = *((int16_t*) (channels[c].chunk->memblock->data + channels[c].chunk->index + d));
+
+                if (volume != 0xFF)
+                    v = v*volume/0xFF;
+            }
+
+            sum += v;
+        }
+
+        if (sum < -0x8000) sum = -0x8000;
+        if (sum > 0x7FFF) sum = 0x7FFF;
+        *(data++) = sum;
+    }
+}
index ecbe33f28dad0702c49e72df0cef4faa7006abe7..651788bae5a1dd59e0373202ce0c6be19560ba34 100644 (file)
@@ -27,7 +27,15 @@ struct sample_spec {
 extern struct sample_spec default_sample_spec;
 
 struct memblock *silence(struct memblock* b, struct sample_spec *spec);
-void add_clip(struct memchunk *target, struct memchunk *chunk, struct sample_spec *spec);
+
+
+struct mix_info {
+    struct memchunk chunk;
+    uint8_t volume;
+    void *userdata;
+};
+
+size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct sample_spec *spec) {
 
 size_t bytes_per_second(struct sample_spec *spec);
 size_t sample_size(struct sample_spec *spec);
index f2d5373d970b0f53946b99ade8b59ef49a6b64de..82cde8f293bbdcb2ddb8abc21d867bd82813ae84 100644 (file)
@@ -21,7 +21,7 @@ struct sink* sink_new(struct core *core, const char *name, const struct sample_s
 
     s->core = core;
     s->sample_spec = *spec;
-    s->input_streams = idxset_new(NULL, NULL);
+    s->inputs = idxset_new(NULL, NULL);
 
     if (name) {
         n = malloc(strlen(name)+9);
@@ -36,198 +36,153 @@ struct sink* sink_new(struct core *core, const char *name, const struct sample_s
     s->notify = NULL;
     s->notify_userdata = NULL;
 
+    fprintf(stderr, "sink: created %u \"%s\".\n", s->index, s->name);
+    
     return s;
 }
 
 void sink_free(struct sink *s) {
-    struct input_stream *i, *j = NULL;
+    struct sink_input *i, *j = NULL;
     assert(s);
 
-    while ((i = idxset_first(s->input_streams, NULL))) {
-        assert(i != j);
-        input_stream_kill(i);
+    while ((i = idxset_first(s->inputs, NULL))) {
+        assert(i != j && i->kill);
+        i->kill(i);
         j = i;
     }
-    idxset_free(s->input_streams, NULL, NULL);
+
+    idxset_free(s->inputs, NULL, NULL);
         
     idxset_remove_by_data(s->core->sinks, s, NULL);
     source_free(s->monitor_source);
 
+    fprintf(stderr, "sink: freed %u \"%s\"\n", s->index, s->name);
+    
     free(s->name);
     free(s);
 }
 
-struct pass1_info {
-    size_t maxlength;
-    unsigned count;
-    struct input_stream *last_input_stream;
-};
-
-static int get_max_length(void *p, uint32_t index, int *del, void*userdata) {
-    struct memchunk chunk;
-    struct pass1_info *info = userdata;
-    struct input_stream*i = p;
-    assert(info && i);
-
-    if (memblockq_peek(i->memblockq, &chunk) != 0)
-        return 0;
-
-    assert(chunk.length);
-    
-    if (info->maxlength > chunk.length)
-        info->maxlength = chunk.length;
-
-    info->count++;
-    info->last_input_stream = i;
-
-    memblock_unref(chunk.memblock);
+void sink_notify(struct sink*s) {
+    assert(s);
 
-    return 0;
+    if (s->notify)
+        s->notify(s, s->notify_userdata);
 }
 
-struct pass2_info {
-    struct memchunk *chunk;
-    struct sample_spec *spec;
-};
-
-static int do_mix(void *p, uint32_t index, int *del, void*userdata) {
-    struct memchunk chunk;
-    struct pass2_info *info = userdata;
-    struct input_stream*i = p;
-    assert(info && info->chunk && info->chunk->memblock && i && info->spec);
-    
-    if (memblockq_peek(i->memblockq, &chunk) != 0)
-        return 0;
-
-    memblock_assert_exclusive(info->chunk->memblock);
-    assert(chunk.length && chunk.length <= info->chunk->memblock->length - info->chunk->index);
-
-    add_clip(info->chunk, &chunk, info->spec);
-    memblock_unref(chunk.memblock);
-    memblockq_drop(i->memblockq, info->chunk->length);
+void sink_set_notify_callback(struct sink *s, void (*notify_callback)(struct sink*sink, void *userdata), void *userdata) {
+    assert(s && notify_callback);
 
-    input_stream_notify(i);
-    return 0;
+    s->notify = notify_callback;
+    s->notify_userdata = userdata;
 }
 
-int sink_render_into(struct sink*s, struct memblock *target, struct memchunk *result) {
-    struct pass1_info pass1_info;
-    struct pass2_info pass2_info;
-    assert(s && target && result);
-    memblock_assert_exclusive(target);
-
-    /* Calculate how many bytes to mix */
-    pass1_info.maxlength = target->length;
-    pass1_info.count = 0;
-    
-    idxset_foreach(s->input_streams, get_max_length, &pass1_info);
-    assert(pass1_info.maxlength);
-
-    /* No data to mix */
-    if (pass1_info.count == 0)
-        return -1;
+static unsigned fill_mix_info(struct sink *s, struct mix_info *info, unsigned maxinfo) {
+    uint32_t index = IDXSET_ANY;
+    struct sink_input *i;
+    unsigned n;
     
-    /* A shortcut if only a single input stream is connected */
-    if (pass1_info.count == 1) {
-        struct input_stream *i = pass1_info.last_input_stream;
-        struct memchunk chunk;
-        size_t l;
-
-        assert(i);
-        
-        if (memblockq_peek(i->memblockq, &chunk) != 0)
-            return -1;
+    assert(s && info);
 
-        l = target->length < chunk.length ? target->length : chunk.length;
-        memcpy(target->data, result->memblock+result->index, l);
-        target->length = l;
-        memblock_unref(chunk.memblock);
-        memblockq_drop(i->memblockq, l);
+    while (maxinfo > 0 && i = idxset_rrobin(s->inputs, &index)) {
+        assert(i->peek);
+        if (i->peek(i, &info->chunk, &info->volume) < 0)
+            continue;
 
-        input_stream_notify(i);
+        assert(info->chunk.memblock && info->chunk.memblock->data && info->chunk.length);
+        info->userdata = i;
         
-        result->memblock = target;
-        result->length = l;
-        result->index = 0;
-        return 0;
+        info++;
+        maxinfo--;
+        n++;
     }
 
-    /* Do the real mixing */
-    result->memblock = silence(target, &s->sample_spec);
-    result->index = 0;
-    result->length = pass1_info.maxlength;
-    pass2_info.chunk = result;
-    pass2_info.spec = &s->sample_spec;
-    idxset_foreach(s->input_streams, do_mix, &pass2_info);
+    return n;
+}
 
-    assert(s->monitor_source);
-    source_post(s->monitor_source, result);
+static void inputs_drop(struct sink *s, struct mix_info *info, unsigned maxinfo, size_t length) {
+    assert(s && info);
     
-    return 0;
+    for (; maxinfo > 0; maxinfo--, info++) {
+        struct sink_input *i = info->userdata;
+        assert(i && info->chunk.memblock);
+        
+        memblock_unref(info->chunk.memblock);
+        assert(i->drop);
+        i->drop(i, length);
+    }
 }
 
 int sink_render(struct sink*s, size_t length, struct memchunk *result) {
-    struct pass1_info pass1_info;
-    struct pass2_info pass2_info;
-    assert(s && result);
-
-    if (!length)
-        length = (size_t) -1;
+    struct mix_info info[MAX_MIX_CHANNELS];
+    unsigned n;
+    size_t l;
+    assert(s && length && result);
     
-    /* Calculate how many bytes to mix */
-    pass1_info.maxlength = length;
-    pass1_info.count = 0;
-    
-    idxset_foreach(s->input_streams, get_max_length, &pass1_info);
-    assert(pass1_info.maxlength);
+    n = fill_mix_info(s, info, MAX_MIX_CHANNELS);
 
-    /* No data to mix */
-    if (pass1_info.count == 0)
+    if (n <= 0)
         return -1;
 
-    if (pass1_info.count == 1) {
-        struct input_stream *i = pass1_info.last_input_stream;
-        size_t l;
+    if (n == 1) {
+        struct sink_info *i = info[0].userdata;
+        assert(i && b);
+        *result = info[0].chunk;
+        memblock_ref(result->memblock);
 
-        assert(i);
+        if (result->length > length)
+            result->length = length;
 
-        if (memblockq_peek(i->memblockq, result) != 0)
-            return -1;
+        l = result->length;
+    } else {
+        result->memblock = memblock_new(length);
+        assert(result->memblock);
 
-        l = length < result->length ? length : result->length;
-        result->length = l;
-        memblockq_drop(i->memblockq, l);
-        input_stream_notify(i);
+        result->length = l = mix_chunks(info, n, result->memblock->data, length, &s->sample_spec);
+        result->index = 0;
         
-        return 0;
+        assert(l);
     }
 
-    /* Do the mixing */
-    result->memblock = silence(memblock_new(result->length), &s->sample_spec);
-    result->index = 0;
-    result->length = pass1_info.maxlength;
-    pass2_info.chunk = result;
-    pass2_info.spec = &s->sample_spec;
-    idxset_foreach(s->input_streams, do_mix, &pass2_info);
-
-    assert(s->monitor_source);
-
-    source_post(s->monitor_source, result);
+    inputs_drop(s, info, n, l);
     return 0;
 }
 
-void sink_notify(struct sink*s) {
-    assert(s);
+int sink_render_into(struct sink*s, struct memblock *target, struct memchunk *result) {
+    struct mix_info info[MAX_MIX_CHANNELS];
+    unsigned n;
+    size_t l;
+    assert(s && target && target->length && target->data && result);
+    
+    n = fill_mix_info(s, info, MAX_MIX_CHANNELS);
 
-    if (s->notify)
-        s->notify(s, s->notify_userdata);
-}
+    if (n <= 0)
+        return -1;
 
-void sink_set_notify_callback(struct sink *s, void (*notify_callback)(struct sink*sink, void *userdata), void *userdata) {
-    assert(s && notify_callback);
+    if (n == 1) {
+        struct sink_info *i = info[0].userdata;
+        assert(i && b);
 
-    s->notify = notify_callback;
-    s->notify_userdata = userdata;
-}
+        l = target->length;
+        if (l > info[0].chunk.length)
+            l = info[0].chunk.length;
+        
+        result->memblock = target;
+        memcpy(target->data, info[0].chunk.memblock->data + info[0].chunk.index, l);
+        result->length = target->length = l;
+        result->index = 0;
 
+        if (result->length > length)
+            result->length = length;
 
+        l = result->length;
+    } else {
+
+        result->memblock = target;
+        result->length = l = mix_chunks(info, n, target->data, target->length, &s->sample_spec);
+        result->index = 0;
+        assert(l);
+    }
+
+    inputs_drop(s, info, n, l);
+    return 0;
+}
index 1678fc75ee61fac2b74200ecabcb1b2d6eb92ee4..bd43d49de757a8650b4e70828e304991be854088 100644 (file)
@@ -10,13 +10,24 @@ struct sink;
 #include "idxset.h"
 #include "source.h"
 
+
+struct sink_input {
+    int (*peek) (struct sink_input *i, struct memchunk *chunk, uint8_t *volume);
+    void (*drop) (struct sink_input *i, size_t length);
+    void (*kill) (struct sink_input *i);
+
+    void *userdata;
+    int index;
+    struct sink *sink;
+};
+
 struct sink {
     char *name;
     uint32_t index;
     
     struct core *core;
     struct sample_spec sample_spec;
-    struct idxset *input_streams;
+    struct idxset *inputs;
 
     struct source *monitor_source;
 
similarity index 100%
rename from src/inputstream.c
rename to src/sinkinput.c
similarity index 100%
rename from src/inputstream.h
rename to src/sinkinput.h
index 2d5e9bbde11b0a537ac4683edf84ea50faa59d8d..a7fc9a64f22970bc7edf9dd34eac8a3e73b69e4b 100644 (file)
@@ -1,3 +1,4 @@
+#include <stdio.h>
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
@@ -24,6 +25,8 @@ struct source* source_new(struct core *core, const char *name, const struct samp
     s->link_change_callback = NULL;
     s->userdata = NULL;
 
+    fprintf(stderr, "source: created %u \"%s\"\n", s->index, s->name);
+    
     return s;
 }
 
@@ -40,6 +43,8 @@ void source_free(struct source *s) {
     
     idxset_remove_by_data(s->core->sources, s, NULL);
 
+    fprintf(stderr, "source: freed %u \"%s\"\n", s->index, s->name);
+
     free(s->name);
     free(s);
 }
similarity index 100%
rename from src/outputstream.c
rename to src/sourceoutput.c
similarity index 100%
rename from src/outputstream.h
rename to src/sourceoutput.h