]> code.delx.au - pulseaudio/blobdiff - src/sink.c
some more work
[pulseaudio] / src / sink.c
index 951191dd48bf660949878adbf06f7402d44e4644..cd12b463fa32ba85fb38be48f0f1efacaa52fc83 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "sink.h"
 #include "sinkinput.h"
+#include "strbuf.h"
 
 #define MAX_MIX_CHANNELS 32
 
@@ -33,6 +34,7 @@ struct sink* sink_new(struct core *core, const char *name, const struct sample_s
     s->volume = 0xFF;
 
     s->notify = NULL;
+    s->get_latency = NULL;
     s->userdata = NULL;
 
     r = idxset_put(core->sinks, s, &s->index);
@@ -79,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;
         
@@ -138,14 +142,18 @@ int sink_render(struct sink*s, size_t length, struct memchunk *result) {
     }
 
     inputs_drop(s, info, n, l);
+
+    assert(s->monitor_source);
+    source_post(s->monitor_source, result);
+
     return 0;
 }
 
-int sink_render_into(struct sink*s, struct memblock *target, struct memchunk *result) {
+int sink_render_into(struct sink*s, struct memchunk *target) {
     struct mix_info info[MAX_MIX_CHANNELS];
     unsigned n;
     size_t l;
-    assert(s && target && target->length && target->data && result);
+    assert(s && target && target->length && target->memblock && target->memblock->data);
     
     n = fill_mix_info(s, info, MAX_MIX_CHANNELS);
 
@@ -160,18 +168,87 @@ int sink_render_into(struct sink*s, struct memblock *target, struct memchunk *re
         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;
-    } else {
+        memcpy(target->memblock->data+target->index, info[0].chunk.memblock->data + info[0].chunk.index, l);
+        target->length = l;
+    } else
+        target->length = l = mix_chunks(info, n, target->memblock->data+target->index, target->length, &s->sample_spec, s->volume);
+    
+    assert(l);
+    inputs_drop(s, info, n, l);
 
-        result->memblock = target;
-        result->length = l = mix_chunks(info, n, target->data, target->length, &s->sample_spec, s->volume);
-        result->index = 0;
-        assert(l);
-    }
+    assert(s->monitor_source);
+    source_post(s->monitor_source, target);
 
-    inputs_drop(s, info, n, l);
     return 0;
 }
+
+void sink_render_into_full(struct sink *s, struct memchunk *target) {
+    struct memchunk chunk;
+    size_t l, d;
+    assert(s && target && target->memblock && target->length && target->memblock->data);
+
+    l = target->length;
+    d = 0;
+    while (l > 0) {
+        chunk = *target;
+        chunk.index += d;
+        chunk.length -= d;
+        
+        if (sink_render_into(s, &chunk) < 0)
+            break;
+
+        d += chunk.length;
+        l -= chunk.length;
+    }
+
+    if (l > 0) {
+        chunk = *target;
+        chunk.index += d;
+        chunk.length -= d;
+        silence_memchunk(&chunk, &s->sample_spec);
+    }
+}
+
+uint32_t sink_get_latency(struct sink *s) {
+    assert(s);
+
+    if (!s->get_latency)
+        return 0;
+
+    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);
+}