summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2010-02-25 02:10:45 +0100
committerArun Raghavan <arun.raghavan@collabora.co.uk>2011-03-28 14:40:59 +0530
commitc524b4c5b59a11c0a85d27d64dfb607246abc141 (patch)
treec01814bbdaf1bff369f9689d268c010320cd8ec5
parent9f52c1064651667f48877f54ae002e97eecd6289 (diff)
memblockq: implement new call pa_memblockq_peek_fixed_size()
-rw-r--r--src/pulsecore/memblockq.c71
-rw-r--r--src/pulsecore/memblockq.h5
-rw-r--r--src/tests/memblockq-test.c44
3 files changed, 107 insertions, 13 deletions
diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index 2b063fac..c7840484 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -481,7 +481,6 @@ 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) {
-
size_t length;
/* How much silence shall we return? */
@@ -527,6 +526,76 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
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) {
int64_t old;
pa_assert(bq);
diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h
index 6132f31b..3775c3f3 100644
--- a/src/pulsecore/memblockq.h
+++ b/src/pulsecore/memblockq.h
@@ -95,6 +95,11 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek, pa
* was passed we return the length of the hole in chunk->length. */
int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk);
+/* Much like pa_memblockq_peek, but guarantees that the returned chunk
+ * will have a length of the block size passed. You must configure a
+ * silence memchunk for this memblockq if you use this call. */
+int pa_memblockq_peek_fixed_size(pa_memblockq *bq, size_t block_size, pa_memchunk *chunk);
+
/* Drop the specified bytes from the queue. */
void pa_memblockq_drop(pa_memblockq *bq, size_t length);
diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c
index ec3f5426..c3afd0a6 100644
--- a/src/tests/memblockq-test.c
+++ b/src/tests/memblockq-test.c
@@ -29,23 +29,43 @@
#include <pulsecore/memblockq.h>
#include <pulsecore/log.h>
+static void dump_chunk(const pa_memchunk *chunk) {
+ size_t n;
+ void *q;
+ char *e;
+
+ pa_assert(chunk);
+
+ printf("[");
+
+ q = pa_memblock_acquire(chunk->memblock);
+ for (e = (char*) q + chunk->index, n = 0; n < chunk->length; n++, e++)
+ printf("%c", *e);
+ pa_memblock_release(chunk->memblock);
+
+ printf("]");
+}
+
static void dump(pa_memblockq *bq) {
- printf(">");
+ pa_memchunk out;
- for (;;) {
- pa_memchunk out;
- char *e;
- size_t n;
- void *q;
+ pa_assert(bq);
+
+ /* First let's dump this as fixed block */
+ printf("FIXED >");
+ pa_memblockq_peek_fixed_size(bq, 64, &out);
+ dump_chunk(&out);
+ pa_memblock_unref(out.memblock);
+ printf("<\n");
+ /* Then let's dump the queue manually */
+ printf("MANUAL>");
+
+ for (;;) {
if (pa_memblockq_peek(bq, &out) < 0)
break;
- q = pa_memblock_acquire(out.memblock);
- for (e = (char*) q + out.index, n = 0; n < out.length; n++)
- printf("%c", *e);
- pa_memblock_release(out.memblock);
-
+ dump_chunk(&out);
pa_memblock_unref(out.memblock);
pa_memblockq_drop(bq, out.length);
}
@@ -70,7 +90,7 @@ int main(int argc, char *argv[]) {
silence.index = 0;
silence.length = pa_memblock_get_length(silence.memblock);
- bq = pa_memblockq_new(0, 40, 10, 2, 4, 4, 40, &silence);
+ bq = pa_memblockq_new(0, 200, 10, 2, 4, 4, 40, &silence);
assert(bq);
chunk1.memblock = pa_memblock_new_fixed(p, (char*) "11", 2, 1);