[pulseaudio-commits] r1649 - in /branches/lennart/src/pulsecore: sink-input.c sink-input.h sink.c sink.h

svnmailer-noreply at 0pointer.de svnmailer-noreply at 0pointer.de
Sat Aug 11 16:46:52 PDT 2007


Author: lennart
Date: Sun Aug 12 01:46:51 2007
New Revision: 1649

URL: http://0pointer.de/cgi-bin/viewcvs.cgi?rev=3D1649&root=3Dpulseaudio&vi=
ew=3Drev
Log:
Resurrect ability to move streams between sinks

Modified:
    branches/lennart/src/pulsecore/sink-input.c
    branches/lennart/src/pulsecore/sink-input.h
    branches/lennart/src/pulsecore/sink.c
    branches/lennart/src/pulsecore/sink.h

Modified: branches/lennart/src/pulsecore/sink-input.c
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/lennart/src/pulsecore/=
sink-input.c?rev=3D1649&root=3Dpulseaudio&r1=3D1648&r2=3D1649&view=3Ddiff
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
--- branches/lennart/src/pulsecore/sink-input.c (original)
+++ branches/lennart/src/pulsecore/sink-input.c Sun Aug 12 01:46:51 2007
@@ -202,7 +202,7 @@
     pa_atomic_store(&i->thread_info.drained, 1);
     i->thread_info.sample_spec =3D i->sample_spec;
     i->thread_info.silence_memblock =3D NULL;
-/*     i->thread_info.move_silence =3D 0; */
+    i->thread_info.move_silence =3D 0; =

     pa_memchunk_reset(&i->thread_info.resampled_chunk);
     i->thread_info.resampler =3D resampler;
     i->thread_info.volume =3D i->volume;
@@ -336,6 +336,7 @@
     return r;
 }
 =

+/* Called from thread context */
 int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *v=
