]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/memblockq.c
Fix up according to Coding Style
[pulseaudio] / src / pulsecore / memblockq.c
index 841b90753feab20aef242c71bc320416e4a04b0c..c76ca841930a7a654f4ce46933c1bba1684de063 100644 (file)
@@ -5,7 +5,7 @@
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
-  by the Free Software Foundation; either version 2 of the License,
+  by the Free Software Foundation; either version 2.1 of the License,
   or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
   or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
@@ -23,8 +23,6 @@
 #include <config.h>
 #endif
 
 #include <config.h>
 #endif
 
-#include <sys/time.h>
-#include <time.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -55,8 +53,7 @@ struct pa_memblockq {
     pa_bool_t in_prebuf;
     pa_memchunk silence;
     pa_mcalign *mcalign;
     pa_bool_t in_prebuf;
     pa_memchunk silence;
     pa_mcalign *mcalign;
-    int64_t missing;
-    size_t requested;
+    int64_t missing, requested;
 };
 
 pa_memblockq* pa_memblockq_new(
 };
 
 pa_memblockq* pa_memblockq_new(
@@ -84,13 +81,14 @@ pa_memblockq* pa_memblockq_new(
     pa_log_debug("memblockq requested: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu maxrewind=%lu",
                  (unsigned long) maxlength, (unsigned long) tlength, (unsigned long) base, (unsigned long) prebuf, (unsigned long) minreq, (unsigned long) maxrewind);
 
     pa_log_debug("memblockq requested: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu maxrewind=%lu",
                  (unsigned long) maxlength, (unsigned long) tlength, (unsigned long) base, (unsigned long) prebuf, (unsigned long) minreq, (unsigned long) maxrewind);
 
-    bq->missing = bq->requested = bq->maxlength = bq->tlength = bq->prebuf = bq->minreq = bq->maxrewind = 0;
+    bq->missing = bq->requested = 0;
+    bq->maxlength = bq->tlength = bq->prebuf = bq->minreq = bq->maxrewind = 0;
     bq->in_prebuf = TRUE;
 
     pa_memblockq_set_maxlength(bq, maxlength);
     pa_memblockq_set_tlength(bq, tlength);
     bq->in_prebuf = TRUE;
 
     pa_memblockq_set_maxlength(bq, maxlength);
     pa_memblockq_set_tlength(bq, tlength);
-    pa_memblockq_set_prebuf(bq, prebuf);
     pa_memblockq_set_minreq(bq, minreq);
     pa_memblockq_set_minreq(bq, minreq);
+    pa_memblockq_set_prebuf(bq, prebuf);
     pa_memblockq_set_maxrewind(bq, maxrewind);
 
     pa_log_debug("memblockq sanitized: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu maxrewind=%lu",
     pa_memblockq_set_maxrewind(bq, maxrewind);
 
     pa_log_debug("memblockq sanitized: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu maxrewind=%lu",
@@ -215,7 +213,7 @@ static void drop_backlog(pa_memblockq *bq) {
     int64_t boundary;
     pa_assert(bq);
 
     int64_t boundary;
     pa_assert(bq);
 
-    boundary = bq->read_index - bq->maxrewind;
+    boundary = bq->read_index - (int64_t) bq->maxrewind;
 
     while (bq->blocks && (bq->blocks->index + (int64_t) bq->blocks->chunk.length <= boundary))
         drop_block(bq, bq->blocks);
 
     while (bq->blocks && (bq->blocks->index + (int64_t) bq->blocks->chunk.length <= boundary))
         drop_block(bq, bq->blocks);
@@ -227,10 +225,10 @@ static pa_bool_t can_push(pa_memblockq *bq, size_t l) {
     pa_assert(bq);
 
     if (bq->read_index > bq->write_index) {
     pa_assert(bq);
 
     if (bq->read_index > bq->write_index) {
-        size_t d =  bq->read_index - bq->write_index;
+        int64_t d = bq->read_index - bq->write_index;
 
 
-        if (l > d)
-            l -= d;
+        if ((int64_t) l > d)
+            l -= (size_t) d;
         else
             return TRUE;
     }
         else
             return TRUE;
     }
@@ -239,16 +237,42 @@ static pa_bool_t can_push(pa_memblockq *bq, size_t l) {
 
     /* Make sure that the list doesn't get too long */
     if (bq->write_index + (int64_t) l > end)
 
     /* Make sure that the list doesn't get too long */
     if (bq->write_index + (int64_t) l > end)
-        if (bq->write_index + l - bq->read_index > bq->maxlength)
+        if (bq->write_index + (int64_t) l - bq->read_index > (int64_t) bq->maxlength)
             return FALSE;
 
     return TRUE;
 }
 
             return FALSE;
 
     return TRUE;
 }
 
+static void write_index_changed(pa_memblockq *bq, int64_t old_write_index, pa_bool_t account) {
+    int64_t delta;
+
+    pa_assert(bq);
+
+    delta = bq->write_index - old_write_index;
+
+    if (account)
+        bq->requested -= delta;
+    else
+        bq->missing -= delta;
+
+    /* pa_log("pushed/seeked %lli: requested counter at %lli, account=%i", (long long) delta, (long long) bq->requested, account); */
+}
+
+static void read_index_changed(pa_memblockq *bq, int64_t old_read_index) {
+    int64_t delta;
+
+    pa_assert(bq);
+
+    delta = bq->read_index - old_read_index;
+    bq->missing += delta;
+
+    /* pa_log("popped %lli: missing counter at %lli", (long long) delta, (long long) bq->missing); */
+}
+
 int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
     struct list_item *q, *n;
     pa_memchunk chunk;
 int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
     struct list_item *q, *n;
     pa_memchunk chunk;
-    int64_t old, delta;
+    int64_t old;
 
     pa_assert(bq);
     pa_assert(uchunk);
 
     pa_assert(bq);
     pa_assert(uchunk);
@@ -294,7 +318,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
             /* This entry isn't touched at all, let's skip it */
             q = q->prev;
         } else if (bq->write_index <= q->index &&
             /* This entry isn't touched at all, let's skip it */
             q = q->prev;
         } else if (bq->write_index <= q->index &&
-            bq->write_index + chunk.length >= q->index + q->chunk.length) {
+                   bq->write_index + (int64_t) chunk.length >= q->index + (int64_t) q->chunk.length) {
 
             /* This entry is fully replaced by the new entry, so let's drop it */
 
 
             /* This entry is fully replaced by the new entry, so let's drop it */
 
@@ -306,7 +330,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
             /* The write index points into this memblock, so let's
              * truncate or split it */
 
             /* The write index points into this memblock, so let's
              * truncate or split it */
 
-            if (bq->write_index + chunk.length < q->index + q->chunk.length) {
+            if (bq->write_index + (int64_t) chunk.length < q->index + (int64_t) q->chunk.length) {
 
                 /* We need to save the end of this memchunk */
                 struct list_item *p;
 
                 /* We need to save the end of this memchunk */
                 struct list_item *p;
@@ -320,11 +344,11 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
                 pa_memblock_ref(p->chunk.memblock);
 
                 /* Calculate offset */
                 pa_memblock_ref(p->chunk.memblock);
 
                 /* Calculate offset */
-                d = bq->write_index + chunk.length - q->index;
+                d = (size_t) (bq->write_index + (int64_t) chunk.length - q->index);
                 pa_assert(d > 0);
 
                 /* Drop it from the new entry */
                 pa_assert(d > 0);
 
                 /* Drop it from the new entry */
-                p->index = q->index + d;
+                p->index = q->index + (int64_t) d;
                 p->chunk.length -= d;
 
                 /* Add it to the list */
                 p->chunk.length -= d;
 
                 /* Add it to the list */
@@ -339,7 +363,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
             }
 
             /* Truncate the chunk */
             }
 
             /* Truncate the chunk */
-            if (!(q->chunk.length = bq->write_index - q->index)) {
+            if (!(q->chunk.length = (size_t) (bq->write_index - q->index))) {
                 struct list_item *p;
                 p = q;
                 q = q->prev;
                 struct list_item *p;
                 p = q;
                 q = q->prev;
@@ -352,13 +376,13 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
             size_t d;
 
             pa_assert(bq->write_index + (int64_t)chunk.length > q->index &&
             size_t d;
 
             pa_assert(bq->write_index + (int64_t)chunk.length > q->index &&
-                   bq->write_index + (int64_t)chunk.length < q->index + (int64_t)q->chunk.length &&
-                   bq->write_index < q->index);
+                      bq->write_index + (int64_t)chunk.length < q->index + (int64_t)q->chunk.length &&
+                      bq->write_index < q->index);
 
             /* The job overwrites the current entry at the end, so let's drop the beginning of this entry */
 
 
             /* The job overwrites the current entry at the end, so let's drop the beginning of this entry */
 
-            d = bq->write_index + chunk.length - q->index;
-            q->index += d;
+            d = (size_t) (bq->write_index + (int64_t) chunk.length - q->index);
+            q->index += (int64_t) d;
             q->chunk.index += d;
             q->chunk.length -= d;
 
             q->chunk.index += d;
             q->chunk.length -= d;
 
@@ -373,11 +397,11 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
         /* Try to merge memory blocks */
 
         if (q->chunk.memblock == chunk.memblock &&
         /* Try to merge memory blocks */
 
         if (q->chunk.memblock == chunk.memblock &&
-            q->chunk.index + (int64_t)q->chunk.length == chunk.index &&
-            bq->write_index == q->index + (int64_t)q->chunk.length) {
+            q->chunk.index + q->chunk.length == chunk.index &&
+            bq->write_index == q->index + (int64_t) q->chunk.length) {
 
             q->chunk.length += chunk.length;
 
             q->chunk.length += chunk.length;
-            bq->write_index += chunk.length;
+            bq->write_index += (int64_t) chunk.length;
             goto finish;
         }
     } else
             goto finish;
         }
     } else
@@ -389,7 +413,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
     n->chunk = chunk;
     pa_memblock_ref(n->chunk.memblock);
     n->index = bq->write_index;
     n->chunk = chunk;
     pa_memblock_ref(n->chunk.memblock);
     n->index = bq->write_index;
-    bq->write_index += n->chunk.length;
+    bq->write_index += (int64_t) n->chunk.length;
 
     n->next = q ? q->next : bq->blocks;
     n->prev = q;
 
     n->next = q ? q->next : bq->blocks;
     n->prev = q;
@@ -408,18 +432,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
 
 finish:
 
 
 finish:
 
-    delta = bq->write_index - old;
-
-    if (delta >= (int64_t) bq->requested) {
-        delta -= bq->requested;
-        bq->requested = 0;
-    } else {
-        bq->requested -= delta;
-        delta = 0;
-    }
-
-    bq->missing -= delta;
-
+    write_index_changed(bq, old, TRUE);
     return 0;
 }
 
     return 0;
 }
 
@@ -466,12 +479,11 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
 
     /* Do we need to spit out silence? */
     if (!bq->current_read || bq->current_read->index > bq->read_index) {
 
     /* Do we need to spit out silence? */
     if (!bq->current_read || bq->current_read->index > bq->read_index) {
-
         size_t length;
 
         /* How much silence shall we return? */
         if (bq->current_read)
         size_t length;
 
         /* How much silence shall we return? */
         if (bq->current_read)
-            length = bq->current_read->index - bq->read_index;
+            length = (size_t) (bq->current_read->index - bq->read_index);
         else if (bq->write_index > bq->read_index)
             length = (size_t) (bq->write_index - bq->read_index);
         else
         else if (bq->write_index > bq->read_index)
             length = (size_t) (bq->write_index - bq->read_index);
         else
@@ -506,14 +518,84 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
 
     pa_assert(bq->read_index >= bq->current_read->index);
     d = bq->read_index - bq->current_read->index;
 
     pa_assert(bq->read_index >= bq->current_read->index);
     d = bq->read_index - bq->current_read->index;
-    chunk->index += d;
-    chunk->length -= d;
+    chunk->index += (size_t) d;
+    chunk->length -= (size_t) d;
+
+    return 0;
+}
+
+int pa_memblockq_peek_fixed_size(pa_memblockq *bq, size_t block_size, pa_memchunk *chunk) {
+    pa_memchunk tchunk, rchunk;
+    int64_t ri;
+    struct list_item *item;
+
+    pa_assert(bq);
+    pa_assert(block_size > 0);
+    pa_assert(chunk);
+    pa_assert(bq->silence.memblock);
+
+    if (pa_memblockq_peek(bq, &tchunk) < 0)
+        return -1;
+
+    if (tchunk.length >= block_size) {
+        *chunk = tchunk;
+        chunk->length = block_size;
+        return 0;
+    }
+
+    rchunk.memblock = pa_memblock_new(pa_memblock_get_pool(tchunk.memblock), block_size);
+    rchunk.index = 0;
+    rchunk.length = tchunk.length;
+
+    pa_memchunk_memcpy(&rchunk, &tchunk);
+    pa_memblock_unref(tchunk.memblock);
+
+    rchunk.index += tchunk.length;
+
+    /* We don't need to call fix_current_read() here, since
+     * pa_memblock_peek() already did that */
+    item = bq->current_read;
+    ri = bq->read_index + tchunk.length;
+
+    while (rchunk.index < block_size) {
+
+        if (!item || item->index > ri) {
+            /* Do we need to append silence? */
+            tchunk = bq->silence;
+
+            if (item)
+                tchunk.length = PA_MIN(tchunk.length, (size_t) (item->index - ri));
+
+        } else {
+            int64_t d;
+
+            /* We can append real data! */
+            tchunk = item->chunk;
+
+            d = ri - item->index;
+            tchunk.index += (size_t) d;
+            tchunk.length -= (size_t) d;
+
+            /* Go to next item for the next iteration */
+            item = item->next;
+        }
+
+        rchunk.length = tchunk.length = PA_MIN(tchunk.length, block_size - rchunk.index);
+        pa_memchunk_memcpy(&rchunk, &tchunk);
+
+        rchunk.index += rchunk.length;
+        ri += rchunk.length;
+    }
+
+    rchunk.index = 0;
+    rchunk.length = block_size;
 
 
+    *chunk = rchunk;
     return 0;
 }
 
 void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
     return 0;
 }
 
 void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
-    int64_t old, delta;
+    int64_t old;
     pa_assert(bq);
     pa_assert(length % bq->base == 0);
 
     pa_assert(bq);
     pa_assert(length % bq->base == 0);
 
@@ -533,38 +615,40 @@ void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
             /* We go through this piece by piece to make sure we don't
              * drop more than allowed by prebuf */
 
             /* We go through this piece by piece to make sure we don't
              * drop more than allowed by prebuf */
 
-            p = bq->current_read->index + bq->current_read->chunk.length;
+            p = bq->current_read->index + (int64_t) bq->current_read->chunk.length;
             pa_assert(p >= bq->read_index);
             d = p - bq->read_index;
 
             if (d > (int64_t) length)
             pa_assert(p >= bq->read_index);
             d = p - bq->read_index;
 
             if (d > (int64_t) length)
-                d = length;
+                d = (int64_t) length;
 
             bq->read_index += d;
 
             bq->read_index += d;
-            length -= d;
+            length -= (size_t) d;
 
         } else {
 
             /* The list is empty, there's nothing we could drop */
 
         } else {
 
             /* The list is empty, there's nothing we could drop */
-            bq->read_index += length;
+            bq->read_index += (int64_t) length;
             break;
         }
     }
 
     drop_backlog(bq);
             break;
         }
     }
 
     drop_backlog(bq);
