Пример #1
0
/* Called from thread context */
static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
    connection *c;

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

    if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) {

        c->playback.underrun = true;

        if (c->dead && pa_sink_input_safe_to_remove(i))
            pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL);

        return -1;
    } else {
        size_t m;

        chunk->length = PA_MIN(length, chunk->length);

        c->playback.underrun = false;

        pa_memblockq_drop(c->input_memblockq, chunk->length);
        m = pa_memblockq_pop_missing(c->input_memblockq);

        if (m > 0)
            if (pa_atomic_add(&c->playback.missing, (int) m) <= 0)
                pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);

        return 0;
    }
}
Пример #2
0
static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
    memblockq_stream *u;

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

    if (!u->memblockq)
        return -1;

    if (pa_memblockq_peek(u->memblockq, chunk) < 0) {

        if (pa_sink_input_safe_to_remove(i)) {

            pa_memblockq_free(u->memblockq);
            u->memblockq = NULL;

            pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u), MEMBLOCKQ_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
        }

        return -1;
    }

    /* If there's no memblock, there's going to be data in the memblockq after
     * a gap with length chunk->length. Drop the the gap and peek the actual
     * data. There should always be some data coming - hence the assert. The
     * gap will occur if the memblockq is rewound beyond index 0.*/
    if (!chunk->memblock) {
        pa_memblockq_drop(u->memblockq, chunk->length);
        pa_assert_se(pa_memblockq_peek(u->memblockq, chunk) >= 0);
    }

    chunk->length = PA_MIN(chunk->length, nbytes);
    pa_memblockq_drop(u->memblockq, chunk->length);

    return 0;
}
Пример #3
0
/* Called from IO thread context */
static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
    file_stream *u;

    pa_sink_input_assert_ref(i);
    pa_assert(chunk);
    u = FILE_STREAM(i->userdata);
    file_stream_assert_ref(u);

    if (!u->memblockq)
        return -1;

    for (;;) {
        pa_memchunk tchunk;
        size_t fs;
        void *p;
        sf_count_t n;

        if (pa_memblockq_peek(u->memblockq, chunk) >= 0) {
            chunk->length = PA_MIN(chunk->length, length);
            pa_memblockq_drop(u->memblockq, chunk->length);
            return 0;
        }

        if (!u->sndfile)
            break;

        tchunk.memblock = pa_memblock_new(i->sink->core->mempool, length);
        tchunk.index = 0;

        p = pa_memblock_acquire(tchunk.memblock);

        if (u->readf_function) {
            fs = pa_frame_size(&i->sample_spec);
            n = u->readf_function(u->sndfile, p, (sf_count_t) (length/fs));
        } else {
            fs = 1;
            n = sf_read_raw(u->sndfile, p, (sf_count_t) length);
        }

        pa_memblock_release(tchunk.memblock);

        if (n <= 0) {
            pa_memblock_unref(tchunk.memblock);

            sf_close(u->sndfile);
            u->sndfile = NULL;
            break;
        }

        tchunk.length = (size_t) n * fs;

        pa_memblockq_push(u->memblockq, &tchunk);
        pa_memblock_unref(tchunk.memblock);
    }

    if (pa_sink_input_safe_to_remove(i)) {
        pa_memblockq_free(u->memblockq);
        u->memblockq = NULL;

        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u), FILE_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
    }

    return -1;
}