diff options
| author | Lennart Poettering <lennart@poettering.net> | 2009-06-22 23:09:46 +0200 | 
|---|---|---|
| committer | Lennart Poettering <lennart@poettering.net> | 2009-06-22 23:09:46 +0200 | 
| commit | fc33f7ee97da6a8b7263620775b7b74b4c754402 (patch) | |
| tree | 519635b1f72acc7613b4b7c4ad70fbc39ab3901b /src/pulse | |
| parent | 048e576a6dfe2bfe62fa33c74c30cc34057ee740 (diff) | |
| parent | e4d914c945c13d23b131d7ba75fbdd03cb6d0043 (diff) | |
Merge most of elmarco/rtclock2
Merge commit 'e4d914c945c13d23b131d7ba75fbdd03cb6d0043'
Diffstat (limited to 'src/pulse')
| -rw-r--r-- | src/pulse/context.c | 37 | ||||
| -rw-r--r-- | src/pulse/context.h | 8 | ||||
| -rw-r--r-- | src/pulse/internal.h | 1 | ||||
| -rw-r--r-- | src/pulse/mainloop-api.h | 1 | ||||
| -rw-r--r-- | src/pulse/mainloop.c | 73 | ||||
| -rw-r--r-- | src/pulse/rtclock.c | 35 | ||||
| -rw-r--r-- | src/pulse/rtclock.h | 39 | ||||
| -rw-r--r-- | src/pulse/stream.c | 24 | ||||
| -rw-r--r-- | src/pulse/timeval.h | 3 | 
9 files changed, 180 insertions, 41 deletions
diff --git a/src/pulse/context.c b/src/pulse/context.c index 3b7bf08d..b71659de 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -54,6 +54,8 @@  #include <pulse/utf8.h>  #include <pulse/util.h>  #include <pulse/i18n.h> +#include <pulse/mainloop.h> +#include <pulse/timeval.h>  #include <pulsecore/winsock.h>  #include <pulsecore/core-error.h> @@ -64,6 +66,7 @@  #include <pulsecore/dynarray.h>  #include <pulsecore/socket-client.h>  #include <pulsecore/pstream-util.h> +#include <pulsecore/core-rtclock.h>  #include <pulsecore/core-util.h>  #include <pulsecore/log.h>  #include <pulsecore/socket-util.h> @@ -540,7 +543,7 @@ static void setup_context(pa_context *c, pa_iochannel *io) {      pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);      pa_assert(!c->pdispatch); -    c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); +    c->pdispatch = pa_pdispatch_new(c->mainloop, c->use_rtclock, command_table, PA_COMMAND_MAX);      if (!c->conf->cookie_valid)          pa_log_info(_("No cookie loaded. Attempting to connect without.")); @@ -757,7 +760,7 @@ static void track_pulseaudio_on_dbus(pa_context *c, DBusBusType type, pa_dbus_wr      pa_assert(conn);      dbus_error_init(&error); -    if (!(*conn = pa_dbus_wrap_connection_new(c->mainloop, type, &error)) || dbus_error_is_set(&error)) { +    if (!(*conn = pa_dbus_wrap_connection_new(c->mainloop, c->use_rtclock, type, &error)) || dbus_error_is_set(&error)) {          pa_log_warn("Unable to contact DBUS: %s: %s", error.name, error.message);          goto finish;      } @@ -827,7 +830,7 @@ static int try_next_connection(pa_context *c) {          pa_xfree(c->server);          c->server = pa_xstrdup(u); -        if (!(c->client = pa_socket_client_new_string(c->mainloop, u, PA_NATIVE_DEFAULT_PORT))) +        if (!(c->client = pa_socket_client_new_string(c->mainloop, c->use_rtclock, u, PA_NATIVE_DEFAULT_PORT)))              continue;          c->is_local = !!pa_socket_client_is_local(c->client); @@ -1443,3 +1446,31 @@ finish:      if (pl)          pa_proplist_free(pl);  } + +pa_time_event* pa_context_rttime_new(pa_context *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata) { +    struct timeval tv; + +    pa_assert(c); +    pa_assert(c->mainloop); + +    if (usec == PA_USEC_INVALID) +        return c->mainloop->time_new(c->mainloop, NULL, cb, userdata); + +    pa_timeval_rtstore(&tv, usec, c->use_rtclock); + +    return c->mainloop->time_new(c->mainloop, &tv, cb, userdata); +} + +void pa_context_rttime_restart(pa_context *c, pa_time_event *e, pa_usec_t usec) { +    struct timeval tv; + +    pa_assert(c); +    pa_assert(c->mainloop); + +    if (usec == PA_USEC_INVALID) +        c->mainloop->time_restart(e, NULL); +    else { +        pa_timeval_rtstore(&tv, usec, c->use_rtclock); +        c->mainloop->time_restart(e, &tv); +    } +} diff --git a/src/pulse/context.h b/src/pulse/context.h index 139d0e0b..cd129313 100644 --- a/src/pulse/context.h +++ b/src/pulse/context.h @@ -260,6 +260,14 @@ pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[]   * introspection functions, such as pa_context_get_client_info(). \since 0.9.11 */  uint32_t pa_context_get_index(pa_context *s); +/** Create a new timer event source for the specified time (wrapper +    for mainloop->time_new). \since 0.9.16 */ +pa_time_event* pa_context_rttime_new(pa_context *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata); +/** Restart a running or expired timer event source (wrapper +    for mainloop->time_restart). \since 0.9.16 */ +void pa_context_rttime_restart(pa_context *c, pa_time_event *e, pa_usec_t usec); + +  PA_C_DECL_END  #endif diff --git a/src/pulse/internal.h b/src/pulse/internal.h index 28a989b3..fa5efd7d 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -89,6 +89,7 @@ struct pa_context {      pa_bool_t server_specified:1;      pa_bool_t no_fail:1;      pa_bool_t do_autospawn:1; +    pa_bool_t use_rtclock:1;      pa_spawn_api spawn_api;      pa_strlist *server_list; diff --git a/src/pulse/mainloop-api.h b/src/pulse/mainloop-api.h index e353ed96..aa0d5e73 100644 --- a/src/pulse/mainloop-api.h +++ b/src/pulse/mainloop-api.h @@ -27,6 +27,7 @@  #include <time.h>  #include <pulse/cdecl.h> +#include <pulse/sample.h>  #include <pulse/version.h>  /** \file diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c index 225fd098..5d0e0ffc 100644 --- a/src/pulse/mainloop.c +++ b/src/pulse/mainloop.c @@ -42,10 +42,12 @@  #include <pulsecore/pipe.h>  #endif +#include <pulse/i18n.h> +#include <pulse/rtclock.h>  #include <pulse/timeval.h>  #include <pulse/xmalloc.h> -#include <pulse/i18n.h> +#include <pulsecore/core-rtclock.h>  #include <pulsecore/core-util.h>  #include <pulsecore/llist.h>  #include <pulsecore/log.h> @@ -75,7 +77,7 @@ struct pa_time_event {      pa_bool_t dead:1;      pa_bool_t enabled:1; -    struct timeval timeval; +    pa_usec_t time;      pa_time_event_cb_t callback;      void *userdata; @@ -317,6 +319,23 @@ static void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy  }  /* Time events */ +static pa_usec_t timeval_load(const struct timeval *tv) { +    pa_bool_t is_rtclock; +    struct timeval ttv; + +    if (!tv) +        return PA_USEC_INVALID; + +    ttv = *tv; +    is_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK); +    ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK; + +    if (!is_rtclock) +        pa_rtclock_from_wallclock(&ttv); + +    return pa_timeval_load(&ttv); +} +  static pa_time_event* mainloop_time_new(          pa_mainloop_api*a,          const struct timeval *tv, @@ -325,11 +344,14 @@ static pa_time_event* mainloop_time_new(      pa_mainloop *m;      pa_time_event *e; +    pa_usec_t t;      pa_assert(a);      pa_assert(a->userdata);      pa_assert(callback); +    t = timeval_load(tv); +      m = a->userdata;      pa_assert(a == &m->api); @@ -337,15 +359,15 @@ static pa_time_event* mainloop_time_new(      e->mainloop = m;      e->dead = FALSE; -    if ((e->enabled = !!tv)) { -        e->timeval = *tv; +    if ((e->enabled = (t != PA_USEC_INVALID))) { +        e->time = t;          m->n_enabled_time_events++;          if (m->cached_next_time_event) {              pa_assert(m->cached_next_time_event->enabled); -            if (pa_timeval_cmp(tv, &m->cached_next_time_event->timeval) < 0) +            if (t < m->cached_next_time_event->time)                  m->cached_next_time_event = e;          }      } @@ -363,24 +385,30 @@ static pa_time_event* mainloop_time_new(  }  static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) { +    pa_bool_t valid; +    pa_usec_t t; +      pa_assert(e);      pa_assert(!e->dead); -    if (e->enabled && !tv) { +    t = timeval_load(tv); + +    valid = (t != PA_USEC_INVALID); +    if (e->enabled && !valid) {          pa_assert(e->mainloop->n_enabled_time_events > 0);          e->mainloop->n_enabled_time_events--; -    } else if (!e->enabled && tv) +    } else if (!e->enabled && valid)          e->mainloop->n_enabled_time_events++; -    if ((e->enabled = !!tv)) { -        e->timeval = *tv; +    if ((e->enabled = valid)) { +        e->time = t;          pa_mainloop_wakeup(e->mainloop);      }      if (e->mainloop->cached_next_time_event && e->enabled) {          pa_assert(e->mainloop->cached_next_time_event->enabled); -        if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0) +        if (t < e->mainloop->cached_next_time_event->time)              e->mainloop->cached_next_time_event = e;      } else if (e->mainloop->cached_next_time_event == e)          e->mainloop->cached_next_time_event = NULL; @@ -721,11 +749,11 @@ static pa_time_event* find_next_time_event(pa_mainloop *m) {          if (t->dead || !t->enabled)              continue; -        if (!n || pa_timeval_cmp(&t->timeval, &n->timeval) < 0) { +        if (!n || t->time < n->time) {              n = t; -            /* Shortcut for tv = { 0, 0 } */ -            if (n->timeval.tv_sec <= 0) +            /* Shortcut for time == 0 */ +            if (n->time == 0)                  break;          }      } @@ -736,7 +764,6 @@ static pa_time_event* find_next_time_event(pa_mainloop *m) {  static int calc_next_timeout(pa_mainloop *m) {      pa_time_event *t; -    struct timeval now;      pa_usec_t usec;      if (!m->n_enabled_time_events) @@ -745,41 +772,41 @@ static int calc_next_timeout(pa_mainloop *m) {      t = find_next_time_event(m);      pa_assert(t); -    if (t->timeval.tv_sec <= 0) +    if (t->time == 0)          return 0; -    pa_gettimeofday(&now); +    usec = t->time - pa_rtclock_now(); -    if (pa_timeval_cmp(&t->timeval, &now) <= 0) +    if (usec <= 0)          return 0; -    usec = pa_timeval_diff(&t->timeval, &now); -    return (int) (usec / 1000); +    return (int) (usec / 1000); /* in milliseconds */  }  static int dispatch_timeout(pa_mainloop *m) {      pa_time_event *e; -    struct timeval now; +    pa_usec_t now;      int r = 0;      pa_assert(m);      if (m->n_enabled_time_events <= 0)          return 0; -    pa_gettimeofday(&now); +    now = pa_rtclock_now();      for (e = m->time_events; e && !m->quit; e = e->next) {          if (e->dead || !e->enabled)              continue; -        if (pa_timeval_cmp(&e->timeval, &now) <= 0) { +        if (e->time <= now) { +            struct timeval tv;              pa_assert(e->callback);              /* Disable time event */              mainloop_time_restart(e, NULL); -            e->callback(&m->api, e, &e->timeval, e->userdata); +            e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, TRUE), e->userdata);              r++;          } diff --git a/src/pulse/rtclock.c b/src/pulse/rtclock.c new file mode 100644 index 00000000..49ff6aae --- /dev/null +++ b/src/pulse/rtclock.c @@ -0,0 +1,35 @@ +/*** +  This file is part of PulseAudio. + +  Copyright 2004-2006 Lennart Poettering + +  PulseAudio is free software; you can redistribute it and/or modify +  it under the terms of the GNU Lesser General Public License as +  published by the Free Software Foundation; either version 2.1 of the +  License, or (at your option) any later version. + +  PulseAudio is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public +  License along with PulseAudio; if not, write to the Free Software +  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +  USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <pulsecore/core-rtclock.h> + +#include "rtclock.h" +#include "timeval.h" + +pa_usec_t pa_rtclock_now(void) { +    struct timeval tv; + +    return pa_timeval_load(pa_rtclock_get(&tv)); +} diff --git a/src/pulse/rtclock.h b/src/pulse/rtclock.h new file mode 100644 index 00000000..eeea6251 --- /dev/null +++ b/src/pulse/rtclock.h @@ -0,0 +1,39 @@ +#ifndef foortclockfoo +#define foortclockfoo + +/*** +  This file is part of PulseAudio. + +  Copyright 2004-2009 Lennart Poettering + +  PulseAudio is free software; you can redistribute it and/or modify +  it under the terms of the GNU Lesser General Public License as +  published by the Free Software Foundation; either version 2.1 of the +  License, or (at your option) any later version. + +  PulseAudio is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public +  License along with PulseAudio; if not, write to the Free Software +  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +  USA. +***/ + +#include <pulse/cdecl.h> +#include <pulse/def.h> +#include <pulse/gccmacro.h> + +/** \file + *  Monotonic clock utility. */ + +PA_C_DECL_BEGIN + +/** Return the current CLOCK_MONOTONIC time in usec.  \since 0.9.16 */ +pa_usec_t pa_rtclock_now(void); + +PA_C_DECL_END + +#endif diff --git a/src/pulse/stream.c b/src/pulse/stream.c index 339a89e5..40556329 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -30,13 +30,14 @@  #include <pulse/def.h>  #include <pulse/timeval.h> +#include <pulse/rtclock.h>  #include <pulse/xmalloc.h>  #include <pulsecore/pstream-util.h>  #include <pulsecore/log.h>  #include <pulsecore/hashmap.h>  #include <pulsecore/macro.h> -#include <pulsecore/rtclock.h> +#include <pulsecore/core-rtclock.h>  #include "fork-detect.h"  #include "internal.h" @@ -319,14 +320,10 @@ static void request_auto_timing_update(pa_stream *s, pa_bool_t force) {      }      if (s->auto_timing_update_event) { -        struct timeval next; -          if (force)              s->auto_timing_interval_usec = AUTO_TIMING_INTERVAL_START_USEC; -        pa_gettimeofday(&next); -        pa_timeval_add(&next, s->auto_timing_interval_usec); -        s->mainloop->time_restart(s->auto_timing_update_event, &next); +        pa_context_rttime_restart(s->context, s->auto_timing_update_event, pa_rtclock_now() + s->auto_timing_interval_usec);          s->auto_timing_interval_usec = PA_MIN(AUTO_TIMING_INTERVAL_END_USEC, s->auto_timing_interval_usec*2);      } @@ -373,7 +370,7 @@ static void check_smoother_status(pa_stream *s, pa_bool_t aposteriori, pa_bool_t      if (!s->smoother)          return; -    x = pa_rtclock_usec(); +    x = pa_rtclock_now();      if (s->timing_info_valid) {          if (aposteriori) @@ -800,7 +797,7 @@ static void invalidate_indexes(pa_stream *s, pa_bool_t r, pa_bool_t w) {      request_auto_timing_update(s, TRUE);  } -static void auto_timing_update_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *tv, void *userdata) { +static void auto_timing_update_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {      pa_stream *s = userdata;      pa_assert(s); @@ -822,12 +819,9 @@ static void create_stream_complete(pa_stream *s) {          s->write_callback(s, (size_t) s->requested_bytes, s->write_userdata);      if (s->flags & PA_STREAM_AUTO_TIMING_UPDATE) { -        struct timeval tv; -        pa_gettimeofday(&tv);          s->auto_timing_interval_usec = AUTO_TIMING_INTERVAL_START_USEC; -        pa_timeval_add(&tv, s->auto_timing_interval_usec);          pa_assert(!s->auto_timing_update_event); -        s->auto_timing_update_event = s->mainloop->time_new(s->mainloop, &tv, &auto_timing_update_callback, s); +	s->auto_timing_update_event = pa_context_rttime_new(s->context, pa_rtclock_now() + s->auto_timing_interval_usec, &auto_timing_update_callback, s);          request_auto_timing_update(s, TRUE);      } @@ -1057,7 +1051,7 @@ static int create_stream(      if (flags & PA_STREAM_INTERPOLATE_TIMING) {          pa_usec_t x; -        x = pa_rtclock_usec(); +        x = pa_rtclock_now();          pa_assert(!s->smoother);          s->smoother = pa_smoother_new( @@ -1594,7 +1588,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,          if (o->stream->smoother) {              pa_usec_t u, x; -            u = x = pa_rtclock_usec() - i->transport_usec; +            u = x = pa_rtclock_now() - i->transport_usec;              if (o->stream->direction == PA_STREAM_PLAYBACK && o->context->version >= 13) {                  pa_usec_t su; @@ -2103,7 +2097,7 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) {      PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_RECORD || !s->timing_info.write_index_corrupt, PA_ERR_NODATA);      if (s->smoother) -        usec = pa_smoother_get(s->smoother, pa_rtclock_usec()); +        usec = pa_smoother_get(s->smoother, pa_rtclock_now());      else          usec = calc_time(s, FALSE); diff --git a/src/pulse/timeval.h b/src/pulse/timeval.h index 651da953..6307735c 100644 --- a/src/pulse/timeval.h +++ b/src/pulse/timeval.h @@ -51,6 +51,9 @@ PA_C_DECL_BEGIN  /** The number of nanoseconds in a microsecond */  #define PA_NSEC_PER_USEC ((pa_usec_t) 1000ULL) +/** Invalid time in usec */ +#define PA_USEC_INVALID ((pa_usec_t) -1) +  struct timeval;  /** Return the current timestamp, just like UNIX gettimeofday() */  | 