-
-    delta = bq->read_index - old;
-    bq->missing += delta;
+    read_index_changed(bq, old);
 }
 
 void pa_memblockq_rewind(pa_memblockq *bq, size_t length) {
 }
 
 void pa_memblockq_rewind(pa_memblockq *bq, size_t length) {
+    int64_t old;
     pa_assert(bq);
     pa_assert(length % bq->base == 0);
 
     pa_assert(bq);
     pa_assert(length % bq->base == 0);
 
+    old = bq->read_index;
+
     /* This is kind of the inverse of pa_memblockq_drop() */
 
     /* This is kind of the inverse of pa_memblockq_drop() */
 
-    bq->read_index -= length;
-    bq->missing -= length;
+    bq->read_index -= (int64_t) length;
+
+    read_index_changed(bq, old);
 }
 
 pa_bool_t pa_memblockq_is_readable(pa_memblockq *bq) {
 }
 
 pa_bool_t pa_memblockq_is_readable(pa_memblockq *bq) {
@@ -600,8 +684,8 @@ size_t pa_memblockq_missing(pa_memblockq *bq) {
     return l >= bq->minreq ? l : 0;
 }
 
     return l >= bq->minreq ? l : 0;
 }
 
-void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) {
-    int64_t old, delta;
+void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek, pa_bool_t account) {
+    int64_t old;
     pa_assert(bq);
 
     old = bq->write_index;
     pa_assert(bq);
 
     old = bq->write_index;
@@ -624,22 +708,11 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) {
     }
 
     drop_backlog(bq);
     }
 
     drop_backlog(bq);
