153a5a1b3Sopenharmony_ci/*** 253a5a1b3Sopenharmony_ci This file is part of PulseAudio. 353a5a1b3Sopenharmony_ci 453a5a1b3Sopenharmony_ci Copyright 2004-2006 Lennart Poettering 553a5a1b3Sopenharmony_ci Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB 653a5a1b3Sopenharmony_ci 753a5a1b3Sopenharmony_ci PulseAudio is free software; you can redistribute it and/or modify 853a5a1b3Sopenharmony_ci it under the terms of the GNU Lesser General Public License as 953a5a1b3Sopenharmony_ci published by the Free Software Foundation; either version 2.1 of the 1053a5a1b3Sopenharmony_ci License, or (at your option) any later version. 1153a5a1b3Sopenharmony_ci 1253a5a1b3Sopenharmony_ci PulseAudio is distributed in the hope that it will be useful, but 1353a5a1b3Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1453a5a1b3Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1553a5a1b3Sopenharmony_ci Lesser General Public License for more details. 1653a5a1b3Sopenharmony_ci 1753a5a1b3Sopenharmony_ci You should have received a copy of the GNU Lesser General Public 1853a5a1b3Sopenharmony_ci License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 1953a5a1b3Sopenharmony_ci***/ 2053a5a1b3Sopenharmony_ci 2153a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H 2253a5a1b3Sopenharmony_ci#include <config.h> 2353a5a1b3Sopenharmony_ci#endif 2453a5a1b3Sopenharmony_ci 2553a5a1b3Sopenharmony_ci#include <stddef.h> 2653a5a1b3Sopenharmony_ci#include <sys/time.h> 2753a5a1b3Sopenharmony_ci 2853a5a1b3Sopenharmony_ci#ifdef HAVE_WINDOWS_H 2953a5a1b3Sopenharmony_ci#include <windows.h> 3053a5a1b3Sopenharmony_ci#endif 3153a5a1b3Sopenharmony_ci 3253a5a1b3Sopenharmony_ci#include <pulsecore/macro.h> 3353a5a1b3Sopenharmony_ci#include <pulsecore/core-util.h> 3453a5a1b3Sopenharmony_ci 3553a5a1b3Sopenharmony_ci#include "timeval.h" 3653a5a1b3Sopenharmony_ci 3753a5a1b3Sopenharmony_cistruct timeval *pa_gettimeofday(struct timeval *tv) { 3853a5a1b3Sopenharmony_ci pa_assert(tv); 3953a5a1b3Sopenharmony_ci 4053a5a1b3Sopenharmony_ci#if defined(OS_IS_WIN32) 4153a5a1b3Sopenharmony_ci /* 4253a5a1b3Sopenharmony_ci * Copied from implementation by Steven Edwards (LGPL). 4353a5a1b3Sopenharmony_ci * Found on wine mailing list. 4453a5a1b3Sopenharmony_ci */ 4553a5a1b3Sopenharmony_ci#if defined(_MSC_VER) || defined(__BORLANDC__) 4653a5a1b3Sopenharmony_ci#define EPOCHFILETIME (116444736000000000i64) 4753a5a1b3Sopenharmony_ci#else 4853a5a1b3Sopenharmony_ci#define EPOCHFILETIME (116444736000000000LL) 4953a5a1b3Sopenharmony_ci#endif 5053a5a1b3Sopenharmony_ci{ 5153a5a1b3Sopenharmony_ci FILETIME ft; 5253a5a1b3Sopenharmony_ci LARGE_INTEGER li; 5353a5a1b3Sopenharmony_ci int64_t t; 5453a5a1b3Sopenharmony_ci 5553a5a1b3Sopenharmony_ci GetSystemTimeAsFileTime(&ft); 5653a5a1b3Sopenharmony_ci li.LowPart = ft.dwLowDateTime; 5753a5a1b3Sopenharmony_ci li.HighPart = ft.dwHighDateTime; 5853a5a1b3Sopenharmony_ci t = li.QuadPart; /* In 100-nanosecond intervals */ 5953a5a1b3Sopenharmony_ci t -= EPOCHFILETIME; /* Offset to the Epoch time */ 6053a5a1b3Sopenharmony_ci t /= 10; /* In microseconds */ 6153a5a1b3Sopenharmony_ci tv->tv_sec = (time_t) (t / PA_USEC_PER_SEC); 6253a5a1b3Sopenharmony_ci tv->tv_usec = (suseconds_t) (t % PA_USEC_PER_SEC); 6353a5a1b3Sopenharmony_ci} 6453a5a1b3Sopenharmony_ci#elif defined(HAVE_GETTIMEOFDAY) 6553a5a1b3Sopenharmony_ci pa_assert_se(gettimeofday(tv, NULL) == 0); 6653a5a1b3Sopenharmony_ci#else 6753a5a1b3Sopenharmony_ci#error "Platform lacks gettimeofday() or equivalent function." 6853a5a1b3Sopenharmony_ci#endif 6953a5a1b3Sopenharmony_ci 7053a5a1b3Sopenharmony_ci return tv; 7153a5a1b3Sopenharmony_ci} 7253a5a1b3Sopenharmony_ci 7353a5a1b3Sopenharmony_cipa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { 7453a5a1b3Sopenharmony_ci pa_usec_t r; 7553a5a1b3Sopenharmony_ci 7653a5a1b3Sopenharmony_ci pa_assert(a); 7753a5a1b3Sopenharmony_ci pa_assert(b); 7853a5a1b3Sopenharmony_ci 7953a5a1b3Sopenharmony_ci /* Check which is the earlier time and swap the two arguments if required. */ 8053a5a1b3Sopenharmony_ci if (PA_UNLIKELY(pa_timeval_cmp(a, b) < 0)) { 8153a5a1b3Sopenharmony_ci const struct timeval *c; 8253a5a1b3Sopenharmony_ci c = a; 8353a5a1b3Sopenharmony_ci a = b; 8453a5a1b3Sopenharmony_ci b = c; 8553a5a1b3Sopenharmony_ci } 8653a5a1b3Sopenharmony_ci 8753a5a1b3Sopenharmony_ci /* Calculate the second difference*/ 8853a5a1b3Sopenharmony_ci r = ((pa_usec_t) a->tv_sec - (pa_usec_t) b->tv_sec) * PA_USEC_PER_SEC; 8953a5a1b3Sopenharmony_ci 9053a5a1b3Sopenharmony_ci /* Calculate the microsecond difference */ 9153a5a1b3Sopenharmony_ci if (a->tv_usec > b->tv_usec) 9253a5a1b3Sopenharmony_ci r += (pa_usec_t) a->tv_usec - (pa_usec_t) b->tv_usec; 9353a5a1b3Sopenharmony_ci else if (a->tv_usec < b->tv_usec) 9453a5a1b3Sopenharmony_ci r -= (pa_usec_t) b->tv_usec - (pa_usec_t) a->tv_usec; 9553a5a1b3Sopenharmony_ci 9653a5a1b3Sopenharmony_ci return r; 9753a5a1b3Sopenharmony_ci} 9853a5a1b3Sopenharmony_ci 9953a5a1b3Sopenharmony_ciint pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { 10053a5a1b3Sopenharmony_ci pa_assert(a); 10153a5a1b3Sopenharmony_ci pa_assert(b); 10253a5a1b3Sopenharmony_ci 10353a5a1b3Sopenharmony_ci if (a->tv_sec < b->tv_sec) 10453a5a1b3Sopenharmony_ci return -1; 10553a5a1b3Sopenharmony_ci 10653a5a1b3Sopenharmony_ci if (a->tv_sec > b->tv_sec) 10753a5a1b3Sopenharmony_ci return 1; 10853a5a1b3Sopenharmony_ci 10953a5a1b3Sopenharmony_ci if (a->tv_usec < b->tv_usec) 11053a5a1b3Sopenharmony_ci return -1; 11153a5a1b3Sopenharmony_ci 11253a5a1b3Sopenharmony_ci if (a->tv_usec > b->tv_usec) 11353a5a1b3Sopenharmony_ci return 1; 11453a5a1b3Sopenharmony_ci 11553a5a1b3Sopenharmony_ci return 0; 11653a5a1b3Sopenharmony_ci} 11753a5a1b3Sopenharmony_ci 11853a5a1b3Sopenharmony_cipa_usec_t pa_timeval_age(const struct timeval *tv) { 11953a5a1b3Sopenharmony_ci struct timeval now; 12053a5a1b3Sopenharmony_ci pa_assert(tv); 12153a5a1b3Sopenharmony_ci 12253a5a1b3Sopenharmony_ci return pa_timeval_diff(pa_gettimeofday(&now), tv); 12353a5a1b3Sopenharmony_ci} 12453a5a1b3Sopenharmony_ci 12553a5a1b3Sopenharmony_cistruct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) { 12653a5a1b3Sopenharmony_ci time_t secs; 12753a5a1b3Sopenharmony_ci pa_assert(tv); 12853a5a1b3Sopenharmony_ci 12953a5a1b3Sopenharmony_ci secs = (time_t) (v/PA_USEC_PER_SEC); 13053a5a1b3Sopenharmony_ci 13153a5a1b3Sopenharmony_ci if (PA_UNLIKELY(tv->tv_sec > PA_INT_TYPE_MAX(time_t) - secs)) 13253a5a1b3Sopenharmony_ci goto overflow; 13353a5a1b3Sopenharmony_ci 13453a5a1b3Sopenharmony_ci tv->tv_sec += secs; 13553a5a1b3Sopenharmony_ci v -= (pa_usec_t) secs * PA_USEC_PER_SEC; 13653a5a1b3Sopenharmony_ci tv->tv_usec += (suseconds_t) v; 13753a5a1b3Sopenharmony_ci 13853a5a1b3Sopenharmony_ci /* Normalize */ 13953a5a1b3Sopenharmony_ci while ((pa_usec_t) tv->tv_usec >= PA_USEC_PER_SEC) { 14053a5a1b3Sopenharmony_ci 14153a5a1b3Sopenharmony_ci if (PA_UNLIKELY(tv->tv_sec >= PA_INT_TYPE_MAX(time_t))) 14253a5a1b3Sopenharmony_ci goto overflow; 14353a5a1b3Sopenharmony_ci 14453a5a1b3Sopenharmony_ci tv->tv_sec++; 14553a5a1b3Sopenharmony_ci tv->tv_usec -= (suseconds_t) PA_USEC_PER_SEC; 14653a5a1b3Sopenharmony_ci } 14753a5a1b3Sopenharmony_ci 14853a5a1b3Sopenharmony_ci return tv; 14953a5a1b3Sopenharmony_ci 15053a5a1b3Sopenharmony_cioverflow: 15153a5a1b3Sopenharmony_ci tv->tv_sec = PA_INT_TYPE_MAX(time_t); 15253a5a1b3Sopenharmony_ci tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1); 15353a5a1b3Sopenharmony_ci return tv; 15453a5a1b3Sopenharmony_ci} 15553a5a1b3Sopenharmony_ci 15653a5a1b3Sopenharmony_cistruct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v) { 15753a5a1b3Sopenharmony_ci time_t secs; 15853a5a1b3Sopenharmony_ci pa_assert(tv); 15953a5a1b3Sopenharmony_ci 16053a5a1b3Sopenharmony_ci secs = (time_t) (v/PA_USEC_PER_SEC); 16153a5a1b3Sopenharmony_ci 16253a5a1b3Sopenharmony_ci if (PA_UNLIKELY(tv->tv_sec < secs)) 16353a5a1b3Sopenharmony_ci goto underflow; 16453a5a1b3Sopenharmony_ci 16553a5a1b3Sopenharmony_ci tv->tv_sec -= secs; 16653a5a1b3Sopenharmony_ci v -= (pa_usec_t) secs * PA_USEC_PER_SEC; 16753a5a1b3Sopenharmony_ci 16853a5a1b3Sopenharmony_ci if (tv->tv_usec >= (suseconds_t) v) 16953a5a1b3Sopenharmony_ci tv->tv_usec -= (suseconds_t) v; 17053a5a1b3Sopenharmony_ci else { 17153a5a1b3Sopenharmony_ci 17253a5a1b3Sopenharmony_ci if (PA_UNLIKELY(tv->tv_sec <= 0)) 17353a5a1b3Sopenharmony_ci goto underflow; 17453a5a1b3Sopenharmony_ci 17553a5a1b3Sopenharmony_ci tv->tv_sec --; 17653a5a1b3Sopenharmony_ci tv->tv_usec += (suseconds_t) (PA_USEC_PER_SEC - v); 17753a5a1b3Sopenharmony_ci } 17853a5a1b3Sopenharmony_ci 17953a5a1b3Sopenharmony_ci return tv; 18053a5a1b3Sopenharmony_ci 18153a5a1b3Sopenharmony_ciunderflow: 18253a5a1b3Sopenharmony_ci tv->tv_sec = 0; 18353a5a1b3Sopenharmony_ci tv->tv_usec = 0; 18453a5a1b3Sopenharmony_ci return tv; 18553a5a1b3Sopenharmony_ci} 18653a5a1b3Sopenharmony_ci 18753a5a1b3Sopenharmony_cistruct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) { 18853a5a1b3Sopenharmony_ci pa_assert(tv); 18953a5a1b3Sopenharmony_ci 19053a5a1b3Sopenharmony_ci if (PA_UNLIKELY(v == PA_USEC_INVALID)) { 19153a5a1b3Sopenharmony_ci tv->tv_sec = PA_INT_TYPE_MAX(time_t); 19253a5a1b3Sopenharmony_ci tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1); 19353a5a1b3Sopenharmony_ci 19453a5a1b3Sopenharmony_ci return tv; 19553a5a1b3Sopenharmony_ci } 19653a5a1b3Sopenharmony_ci 19753a5a1b3Sopenharmony_ci tv->tv_sec = (time_t) (v / PA_USEC_PER_SEC); 19853a5a1b3Sopenharmony_ci tv->tv_usec = (suseconds_t) (v % PA_USEC_PER_SEC); 19953a5a1b3Sopenharmony_ci 20053a5a1b3Sopenharmony_ci return tv; 20153a5a1b3Sopenharmony_ci} 20253a5a1b3Sopenharmony_ci 20353a5a1b3Sopenharmony_cipa_usec_t pa_timeval_load(const struct timeval *tv) { 20453a5a1b3Sopenharmony_ci 20553a5a1b3Sopenharmony_ci if (PA_UNLIKELY(!tv)) 20653a5a1b3Sopenharmony_ci return PA_USEC_INVALID; 20753a5a1b3Sopenharmony_ci 20853a5a1b3Sopenharmony_ci return 20953a5a1b3Sopenharmony_ci (pa_usec_t) tv->tv_sec * PA_USEC_PER_SEC + 21053a5a1b3Sopenharmony_ci (pa_usec_t) tv->tv_usec; 21153a5a1b3Sopenharmony_ci} 212