olume) {
     int ret =3D -1;
     int do_volume_adj_here;
@@ -350,24 +351,24 @@
 =

     pa_assert(i->thread_info.state =3D=3D PA_SINK_INPUT_RUNNING || i->thre=
ad_info.state =3D=3D PA_SINK_INPUT_DRAINED);
 =

-/*     if (i->thread_info.move_silence > 0) { */
-/*         size_t l; */
-
-/*         /\* We have just been moved and shall play some silence for a */
-/*          * while until the old sink has drained its playback buffer *\/=
 */
-
-/*         if (!i->thread_info.silence_memblock) */
-/*             i->thread_info.silence_memblock =3D pa_silence_memblock_new=
(i->sink->core->mempool, &i->sink->sample_spec, SILENCE_BUFFER_LENGTH); */
-
-/*         chunk->memblock =3D pa_memblock_ref(i->thread_info.silence_memb=
lock); */
-/*         chunk->index =3D 0; */
-/*         l =3D pa_memblock_get_length(chunk->memblock); */
-/*         chunk->length =3D i->move_silence < l ? i->move_silence : l; */
-
-/*         ret =3D 0; */
-/*         do_volume_adj_here =3D 1; */
-/*         goto finish; */
-/*     } */
+    if (i->thread_info.move_silence > 0) {
+        size_t l;
+
+        /* We have just been moved and shall play some silence for a
+         * while until the old sink has drained its playback buffer */
+
+        if (!i->thread_info.silence_memblock)
+            i->thread_info.silence_memblock =3D pa_silence_memblock_new(i-=
>sink->core->mempool, &i->sink->sample_spec, SILENCE_BUFFER_LENGTH);
+
+        chunk->memblock =3D pa_memblock_ref(i->thread_info.silence_membloc=
k);
+        chunk->index =3D 0;
+        l =3D pa_memblock_get_length(chunk->memblock);
+        chunk->length =3D i->thread_info.move_silence < l ? i->thread_info=
.move_silence : l;
+
+        ret =3D 0;
+        do_volume_adj_here =3D 1;
+        goto finish;
+    }
 =

     if (!i->thread_info.resampler) {
         do_volume_adj_here =3D 0; /* FIXME??? */
@@ -437,36 +438,25 @@
     return ret;
 }
 =

+/* Called from thread context */
 void pa_sink_input_drop(pa_sink_input *i, size_t length) {
     pa_sink_input_assert_ref(i);
     pa_assert(length > 0);
 =

-/*     if (i->move_silence > 0) { */
-
-/*         if (chunk) { */
-/*             size_t l; */
-
-/*             l =3D pa_memblock_get_length(i->silence_memblock); */
-
-/*             if (chunk->memblock !=3D i->silence_memblock || */
-/*                 chunk->index !=3D 0 || */
-/*                 (chunk->memblock && (chunk->length !=3D (l < i->move_si=
lence ? l : i->move_silence)))) */
-/*                 return; */
-
-/*         } */
-
-/*         pa_assert(i->move_silence >=3D length); */
-
-/*         i->move_silence -=3D length; */
-
-/*         if (i->move_silence <=3D 0) { */
-/*             pa_assert(i->silence_memblock); */
-/*             pa_memblock_unref(i->silence_memblock); */
-/*             i->silence_memblock =3D NULL; */
-/*         } */
-
-/*         return; */
-/*     } */
+    if (i->thread_info.move_silence > 0) {
+
+        pa_assert(i->thread_info.move_silence >=3D length);
+
+        i->thread_info.move_silence -=3D length;
+
+        if (i->thread_info.move_silence <=3D 0) {
+            pa_assert(i->thread_info.silence_memblock);
+            pa_memblock_unref(i->thread_info.silence_memblock);
+            i->thread_info.silence_memblock =3D NULL;
+        }
+
+        return;
+    }
 =

     if (i->thread_info.resampled_chunk.memblock) {
         size_t l =3D length;
@@ -509,11 +499,14 @@
                     length -=3D l;
                     =

                 } else {
+                    size_t l;
+
                     /* Hmmm, peeking failed, so let's at least drop
                      * the right amount of data */
-                    =

-                    if (i->drop)
-                        i->drop(i, pa_resampler_request(i->thread_info.res=
ampler, length));
+
+                    if ((l =3D pa_resampler_request(i->thread_info.resampl=
er, length)) > 0)
+                        if (i->drop)
+                            i->drop(i, l);
                             =

                     break;
                 }
@@ -609,166 +602,166 @@
 }
 =

 int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately=
) {
-/*     pa_resampler *new_resampler =3D NULL; */
-/*     pa_memblockq *buffer =3D NULL; */
-/*     pa_sink *origin; */
+    pa_resampler *new_resampler =3D NULL;
+    pa_sink *origin;
+    pa_usec_t silence_usec =3D 0;
+    pa_sink_input_move_info info;
 =

     pa_sink_input_assert_ref(i);
     pa_sink_assert_ref(dest);
 =

-    return -1;
-
-/*     origin =3D i->sink; */
-
-/*     if (dest =3D=3D origin) */
-/*         return 0; */
-
-/*     if (pa_idxset_size(dest->inputs) >=3D PA_MAX_INPUTS_PER_SINK) { */
-/*         pa_log_warn("Failed to move sink input: too many inputs per sin=
k."); */
-/*         return -1; */
-/*     } */
-
-/*     if (i->resampler && */
-/*         pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) =
&& */
-/*         pa_channel_map_equal(&origin->channel_map, &dest->channel_map))=
 */
-
-/*         /\* Try to reuse the old resampler if possible *\/ */
-/*         new_resampler =3D i->resampler; */
-
-/*     else if ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) || */
-/*         !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) || */
-/*         !pa_channel_map_equal(&i->channel_map, &dest->channel_map)) { */
-
-/*         /\* Okey, we need a new resampler for the new sink *\/ */
-
-/*         if (!(new_resampler =3D pa_resampler_new( */
-/*                       dest->core->mempool, */
-/*                       &i->sample_spec, &i->channel_map, */
-/*                       &dest->sample_spec, &dest->channel_map, */
-/*                       i->resample_method))) { */
-/*             pa_log_warn("Unsupported resampling operation."); */
-/*             return -1; */
-/*         } */
-/*     } */
-
-/*     if (!immediately) { */
-/*         pa_usec_t old_latency, new_latency; */
-/*         pa_usec_t silence_usec =3D 0; */
-
-/*         buffer =3D pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_=
size(&origin->sample_spec), 0, 0, NULL); */
-
-/*         /\* Let's do a little bit of Voodoo for compensating latency */
-/*          * differences *\/ */
-
-/*         old_latency =3D pa_sink_get_latency(origin); */
-/*         new_latency =3D pa_sink_get_latency(dest); */
-
-/*         /\* The already resampled data should go to the old sink *\/ */
-
-/*         if (old_latency >=3D new_latency) { */
-
-/*             /\* The latency of the old sink is larger than the latency =
*/
-/*              * of the new sink. Therefore to compensate for the */
-/*              * difference we to play silence on the new one for a */
-/*              * while *\/ */
-
-/*             silence_usec =3D old_latency - new_latency; */
-
-/*         } else { */
-/*             size_t l; */
-/*             int volume_is_norm; */
-
-/*             /\* The latency of new sink is larger than the latency of */
-/*              * the old sink. Therefore we have to precompute a little */
-/*              * and make sure that this is still played on the old */
-/*              * sink, until we can play the first sample on the new */
-/*              * sink.*\/ */
-
-/*             l =3D pa_usec_to_bytes(new_latency - old_latency, &origin->=
sample_spec); */
-
-/*             volume_is_norm =3D pa_cvolume_is_norm(&i->volume); */
-
-/*             while (l > 0) { */
-/*                 pa_memchunk chunk; */
-/*                 pa_cvolume volume; */
-/*                 size_t n; */
-
-/*                 if (pa_sink_input_peek(i, &chunk, &volume) < 0) */
-/*                     break; */
-
-/*                 n =3D chunk.length > l ? l : chunk.length; */
-/*                 pa_sink_input_drop(i, &chunk, n); */
-/*                 chunk.length =3D n; */
-
-/*                 if (!volume_is_norm) { */
-/*                     pa_memchunk_make_writable(&chunk, 0); */
-/*                     pa_volume_memchunk(&chunk, &origin->sample_spec, &v=
olume); */
-/*                 } */
-
-/*                 if (pa_memblockq_push(buffer, &chunk) < 0) { */
-/*                     pa_memblock_unref(chunk.memblock); */
-/*                     break; */
-/*                 } */
-
-/*                 pa_memblock_unref(chunk.memblock); */
-/*                 l -=3D n; */
-/*             } */
-/*         } */
-
-/*         if (i->resampled_chunk.memblock) { */
-
-/*             /\* There is still some data left in the already resampled =
*/
-/*              * memory block. Hence, let's output it on the old sink */
-/*              * and sleep so long on the new sink *\/ */
-
-/*             pa_memblockq_push(buffer, &i->resampled_chunk); */
-/*             silence_usec +=3D pa_bytes_to_usec(i->resampled_chunk.lengt=
h, &origin->sample_spec); */
-/*         } */
-
-/*         /\* Calculate the new sleeping time *\/ */
-/*         i->move_silence =3D pa_usec_to_bytes( */
-/*                 pa_bytes_to_usec(i->move_silence, &i->sample_spec) + */
-/*                 silence_usec, */
-/*                 &i->sample_spec); */
-/*     } */
-
-/*     /\* Okey, let's move it *\/ */
-/*     pa_idxset_remove_by_data(origin->inputs, i, NULL); */
-/*     pa_idxset_put(dest->inputs, i, NULL); */
-/*     i->sink =3D dest; */
-
-/*     /\* Replace resampler *\/ */
-/*     if (new_resampler !=3D i->resampler) { */
-/*         if (i->resampler) */
-/*             pa_resampler_free(i->resampler); */
-/*         i->resampler =3D new_resampler; */
-
-/*         /\* if the resampler changed, the silence memblock is */
-/*          * probably invalid now, too *\/ */
-/*         if (i->silence_memblock) { */
-/*             pa_memblock_unref(i->silence_memblock); */
-/*             i->silence_memblock =3D NULL; */
-/*         } */
-/*     } */
-
-/*     /\* Dump already resampled data *\/ */
-/*     if (i->resampled_chunk.memblock) { */
-/*         pa_memblock_unref(i->resampled_chunk.memblock); */
-/*         i->resampled_chunk.memblock =3D NULL; */
-/*         i->resampled_chunk.index =3D i->resampled_chunk.length =3D 0; */
-/*     } */
-
-/*     /\* Notify everyone *\/ */
-/*     pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPU=
T|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); */
-/*     pa_sink_notify(i->sink); */
-
-/*     /\* Ok, now let's feed the precomputed buffer to the old sink *\/ */
-/*     if (buffer) */
-/*         pa_play_memblockq(origin, "Ghost Stream", &origin->sample_spec,=
 &origin->channel_map, buffer, NULL); */
-
-/*     return 0; */
-}
-
+    origin =3D i->sink;
+
+    if (dest =3D=3D origin)
+        return 0;
+
+    if (i->sync_next || i->sync_prev) {
+        pa_log_warn("Moving synchronised streams not supported.");
+        return -1;
+    }
+
+    if (pa_idxset_size(dest->inputs) >=3D PA_MAX_INPUTS_PER_SINK) {
+        pa_log_warn("Failed to move sink input: too many inputs per sink."=
);
+        return -1;
+    }
+
+    if (i->thread_info.resampler &&
+        pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) &&
+        pa_channel_map_equal(&origin->channel_map, &dest->channel_map))
+
+        /* Try to reuse the old resampler if possible */
+        new_resampler =3D i->thread_info.resampler;
+
+    else if ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
+        !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) ||
+        !pa_channel_map_equal(&i->channel_map, &dest->channel_map)) {
+
+        /* Okey, we need a new resampler for the new sink */
+
+        if (!(new_resampler =3D pa_resampler_new(
+                      dest->core->mempool,
+                      &i->sample_spec, &i->channel_map,
+                      &dest->sample_spec, &dest->channel_map,
+                      i->resample_method))) {
+            pa_log_warn("Unsupported resampling operation.");
+            return -1;
+        }
+    }
+
+    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE], i);
+
+    memset(&info, 0, sizeof(info));
+    info.sink_input =3D i;
+    =