-
-    delta = bq->write_index - old;
-
-    if (delta >= (int64_t) bq->requested) {
-        delta -= bq->requested;
-        bq->requested = 0;
-    } else if (delta >= 0) {
-        bq->requested -= delta;
-        delta = 0;
-    }
-
-    bq->missing -= delta;
+    write_index_changed(bq, old, account);
 }
 
 }
 
-void pa_memblockq_flush_write(pa_memblockq *bq) {
-    int64_t old, delta;
+void pa_memblockq_flush_write(pa_memblockq *bq, pa_bool_t account) {
+    int64_t old;
     pa_assert(bq);
 
     pa_memblockq_silence(bq);
     pa_assert(bq);
 
     pa_memblockq_silence(bq);
@@ -648,22 +721,11 @@ void pa_memblockq_flush_write(pa_memblockq *bq) {
     bq->write_index = bq->read_index;
 
     pa_memblockq_prebuf_force(bq);
     bq->write_index = bq->read_index;
 
     pa_memblockq_prebuf_force(bq);
-
-    delta = bq->write_index - old;
-
-    if (delta >= (int64_t) bq->requested) {
-        delta -= bq->requested;
-        bq->requested = 0;
-    } else if (delta >= 0) {
-        bq->requested -= delta;
-        delta = 0;
-    }
-
-    bq->missing -= delta;
+    write_index_changed(bq, old, account);
 }
 
 void pa_memblockq_flush_read(pa_memblockq *bq) {
 }
 
 void pa_memblockq_flush_read(pa_memblockq *bq) {
-    int64_t old, delta;
+    int64_t old;
     pa_assert(bq);
 
     pa_memblockq_silence(bq);
     pa_assert(bq);
 
     pa_memblockq_silence(bq);
@@ -672,9 +734,7 @@ void pa_memblockq_flush_read(pa_memblockq *bq) {
     bq->read_index = bq->write_index;
 
     pa_memblockq_prebuf_force(bq);
     bq->read_index = bq->write_index;
 
     pa_memblockq_prebuf_force(bq);
-
-    delta = bq->read_index - old;
-    bq->missing += delta;
+    read_index_changed(bq, old);
 }
 
 size_t pa_memblockq_get_tlength(pa_memblockq *bq) {
 }
 
 size_t pa_memblockq_get_tlength(pa_memblockq *bq) {
@@ -689,6 +749,12 @@ size_t pa_memblockq_get_minreq(pa_memblockq *bq) {
     return bq->minreq;
 }
 
     return bq->minreq;
 }
 
+size_t pa_memblockq_get_maxrewind(pa_memblockq *bq) {
+    pa_assert(bq);
+
+    return bq->maxrewind;
+}
+
 int64_t pa_memblockq_get_read_index(pa_memblockq *bq) {
     pa_assert(bq);
 
 int64_t pa_memblockq_get_read_index(pa_memblockq *bq) {
     pa_assert(bq);
 
@@ -765,8 +831,11 @@ size_t pa_memblockq_pop_missing(pa_memblockq *bq) {
         return 0;
 
     l = (size_t) bq->missing;
         return 0;
 
     l = (size_t) bq->missing;
+
+    bq->requested += bq->missing;
     bq->missing = 0;
     bq->missing = 0;
-    bq->requested += l;
+
+    /* pa_log("sent %lli: request counter is at %lli", (long long) l, (long long) bq->requested); */
 
     return l;
 }
 
     return l;
 }
@@ -781,16 +850,13 @@ void pa_memblockq_set_maxlength(pa_memblockq *bq, size_t maxlength) {
 
     if (bq->tlength > bq->maxlength)
         pa_memblockq_set_tlength(bq, bq->maxlength);
 
     if (bq->tlength > bq->maxlength)
         pa_memblockq_set_tlength(bq, bq->maxlength);
-
-    if (bq->prebuf > bq->maxlength)
-        pa_memblockq_set_prebuf(bq, bq->maxlength);
 }
 
 void pa_memblockq_set_tlength(pa_memblockq *bq, size_t tlength) {
     size_t old_tlength;
     pa_assert(bq);
 
 }
 
 void pa_memblockq_set_tlength(pa_memblockq *bq, size_t tlength) {
     size_t old_tlength;
     pa_assert(bq);
 
-    if (tlength <= 0)
+    if (tlength <= 0 || tlength == (size_t) -1)
         tlength = bq->maxlength;
 
     old_tlength = bq->tlength;
         tlength = bq->maxlength;
 
     old_tlength = bq->tlength;
@@ -799,55 +865,72 @@ void pa_memblockq_set_tlength(pa_memblockq *bq, size_t tlength) {
     if (bq->tlength > bq->maxlength)
         bq->tlength = bq->maxlength;
 
     if (bq->tlength > bq->maxlength)
         bq->tlength = bq->maxlength;
 
-    if (bq->prebuf > bq->tlength)
-        pa_memblockq_set_prebuf(bq, bq->tlength);
-
     if (bq->minreq > bq->tlength)
         pa_memblockq_set_minreq(bq, bq->tlength);
 
     if (bq->minreq > bq->tlength)
         pa_memblockq_set_minreq(bq, bq->tlength);
 
+    if (bq->prebuf > bq->tlength+bq->base-bq->minreq)
+        pa_memblockq_set_prebuf(bq, bq->tlength+bq->base-bq->minreq);
+
     bq->missing += (int64_t) bq->tlength - (int64_t) old_tlength;
 }
 
     bq->missing += (int64_t) bq->tlength - (int64_t) old_tlength;
 }
 
+void pa_memblockq_set_minreq(pa_memblockq *bq, size_t minreq) {
+    pa_assert(bq);
+
+    bq->minreq = (minreq/bq->base)*bq->base;
+
+    if (bq->minreq > bq->tlength)
+        bq->minreq = bq->tlength;
+
+    if (bq->minreq < bq->base)
+        bq->minreq = bq->base;
+
+    if (bq->prebuf > bq->tlength+bq->base-bq->minreq)
+        pa_memblockq_set_prebuf(bq, bq->tlength+bq->base-bq->minreq);
+}
+
 void pa_memblockq_set_prebuf(pa_memblockq *bq, size_t prebuf) {
     pa_assert(bq);
 
     if (prebuf == (size_t) -1)
 void pa_memblockq_set_prebuf(pa_memblockq *bq, size_t prebuf) {
     pa_assert(bq);
 
     if (prebuf == (size_t) -1)
-        prebuf = bq->tlength;
+        prebuf = bq->tlength+bq->base-bq->minreq;
 
     bq->prebuf = ((prebuf+bq->base-1)/bq->base)*bq->base;
 
     if (prebuf > 0 && bq->prebuf < bq->base)
         bq->prebuf = bq->base;
 
 
     bq->prebuf = ((prebuf+bq->base-1)/bq->base)*bq->base;
 
     if (prebuf > 0 && bq->prebuf < bq->base)
         bq->prebuf = bq->base;
 
-    if (bq->prebuf > bq->tlength)
-        bq->prebuf = bq->tlength;
+    if (bq->prebuf > bq->tlength+bq->base-bq->minreq)
+        bq->prebuf = bq->tlength+bq->base-bq->minreq;
 
     if (bq->prebuf <= 0 || pa_memblockq_get_length(bq) >= bq->prebuf)
         bq->in_prebuf = FALSE;
 
     if (bq->prebuf <= 0 || pa_memblockq_get_length(bq) >= bq->prebuf)
         bq->in_prebuf = FALSE;
-
-    if (bq->minreq > bq->prebuf)
-        pa_memblockq_set_minreq(bq, bq->prebuf);
 }
 
 }
 
-void pa_memblockq_set_minreq(pa_memblockq *bq, size_t minreq) {
+void pa_memblockq_set_maxrewind(pa_memblockq *bq, size_t maxrewind) {
     pa_assert(bq);
 
     pa_assert(bq);
 
-    bq->minreq = (minreq/bq->base)*bq->base;
-
-    if (bq->minreq > bq->tlength)
-        bq->minreq = bq->tlength;
+    bq->maxrewind = (maxrewind/bq->base)*bq->base;
+}
 
 
-    if (bq->minreq > bq->prebuf)
-        bq->minreq = bq->prebuf;
+void pa_memblockq_apply_attr(pa_memblockq *bq, const pa_buffer_attr *a) {
+    pa_assert(bq);
+    pa_assert(a);
 
 
-    if (bq->minreq < bq->base)
-        bq->minreq = bq->base;
+    pa_memblockq_set_maxlength(bq, a->maxlength);
+    pa_memblockq_set_tlength(bq, a->tlength);
+    pa_memblockq_set_prebuf(bq, a->prebuf);
+    pa_memblockq_set_minreq(bq, a->minreq);
 }
 
 }
 
-void pa_memblockq_set_maxrewind(pa_memblockq *bq, size_t maxrewind) {
+void pa_memblockq_get_attr(pa_memblockq *bq, pa_buffer_attr *a) {
     pa_assert(bq);
     pa_assert(bq);
+    pa_assert(a);
 
 
-    bq->maxrewind = (maxrewind/bq->base)*bq->base;
+    a->maxlength = (uint32_t) pa_memblockq_get_maxlength(bq);
+    a->tlength = (uint32_t) pa_memblockq_get_tlength(bq);
+    a->prebuf = (uint32_t) pa_memblockq_get_prebuf(bq);
+    a->minreq = (uint32_t) pa_memblockq_get_minreq(bq);
 }
 
 int pa_memblockq_splice(pa_memblockq *bq, pa_memblockq *source) {
 }
 
 int pa_memblockq_splice(pa_memblockq *bq, pa_memblockq *source) {
@@ -874,7 +957,7 @@ int pa_memblockq_splice(pa_memblockq *bq, pa_memblockq *source) {
 
             pa_memblock_unref(chunk.memblock);
         } else
 
             pa_memblock_unref(chunk.memblock);
         } else
-            pa_memblockq_seek(bq, chunk.length, PA_SEEK_RELATIVE);
+            pa_memblockq_seek(bq, (int64_t) chunk.length, PA_SEEK_RELATIVE, TRUE);
 
         pa_memblockq_drop(bq, chunk.length);
     }
 
         pa_memblockq_drop(bq, chunk.length);
     }