pulseaudio/src/pulsecore/rtclock.c
Finn Thain 0329edd179 revive solaris module
Hi All,

This patch fixes the solaris audio device source and sink, and fixes some
portability issues that break the build on solaris. Questions and comments
welcomed.

I've tested this patch only with OpenSolaris Express snv 103. Eventually I
hope to be able to test a few older releases and older hardware (though it
is hard to say whether there is much interest in those).

This is my first brush with pulseaudio and so I read the wiki docs and
some of the source code but I'm still unsure of a few things. In
particular I'm wondering about rewind processing, corking and what (if
anything) the module needs for those. I'm also unclear on the implications
of thread_info.buffer_size, .fragment_size and .max_request, and whether
my code is correct or not.

This patch disables link map/library versioning unless ld is GNU ld.
Another approach for solaris would be to use that linker's -M option, but
I couldn't make that work (due to undefined mainloop, browse and simple
symbols when linking pacat. I can post the errors if anyone is intested.)

Thanks,
Finn Thain
2009-03-03 22:27:00 +01:00

154 lines
3.6 KiB
C

/***
This file is part of PulseAudio.
Copyright 2004-2006 Lennart Poettering
Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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 <stddef.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
#endif
#include <pulse/timeval.h>
#include <pulsecore/macro.h>
#include <pulsecore/core-error.h>
#include "rtclock.h"
pa_usec_t pa_rtclock_age(const struct timeval *tv) {
struct timeval now;
pa_assert(tv);
return pa_timeval_diff(pa_rtclock_get(&now), tv);
}
struct timeval *pa_rtclock_get(struct timeval *tv) {
#ifdef HAVE_CLOCK_GETTIME
struct timespec ts;
#ifdef CLOCK_MONOTONIC
/* No locking or atomic ops for no_monotonic here */
static pa_bool_t no_monotonic = FALSE;
if (!no_monotonic)
if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
no_monotonic = TRUE;
if (no_monotonic)
#endif
pa_assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
pa_assert(tv);
tv->tv_sec = ts.tv_sec;
tv->tv_usec = ts.tv_nsec / 1000;
return tv;
#else /* HAVE_CLOCK_GETTIME */
return pa_gettimeofday(tv);
#endif
}
pa_bool_t pa_rtclock_hrtimer(void) {
#ifdef HAVE_CLOCK_GETTIME
struct timespec ts;
#ifdef CLOCK_MONOTONIC
if (clock_getres(CLOCK_MONOTONIC, &ts) >= 0)
return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000;
#endif
pa_assert_se(clock_getres(CLOCK_REALTIME, &ts) == 0);
return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000;
#else /* HAVE_CLOCK_GETTIME */
return FALSE;
#endif
}
void pa_rtclock_hrtimer_enable(void) {
#ifdef PR_SET_TIMERSLACK
int slack_ns;
if ((slack_ns = prctl(PR_GET_TIMERSLACK, 0, 0, 0, 0)) < 0) {
pa_log_info("PR_GET_TIMERSLACK/PR_SET_TIMERSLACK not supported.");
return;
}
pa_log_debug("Timer slack set to %i us.", slack_ns/1000);
slack_ns = 500000000;
pa_log_debug("Setting timer slack to %i us.", slack_ns/1000);
if (prctl(PR_SET_TIMERSLACK, slack_ns, 0, 0, 0) < 0) {
pa_log_warn("PR_SET_TIMERSLACK failed: %s", pa_cstrerror(errno));
return;
}
#endif
}
pa_usec_t pa_rtclock_usec(void) {
struct timeval tv;
return pa_timeval_load(pa_rtclock_get(&tv));
}
struct timeval* pa_rtclock_from_wallclock(struct timeval *tv) {
#ifdef HAVE_CLOCK_GETTIME
struct timeval wc_now, rt_now;
pa_gettimeofday(&wc_now);
pa_rtclock_get(&rt_now);
pa_assert(tv);
if (pa_timeval_cmp(&wc_now, tv) < 0)
pa_timeval_add(&rt_now, pa_timeval_diff(tv, &wc_now));
else
pa_timeval_sub(&rt_now, pa_timeval_diff(&wc_now, tv));
*tv = rt_now;
#endif
return tv;
}
pa_usec_t pa_timespec_load(const struct timespec *ts) {
pa_assert(ts);
return
(pa_usec_t) ts->tv_sec * PA_USEC_PER_SEC +
(pa_usec_t) ts->tv_nsec / PA_NSEC_PER_USEC;
}