/* Called from I/O thread context */
static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
    struct userdata *u;
    size_t amount = 0;

    pa_sink_input_assert_ref(i);
    pa_assert_se(u = i->userdata);

    if (u->sink->thread_info.rewind_nbytes > 0) {
        size_t max_rewrite;

        max_rewrite = nbytes + pa_memblockq_get_length(u->memblockq);
        amount = PA_MIN(u->sink->thread_info.rewind_nbytes, max_rewrite);
        u->sink->thread_info.rewind_nbytes = 0;

        if (amount > 0) {
            unsigned c;

            pa_memblockq_seek(u->memblockq, - (int64_t) amount, PA_SEEK_RELATIVE, TRUE);

            pa_log_debug("Resetting plugin");

            /* Reset the plugin */
            if (u->descriptor->deactivate)
                for (c = 0; c < (u->channels / u->max_ladspaport_count); c++)
                    u->descriptor->deactivate(u->handle[c]);
            if (u->descriptor->activate)
                for (c = 0; c < (u->channels / u->max_ladspaport_count); c++)
                    u->descriptor->activate(u->handle[c]);
        }
    }

    pa_sink_process_rewind(u->sink, amount);
    pa_memblockq_rewind(u->memblockq, nbytes);
}
Exemple #2
0
/* Called from thread context */
void pa_source_output_process_rewind(pa_source_output *o, size_t nbytes /* in source sample spec */) {

    pa_source_output_assert_ref(o);
    pa_source_output_assert_io_context(o);
    pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->thread_info.state));
    pa_assert(pa_frame_aligned(nbytes, &o->source->sample_spec));

    if (nbytes <= 0)
        return;

    if (o->process_rewind) {
        pa_assert(pa_memblockq_get_length(o->thread_info.delay_memblockq) == 0);

        if (o->thread_info.resampler)
            nbytes = pa_resampler_result(o->thread_info.resampler, nbytes);

        pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) nbytes);

        if (nbytes > 0)
            o->process_rewind(o, nbytes);

        if (o->thread_info.resampler)
            pa_resampler_reset(o->thread_info.resampler);

    } else
        pa_memblockq_rewind(o->thread_info.delay_memblockq, nbytes);
}
/* Called from I/O thread context */
static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
    struct userdata *u;
    size_t amount = 0;

    pa_sink_input_assert_ref(i);
    pa_assert_se(u = i->userdata);

    if (u->sink->thread_info.rewind_nbytes > 0) {
        size_t max_rewrite;

        max_rewrite = nbytes * u->sink_fs / u->fs + pa_memblockq_get_length(u->memblockq);
        amount = PA_MIN(u->sink->thread_info.rewind_nbytes * u->sink_fs / u->fs, max_rewrite);
        u->sink->thread_info.rewind_nbytes = 0;

        if (amount > 0) {
            pa_memblockq_seek(u->memblockq, - (int64_t) amount, PA_SEEK_RELATIVE, true);

            /* Reset the input buffer */
            memset(u->input_buffer, 0, u->hrir_samples * u->sink_fs);
            u->input_buffer_offset = 0;
        }
    }

    pa_sink_process_rewind(u->sink, amount);
    pa_memblockq_rewind(u->memblockq, nbytes * u->sink_fs / u->fs);
}
Exemple #4
0
/* Called from I/O thread context */
static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
    struct session *s;

    pa_sink_input_assert_ref(i);
    pa_assert_se(s = i->userdata);

    pa_memblockq_rewind(s->memblockq, nbytes);
}
/* Called from output thread context */
static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
    struct userdata *u;

    pa_sink_input_assert_ref(i);
    pa_sink_input_assert_io_context(i);
    pa_assert_se(u = i->userdata);

    pa_memblockq_rewind(u->memblockq, nbytes);
}
static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
    memblockq_stream *u;

    pa_sink_input_assert_ref(i);
    u = MEMBLOCKQ_STREAM(i->userdata);
    memblockq_stream_assert_ref(u);

    if (!u->memblockq)
        return;

    pa_memblockq_rewind(u->memblockq, nbytes);
}
/* Called from thread context */
static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
    connection *c;

    pa_sink_input_assert_ref(i);
    c = CONNECTION(i->userdata);
    connection_assert_ref(c);

    /* If we are in an underrun, then we don't rewind */
    if (i->thread_info.underrun_for > 0)
        return;

    pa_memblockq_rewind(c->input_memblockq, nbytes);
}
/* Called from I/O thread context */
static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
    struct userdata *u;
    size_t amount = 0;

    pa_sink_input_assert_ref(i);
    pa_assert_se(u = i->userdata);

    if (u->sink->thread_info.rewind_nbytes > 0) {
        size_t max_rewrite;

        max_rewrite = nbytes + pa_memblockq_get_length(u->memblockq);
        amount = PA_MIN(u->sink->thread_info.rewind_nbytes, max_rewrite);
        u->sink->thread_info.rewind_nbytes = 0;

        if (amount > 0) {
            pa_memblockq_seek(u->memblockq, - (int64_t) amount, PA_SEEK_RELATIVE, TRUE);

            /* (5) PUT YOUR CODE HERE TO RESET YOUR FILTER  */
        }
    }

    pa_sink_process_rewind(u->sink, amount);
    pa_memblockq_rewind(u->memblockq, nbytes);
}
int main(int argc, char *argv[]) {
    int ret;

    pa_mempool *p;
    pa_memblockq *bq;
    pa_memchunk chunk1, chunk2, chunk3, chunk4;
    pa_memchunk silence;
    pa_sample_spec ss = {
        .format = PA_SAMPLE_S16LE,
        .rate = 48000,
        .channels = 1
    };

    pa_log_set_level(PA_LOG_DEBUG);

    p = pa_mempool_new(FALSE, 0);

    pa_assert_se(silence.memblock = pa_memblock_new_fixed(p, (char*) "__", 2, 1));
    silence.index = 0;
    silence.length = pa_memblock_get_length(silence.memblock);

    pa_assert_se(bq = pa_memblockq_new("test memblockq", 0, 200, 10, &ss, 4, 4, 40, &silence));

    pa_assert_se(chunk1.memblock = pa_memblock_new_fixed(p, (char*) "11", 2, 1));
    chunk1.index = 0;
    chunk1.length = 2;

    pa_assert_se(chunk2.memblock = pa_memblock_new_fixed(p, (char*) "XX22", 4, 1));
    chunk2.index = 2;
    chunk2.length = 2;

    pa_assert_se(chunk3.memblock = pa_memblock_new_fixed(p, (char*) "3333", 4, 1));
    chunk3.index = 0;
    chunk3.length = 4;

    pa_assert_se(chunk4.memblock = pa_memblock_new_fixed(p, (char*) "44444444", 8, 1));
    chunk4.index = 0;
    chunk4.length = 8;

    ret = pa_memblockq_push(bq, &chunk1);
    assert(ret == 0);

    ret = pa_memblockq_push(bq, &chunk2);
    assert(ret == 0);

    ret = pa_memblockq_push(bq, &chunk3);
    assert(ret == 0);

    ret = pa_memblockq_push(bq, &chunk4);
    assert(ret == 0);

    pa_memblockq_seek(bq, -6, 0, TRUE);
    ret = pa_memblockq_push(bq, &chunk3);
    assert(ret == 0);

    pa_memblockq_seek(bq, -2, 0, TRUE);
    ret = pa_memblockq_push(bq, &chunk1);
    assert(ret == 0);

    pa_memblockq_seek(bq, -10, 0, TRUE);
    ret = pa_memblockq_push(bq, &chunk4);
    assert(ret == 0);

    pa_memblockq_seek(bq, 10, 0, TRUE);

    ret = pa_memblockq_push(bq, &chunk1);
    assert(ret == 0);

    pa_memblockq_seek(bq, -6, 0, TRUE);
    ret = pa_memblockq_push(bq, &chunk2);
    assert(ret == 0);

    /* Test splitting */
    pa_memblockq_seek(bq, -12, 0, TRUE);
    ret = pa_memblockq_push(bq, &chunk1);
    assert(ret == 0);

    pa_memblockq_seek(bq, 20, 0, TRUE);

    /* Test merging */
    ret = pa_memblockq_push(bq, &chunk3);
    assert(ret == 0);
    pa_memblockq_seek(bq, -2, 0, TRUE);

    chunk3.index += 2;
    chunk3.length -= 2;
    ret = pa_memblockq_push(bq, &chunk3);
    assert(ret == 0);

    pa_memblockq_seek(bq, 30, PA_SEEK_RELATIVE, TRUE);

    dump(bq);

    pa_memblockq_rewind(bq, 52);

    dump(bq);

    pa_memblockq_free(bq);
    pa_memblock_unref(silence.memblock);
    pa_memblock_unref(chunk1.memblock);
    pa_memblock_unref(chunk2.memblock);
    pa_memblock_unref(chunk3.memblock);
    pa_memblock_unref(chunk4.memblock);

    pa_mempool_free(p);

    return 0;
}