]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/sink.c
get rid of svn $ keywords
[pulseaudio] / src / pulsecore / sink.c
index 31c3cfc8fa8cb7dc74dda165388bd3b1ec9e2c4c..7b6bb1b5303254cbd108f25a1f4836769ba5a410 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id$ */
-
 /***
   This file is part of PulseAudio.
 
@@ -248,6 +246,9 @@ pa_sink* pa_sink_new(
         return NULL;
     }
 
+    s->monitor_source->min_latency = s->min_latency;
+    s->monitor_source->max_latency = s->max_latency;
+
     s->monitor_source->monitor_of = s;
     pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
 
@@ -495,24 +496,25 @@ static unsigned fill_mix_info(pa_sink *s, size_t *length, pa_mix_info *info, uns
     return n;
 }
 
-static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, size_t length) {
+static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, pa_memchunk *result) {
     pa_sink_input *i;
     void *state = NULL;
     unsigned p = 0;
     unsigned n_unreffed = 0;
 
     pa_sink_assert_ref(s);
+    pa_assert(result);
+    pa_assert(result->memblock);
+    pa_assert(result->length > 0);
 
     /* We optimize for the case where the order of the inputs has not changed */
 
     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
         unsigned j;
-        pa_mix_info* m;
+        pa_mix_info* m = NULL;
 
         pa_sink_input_assert_ref(i);
 
-        m = NULL;
-
         /* Let's try to find the matching entry info the pa_mix_info array */
         for (j = 0; j < n; j ++) {
 
@@ -527,14 +529,47 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, size_t length
         }
 
         /* Drop read data */
-        pa_sink_input_drop(i, length);
+        pa_sink_input_drop(i, result->length);
+
+        if (s->monitor_source && PA_SOURCE_IS_OPENED(pa_source_get_state(s->monitor_source))) {
+
+            if (pa_hashmap_size(i->thread_info.direct_outputs) > 0) {
+                void *ostate = NULL;
+                pa_source_output *o;
+                pa_memchunk c;
+
+                if (m && m->chunk.memblock) {
+                    c = m->chunk;
+                    pa_memblock_ref(c.memblock);
+                    pa_assert(result->length <= c.length);
+                    c.length = result->length;
+
+                    pa_memchunk_make_writable(&c, 0);
+                    pa_volume_memchunk(&c, &s->sample_spec, &m->volume);
+                } else {
+                    c = s->silence;
+                    pa_memblock_ref(c.memblock);
+                    pa_assert(result->length <= c.length);
+                    c.length = result->length;
+                }
+
+                while ((o = pa_hashmap_iterate(i->thread_info.direct_outputs, &ostate, NULL))) {
+                    pa_source_output_assert_ref(o);
+                    pa_assert(o->direct_on_input == i);
+                    pa_source_post_direct(s->monitor_source, o, &c);
+                }
+
+                pa_memblock_unref(c.memblock);
+            }
+        }
 
         if (m) {
-            pa_sink_input_unref(m->userdata);
-            m->userdata = NULL;
             if (m->chunk.memblock)
                 pa_memblock_unref(m->chunk.memblock);
-            pa_memchunk_reset(&m->chunk);
+                pa_memchunk_reset(&m->chunk);
+
+            pa_sink_input_unref(m->userdata);
+            m->userdata = NULL;
 
             n_unreffed += 1;
         }
@@ -551,6 +586,9 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, size_t length
                 pa_memblock_unref(info->chunk.memblock);
         }
     }
+
+    if (s->monitor_source && PA_SOURCE_IS_OPENED(pa_source_get_state(s->monitor_source)))
+        pa_source_post(s->monitor_source, result);
 }
 
 void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
@@ -621,10 +659,7 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
     }
 
     if (s->thread_info.state == PA_SINK_RUNNING)
-        inputs_drop(s, info, n, result->length);
-
-    if (s->monitor_source && PA_SOURCE_IS_OPENED(pa_source_get_state(s->monitor_source)))
-        pa_source_post(s->monitor_source, result);
+        inputs_drop(s, info, n, result);
 
     pa_sink_unref(s);
 }
@@ -650,6 +685,8 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
     if (length > block_size_max)
         length = pa_frame_align(block_size_max, &s->sample_spec);
 
+    pa_assert(length > 0);
+
     n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, &length, info, MAX_MIX_CHANNELS) : 0;
 
     if (n == 0) {
@@ -673,8 +710,8 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
             vchunk = info[0].chunk;
             pa_memblock_ref(vchunk.memblock);
 
-            if (vchunk.length > target->length)
-                vchunk.length = target->length;
+            if (vchunk.length > length)
+                vchunk.length = length;
 
             if (!pa_cvolume_is_norm(&volume)) {
                 pa_memchunk_make_writable(&vchunk, 0);
@@ -700,10 +737,7 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
     }
 
     if (s->thread_info.state == PA_SINK_RUNNING)
-        inputs_drop(s, info, n, target->length);
-
-    if (s->monitor_source && PA_SOURCE_IS_OPENED(pa_source_get_state(s->monitor_source)))
-        pa_source_post(s->monitor_source, target);
+        inputs_drop(s, info, n, target);
 
     pa_sink_unref(s);
 }
@@ -1228,6 +1262,7 @@ pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
     pa_usec_t result = (pa_usec_t) -1;
     pa_sink_input *i;
     void *state = NULL;
+    pa_usec_t monitor_latency;
 
     pa_sink_assert_ref(s);
 
@@ -1240,6 +1275,12 @@ pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
             (result == (pa_usec_t) -1 || result > i->thread_info.requested_sink_latency))
             result = i->thread_info.requested_sink_latency;
 
+    monitor_latency = pa_source_get_requested_latency_within_thread(s->monitor_source);
+
+    if (monitor_latency != (pa_usec_t) -1 &&
+        (result == (pa_usec_t) -1 || result > monitor_latency))
+        result = monitor_latency;
+
     if (result != (pa_usec_t) -1) {
         if (s->max_latency > 0 && result > s->max_latency)
             result = s->max_latency;
@@ -1293,10 +1334,33 @@ void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
 void pa_sink_invalidate_requested_latency(pa_sink *s) {
 
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
 
     s->thread_info.requested_latency_valid = FALSE;
 
     if (s->update_requested_latency)
         s->update_requested_latency(s);
 }
+
+void pa_sink_set_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
+    pa_sink_assert_ref(s);
+
+    /* min_latency == 0:           no limit
+     * min_latency == (size_t) -1: default limit
+     * min_latency anything else:  specified limit
+     *
+     * Similar for max_latency */
+
+    if (min_latency == (pa_usec_t) -1)
+        min_latency = DEFAULT_MIN_LATENCY;
+
+    if (max_latency == (pa_usec_t) -1)
+        max_latency = min_latency;
+
+    pa_assert(!min_latency || !max_latency ||
+              min_latency <= max_latency);
+
+    s->min_latency = min_latency;
+    s->max_latency = max_latency;
+
+    pa_source_set_latency_range(s->monitor_source, min_latency, max_latency);
+}