[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. ee79b05b31bc0e4ac331d2fbe869079c122e973b

Lennart Poettering gitmailer-noreply at 0pointer.de
Thu Jun 26 10:04:41 PDT 2008


This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.

The master branch has been updated
      from  517727ebdcd9d6dbc7eacdc843f886ed2e0f38f6 (commit)

- Log -----------------------------------------------------------------
ee79b05... rework logic to request automatic timing updates a bit
4b8c4ef... reorder a few things to get rid of an uneeded comparison
97084e8... add a FIXME
7d3d3fc... move initialization order of validity bools around a bit
36d6c71... unify smoother pause/resume handling in a single function check_smoother_status()
dcbb7f2... convert to double only once, and make sure we can deal with negative results of -y
eab1cb8... make sure to call process_rewind() under all circumstances before we do the next loop iteration
1e36b57... use the newer name for monotonic/monotonous
2c5a33d... remove redundant check
85b83e8... properly initialize pa_stream::corked based on the flags
1514d13... split pa_memblockq_flush() into two flush commands, one which fixes up the read ptr, and one which fixes up the write ptr
5fccac9... comment two functions in memblockq.c
ec10f5f... use the bight lighter _silence() instead of _flush() when destructing our little q
dd8b909... fix up if the smoother shall be resumed 'before' it was actually paused
b4302ca... fix up monotonicity of input to _get() instead of hitting an assert
63b68f4... call the enum PA_STREAM_NOT_MONOTONIC and make PA_STREAM_NOT_MONOTONOUS an alias for that
df2650e... fix return value of pa_namereg_make_valid_name()
c5cbeb5... choose more sensible default buffer sizes for old clients
-----------------------------------------------------------------------

Summary of changes:
 src/modules/module-alsa-sink.c   |   11 ++-
 src/modules/module-combine.c     |    5 +-
 src/modules/module-esound-sink.c |    4 +
 src/modules/module-jack-sink.c   |    4 +
 src/modules/module-null-sink.c   |    8 +-
 src/modules/module-pipe-sink.c   |    8 +-
 src/modules/module-tunnel.c      |    6 +
 src/pulse/def.h                  |   13 ++-
 src/pulse/stream.c               |  211 ++++++++++++++++++++-----------------
 src/pulsecore/memblockq.c        |   19 +++-
 src/pulsecore/memblockq.h        |   45 +++++----
 src/pulsecore/namereg.c          |    4 +-
 src/pulsecore/namereg.h          |    2 +-
 src/pulsecore/protocol-native.c  |    4 +-
 src/pulsecore/sink-input.c       |   25 ++---
 src/pulsecore/sink.c             |   42 +++++---
 src/pulsecore/sink.h             |    1 +
 src/pulsecore/time-smoother.c    |   22 +++--
 18 files changed, 258 insertions(+), 176 deletions(-)

-----------------------------------------------------------------------

commit c5cbeb5ed294af7aaae8a8bb674526da2fecdd84
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jun 25 02:28:33 2008 +0200

    choose more sensible default buffer sizes for old clients

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 3bee7a0..b3f9697 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -119,6 +119,11 @@ pa_stream *pa_stream_new_with_proplist(
     s->requested_bytes = 0;
     memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
 
+    /* We initialize der target length here, so that if the user
+     * passes no explicit buffering metrics the default is similar to
+     * what older PA versions provided. */
+    s->buffer_attr.tlength = pa_usec_to_bytes(250*PA_USEC_PER_MSEC, ss); /* 250ms of buffering */
+
     s->device_index = PA_INVALID_INDEX;
     s->device_name = NULL;
     s->suspended = FALSE;
@@ -685,16 +690,19 @@ static void automatic_buffer_attr(pa_stream *s, pa_buffer_attr *attr, const pa_s
         return;
 
     /* Version older than 0.9.10 didn't do server side buffer_attr
-     * selection, hence we have to fake it on the client side */
+     * selection, hence we have to fake it on the client side. */
+
+    /* We choose fairly conservative values here, to not confuse
+     * old clients with extremely large playback buffers */
 
     if (!attr->maxlength <= 0)
         attr->maxlength = 4*1024*1024; /* 4MB is the maximum queue length PulseAudio <= 0.9.9 supported. */
 
     if (!attr->tlength <= 0)
-        attr->tlength = pa_bytes_per_second(ss)*2; /* 2s of buffering */
+        attr->tlength = pa_usec_to_bytes(250*PA_USEC_PER_MSEC, ss); /* 250ms of buffering */
 
     if (!attr->minreq <= 0)
-        attr->minreq = (2*attr->tlength)/10; /* Ask for more data when there are only 200ms left in the playback buffer */
+        attr->minreq = (attr->tlength)/5; /* Ask for more data when there are only 200ms left in the playback buffer */
 
     if (!attr->prebuf)
         attr->prebuf = attr->tlength; /* Start to play only when the playback is fully filled up once */

commit df2650e7a5167dbfc625727e0f189c21bc0e15e6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 00:27:02 2008 +0200

    fix return value of pa_namereg_make_valid_name()

diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c
index 38d308c..3042054 100644
--- a/src/pulsecore/namereg.c
+++ b/src/pulsecore/namereg.c
@@ -70,7 +70,7 @@ pa_bool_t pa_namereg_is_valid_name(const char *name) {
     return TRUE;
 }
 
-const char* pa_namereg_make_valid_name(const char *name) {
+char* pa_namereg_make_valid_name(const char *name) {
     const char *a;
     char *b, *n;
 
@@ -109,7 +109,7 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t
         return NULL;
 
     if ((type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE) &&
-        !pa_namereg_is_valid_name(name) ) {
+        !pa_namereg_is_valid_name(name)) {
 
         if (fail)
             return NULL;
diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h
index b460382..3c1de8e 100644
--- a/src/pulsecore/namereg.h
+++ b/src/pulsecore/namereg.h
@@ -44,6 +44,6 @@ const char *pa_namereg_get_default_sink_name(pa_core *c);
 const char *pa_namereg_get_default_source_name(pa_core *c);
 
 pa_bool_t pa_namereg_is_valid_name(const char *name);
-const char* pa_namereg_make_valid_name(const char *name);
+char* pa_namereg_make_valid_name(const char *name);
 
 #endif

commit 63b68f418e2bf905ebb6068aaa4fd05467d8e1ba
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 00:27:54 2008 +0200

    call the enum PA_STREAM_NOT_MONOTONIC and make PA_STREAM_NOT_MONOTONOUS an alias for that

diff --git a/src/pulse/def.h b/src/pulse/def.h
index a91c103..8407dde 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -120,7 +120,7 @@ typedef enum pa_stream_flags {
                                        * of sense to combine this
                                        * option with
                                        * PA_STREAM_AUTO_TIMING_UPDATE. */
-    PA_STREAM_NOT_MONOTONOUS = 4,    /**< Don't force the time to
+    PA_STREAM_NOT_MONOTONIC = 4,    /**< Don't force the time to
                                       * increase monotonically. If
                                       * this option is enabled,
                                       * pa_stream_get_time() will not
@@ -135,7 +135,12 @@ typedef enum pa_stream_flags {
                                       * caused the time to to jump
                                       * ahead can be corrected
                                       * quickly, without the need to
-                                      * wait. */
+                                      * wait. (Please note that this
+                                      * flag was named
+                                      * PA_STREAM_NOT_MONOTONOUS in
+                                      * releases prior to 0.9.11. The
+                                      * old name is still defined too,
+                                      * for compatibility reasons. */
     PA_STREAM_AUTO_TIMING_UPDATE = 8, /**< If set timing update requests
                                        * are issued periodically
                                        * automatically. Combined with
@@ -237,8 +242,8 @@ typedef enum pa_stream_flags {
 } pa_stream_flags_t;
 
 
-/** English is an evil language \since 0.9.11 */
-#define PA_STREAM_NOT_MONOTONIC PA_STREAM_NOT_MONOTONOUS
+/** English is an evil language */
+#define PA_STREAM_NOT_MONOTONOUS PA_STREAM_NOT_MONOTONIC
 
 /** Playback and record buffer metrics */
 typedef struct pa_buffer_attr {

commit b4302cacf94b0e720befc120ae9fe71be77a8973
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 00:29:59 2008 +0200

    fix up monotonicity of input to _get() instead of hitting an assert

diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
index fe5a4f1..013edfc 100644
--- a/src/pulsecore/time-smoother.c
+++ b/src/pulsecore/time-smoother.c
@@ -373,12 +373,15 @@ pa_usec_t pa_smoother_get(pa_smoother *s, pa_usec_t x) {
 
     x = PA_LIKELY(x >= s->time_offset) ? x - s->time_offset : 0;
 
+    if (s->monotonic)
+        if (x <= s->last_x)
+            x = s->last_x;
+
     estimate(s, x, &y, NULL);
 
     if (s->monotonic) {
 
         /* Make sure the querier doesn't jump forth and back. */
-        pa_assert(x >= s->last_x);
         s->last_x = x;
 
         if (y < s->last_y)

commit dd8b90953255db7529d6efa597c5996ac10d8849
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 00:31:39 2008 +0200

    fix up if the smoother shall be resumed 'before' it was actually paused

diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
index 013edfc..40220ad 100644
--- a/src/pulsecore/time-smoother.c
+++ b/src/pulsecore/time-smoother.c
@@ -421,7 +421,8 @@ void pa_smoother_resume(pa_smoother *s, pa_usec_t x) {
     if (!s->paused)
         return;
 
-    pa_assert(x >= s->pause_time);
+    if (x < s->pause_time)
+        x = s->pause_time;
 
 /*     pa_log_debug("resume(%llu)", (unsigned long long) x); */
 
@@ -458,5 +459,4 @@ void pa_smoother_reset(pa_smoother *s) {
 
     s->n_history = 0;
     s->abc_valid = FALSE;
-
 }

commit ec10f5fdd33065afad5abb0a3c3c7802fc9d32f6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 00:33:07 2008 +0200

    use the bight lighter _silence() instead of _flush() when destructing our little q

diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index a9f28a0..9ce3372 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -110,7 +110,7 @@ pa_memblockq* pa_memblockq_new(
 void pa_memblockq_free(pa_memblockq* bq) {
     pa_assert(bq);
 
-    pa_memblockq_flush(bq);
+    pa_memblockq_silence(bq);
 
     if (bq->silence.memblock)
         pa_memblock_unref(bq->silence.memblock);

commit 5fccac94e737a760c12fb82e5cd4a82362c17a24
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 00:36:05 2008 +0200

    comment two functions in memblockq.c

diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h
index 81f7cbb..ad3eea4 100644
--- a/src/pulsecore/memblockq.h
+++ b/src/pulsecore/memblockq.h
@@ -160,11 +160,13 @@ void pa_memblockq_willneed(pa_memblockq *bq);
  * data for the future nor data in the backlog. */
 pa_bool_t pa_memblockq_is_empty(pa_memblockq *bq);
 
+/* Drop everything in the queue, but don't modify the indexes */
 void pa_memblockq_silence(pa_memblockq *bq);
 
 /* Check whether we currently are in prebuf state */
 pa_bool_t pa_memblockq_prebuf_active(pa_memblockq *bq);
 
+/* Return how many items are currently stored in the queue */
 unsigned pa_memblockq_get_nblocks(pa_memblockq *bq);
 
 size_t pa_memblockq_get_base(pa_memblockq *bq);

commit 1514d138353f04578d885d9cb18c528d9b562a83
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 00:39:31 2008 +0200

    split pa_memblockq_flush() into two flush commands, one which fixes up the read ptr, and one which fixes up the write ptr

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index cef7a99..8c155da 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -525,7 +525,7 @@ static int sink_input_process_msg(pa_msgobject *obj, int code, void *data, int64
             if (PA_SINK_IS_OPENED(o->sink_input->sink->thread_info.state))
                 pa_memblockq_push_align(o->memblockq, chunk);
             else
-                pa_memblockq_flush(o->memblockq);
+                pa_memblockq_flush_write(o->memblockq);
 
             return 0;
     }
@@ -555,7 +555,7 @@ static void enable_output(struct output *o) {
 
     if (output_create_sink_input(o) >= 0) {
 
-        pa_memblockq_flush(o->memblockq);
+        pa_memblockq_flush_write(o->memblockq);
 
         pa_sink_input_put(o->sink_input);
 
diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index 9ce3372..841b907 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -638,7 +638,7 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) {
     bq->missing -= delta;
 }
 
-void pa_memblockq_flush(pa_memblockq *bq) {
+void pa_memblockq_flush_write(pa_memblockq *bq) {
     int64_t old, delta;
     pa_assert(bq);
 
@@ -662,6 +662,21 @@ void pa_memblockq_flush(pa_memblockq *bq) {
     bq->missing -= delta;
 }
 
+void pa_memblockq_flush_read(pa_memblockq *bq) {
+    int64_t old, delta;
+    pa_assert(bq);
+
+    pa_memblockq_silence(bq);
+
+    old = bq->read_index;
+    bq->read_index = bq->write_index;
+
+    pa_memblockq_prebuf_force(bq);
+
+    delta = bq->read_index - old;
+    bq->missing += delta;
+}
+
 size_t pa_memblockq_get_tlength(pa_memblockq *bq) {
     pa_assert(bq);
 
diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h
index ad3eea4..4b9450f 100644
--- a/src/pulsecore/memblockq.h
+++ b/src/pulsecore/memblockq.h
@@ -84,6 +84,9 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *chunk);
  * you know what you do. */
 int pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk);
 
+/* Manipulate the write pointer */
+void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek);
+
 /* Return a copy of the next memory chunk in the queue. It is not
  * removed from the queue. There are two reasons this function might
  * fail: 1. prebuffering is active, 2. queue is empty and no silence
@@ -95,6 +98,9 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk);
 /* Drop the specified bytes from the queue. */
 void pa_memblockq_drop(pa_memblockq *bq, size_t length);
 
+/* Rewind the read index. If the history is shorter than the specified length we'll point to silence afterwards. */
+void pa_memblockq_rewind(pa_memblockq *bq, size_t length);
+
 /* Test if the pa_memblockq is currently readable, that is, more data than base */
 pa_bool_t pa_memblockq_is_readable(pa_memblockq *bq);
 
@@ -111,26 +117,11 @@ size_t pa_memblockq_pop_missing(pa_memblockq *bq);
 /* Directly moves the data from the source memblockq into bq */
 int pa_memblockq_splice(pa_memblockq *bq, pa_memblockq *source);
 
-/* Returns the minimal request value */
-size_t pa_memblockq_get_minreq(pa_memblockq *bq);
-
-/* Manipulate the write pointer */
-void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek);
-
 /* Set the queue to silence, set write index to read index */
-void pa_memblockq_flush(pa_memblockq *bq);
-
-/* Get Target length */
-size_t pa_memblockq_get_tlength(pa_memblockq *bq);
-
-/* Return the current read index */
-int64_t pa_memblockq_get_read_index(pa_memblockq *bq);
-
-/* Return the current write index */
-int64_t pa_memblockq_get_write_index(pa_memblockq *bq);
+void pa_memblockq_flush_write(pa_memblockq *bq);
 
-/* Rewind the read index. If the history is shorter than the specified length we'll point to silence afterwards. */
-void pa_memblockq_rewind(pa_memblockq *bq, size_t length);
+/* Set the queue to silence, set write read index to write index*/
+void pa_memblockq_flush_read(pa_memblockq *bq);
 
 /* Ignore prebuf for now */
 void pa_memblockq_prebuf_disable(pa_memblockq *bq);
@@ -141,9 +132,24 @@ void pa_memblockq_prebuf_force(pa_memblockq *bq);
 /* Return the maximum length of the queue in bytes */
 size_t pa_memblockq_get_maxlength(pa_memblockq *bq);
 
+/* Get Target length */
+size_t pa_memblockq_get_tlength(pa_memblockq *bq);
+
 /* Return the prebuffer length in bytes */
 size_t pa_memblockq_get_prebuf(pa_memblockq *bq);
 
+/* Returns the minimal request value */
+size_t pa_memblockq_get_minreq(pa_memblockq *bq);
+
+/* Return the base unit in bytes */
+size_t pa_memblockq_get_base(pa_memblockq *bq);
+
+/* Return the current read index */
+int64_t pa_memblockq_get_read_index(pa_memblockq *bq);
+
+/* Return the current write index */
+int64_t pa_memblockq_get_write_index(pa_memblockq *bq);
+
 /* Change metrics. Always call in order. */
 void pa_memblockq_set_maxlength(pa_memblockq *memblockq, size_t maxlength); /* might modify tlength, prebuf, minreq too */
 void pa_memblockq_set_tlength(pa_memblockq *memblockq, size_t tlength); /* might modify minreq, too */
@@ -169,6 +175,5 @@ pa_bool_t pa_memblockq_prebuf_active(pa_memblockq *bq);
 /* Return how many items are currently stored in the queue */
 unsigned pa_memblockq_get_nblocks(pa_memblockq *bq);
 
-size_t pa_memblockq_get_base(pa_memblockq *bq);
 
 #endif
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 923a566..862b062 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -1196,7 +1196,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 
             switch  (code) {
                 case SINK_INPUT_MESSAGE_FLUSH:
-                    func = pa_memblockq_flush;
+                    func = pa_memblockq_flush_write;
                     break;
 
                 case SINK_INPUT_MESSAGE_PREBUF_FORCE:
@@ -3072,7 +3072,7 @@ static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_U
     s = pa_idxset_get_by_index(c->record_streams, idx);
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
 
-    pa_memblockq_flush(s->memblockq);
+    pa_memblockq_flush_read(s->memblockq);
     pa_pstream_send_simple_ack(c->pstream, tag);
 }
 
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 43e7bb2..be16970 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -664,7 +664,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
         /* We were asked to drop all buffered data, and rerequest new
          * data from implementor the next time push() is called */
 
-        pa_memblockq_flush(i->thread_info.render_memblockq);
+        pa_memblockq_flush_write(i->thread_info.render_memblockq);
 
     } else if (i->thread_info.rewrite_nbytes > 0) {
         size_t max_rewrite, amount;

commit 85b83e8e8cb7ddc154f6bf06b588ea93fe263186
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 00:42:09 2008 +0200

    properly initialize pa_stream::corked based on the flags

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index b3f9697..33ab710 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -880,6 +880,7 @@ static int create_stream(
 
     s->direction = direction;
     s->flags = flags;
+    s->corked = !!(flags & PA_STREAM_START_CORKED);
 
     if (sync_stream)
         s->syncid = sync_stream->syncid;
@@ -919,7 +920,7 @@ static int create_stream(
             PA_TAG_U32, PA_INVALID_INDEX,
             PA_TAG_STRING, dev,
             PA_TAG_U32, s->buffer_attr.maxlength,
-            PA_TAG_BOOLEAN, !!(flags & PA_STREAM_START_CORKED),
+            PA_TAG_BOOLEAN, s->corked,
             PA_TAG_INVALID);
 
     if (s->direction == PA_STREAM_PLAYBACK) {

commit 2c5a33d9d8427c9add8085b05356c910a6f6ee94
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 00:43:30 2008 +0200

    remove redundant check

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 33ab710..709f1b7 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -604,15 +604,12 @@ void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, PA_GCC
 
     request_auto_timing_update(s, TRUE);
 
-    if (s->state == PA_STREAM_READY) {
-
-        if (command == PA_COMMAND_OVERFLOW) {
-            if (s->overflow_callback)
-                s->overflow_callback(s, s->overflow_userdata);
-        } else if (command == PA_COMMAND_UNDERFLOW) {
-            if (s->underflow_callback)
-                s->underflow_callback(s, s->underflow_userdata);
-        }
+    if (command == PA_COMMAND_OVERFLOW) {
+        if (s->overflow_callback)
+            s->overflow_callback(s, s->overflow_userdata);
+    } else if (command == PA_COMMAND_UNDERFLOW) {
+        if (s->underflow_callback)
+            s->underflow_callback(s, s->underflow_userdata);
     }
 
  finish:

commit 1e36b57b13d421dab20c436e0ae302acc34fbac9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 00:44:19 2008 +0200

    use the newer name for monotonic/monotonous

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 709f1b7..c75e38e 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -892,7 +892,7 @@ static int create_stream(
         if (s->smoother)
             pa_smoother_free(s->smoother);
 
-        s->smoother = pa_smoother_new(SMOOTHER_ADJUST_TIME, SMOOTHER_HISTORY_TIME, !(flags & PA_STREAM_NOT_MONOTONOUS), SMOOTHER_MIN_HISTORY);
+        s->smoother = pa_smoother_new(SMOOTHER_ADJUST_TIME, SMOOTHER_HISTORY_TIME, !(flags & PA_STREAM_NOT_MONOTONIC), SMOOTHER_MIN_HISTORY);
 
         x = pa_rtclock_usec();
         pa_smoother_set_time_offset(s->smoother, x);

commit eab1cb8df952bc302d14efd1640d96f8bbdb148a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 02:56:00 2008 +0200

    make sure to call process_rewind() under all circumstances before we do the next loop iteration

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 6765775..5818dee 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -882,7 +882,7 @@ static void sink_update_requested_latency_cb(pa_sink *s) {
 
     if (u->hwbuf_unused_frames > before) {
         pa_log_debug("Requesting rewind due to latency change.");
-        pa_sink_request_rewind(s, 0);
+        pa_sink_request_rewind(s, (size_t) -1);
     }
 }
 
@@ -967,9 +967,12 @@ static void thread_func(void *userdata) {
             int work_done;
             pa_usec_t sleep_usec;
 
-            if (u->sink->thread_info.rewind_nbytes > 0)
-                if (process_rewind(u) < 0)
-                    goto fail;
+            if (u->sink->thread_info.rewind_requested) {
+                if (u->sink->thread_info.rewind_nbytes <= 0)
+                    pa_sink_process_rewind(u->sink, 0);
+                else if (process_rewind(u) < 0)
+                        goto fail;
+            }
 
             if (u->use_mmap)
                 work_done = mmap_write(u, &sleep_usec);
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 8c155da..7d8e140 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -410,7 +410,6 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
     struct output *o;
 
     pa_sink_input_assert_ref(i);
-    pa_assert(nbytes > 0);
     pa_assert_se(o = i->userdata);
 
     pa_memblockq_rewind(o->memblockq, nbytes);
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index e189feb..6ca6497 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -204,6 +204,10 @@ static void thread_func(void *userdata) {
     for (;;) {
         int ret;
 
+        if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
+            if (u->sink->thread_info.rewind_requested)
+                pa_sink_process_rewind(u->sink, 0);
+
         if (u->rtpoll_item) {
             struct pollfd *pollfd;
             pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c
index c4d47f8..edc543a 100644
--- a/src/modules/module-jack-sink.c
+++ b/src/modules/module-jack-sink.c
@@ -222,6 +222,10 @@ static void thread_func(void *userdata) {
     for (;;) {
         int ret;
 
+        if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
+            if (u->sink->thread_info.rewind_requested)
+                pa_sink_process_rewind(u->sink, 0);
+
         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
             goto fail;
 
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 604ab15..9162960 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -204,8 +204,12 @@ static void thread_func(void *userdata) {
 
             now = pa_rtclock_usec();
 
-            if (u->sink->thread_info.rewind_nbytes > 0)
-                process_rewind(u, now);
+            if (u->sink->thread_info.rewind_requested) {
+                if (u->sink->thread_info.rewind_nbytes > 0)
+                    process_rewind(u, now);
+                else
+                    pa_sink_process_rewind(u->sink, 0);
+            }
 
             if (u->timestamp <= now)
                 process_render(u, now);
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index cd25b89..0999935 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -184,8 +184,12 @@ static void thread_func(void *userdata) {
         /* Render some data and write it to the fifo */
         if (u->sink->thread_info.state == PA_SINK_RUNNING) {
 
-            if (u->sink->thread_info.rewind_nbytes > 0)
-                process_rewind(u);
+            if (u->sink->thread_info.rewind_requested) {
+                if (u->sink->thread_info.rewind_nbytes > 0)
+                    process_rewind(u);
+                else
+                    pa_sink_process_rewind(u->sink, 0);
+            }
 
             if (pollfd->revents) {
                 if (process_render(u) < 0)
diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index 86f3081..1890646 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -605,6 +605,12 @@ static void thread_func(void *userdata) {
     for (;;) {
         int ret;
 
+#ifdef TUNNEL_SINK
+        if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
+            if (u->sink->thread_info.rewind_requested)
+                pa_sink_process_rewind(u->sink, 0);
+#endif
+
         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
             goto fail;
 
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index be16970..4086b85 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -491,12 +491,6 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
               i->thread_info.state == PA_SINK_INPUT_CORKED ||
               i->thread_info.state == PA_SINK_INPUT_DRAINED);
 
-    /* If there's still some rewrite request the handle, but the sink
-    didn't do this for us, we do it here. However, since the sink
-    apparently doesn't support rewinding, we pass 0 here. This still
-    allows rewinding through the render buffer. */
-    pa_sink_input_process_rewind(i, 0);
-
     block_size_max_sink_input = i->thread_info.resampler ?
         pa_resampler_max_block_size(i->thread_info.resampler) :
         pa_frame_align(pa_mempool_block_size_max(i->sink->core->mempool), &i->sample_spec);
@@ -633,18 +627,13 @@ void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec *
 
 /*     pa_log_debug("dropping %lu", (unsigned long) nbytes); */
 
-    /* If there's still some rewrite request the handle, but the sink
-    didn't do this for us, we do it here. However, since the sink
-    apparently doesn't support rewinding, we pass 0 here. This still
-    allows rewinding through the render buffer. */
-    pa_sink_input_process_rewind(i, 0);
-
     pa_memblockq_drop(i->thread_info.render_memblockq, nbytes);
 }
 
 /* Called from thread context */
 void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
     size_t lbq;
+    pa_bool_t called;
     pa_sink_input_assert_ref(i);
 
     pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
@@ -685,6 +674,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
             /* Tell the implementor */
             if (i->process_rewind)
                 i->process_rewind(i, amount);
+            called = TRUE;
 
             /* Convert back to to sink domain */
             if (i->thread_info.resampler)
@@ -703,6 +693,10 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
         }
     }
 
+    if (!called)
+        if (i->process_rewind)
+            i->process_rewind(i, 0);
+
     i->thread_info.rewrite_nbytes = 0;
     i->thread_info.rewrite_flush = FALSE;
 }
@@ -1143,6 +1137,8 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes  /* in our sam
     pa_sink_input_assert_ref(i);
     pa_assert(i->thread_info.rewrite_nbytes == 0);
 
+/*     pa_log_debug("request rewrite %lu", (unsigned long) nbytes); */
+
     /* We don't take rewind requests while we are corked */
     if (i->thread_info.state == PA_SINK_INPUT_CORKED)
         return;
@@ -1184,6 +1180,9 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes  /* in our sam
 
     if (nbytes > lbq)
         pa_sink_request_rewind(i->sink, nbytes - lbq);
+    else
+        /* This call will make sure process_rewind() is called later */
+        pa_sink_request_rewind(i->sink, 0);
 }
 
 /* Called from main context */
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index edb023b..0866829 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -212,6 +212,7 @@ pa_sink* pa_sink_new(
     s->thread_info.soft_muted = FALSE;
     s->thread_info.state = s->state;
     s->thread_info.rewind_nbytes = 0;
+    s->thread_info.rewind_requested = FALSE;
     s->thread_info.max_rewind = 0;
     s->thread_info.max_request = 0;
     s->thread_info.requested_latency_valid = FALSE;
@@ -454,21 +455,20 @@ void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
     pa_sink_assert_ref(s);
     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
 
-    /* Make sure the sink code already reset the counter! */
-    pa_assert(s->thread_info.rewind_nbytes <= 0);
-
-    if (nbytes <= 0)
-        return;
+    s->thread_info.rewind_nbytes = 0;
+    s->thread_info.rewind_requested = FALSE;
 
-    pa_log_debug("Processing rewind...");
+    if (nbytes > 0)
+        pa_log_debug("Processing rewind...");
 
     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
         pa_sink_input_assert_ref(i);
         pa_sink_input_process_rewind(i, nbytes);
     }
 
-    if (s->monitor_source && PA_SOURCE_IS_OPENED(s->monitor_source->thread_info.state))
-        pa_source_process_rewind(s->monitor_source, nbytes);
+    if (nbytes > 0)
+        if (s->monitor_source && PA_SOURCE_IS_OPENED(s->monitor_source->thread_info.state))
+            pa_source_process_rewind(s->monitor_source, nbytes);
 }
 
 /* Called from IO thread context */
@@ -620,7 +620,8 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
 
     pa_sink_ref(s);
 
-    s->thread_info.rewind_nbytes = 0;
+    pa_assert(!s->thread_info.rewind_requested);
+    pa_assert(s->thread_info.rewind_nbytes == 0);
 
     if (length <= 0)
         length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
@@ -696,7 +697,8 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
 
     pa_sink_ref(s);
 
-    s->thread_info.rewind_nbytes = 0;
+    pa_assert(!s->thread_info.rewind_requested);
+    pa_assert(s->thread_info.rewind_nbytes == 0);
 
     length = target->length;
     block_size_max = pa_mempool_block_size_max(s->core->mempool);
@@ -774,7 +776,8 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
 
     pa_sink_ref(s);
 
-    s->thread_info.rewind_nbytes = 0;
+    pa_assert(!s->thread_info.rewind_requested);
+    pa_assert(s->thread_info.rewind_nbytes == 0);
 
     l = target->length;
     d = 0;
@@ -800,7 +803,8 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
     pa_assert(pa_frame_aligned(length, &s->sample_spec));
     pa_assert(result);
 
-    s->thread_info.rewind_nbytes = 0;
+    pa_assert(!s->thread_info.rewind_requested);
+    pa_assert(s->thread_info.rewind_nbytes == 0);
 
     /*** This needs optimization ***/
 
@@ -1067,7 +1071,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 pa_sink_input_unref(i);
 
             pa_sink_invalidate_requested_latency(s);
-            pa_sink_request_rewind(s, 0);
+            pa_sink_request_rewind(s, (size_t) -1);
 
             return 0;
         }
@@ -1112,7 +1116,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             pa_sink_invalidate_requested_latency(s);
 
             pa_log_debug("Requesting rewind due to started move");
-            pa_sink_request_rewind(s, 0);
+            pa_sink_request_rewind(s, (size_t) -1);
 
             return 0;
         }
@@ -1162,13 +1166,13 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
         case PA_SINK_MESSAGE_SET_VOLUME:
             s->thread_info.soft_volume = *((pa_cvolume*) userdata);
 
-            pa_sink_request_rewind(s, 0);
+            pa_sink_request_rewind(s, (size_t) -1);
             return 0;
 
         case PA_SINK_MESSAGE_SET_MUTE:
             s->thread_info.soft_muted = PA_PTR_TO_UINT(userdata);
 
-            pa_sink_request_rewind(s, 0);
+            pa_sink_request_rewind(s, (size_t) -1);
             return 0;
 
         case PA_SINK_MESSAGE_GET_VOLUME:
@@ -1309,15 +1313,17 @@ void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
     pa_sink_assert_ref(s);
     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
 
-    if (nbytes <= 0)
+    if (nbytes == (size_t) -1)
         nbytes = s->thread_info.max_rewind;
 
     nbytes = PA_MIN(nbytes, s->thread_info.max_rewind);
 
-    if (nbytes <= s->thread_info.rewind_nbytes)
+    if (s->thread_info.rewind_requested &&
+        nbytes <= s->thread_info.rewind_nbytes)
         return;
 
     s->thread_info.rewind_nbytes = nbytes;
+    s->thread_info.rewind_requested = TRUE;
 
     if (s->request_rewind)
         s->request_rewind(s);
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index b73944e..604be26 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -145,6 +145,7 @@ struct pa_sink {
 
         /* Maximum of what clients requested to rewind in this cycle */
         size_t rewind_nbytes;
+        pa_bool_t rewind_requested;
 
         pa_usec_t min_latency; /* we won't go below this latency */
         pa_usec_t max_latency; /* An upper limit for the latencies */

commit dcbb7f2680a2b8a74691ec0ef1334fb655cf9bf6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 18:49:02 2008 +0200

    convert to double only once, and make sure we can deal with negative results of -y

diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
index 40220ad..d023148 100644
--- a/src/pulsecore/time-smoother.c
+++ b/src/pulsecore/time-smoother.c
@@ -295,24 +295,29 @@ static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) {
             *deriv = s->dp;
 
     } else {
+        double tx, ty;
 
         /* Ok, we're not yet on track, thus let's interpolate, and
          * make sure that the first derivative is smooth */
 
         calc_abc(s);
 
+        tx = (double) x;
+
         /* Move to origin */
-        x -= s->ex;
+        tx -= (double) s->ex;
 
         /* Horner scheme */
-        *y = (pa_usec_t) ((double) x * (s->c + (double) x * (s->b + (double) x * s->a)));
+        ty = (tx * (s->c + tx * (s->b + tx * s->a)));
 
         /* Move back from origin */
-        *y += s->ey;
+        ty += (double) s->ey;
+
+        *y = ty >= 0 ? (pa_usec_t) ty : 0;
 
         /* Horner scheme */
         if (deriv)
-            *deriv = s->c + ((double) x * (s->b*2 + (double) x * s->a*3));
+            *deriv = s->c + (tx * (s->b*2 + tx * s->a*3));
     }
 
     /* Guarantee monotonicity */

commit 36d6c712d8f06c7d96229c8543956cc7ffdf3c25
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 19:00:42 2008 +0200

    unify smoother pause/resume handling in a single function check_smoother_status()

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index c75e38e..0c7df14 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -342,6 +342,41 @@ finish:
     pa_context_unref(c);
 }
 
+static void check_smoother_status(pa_stream *s, pa_bool_t aposteriori, pa_bool_t force_start, pa_bool_t force_stop) {
+    pa_usec_t x;
+
+    pa_assert(s);
+    pa_assert(!force_start || !force_stop);
+
+    if (!s->smoother)
+        return;
+
+    x = pa_rtclock_usec();
+
+    if (s->timing_info_valid) {
+        if (aposteriori)
+            x -= s->timing_info.transport_usec;
+        else
+            x += s->timing_info.transport_usec;
+
+        if (s->direction == PA_STREAM_PLAYBACK)
+            /* it takes a while until the pause/resume is actually
+             * audible */
+            x += s->timing_info.sink_usec;
+        else
+            /* Data froma  while back will be dropped */
+            x -= s->timing_info.source_usec;
+    }
+
+    if (s->suspended || s->corked || force_stop)
+        pa_smoother_pause(s->smoother, x);
+    else if (force_start || s->buffer_attr.prebuf == 0)
+        pa_smoother_resume(s->smoother, x);
+
+    /* Please note that we have no idea if playback actually started
+     * if prebuf is non-zero! */
+}
+
 void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
     pa_context *c = userdata;
     pa_stream *s;
@@ -429,6 +464,7 @@ void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED u
 
     s->suspended = suspended;
 
+    check_smoother_status(s, TRUE, FALSE, FALSE);
     request_auto_timing_update(s, TRUE);
 
     if (s->moved_callback)
@@ -472,18 +508,7 @@ void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUS
 
     s->suspended = suspended;
 
-    if (s->smoother) {
-        pa_usec_t x = pa_rtclock_usec();
-
-        if (s->timing_info_valid)
-            x -= s->timing_info.transport_usec;
-
-        if (s->suspended || s->corked)
-            pa_smoother_pause(s->smoother, x);
-        else
-            pa_smoother_resume(s->smoother, x);
-    }
-
+    check_smoother_status(s, TRUE, FALSE, FALSE);
     request_auto_timing_update(s, TRUE);
 
     if (s->suspended_callback)
@@ -523,6 +548,7 @@ void pa_command_stream_started(pa_pdispatch *pd, uint32_t command, uint32_t tag,
     if (s->state != PA_STREAM_READY)
         goto finish;
 
+    check_smoother_status(s, TRUE, TRUE, FALSE);
     request_auto_timing_update(s, TRUE);
 
     if (s->started_callback)
@@ -592,15 +618,8 @@ void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, PA_GCC
     if (s->state != PA_STREAM_READY)
         goto finish;
 
-    if (s->smoother)
-        if (s->direction == PA_STREAM_PLAYBACK && s->buffer_attr.prebuf > 0) {
-            pa_usec_t x = pa_rtclock_usec();
-
-            if (s->timing_info_valid)
-                x -= s->timing_info.transport_usec;
-
-            pa_smoother_pause(s->smoother, x);
-        }
+    if (s->buffer_attr.prebuf > 0)
+        check_smoother_status(s, TRUE, FALSE, TRUE);
 
     request_auto_timing_update(s, TRUE);
 
@@ -676,6 +695,8 @@ static void create_stream_complete(pa_stream *s) {
 
         request_auto_timing_update(s, TRUE);
     }
+
+    check_smoother_status(s, TRUE, FALSE, FALSE);
 }
 
 static void automatic_buffer_attr(pa_stream *s, pa_buffer_attr *attr, const pa_sample_spec *ss) {
@@ -1704,15 +1725,7 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi
     pa_pstream_send_tagstruct(s->context->pstream, t);
     pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
 
-    if (s->smoother) {
-        pa_usec_t x = pa_rtclock_usec();
-
-        if (s->timing_info_valid)
-            x += s->timing_info.transport_usec;
-
-        if (s->suspended || s->corked)
-            pa_smoother_pause(s->smoother, x);
-    }
+    check_smoother_status(s, FALSE, FALSE, FALSE);
 
     if (s->direction == PA_STREAM_PLAYBACK)
         invalidate_indexes(s, TRUE, FALSE);

commit 7d3d3fc15d43e61fbecf1746db88ca2edc1c51ff
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 19:01:51 2008 +0200

    move initialization order of validity bools around a bit

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 0c7df14..43fc2fe 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -1292,13 +1292,9 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
 
     i = &o->stream->timing_info;
 
-/*     pa_log("pre corrupt w:%u r:%u\n", !o->stream->timing_info_valid || i->write_index_corrupt,!o->stream->timing_info_valid || i->read_index_corrupt); */
-
     o->stream->timing_info_valid = FALSE;
-    i->write_index_corrupt = FALSE;
-    i->read_index_corrupt = FALSE;
-
-/*     pa_log("timing update %u\n", tag); */
+    i->write_index_corrupt = TRUE;
+    i->read_index_corrupt = TRUE;
 
     if (command != PA_COMMAND_REPLY) {
         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
@@ -1332,8 +1328,10 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
             pa_context_fail(o->context, PA_ERR_PROTOCOL);
             goto finish;
         }
-
         o->stream->timing_info_valid = TRUE;
+        i->write_index_corrupt = FALSE;
+        i->read_index_corrupt = FALSE;
+
         i->playing = (int) playing;
         i->since_underrun = playing ? playing_for : underrun_for;
 

commit 97084e87c47071482ee9e2102bb480e67b0f5e8d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 19:02:14 2008 +0200

    add a FIXME

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 43fc2fe..adce7ad 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -1092,6 +1092,8 @@ int pa_stream_write(
     else
         s->requested_bytes = 0;
 
+    /* FIXME!!! ^^^ will break when offset is != 0 and mode is not RELATIVE*/
+
     if (s->direction == PA_STREAM_PLAYBACK) {
 
         /* Update latency request correction */

commit 4b8c4ef932e41404536e51d00b9bf010918151d6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 19:03:16 2008 +0200

    reorder a few things to get rid of an uneeded comparison

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index adce7ad..66964d3 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -1371,8 +1371,8 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
             int n, j;
             uint32_t ctag = tag;
 
-            /* Go through the saved correction values and add up the total correction.*/
-
+            /* Go through the saved correction values and add up the
+             * total correction.*/
             for (n = 0, j = o->stream->current_write_index_correction+1;
                  n < PA_MAX_WRITE_INDEX_CORRECTIONS;
                  n++, j = (j + 1) % PA_MAX_WRITE_INDEX_CORRECTIONS) {
@@ -1388,7 +1388,6 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
                 /* Now fix the write index */
                 if (o->stream->write_index_corrections[j].corrupt) {
                     /* A corrupting seek was made */
-                    i->write_index = 0;
                     i->write_index_corrupt = TRUE;
                 } else if (o->stream->write_index_corrections[j].absolute) {
                     /* An absolute seek was made */
@@ -1399,21 +1398,8 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
                     i->write_index += o->stream->write_index_corrections[j].value;
                 }
             }
-        }
-
-        if (o->stream->direction == PA_STREAM_RECORD) {
-            /* Read index correction */
-
-            if (!i->read_index_corrupt)
-                i->read_index -= pa_memblockq_get_length(o->stream->record_memblockq);
-        }
-
-/*     pa_log("post corrupt w:%u r:%u\n", i->write_index_corrupt || !o->stream->timing_info_valid, i->read_index_corrupt || !o->stream->timing_info_valid); */
-
-        /* Clear old correction entries */
-        if (o->stream->direction == PA_STREAM_PLAYBACK) {
-            int n;
 
+            /* Clear old correction entries */
             for (n = 0; n < PA_MAX_WRITE_INDEX_CORRECTIONS; n++) {
                 if (!o->stream->write_index_corrections[n].valid)
                     continue;
@@ -1423,6 +1409,13 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
             }
         }
 
+        if (o->stream->direction == PA_STREAM_RECORD) {
+            /* Read index correction */
+
+            if (!i->read_index_corrupt)
+                i->read_index -= pa_memblockq_get_length(o->stream->record_memblockq);
+        }
+
         /* Update smoother */
         if (o->stream->smoother) {
             pa_usec_t u, x;

commit ee79b05b31bc0e4ac331d2fbe869079c122e973b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 26 19:03:53 2008 +0200

    rework logic to request automatic timing updates a bit

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 66964d3..89838c5 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -1422,8 +1422,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
 
             u = x = pa_rtclock_usec() - i->transport_usec;
 
-            if (o->stream->direction == PA_STREAM_PLAYBACK &&
-                o->context->version >= 13) {
+            if (o->stream->direction == PA_STREAM_PLAYBACK && o->context->version >= 13) {
                 pa_usec_t su;
 
                 /* If we weren't playing then it will take some time
@@ -1720,8 +1719,9 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi
 
     check_smoother_status(s, FALSE, FALSE, FALSE);
 
-    if (s->direction == PA_STREAM_PLAYBACK)
-        invalidate_indexes(s, TRUE, FALSE);
+    /* This might cause the indexes to hang/start again, hence
+     * let's request a timing update */
+    request_auto_timing_update(s, TRUE);
 
     return o;
 }
@@ -1755,32 +1755,25 @@ pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *use
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
 
-    if ((o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata))) {
-
-        if (s->direction == PA_STREAM_PLAYBACK) {
-            if (s->write_index_corrections[s->current_write_index_correction].valid)
-                s->write_index_corrections[s->current_write_index_correction].corrupt = TRUE;
-
-            if (s->timing_info_valid)
-                s->timing_info.write_index_corrupt = TRUE;
+    if (!(o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata)))
+        return NULL;
 
-            if (s->buffer_attr.prebuf > 0)
-                invalidate_indexes(s, TRUE, FALSE);
-            else
-                request_auto_timing_update(s, TRUE);
+    if (s->direction == PA_STREAM_PLAYBACK) {
 
-            if (s->smoother && s->buffer_attr.prebuf > 0) {
-                pa_usec_t x = pa_rtclock_usec();
+        if (s->write_index_corrections[s->current_write_index_correction].valid)
+            s->write_index_corrections[s->current_write_index_correction].corrupt = TRUE;
 
-                if (s->timing_info_valid)
-                    x += s->timing_info.transport_usec;
+        if (s->buffer_attr.prebuf > 0)
+            check_smoother_status(s, FALSE, FALSE, TRUE);
 
-                pa_smoother_pause(s->smoother, x);
-            }
+        /* This will change the write index, but leave the
+         * read index untouched. */
+        invalidate_indexes(s, FALSE, TRUE);
 
-        } else
-            invalidate_indexes(s, FALSE, TRUE);
-    }
+    } else
+        /* For record streams this has no influence on the write
+         * index, but the read index might jump. */
+        invalidate_indexes(s, TRUE, FALSE);
 
     return o;
 }
@@ -1795,8 +1788,12 @@ pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *us
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE);
 
-    if ((o = stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata)))
-        invalidate_indexes(s, TRUE, FALSE);
+    if (!(o = stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata)))
+        return NULL;
+
+    /* This might cause the read index to hang again, hence
+     * let's request a timing update */
+    request_auto_timing_update(s, TRUE);
 
     return o;
 }
@@ -1811,8 +1808,12 @@ pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *u
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE);
 
-    if ((o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata)))
-        invalidate_indexes(s, TRUE, FALSE);
+    if (!(o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata)))
+        return NULL;
+
+    /* This might cause the read index to start moving again, hence
+     * let's request a timing update */
+    request_auto_timing_update(s, TRUE);
 
     return o;
 }
@@ -2062,6 +2063,10 @@ pa_operation* pa_stream_set_buffer_attr(pa_stream *s, const pa_buffer_attr *attr
     pa_pstream_send_tagstruct(s->context->pstream, t);
     pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_set_buffer_attr_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
 
+    /* This might cause changes in the read/write indexex, hence let's
+     * request a timing update */
+    request_auto_timing_update(s, TRUE);
+
     return o;
 }
 

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list