+    if (!immediately) {
+        pa_usec_t old_latency, new_latency;
+
+        /* Let's do a little bit of Voodoo for compensating latency
+         * differences. We assume that the accuracy for our
+         * estimations is still good enough, even though we do these
+         * operations non-atomic. */
+
+        old_latency =3D pa_sink_get_latency(origin);
+        new_latency =3D pa_sink_get_latency(dest);
+
+        /* The already resampled data should go to the old sink */
+
+        if (old_latency >=3D new_latency) {
+
+            /* The latency of the old sink is larger than the latency
+             * of the new sink. Therefore to compensate for the
+             * difference we to play silence on the new one for a
+             * while */
+
+            silence_usec =3D old_latency - new_latency;
+
+        } else {
+
+            /* The latency of new sink is larger than the latency of
+             * the old sink. Therefore we have to precompute a little
+             * and make sure that this is still played on the old
+             * sink, until we can play the first sample on the new
+             * sink.*/
+
+            info.buffer_bytes =3D pa_usec_to_bytes(new_latency - old_laten=
cy, &origin->sample_spec);
+        }
+
+        /* Okey, let's move it */
+        =

+        if (info.buffer_bytes > 0) {
+            =

+            info.ghost_sink_input =3D pa_memblockq_sink_input_new(
+                    origin,
+                    "Ghost Stream",
+                    &origin->sample_spec,
+                    &origin->channel_map,
+                    NULL,
+                    NULL);
+
+            info.buffer =3D pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_=
frame_size(&origin->sample_spec), 0, 0, NULL);
+        }
+    }
+
+    pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_M=
ESSAGE_REMOVE_INPUT_AND_BUFFER, &info, 0, NULL);
+
+    if (info.ghost_sink_input) {
+        /* Basically, do what pa_sink_input_put() does ...*/
+        pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INP=
UT|PA_SUBSCRIPTION_EVENT_NEW, info.ghost_sink_input->index);
+        pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], i=
nfo.ghost_sink_input);
+        pa_sink_input_unref(info.ghost_sink_input);
+    }
+    =

