summaryrefslogtreecommitdiffstats
path: root/src/pulse
diff options
context:
space:
mode:
Diffstat (limited to 'src/pulse')
-rw-r--r--src/pulse/context.c5
-rw-r--r--src/pulse/def.h5
-rw-r--r--src/pulse/gccmacro.h2
-rw-r--r--src/pulse/mainloop.c179
-rw-r--r--src/pulse/proplist.h3
-rw-r--r--src/pulse/timeval.c67
-rw-r--r--src/pulse/timeval.h7
7 files changed, 163 insertions, 105 deletions
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 894ab2e0..23ae30ce 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -1045,7 +1045,10 @@ pa_context_state_t pa_context_get_state(pa_context *c) {
}
int pa_context_errno(pa_context *c) {
- pa_assert(c);
+
+ if (!c)
+ return PA_ERR_INVALID;
+
pa_assert(PA_REFCNT_VALUE(c) >= 1);
return c->error;
diff --git a/src/pulse/def.h b/src/pulse/def.h
index 1a7da974..e839bd92 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -95,13 +95,14 @@ static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x) {
typedef enum pa_operation_state {
PA_OPERATION_RUNNING, /**< The operation is still running */
PA_OPERATION_DONE, /**< The operation has been completed */
- PA_OPERATION_CANCELED /**< The operation has been canceled */
+ PA_OPERATION_CANCELLED /**< The operation has been cancelled. Before 0.9.18 this was called PA_OPERATION_CANCELED. That name is still available for compatibility. */
} pa_operation_state_t;
/** \cond fulldocs */
#define PA_OPERATION_RUNNING PA_OPERATION_RUNNING
#define PA_OPERATION_DONE PA_OPERATION_DONE
-#define PA_OPERATION_CANCELED PA_OPERATION_CANCELED
+#define PA_OPERATION_CANCELED PA_OPERATION_CANCELLED
+#define PA_OPERATION_CANCELLED PA_OPERATION_CANCELLED
/** \endcond */
/** An invalid index */
diff --git a/src/pulse/gccmacro.h b/src/pulse/gccmacro.h
index e85ecb66..57e80509 100644
--- a/src/pulse/gccmacro.h
+++ b/src/pulse/gccmacro.h
@@ -118,7 +118,7 @@
#endif
#ifndef PA_GCC_WEAKREF
-#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ > 1)) || (__GNUC__ > 4))
+#if defined(__GNUC__) && defined(__ELF__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ > 1)) || (__GNUC__ > 4))
/** Macro for usgae of GCC's weakref attribute */
#define PA_GCC_WEAKREF(x) __attribute__((weakref(#x)));
#endif
diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c
index 93a4742d..090ac8c2 100644
--- a/src/pulse/mainloop.c
+++ b/src/pulse/mainloop.c
@@ -78,6 +78,7 @@ struct pa_time_event {
pa_bool_t dead:1;
pa_bool_t enabled:1;
+ pa_bool_t use_rtclock:1;
pa_usec_t time;
pa_time_event_cb_t callback;
@@ -112,7 +113,7 @@ struct pa_mainloop {
struct pollfd *pollfds;
unsigned max_pollfds, n_pollfds;
- int prepared_timeout;
+ pa_usec_t prepared_timeout;
pa_time_event *cached_next_time_event;
pa_mainloop_api api;
@@ -172,17 +173,14 @@ static pa_io_event* mainloop_io_new(
m = a->userdata;
pa_assert(a == &m->api);
- e = pa_xnew(pa_io_event, 1);
+ e = pa_xnew0(pa_io_event, 1);
e->mainloop = m;
- e->dead = FALSE;
e->fd = fd;
e->events = events;
- e->pollfd = NULL;
e->callback = callback;
e->userdata = userdata;
- e->destroy_callback = NULL;
#ifdef OS_IS_WIN32
{
@@ -265,16 +263,14 @@ static pa_defer_event* mainloop_defer_new(
m = a->userdata;
pa_assert(a == &m->api);
- e = pa_xnew(pa_defer_event, 1);
+ e = pa_xnew0(pa_defer_event, 1);
e->mainloop = m;
- e->dead = FALSE;
e->enabled = TRUE;
m->n_enabled_defer_events++;
e->callback = callback;
e->userdata = userdata;
- e->destroy_callback = NULL;
PA_LLIST_PREPEND(pa_defer_event, m->defer_events, e);
@@ -320,18 +316,20 @@ 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;
+static pa_usec_t make_rt(const struct timeval *tv, pa_bool_t *use_rtclock) {
struct timeval ttv;
- if (!tv)
+ if (!tv) {
+ *use_rtclock = FALSE;
return PA_USEC_INVALID;
+ }
ttv = *tv;
- is_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK);
- ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK;
+ *use_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK);
- if (!is_rtclock)
+ if (*use_rtclock)
+ ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK;
+ else
pa_rtclock_from_wallclock(&ttv);
return pa_timeval_load(&ttv);
@@ -346,22 +344,23 @@ static pa_time_event* mainloop_time_new(
pa_mainloop *m;
pa_time_event *e;
pa_usec_t t;
+ pa_bool_t use_rtclock = FALSE;
pa_assert(a);
pa_assert(a->userdata);
pa_assert(callback);
- t = timeval_load(tv);
+ t = make_rt(tv, &use_rtclock);
m = a->userdata;
pa_assert(a == &m->api);
- e = pa_xnew(pa_time_event, 1);
+ e = pa_xnew0(pa_time_event, 1);
e->mainloop = m;
- e->dead = FALSE;
if ((e->enabled = (t != PA_USEC_INVALID))) {
e->time = t;
+ e->use_rtclock= use_rtclock;
m->n_enabled_time_events++;
@@ -375,7 +374,6 @@ static pa_time_event* mainloop_time_new(
e->callback = callback;
e->userdata = userdata;
- e->destroy_callback = NULL;
PA_LLIST_PREPEND(pa_time_event, m->time_events, e);
@@ -388,11 +386,12 @@ 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_bool_t use_rtclock = FALSE;
pa_assert(e);
pa_assert(!e->dead);
- t = timeval_load(tv);
+ t = make_rt(tv, &use_rtclock);
valid = (t != PA_USEC_INVALID);
if (e->enabled && !valid) {
@@ -403,6 +402,7 @@ static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
if ((e->enabled = valid)) {
e->time = t;
+ e->use_rtclock = use_rtclock;
pa_mainloop_wakeup(e->mainloop);
}
@@ -480,9 +480,8 @@ pa_mainloop *pa_mainloop_new(void) {
pa_init_i18n();
- m = pa_xnew(pa_mainloop, 1);
+ m = pa_xnew0(pa_mainloop, 1);
- m->wakeup_pipe_type = 0;
if (pipe(m->wakeup_pipe) < 0) {
pa_log_error("ERROR: cannot create wakeup pipe");
pa_xfree(m);
@@ -493,43 +492,23 @@ pa_mainloop *pa_mainloop_new(void) {
pa_make_fd_nonblock(m->wakeup_pipe[1]);
pa_make_fd_cloexec(m->wakeup_pipe[0]);
pa_make_fd_cloexec(m->wakeup_pipe[1]);
- m->wakeup_requested = FALSE;
-
- PA_LLIST_HEAD_INIT(pa_io_event, m->io_events);
- PA_LLIST_HEAD_INIT(pa_time_event, m->time_events);
- PA_LLIST_HEAD_INIT(pa_defer_event, m->defer_events);
-
- m->n_enabled_defer_events = m->n_enabled_time_events = m->n_io_events = 0;
- m->io_events_please_scan = m->time_events_please_scan = m->defer_events_please_scan = 0;
-
- m->cached_next_time_event = NULL;
- m->prepared_timeout = 0;
- m->pollfds = NULL;
- m->max_pollfds = m->n_pollfds = 0;
m->rebuild_pollfds = TRUE;
- m->quit = FALSE;
- m->retval = 0;
-
m->api = vtable;
m->api.userdata = m;
m->state = STATE_PASSIVE;
- m->poll_func = NULL;
- m->poll_func_userdata = NULL;
m->poll_func_ret = -1;
return m;
}
static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) {
- pa_io_event *e;
+ pa_io_event *e, *n;
- e = m->io_events;
- while (e) {
- pa_io_event *n = e->next;
+ PA_LLIST_FOREACH_SAFE(e, n, m->io_events) {
if (!force && m->io_events_please_scan <= 0)
break;
@@ -549,19 +528,15 @@ static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) {
m->rebuild_pollfds = TRUE;
}
-
- e = n;
}
pa_assert(m->io_events_please_scan == 0);
}
static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) {
- pa_time_event *e;
+ pa_time_event *e, *n;
- e = m->time_events;
- while (e) {
- pa_time_event *n = e->next;
+ PA_LLIST_FOREACH_SAFE(e, n, m->time_events) {
if (!force && m->time_events_please_scan <= 0)
break;
@@ -585,19 +560,15 @@ static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) {
pa_xfree(e);
}
-
- e = n;
}
pa_assert(m->time_events_please_scan == 0);
}
static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) {
- pa_defer_event *e;
+ pa_defer_event *e, *n;
- e = m->defer_events;
- while (e) {
- pa_defer_event *n = e->next;
+ PA_LLIST_FOREACH_SAFE(e, n, m->defer_events) {
if (!force && m->defer_events_please_scan <= 0)
break;
@@ -621,8 +592,6 @@ static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) {
pa_xfree(e);
}
-
- e = n;
}
pa_assert(m->defer_events_please_scan == 0);
@@ -679,7 +648,7 @@ static void rebuild_pollfds(pa_mainloop *m) {
m->n_pollfds++;
}
- for (e = m->io_events; e; e = e->next) {
+ PA_LLIST_FOREACH(e, m->io_events) {
if (e->dead) {
e->pollfd = NULL;
continue;
@@ -697,36 +666,46 @@ static void rebuild_pollfds(pa_mainloop *m) {
m->rebuild_pollfds = FALSE;
}
-static int dispatch_pollfds(pa_mainloop *m) {
+static unsigned dispatch_pollfds(pa_mainloop *m) {
pa_io_event *e;
- int r = 0, k;
+ unsigned r = 0, k;
pa_assert(m->poll_func_ret > 0);
- for (e = m->io_events, k = m->poll_func_ret; e && !m->quit && k > 0; e = e->next) {
+ k = m->poll_func_ret;
+
+ PA_LLIST_FOREACH(e, m->io_events) {
+
+ if (k <= 0 || m->quit)
+ break;
+
if (e->dead || !e->pollfd || !e->pollfd->revents)
continue;
pa_assert(e->pollfd->fd == e->fd);
pa_assert(e->callback);
+
e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata);
e->pollfd->revents = 0;
r++;
-
k--;
}
return r;
}
-static int dispatch_defer(pa_mainloop *m) {
+static unsigned dispatch_defer(pa_mainloop *m) {
pa_defer_event *e;
- int r = 0;
+ unsigned r = 0;
if (m->n_enabled_defer_events <= 0)
return 0;
- for (e = m->defer_events; e && !m->quit; e = e->next) {
+ PA_LLIST_FOREACH(e, m->defer_events) {
+
+ if (m->quit)
+ break;
+
if (e->dead || !e->enabled)
continue;
@@ -745,7 +724,7 @@ static pa_time_event* find_next_time_event(pa_mainloop *m) {
if (m->cached_next_time_event)
return m->cached_next_time_event;
- for (t = m->time_events; t; t = t->next) {
+ PA_LLIST_FOREACH(t, m->time_events) {
if (t->dead || !t->enabled)
continue;
@@ -763,12 +742,12 @@ static pa_time_event* find_next_time_event(pa_mainloop *m) {
return n;
}
-static int calc_next_timeout(pa_mainloop *m) {
+static pa_usec_t calc_next_timeout(pa_mainloop *m) {
pa_time_event *t;
pa_usec_t clock_now;
- if (!m->n_enabled_time_events)
- return -1;
+ if (m->n_enabled_time_events <= 0)
+ return PA_USEC_INVALID;
pa_assert_se(t = find_next_time_event(m));
@@ -780,13 +759,13 @@ static int calc_next_timeout(pa_mainloop *m) {
if (t->time <= clock_now)
return 0;
- return (int) ((t->time - clock_now) / 1000); /* in milliseconds */
+ return t->time - clock_now;
}
-static int dispatch_timeout(pa_mainloop *m) {
+static unsigned dispatch_timeout(pa_mainloop *m) {
pa_time_event *e;
pa_usec_t now;
- int r = 0;
+ unsigned r = 0;
pa_assert(m);
if (m->n_enabled_time_events <= 0)
@@ -794,7 +773,10 @@ static int dispatch_timeout(pa_mainloop *m) {
now = pa_rtclock_now();
- for (e = m->time_events; e && !m->quit; e = e->next) {
+ PA_LLIST_FOREACH(e, m->time_events) {
+
+ if (m->quit)
+ break;
if (e->dead || !e->enabled)
continue;
@@ -806,7 +788,7 @@ static int dispatch_timeout(pa_mainloop *m) {
/* Disable time event */
mainloop_time_restart(e, NULL);
- e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, TRUE), e->userdata);
+ e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, e->use_rtclock), e->userdata);
r++;
}
@@ -834,7 +816,8 @@ static void clear_wakeup(pa_mainloop *m) {
return;
if (m->wakeup_requested) {
- while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c));
+ while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c))
+ ;
m->wakeup_requested = 0;
}
}
@@ -850,12 +833,17 @@ int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
goto quit;
if (m->n_enabled_defer_events <= 0) {
+
if (m->rebuild_pollfds)
rebuild_pollfds(m);
m->prepared_timeout = calc_next_timeout(m);
- if (timeout >= 0 && (timeout < m->prepared_timeout || m->prepared_timeout < 0))
- m->prepared_timeout = timeout;
+ if (timeout >= 0) {
+ uint64_t u = (uint64_t) timeout * PA_USEC_PER_MSEC;
+
+ if (u < m->prepared_timeout || m->prepared_timeout == PA_USEC_INVALID)
+ m->prepared_timeout = timeout;
+ }
}
m->state = STATE_PREPARED;
@@ -866,6 +854,13 @@ quit:
return -2;
}
+static int usec_to_timeout(pa_usec_t u) {
+ if (u == PA_USEC_INVALID)
+ return -1;
+
+ return (u + PA_USEC_PER_MSEC - 1) / PA_USEC_PER_MSEC;
+}
+
int pa_mainloop_poll(pa_mainloop *m) {
pa_assert(m);
pa_assert(m->state == STATE_PREPARED);
@@ -881,9 +876,24 @@ int pa_mainloop_poll(pa_mainloop *m) {
pa_assert(!m->rebuild_pollfds);
if (m->poll_func)
- m->poll_func_ret = m->poll_func(m->pollfds, m->n_pollfds, m->prepared_timeout, m->poll_func_userdata);
- else
- m->poll_func_ret = poll(m->pollfds, m->n_pollfds, m->prepared_timeout);
+ m->poll_func_ret = m->poll_func(
+ m->pollfds, m->n_pollfds,
+ usec_to_timeout(m->prepared_timeout),
+ m->poll_func_userdata);
+ else {
+#ifdef HAVE_PPOLL
+ struct timespec ts;
+
+ m->poll_func_ret = ppoll(
+ m->pollfds, m->n_pollfds,
+ m->prepared_timeout == PA_USEC_INVALID ? NULL : pa_timespec_store(&ts, m->prepared_timeout),
+ NULL);
+#else
+ m->poll_func_ret = poll(
+ m->pollfds, m->n_pollfds,
+ usec_to_timeout(m->prepared_timeout));
+#endif
+ }
if (m->poll_func_ret < 0) {
if (errno == EINTR)
@@ -902,7 +912,7 @@ quit:
}
int pa_mainloop_dispatch(pa_mainloop *m) {
- int dispatched = 0;
+ unsigned dispatched = 0;
pa_assert(m);
pa_assert(m->state == STATE_POLLED);
@@ -928,7 +938,7 @@ int pa_mainloop_dispatch(pa_mainloop *m) {
m->state = STATE_PASSIVE;
- return dispatched;
+ return (int) dispatched;
quit:
m->state = STATE_QUIT;
@@ -937,6 +947,7 @@ quit:
int pa_mainloop_get_retval(pa_mainloop *m) {
pa_assert(m);
+
return m->retval;
}
@@ -965,7 +976,8 @@ quit:
int pa_mainloop_run(pa_mainloop *m, int *retval) {
int r;
- while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0);
+ while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0)
+ ;
if (r == -2)
return 1;
@@ -985,6 +997,7 @@ void pa_mainloop_quit(pa_mainloop *m, int retval) {
pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) {
pa_assert(m);
+
return &m->api;
}
diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h
index 8bf9c482..8dff8df4 100644
--- a/src/pulse/proplist.h
+++ b/src/pulse/proplist.h
@@ -115,6 +115,9 @@ PA_C_DECL_BEGIN
/** For streams that belong to a window on the screen: relative position of the window center on the screen, float formatted as text string, ranging from 0.0 (top of the screen) to 1.0 (bottom of the screen). e.g. "0.43". \since 0.9.17 */
#define PA_PROP_WINDOW_VPOS "window.vpos"
+/** For streams that belong to a window on the screen: if the windowing system supports multiple desktops, a comma seperated list of indexes of the desktops this window is visible on. If this property is an empty string, it is visible on all desktops (i.e. 'sticky'). The first desktop is 0. e.g. "0,2,3" \since 0.9.18 */
+#define PA_PROP_WINDOW_DESKTOP "window.desktop"
+
/** For streams that belong to an X11 window on the screen: the X11 display string. e.g. ":0.0" */
#define PA_PROP_WINDOW_X11_DISPLAY "window.x11.display"
diff --git a/src/pulse/timeval.c b/src/pulse/timeval.c
index 376cf13c..cde4417c 100644
--- a/src/pulse/timeval.c
+++ b/src/pulse/timeval.c
@@ -33,6 +33,7 @@
#include <pulsecore/winsock.h>
#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
#include "timeval.h"
@@ -54,9 +55,9 @@ struct timeval *pa_gettimeofday(struct timeval *tv) {
#define EPOCHFILETIME (116444736000000000LL)
#endif
- FILETIME ft;
- LARGE_INTEGER li;
- __int64 t;
+ FILETIME ft;
+ LARGE_INTEGER li;
+ int64_t t;
pa_assert(tv);
@@ -82,7 +83,7 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
pa_assert(b);
/* Check which whan is the earlier time and swap the two arguments if required. */
- if (pa_timeval_cmp(a, b) < 0) {
+ if (PA_UNLIKELY(pa_timeval_cmp(a, b) < 0)) {
const struct timeval *c;
c = a;
a = b;
@@ -94,9 +95,9 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
/* Calculate the microsecond difference */
if (a->tv_usec > b->tv_usec)
- r += ((pa_usec_t) a->tv_usec - (pa_usec_t) b->tv_usec);
+ r += (pa_usec_t) a->tv_usec - (pa_usec_t) b->tv_usec;
else if (a->tv_usec < b->tv_usec)
- r -= ((pa_usec_t) b->tv_usec - (pa_usec_t) a->tv_usec);
+ r -= (pa_usec_t) b->tv_usec - (pa_usec_t) a->tv_usec;
return r;
}
@@ -128,45 +129,77 @@ pa_usec_t pa_timeval_age(const struct timeval *tv) {
}
struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) {
- unsigned long secs;
+ time_t secs;
pa_assert(tv);
- secs = (unsigned long) (v/PA_USEC_PER_SEC);
- tv->tv_sec += (time_t) secs;
- v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
+ secs = (time_t) (v/PA_USEC_PER_SEC);
+ if (PA_UNLIKELY(tv->tv_sec > PA_INT_TYPE_MAX(time_t) - secs))
+ goto overflow;
+
+ tv->tv_sec += secs;
+ v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
tv->tv_usec += (suseconds_t) v;
/* Normalize */
- while ((unsigned) tv->tv_usec >= PA_USEC_PER_SEC) {
+ while ((pa_usec_t) tv->tv_usec >= PA_USEC_PER_SEC) {
+
+ if (PA_UNLIKELY(tv->tv_sec >= PA_INT_TYPE_MAX(time_t)))
+ goto overflow;
+
tv->tv_sec++;
tv->tv_usec -= (suseconds_t) PA_USEC_PER_SEC;
}
return tv;
+
+overflow:
+ tv->tv_sec = PA_INT_TYPE_MAX(time_t);
+ tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1);
+ return tv;
}
struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v) {
- unsigned long secs;
+ time_t secs;
pa_assert(tv);
- secs = (unsigned long) (v/PA_USEC_PER_SEC);
- tv->tv_sec -= (time_t) secs;
- v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
+ secs = (time_t) (v/PA_USEC_PER_SEC);
+
+ if (PA_UNLIKELY(tv->tv_sec < secs))
+ goto underflow;
+
+ tv->tv_sec -= secs;
+ v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
if (tv->tv_usec >= (suseconds_t) v)
tv->tv_usec -= (suseconds_t) v;
else {
+
+ if (PA_UNLIKELY(tv->tv_sec <= 0))
+ goto underflow;
+
tv->tv_sec --;
tv->tv_usec += (suseconds_t) (PA_USEC_PER_SEC - v);
}
return tv;
+
+underflow:
+ tv->tv_sec = 0;
+ tv->tv_usec = 0;
+ return tv;
}
struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) {
pa_assert(tv);
+ if (PA_UNLIKELY(v == PA_USEC_INVALID)) {
+ tv->tv_sec = PA_INT_TYPE_MAX(time_t);
+ tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1);
+
+ return tv;
+ }
+
tv->tv_sec = (time_t) (v / PA_USEC_PER_SEC);
tv->tv_usec = (suseconds_t) (v % PA_USEC_PER_SEC);
@@ -174,7 +207,9 @@ struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) {
}
pa_usec_t pa_timeval_load(const struct timeval *tv) {
- pa_assert(tv);
+
+ if (PA_UNLIKELY(!tv))
+ return PA_USEC_INVALID;
return
(pa_usec_t) tv->tv_sec * PA_USEC_PER_SEC +
diff --git a/src/pulse/timeval.h b/src/pulse/timeval.h
index 48c6cdb3..3cea5d3b 100644
--- a/src/pulse/timeval.h
+++ b/src/pulse/timeval.h
@@ -51,12 +51,15 @@ PA_C_DECL_BEGIN
/** The number of nanoseconds in a microsecond */
#define PA_NSEC_PER_USEC ((unsigned long long) 1000ULL)
-/** Invalid time in usec */
+/** Invalid time in usec. \since 0.9.15 */
#define PA_USEC_INVALID ((pa_usec_t) -1)
+/** Biggest time in usec. \since 0.9.18 */
+#define PA_USEC_MAX ((pa_usec_t) -2)
+
struct timeval;
-/** Return the current timestamp, just like UNIX gettimeofday() */
+/** Return the current wallclock timestamp, just like UNIX gettimeofday(). */
struct timeval *pa_gettimeofday(struct timeval *tv);
/** Calculate the difference between the two specified timeval