diff options
| -rw-r--r-- | src/pulsecore/memblockq.c | 71 | ||||
| -rw-r--r-- | src/pulsecore/memblockq.h | 5 | ||||
| -rw-r--r-- | src/tests/memblockq-test.c | 44 | 
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); | 