+    pa_idxset_remove_by_data(origin->inputs, i, NULL);
+    pa_idxset_put(dest->inputs, i, NULL);
+    i->sink =3D dest;
+
+    /* Replace resampler */
+    if (new_resampler !=3D i->thread_info.resampler) {
+        if (i->thread_info.resampler)
+            pa_resampler_free(i->thread_info.resampler);
+        i->thread_info.resampler =3D new_resampler;
+
+        /* if the resampler changed, the silence memblock is
+         * probably invalid now, too */
+        if (i->thread_info.silence_memblock) {
+            pa_memblock_unref(i->thread_info.silence_memblock);
+            i->thread_info.silence_memblock =3D NULL;
+        }
+    }
+
+    /* Dump already resampled data */
+    if (i->thread_info.resampled_chunk.memblock) {
+        /* Hmm, this data has already been added to the ghost queue, presu=
mably, hence let's sleep a little bit longer */
+        silence_usec +=3D pa_bytes_to_usec(i->thread_info.resampled_chunk.=
length, &origin->sample_spec);
+        pa_memblock_unref(i->thread_info.resampled_chunk.memblock);
+        pa_memchunk_reset(&i->thread_info.resampled_chunk);
+    }
+
+    /* Calculate the new sleeping time */
+    if (immediately)
+        i->thread_info.move_silence =3D 0;
+    else
+        i->thread_info.move_silence =3D pa_usec_to_bytes(
+                pa_bytes_to_usec(i->thread_info.move_silence, &i->sample_s=
pec) +
+                silence_usec,
+                &i->sample_spec);
+
+    pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_M=
ESSAGE_ADD_INPUT, i, 0, NULL);
+    =

