Logo Search packages:      
Sourcecode: pulseaudio version File versions  Download package

int pa_stream_write ( pa_stream p,
const void *  data,
size_t  nbytes,
pa_free_cb_t  free_cb,
int64_t  offset,
pa_seek_mode_t  seek 
)

Write some data to the server (for playback streams), if free_cb is non-NULL this routine is called when all data has been written out and an internal reference to the specified data is kept, the data is not copied. If NULL, the data is copied into an internal buffer. The client may freely seek around in the output buffer. For most applications passing 0 and PA_SEEK_RELATIVE as arguments for offset and seek should be useful. After the write call succeeded the write index will be at the position after where this chunk of data has been written to.

As an optimization for avoiding needless memory copies you may call pa_stream_begin_write() before this call and then place your audio data directly in the memory area returned by that call. Then, pass a pointer to that memory area to pa_stream_write(). After the invocation of pa_stream_write() the memory area may no longer be accessed. Any further explicit freeing of the memory area is not necessary. It is OK to write the memory area returned by pa_stream_begin_write() only partially with this call, skipping bytes both at the end and at the beginning of the reserved memory area.

Parameters:
pThe stream to use
dataThe data to write
nbytesThe length of the data to write in bytes
free_cbA cleanup routine for the data or NULL to request an internal copy
offsetOffset for seeking, must be 0 for upload streams
seekSeek mode, must be PA_SEEK_RELATIVE for upload streams

Definition at line 1293 of file stream.c.

References PA_ERR_BADSTATE, PA_ERR_FORKED, PA_ERR_INVALID, PA_SEEK_ABSOLUTE, PA_SEEK_RELATIVE, PA_SEEK_RELATIVE_END, PA_STREAM_PLAYBACK, PA_STREAM_READY, PA_STREAM_UPLOAD, pa_timing_info::write_index, and pa_timing_info::write_index_corrupt.

                             {

    pa_assert(s);
    pa_assert(PA_REFCNT_VALUE(s) >= 1);
    pa_assert(data);

    PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_PLAYBACK || s->direction == PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    PA_CHECK_VALIDITY(s->context, seek <= PA_SEEK_RELATIVE_END, PA_ERR_INVALID);
    PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_PLAYBACK || (seek == PA_SEEK_RELATIVE && offset == 0), PA_ERR_INVALID);
    PA_CHECK_VALIDITY(s->context,
                      !s->write_memblock ||
                      ((data >= s->write_data) &&
                       ((const char*) data + length <= (const char*) s->write_data + pa_memblock_get_length(s->write_memblock))),
                      PA_ERR_INVALID);
    PA_CHECK_VALIDITY(s->context, !free_cb || !s->write_memblock, PA_ERR_INVALID);

    if (s->write_memblock) {
        pa_memchunk chunk;

        /* pa_stream_write_begin() was called before */

        pa_memblock_release(s->write_memblock);

        chunk.memblock = s->write_memblock;
        chunk.index = (const char *) data - (const char *) s->write_data;
        chunk.length = length;

        s->write_memblock = NULL;
        s->write_data = NULL;

        pa_pstream_send_memblock(s->context->pstream, s->channel, offset, seek, &chunk);
        pa_memblock_unref(chunk.memblock);

    } else {
        pa_seek_mode_t t_seek = seek;
        int64_t t_offset = offset;
        size_t t_length = length;
        const void *t_data = data;

        /* pa_stream_write_begin() was not called before */

        while (t_length > 0) {
            pa_memchunk chunk;

            chunk.index = 0;

            if (free_cb && !pa_pstream_get_shm(s->context->pstream)) {
                chunk.memblock = pa_memblock_new_user(s->context->mempool, (void*) t_data, t_length, free_cb, 1);
                chunk.length = t_length;
            } else {
                void *d;

                chunk.length = PA_MIN(t_length, pa_mempool_block_size_max(s->context->mempool));
                chunk.memblock = pa_memblock_new(s->context->mempool, chunk.length);

                d = pa_memblock_acquire(chunk.memblock);
                memcpy(d, t_data, chunk.length);
                pa_memblock_release(chunk.memblock);
            }

            pa_pstream_send_memblock(s->context->pstream, s->channel, t_offset, t_seek, &chunk);

            t_offset = 0;
            t_seek = PA_SEEK_RELATIVE;

            t_data = (const uint8_t*) t_data + chunk.length;
            t_length -= chunk.length;

            pa_memblock_unref(chunk.memblock);
        }

        if (free_cb && pa_pstream_get_shm(s->context->pstream))
            free_cb((void*) data);
    }

    /* This is obviously wrong since we ignore the seeking index . But
     * that's OK, the server side applies the same error */
    s->requested_bytes -= (seek == PA_SEEK_RELATIVE ? offset : 0) + (int64_t) length;

    /* pa_log("wrote %lli, now at %lli", (long long) length, (long long) s->requested_bytes); */

    if (s->direction == PA_STREAM_PLAYBACK) {

        /* Update latency request correction */
        if (s->write_index_corrections[s->current_write_index_correction].valid) {

            if (seek == PA_SEEK_ABSOLUTE) {
                s->write_index_corrections[s->current_write_index_correction].corrupt = FALSE;
                s->write_index_corrections[s->current_write_index_correction].absolute = TRUE;
                s->write_index_corrections[s->current_write_index_correction].value = offset + (int64_t) length;
            } else if (seek == PA_SEEK_RELATIVE) {
                if (!s->write_index_corrections[s->current_write_index_correction].corrupt)
                    s->write_index_corrections[s->current_write_index_correction].value += offset + (int64_t) length;
            } else
                s->write_index_corrections[s->current_write_index_correction].corrupt = TRUE;
        }

        /* Update the write index in the already available latency data */
        if (s->timing_info_valid) {

            if (seek == PA_SEEK_ABSOLUTE) {
                s->timing_info.write_index_corrupt = FALSE;
                s->timing_info.write_index = offset + (int64_t) length;
            } else if (seek == PA_SEEK_RELATIVE) {
                if (!s->timing_info.write_index_corrupt)
                    s->timing_info.write_index += offset + (int64_t) length;
            } else
                s->timing_info.write_index_corrupt = TRUE;
        }

        if (!s->timing_info_valid || s->timing_info.write_index_corrupt)
            request_auto_timing_update(s, TRUE);
    }

    return 0;
}

Generated by  Doxygen 1.6.0   Back to index