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

int pa_stream_get_time ( pa_stream s,
pa_usec_t r_usec 
)

Return the current playback/recording time. This is based on the data in the timing info structure returned by pa_stream_get_timing_info(). This function will usually only return new data if a timing info update has been recieved. Only if timing interpolation has been requested (PA_STREAM_INTERPOLATE_TIMING) the data from the last timing update is used for an estimation of the current playback/recording time based on the local time that passed since the timing info structure has been acquired. The time value returned by this function is guaranteed to increase monotonically. (that means: the returned value is always greater or equal to the value returned on the last call) This behaviour can be disabled by using PA_STREAM_NOT_MONOTONOUS. This may be desirable to deal better with bad estimations of transport latencies, but may have strange effects if the application is not able to deal with time going 'backwards'.

Since:
0.6

Definition at line 1464 of file stream.c.

References PA_ERR_BADSTATE, PA_ERR_NODATA, PA_STREAM_INTERPOLATE_TIMING, PA_STREAM_NOT_MONOTONOUS, PA_STREAM_PLAYBACK, PA_STREAM_READY, PA_STREAM_RECORD, and PA_STREAM_UPLOAD.

                                                        {
    pa_usec_t usec = 0;

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

    PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    PA_CHECK_VALIDITY(s->context, s->timing_info_valid, PA_ERR_NODATA);
    PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_PLAYBACK || !s->timing_info.read_index_corrupt, PA_ERR_NODATA);
    PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_RECORD || !s->timing_info.write_index_corrupt, PA_ERR_NODATA);

    if (s->cached_time_valid)
        /* We alredy calculated the time value for this timing info, so let's reuse it */
        usec = s->cached_time;
    else {
        if (s->direction == PA_STREAM_PLAYBACK) {
            /* The last byte that was written into the output device
             * had this time value associated */
            usec = pa_bytes_to_usec(s->timing_info.read_index < 0 ? 0 : (uint64_t) s->timing_info.read_index, &s->sample_spec);

            if (!s->corked) {
                /* Because the latency info took a little time to come
                 * to us, we assume that the real output time is actually
                 * a little ahead */
                usec += s->timing_info.transport_usec;

                /* However, the output device usually maintains a buffer
                   too, hence the real sample currently played is a little
                   back  */
                if (s->timing_info.sink_usec >= usec)
                    usec = 0;
                else
                    usec -= s->timing_info.sink_usec;
            }

        } else if (s->direction == PA_STREAM_RECORD) {
            /* The last byte written into the server side queue had
             * this time value associated */
            usec = pa_bytes_to_usec(s->timing_info.write_index < 0 ? 0 : (uint64_t) s->timing_info.write_index, &s->sample_spec);

            if (!s->corked) {
                /* Add transport latency */
                usec += s->timing_info.transport_usec;

                /* Add latency of data in device buffer */
                usec += s->timing_info.source_usec;

                /* If this is a monitor source, we need to correct the
                 * time by the playback device buffer */
                if (s->timing_info.sink_usec >= usec)
                    usec = 0;
                else
                    usec -= s->timing_info.sink_usec;
            }
        }

        s->cached_time = usec;
        s->cached_time_valid = 1;
    }

    /* Interpolate if requested */
    if (s->flags & PA_STREAM_INTERPOLATE_TIMING) {

        /* We just add the time that passed since the latency info was
         * current */
        if (!s->corked && s->timing_info.playing) {
            struct timeval now;
            usec += pa_timeval_diff(pa_gettimeofday(&now), &s->timing_info.timestamp);
        }
    }

    /* Make sure the time runs monotonically */
    if (!(s->flags & PA_STREAM_NOT_MONOTONOUS)) {
        if (usec < s->previous_time)
            usec = s->previous_time;
        else
            s->previous_time = usec;
    }

    if (r_usec)
        *r_usec = usec;

    return 0;
}


Generated by  Doxygen 1.6.0   Back to index