+    pa_sink_update_status(origin);
+    pa_sink_update_status(dest);
+
+    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_POST],=
 i);
+    =

+    pa_log_debug("Successfully moved sink input %i from %s to %s.", i->ind=
ex, origin->name, dest->name);
+    =

+    /* Notify everyone */
+    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|P=
A_SUBSCRIPTION_EVENT_CHANGE, i->index);
+
+    return 0;
+}
+
+/* Called from thread context */
 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, i=
nt64_t offset, pa_memchunk *chunk) {
     pa_sink_input *i =3D PA_SINK_INPUT(o);
 =

@@ -789,19 +782,18 @@
             if (i->thread_info.resampled_chunk.memblock)
                 *r +=3D pa_bytes_to_usec(i->thread_info.resampled_chunk.le=
ngth, &i->sink->sample_spec);
 =

-/*             if (i->move_silence) */
-/*                 r +=3D pa_bytes_to_usec(i->move_silence, &i->sink->samp=
le_spec); */
+            if (i->thread_info.move_silence) =

+                *r +=3D pa_bytes_to_usec(i->thread_info.move_silence, &i->=
sink->sample_spec); =

 =

             return 0;
         }
 =

-        case PA_SINK_INPUT_MESSAGE_SET_RATE: {
+        case PA_SINK_INPUT_MESSAGE_SET_RATE: =

 =

             i->thread_info.sample_spec.rate =3D PA_PTR_TO_UINT(userdata);
             pa_resampler_set_input_rate(i->thread_info.resampler, PA_PTR_T=
O_UINT(userdata));
 =

             return 0;
-        }
 =

         case PA_SINK_INPUT_MESSAGE_SET_STATE: {
             pa_sink_input *ssync;

Modified: branches/lennart/src/pulsecore/sink-input.h
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/lennart/src/pulsecore/=
sink-input.h?rev=3D1649&root=3Dpulseaudio&r1=3D1648&r2=3D1649&view=3Ddiff
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
--- branches/lennart/src/pulsecore/sink-input.h (original)
+++ branches/lennart/src/pulsecore/sink-input.h Sun Aug 12 01:46:51 2007
@@ -95,7 +95,7 @@
         /* Some silence to play before the actual data. This is used to
          * compensate for latency differences when moving a sink input
          * "hot" between sinks. */
-        /*         size_t move_silence; */
+        size_t move_silence;
         pa_memblock *silence_memblock;               /* may be NULL */
 =

         pa_sink_input *sync_prev, *sync_next;
@@ -188,4 +188,11 @@
 void pa_sink_input_drop(pa_sink_input *i, size_t length);
 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, i=
nt64_t offset, pa_memchunk *chunk);
 =

+typedef struct pa_sink_input_move_info {
+    pa_sink_input *sink_input;
+    pa_sink_input *ghost_sink_input;
+    pa_memblockq *buffer;
+    size_t buffer_bytes;
+} pa_sink_input_move_info;
+
 #endif

Modified: branches/lennart/src/pulsecore/sink.c
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/lennart/src/pulsecore/=
sink.c?rev=3D1649&root=3Dpulseaudio&r1=3D1648&r2=3D1649&view=3Ddiff
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
--- branches/lennart/src/pulsecore/sink.c (original)
+++ branches/lennart/src/pulsecore/sink.c Sun Aug 12 01:46:51 2007
@@ -42,6 +42,7 @@
 #include <pulsecore/core-subscribe.h>
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
+#include <pulsecore/play-memblockq.h>
 =

 #include "sink.h"
 =

@@ -721,6 +722,72 @@
             return 0;
         }
 =

+        case PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER: {
+            pa_sink_input_move_info *info =3D userdata;
+            int volume_is_norm;
+
+            /* We don't support moving synchronized streams. */
+            pa_assert(!info->sink_input->sync_prev);
+            pa_assert(!info->sink_input->sync_next);
+            pa_assert(!info->sink_input->thread_info.sync_next);
+            pa_assert(!info->sink_input->thread_info.sync_prev);
+            =

+            if (info->ghost_sink_input) {
+                pa_assert(info->buffer_bytes > 0);
+                pa_assert(info->buffer);
+                =

+                volume_is_norm =3D pa_cvolume_is_norm(&info->sink_input->t=
hread_info.volume);
+
+                pa_log_debug("Buffering %u bytes ...", info->buffer_bytes);
+                =

+                while (info->buffer_bytes > 0) {
+                    pa_memchunk memchunk;
+                    pa_cvolume volume;
+                    size_t n;
+                    =

+                    if (pa_sink_input_peek(info->sink_input, &memchunk, &v=
olume) < 0)
+                        break;
+                    =

+                    n =3D memchunk.length > info->buffer_bytes ? info->buf=
fer_bytes : memchunk.length;
+                    pa_sink_input_drop(info->sink_input, n);
+                    memchunk.length =3D n;
+                    =

+                    if (!volume_is_norm) {
+                        pa_memchunk_make_writable(&memchunk, 0);
+                        pa_volume_memchunk(&memchunk, &s->sample_spec, &vo=
lume);
+                    }
+                    =

+                    if (pa_memblockq_push(info->buffer, &memchunk) < 0) {
+                        pa_memblock_unref(memchunk.memblock);
+                        break;
+                    }
+                    =

+                    pa_memblock_unref(memchunk.memblock);
+                    info->buffer_bytes -=3D n;
+                }
+
+                /* Add the remaining already resampled chunk to the buffer=
 */
+                if (info->sink_input->thread_info.resampled_chunk.memblock)
+                    pa_memblockq_push(info->buffer, &info->sink_input->thr=
ead_info.resampled_chunk);
+
+                pa_memblockq_sink_input_set_queue(info->ghost_sink_input, =
info->buffer);
+
+                pa_log_debug("Buffered %u bytes ...", pa_memblockq_get_len=
gth(info->buffer));
+            }
+
+            /* Let's remove the sink input ...*/
+            if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(=
info->sink_input->index)))
+                pa_sink_input_unref(info->sink_input);
+
+            /* .. and add the ghost sink input instead */
+            if (info->ghost_sink_input) {
+                pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(inf=
o->ghost_sink_input->index), pa_sink_input_ref(info->ghost_sink_input));
+                info->ghost_sink_input->thread_info.sync_prev =3D info->gh=
ost_sink_input->thread_info.sync_next =3D NULL;
+            }
+            =

+            return 0;
+        }
+
         case PA_SINK_MESSAGE_SET_VOLUME:
             s->thread_info.soft_volume =3D *((pa_cvolume*) userdata);
             return 0;

Modified: branches/lennart/src/pulsecore/sink.h
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/lennart/src/pulsecore/=
sink.h?rev=3D1649&root=3Dpulseaudio&r1=3D1648&r2=3D1649&view=3Ddiff
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
--- branches/lennart/src/pulsecore/sink.h (original)
+++ branches/lennart/src/pulsecore/sink.h Sun Aug 12 01:46:51 2007
@@ -110,6 +110,7 @@
     PA_SINK_MESSAGE_GET_LATENCY,
     PA_SINK_MESSAGE_SET_STATE,
     PA_SINK_MESSAGE_PING,
+    PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER,
     PA_SINK_MESSAGE_MAX
 } pa_sink_message_t;
 =





More information about the pulseaudio-commits mailing list