summaryrefslogtreecommitdiff
path: root/portmidi/porttime
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2024-10-07 19:30:56 +0200
committerMitja Felicijan <mitja.felicijan@gmail.com>2024-10-07 19:30:56 +0200
commit40a899bd6ee536eae093337bf2d0dcc8db4e46f1 (patch)
tree485ace3e6fd28b91f394efd277732651e10824d8 /portmidi/porttime
parent6fc4bddfdf8e056469f316c1a0fe488efbb4253a (diff)
downloadttdaw-40a899bd6ee536eae093337bf2d0dcc8db4e46f1.tar.gz
Moved example code examples folder
Diffstat (limited to 'portmidi/porttime')
-rwxr-xr-xportmidi/porttime/porttime.c3
-rwxr-xr-xportmidi/porttime/porttime.h103
-rw-r--r--portmidi/porttime/pthaiku.cpp88
-rwxr-xr-xportmidi/porttime/ptlinux.c139
-rwxr-xr-xportmidi/porttime/ptmacosx_cf.c140
-rwxr-xr-xportmidi/porttime/ptmacosx_mach.c204
-rwxr-xr-xportmidi/porttime/ptwinmm.c70
7 files changed, 0 insertions, 747 deletions
diff --git a/portmidi/porttime/porttime.c b/portmidi/porttime/porttime.c
deleted file mode 100755
index 71b06f4..0000000
--- a/portmidi/porttime/porttime.c
+++ /dev/null
@@ -1,3 +0,0 @@
-/* porttime.c -- portable API for millisecond timer */
-
-/* There is no machine-independent implementation code to put here */
diff --git a/portmidi/porttime/porttime.h b/portmidi/porttime/porttime.h
deleted file mode 100755
index 0a61c5c..0000000
--- a/portmidi/porttime/porttime.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/** @file porttime.h portable interface to millisecond timer. */
-
-/* CHANGE LOG FOR PORTTIME
- 10-Jun-03 Mark Nelson & RBD
- boost priority of timer thread in ptlinux.c implementation
- */
-
-#ifndef PORTMIDI_PORTTIME_H
-#define PORTMIDI_PORTTIME_H
-
-/* Should there be a way to choose the source of time here? */
-
-#ifdef WIN32
-#ifndef INT32_DEFINED
-// rather than having users install a special .h file for windows,
-// just put the required definitions inline here. portmidi.h uses
-// these too, so the definitions are (unfortunately) duplicated there
-typedef int int32_t;
-typedef unsigned int uint32_t;
-#define INT32_DEFINED
-#endif
-#else
-#include <stdint.h> // needed for int32_t
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef PMEXPORT
-#ifdef _WINDLL
-#define PMEXPORT __declspec(dllexport)
-#else
-#define PMEXPORT
-#endif
-#endif
-
-/** @defgroup grp_porttime PortTime: Millisecond Timer
- @{
-*/
-
-typedef enum {
- ptNoError = 0, /* success */
- ptHostError = -10000, /* a system-specific error occurred */
- ptAlreadyStarted, /* cannot start timer because it is already started */
- ptAlreadyStopped, /* cannot stop timer because it is already stopped */
- ptInsufficientMemory /* memory could not be allocated */
-} PtError; /**< @brief @enum PtError PortTime error code; a common return type.
- * No error is indicated by zero; errors are indicated by < 0.
- */
-
-/** real time or time offset in milliseconds. */
-typedef int32_t PtTimestamp;
-
-/** a function that gets a current time */
-typedef void (PtCallback)(PtTimestamp timestamp, void *userData);
-
-/** start a real-time clock service.
-
- @param resolution the timer resolution in ms. The time will advance every
- \p resolution ms.
-
- @param callback a function pointer to be called every resolution ms.
-
- @param userData is passed to \p callback as a parameter.
-
- @return #ptNoError on success. See #PtError for other values.
-*/
-PMEXPORT PtError Pt_Start(int resolution, PtCallback *callback, void *userData);
-
-/** stop the timer.
-
- @return #ptNoError on success. See #PtError for other values.
-*/
-PMEXPORT PtError Pt_Stop(void);
-
-/** test if the timer is running.
-
- @return TRUE or FALSE
-*/
-PMEXPORT int Pt_Started(void);
-
-/** get the current time in ms.
-
- @return the current time
-*/
-PMEXPORT PtTimestamp Pt_Time(void);
-
-/** pauses the current thread, allowing other threads to run.
-
- @param duration the length of the pause in ms. The true duration
- of the pause may be rounded to the nearest or next clock tick
- as determined by resolution in #Pt_Start().
-*/
-PMEXPORT void Pt_Sleep(int32_t duration);
-
-/** @} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // PORTMIDI_PORTTIME_H
diff --git a/portmidi/porttime/pthaiku.cpp b/portmidi/porttime/pthaiku.cpp
deleted file mode 100644
index 9d8de14..0000000
--- a/portmidi/porttime/pthaiku.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-// pthaiku.cpp - portable timer implementation for Haiku
-
-#include "porttime.h"
-#include <Looper.h>
-#include <MessageRunner.h>
-#include <OS.h>
-
-namespace {
- const uint32 timerMessage = 'PTTM';
-
- struct TimerLooper : BLooper {
- TimerLooper() : BLooper() {
- }
-
-
- virtual void MessageReceived(BMessage *message)
- {
- PtCallback *callback;
- void *userData;
- if (message->what == timerMessage && message->FindPointer("callback", (void**)&callback) == B_OK && message->FindPointer("userData", &userData) == B_OK) {
- (*callback)(Pt_Time(), userData);
- }
- BLooper::MessageReceived(message);
- }
- };
-
- bool time_started_flag = false;
- bigtime_t time_offset;
- TimerLooper *timerLooper;
- BMessageRunner *timerRunner;
-}
-
-extern "C" {
- PtError Pt_Start(int resolution, PtCallback *callback, void *userData)
- {
- if (time_started_flag) return ptAlreadyStarted;
- time_offset = system_time();
- if (callback) {
- timerLooper = new TimerLooper;
- timerLooper->Run();
- BMessenger target(timerLooper);
- BMessage message(timerMessage);
- message.AddPointer("callback", (void*)callback);
- message.AddPointer("userData", userData);
- bigtime_t interval = resolution * 1000;
- timerRunner = new BMessageRunner(target, &message, interval);
- if(timerRunner->InitCheck() != B_OK) {
- delete timerRunner;
- timerRunner = NULL;
- timerLooper->PostMessage(B_QUIT_REQUESTED);
- timerLooper = NULL;
- return ptHostError;
- }
- }
- time_started_flag = true;
- return ptNoError;
- }
-
-
- PtError Pt_Stop()
- {
- if (!time_started_flag) return ptAlreadyStopped;
- time_started_flag = false;
- delete timerRunner;
- timerRunner = NULL;
- timerLooper->PostMessage(B_QUIT_REQUESTED);
- timerLooper = NULL;
- return ptNoError;
- }
-
-
- int Pt_Started()
- {
- return time_started_flag;
- }
-
-
- PtTimestamp Pt_Time()
- {
- return (system_time() - time_offset) / 1000;
- }
-
-
- void Pt_Sleep(int32_t duration)
- {
- snooze(duration * 1000);
- }
-}
diff --git a/portmidi/porttime/ptlinux.c b/portmidi/porttime/ptlinux.c
deleted file mode 100755
index c4af5c1..0000000
--- a/portmidi/porttime/ptlinux.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/* ptlinux.c -- portable timer implementation for linux */
-
-
-/* IMPLEMENTATION NOTES (by Mark Nelson):
-
-Unlike Windows, Linux has no system call to request a periodic callback,
-so if Pt_Start() receives a callback parameter, it must create a thread
-that wakes up periodically and calls the provided callback function.
-If running as superuser, use setpriority() to renice thread to -20.
-One could also set the timer thread to a real-time priority (SCHED_FIFO
-and SCHED_RR), but this is dangerous for This is necessary because
-if the callback hangs it'll never return. A more serious reason
-is that the current scheduler implementation busy-waits instead
-of sleeping when realtime threads request a sleep of <=2ms (as a way
-to get around the 10ms granularity), which means the thread would never
-let anyone else on the CPU.
-
-CHANGE LOG
-
-18-Jul-03 Roger Dannenberg -- Simplified code to set priority of timer
- thread. Simplified implementation notes.
-
-*/
-/* stdlib, stdio, unistd, and sys/types were added because they appeared
- * in a Gentoo patch, but I'm not sure why they are needed. -RBD
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include "porttime.h"
-#include "time.h"
-#include "sys/resource.h"
-#include "pthread.h"
-
-#define TRUE 1
-#define FALSE 0
-
-#ifndef CLOCK_MONOTONIC_RAW
-#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
-#endif
-
-static int time_started_flag = FALSE;
-static struct timespec time_offset = {0, 0};
-static pthread_t pt_thread_pid;
-static int pt_thread_created = FALSE;
-
-/* note that this is static data -- we only need one copy */
-typedef struct {
- int id;
- int resolution;
- PtCallback *callback;
- void *userData;
-} pt_callback_parameters;
-
-static int pt_callback_proc_id = 0;
-
-static void *Pt_CallbackProc(void *p)
-{
- pt_callback_parameters *parameters = (pt_callback_parameters *) p;
- int mytime = 1;
- /* to kill a process, just increment the pt_callback_proc_id */
- /* printf("pt_callback_proc_id %d, id %d\n", pt_callback_proc_id,
- parameters->id); */
- if (geteuid() == 0) setpriority(PRIO_PROCESS, 0, -20);
- while (pt_callback_proc_id == parameters->id) {
- /* wait for a multiple of resolution ms */
- struct timeval timeout;
- int delay = mytime++ * parameters->resolution - Pt_Time();
- if (delay < 0) delay = 0;
- timeout.tv_sec = 0;
- timeout.tv_usec = delay * 1000;
- select(0, NULL, NULL, NULL, &timeout);
- (*(parameters->callback))(Pt_Time(), parameters->userData);
- }
- /* printf("Pt_CallbackProc exiting\n"); */
- // free(parameters);
- return NULL;
-}
-
-
-PtError Pt_Start(int resolution, PtCallback *callback, void *userData)
-{
- if (time_started_flag) return ptNoError;
- /* need this set before process runs: */
- clock_gettime(CLOCK_MONOTONIC_RAW, &time_offset);
- if (callback) {
- int res;
- pt_callback_parameters *parms = (pt_callback_parameters *)
- malloc(sizeof(pt_callback_parameters));
- if (!parms) return ptInsufficientMemory;
- parms->id = pt_callback_proc_id;
- parms->resolution = resolution;
- parms->callback = callback;
- parms->userData = userData;
- res = pthread_create(&pt_thread_pid, NULL,
- Pt_CallbackProc, parms);
- if (res != 0) return ptHostError;
- pt_thread_created = TRUE;
- }
- time_started_flag = TRUE;
- return ptNoError;
-}
-
-
-PtError Pt_Stop()
-{
- /* printf("Pt_Stop called\n"); */
- pt_callback_proc_id++;
- if (pt_thread_created) {
- pthread_join(pt_thread_pid, NULL);
- pt_thread_created = FALSE;
- }
- time_started_flag = FALSE;
- return ptNoError;
-}
-
-
-int Pt_Started()
-{
- return time_started_flag;
-}
-
-
-PtTimestamp Pt_Time()
-{
- long seconds, ms;
- struct timespec now;
- clock_gettime(CLOCK_MONOTONIC_RAW, &now);
- seconds = now.tv_sec - time_offset.tv_sec;
- ms = (now.tv_nsec - time_offset.tv_nsec) / 1000000; /* round down */
- return seconds * 1000 + ms;
-}
-
-
-void Pt_Sleep(int32_t duration)
-{
- usleep(duration * 1000);
-}
diff --git a/portmidi/porttime/ptmacosx_cf.c b/portmidi/porttime/ptmacosx_cf.c
deleted file mode 100755
index a174c86..0000000
--- a/portmidi/porttime/ptmacosx_cf.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/* ptmacosx.c -- portable timer implementation for mac os x */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <pthread.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-#import <mach/mach.h>
-#import <mach/mach_error.h>
-#import <mach/mach_time.h>
-#import <mach/clock.h>
-
-#include "porttime.h"
-
-#define THREAD_IMPORTANCE 30
-#define LONG_TIME 1000000000.0
-
-static int time_started_flag = FALSE;
-static CFAbsoluteTime startTime = 0.0;
-static CFRunLoopRef timerRunLoop;
-
-typedef struct {
- int resolution;
- PtCallback *callback;
- void *userData;
-} PtThreadParams;
-
-
-void Pt_CFTimerCallback(CFRunLoopTimerRef timer, void *info)
-{
- PtThreadParams *params = (PtThreadParams*)info;
- (*params->callback)(Pt_Time(), params->userData);
-}
-
-static void* Pt_Thread(void *p)
-{
- CFTimeInterval timerInterval;
- CFRunLoopTimerContext timerContext;
- CFRunLoopTimerRef timer;
- PtThreadParams *params = (PtThreadParams*)p;
- //CFTimeInterval timeout;
-
- /* raise the thread's priority */
- kern_return_t error;
- thread_extended_policy_data_t extendedPolicy;
- thread_precedence_policy_data_t precedencePolicy;
-
- extendedPolicy.timeshare = 0;
- error = thread_policy_set(mach_thread_self(), THREAD_EXTENDED_POLICY,
- (thread_policy_t)&extendedPolicy,
- THREAD_EXTENDED_POLICY_COUNT);
- if (error != KERN_SUCCESS) {
- mach_error("Couldn't set thread timeshare policy", error);
- }
-
- precedencePolicy.importance = THREAD_IMPORTANCE;
- error = thread_policy_set(mach_thread_self(), THREAD_PRECEDENCE_POLICY,
- (thread_policy_t)&precedencePolicy,
- THREAD_PRECEDENCE_POLICY_COUNT);
- if (error != KERN_SUCCESS) {
- mach_error("Couldn't set thread precedence policy", error);
- }
-
- /* set up the timer context */
- timerContext.version = 0;
- timerContext.info = params;
- timerContext.retain = NULL;
- timerContext.release = NULL;
- timerContext.copyDescription = NULL;
-
- /* create a new timer */
- timerInterval = (double)params->resolution / 1000.0;
- timer = CFRunLoopTimerCreate(NULL, startTime+timerInterval, timerInterval,
- 0, 0, Pt_CFTimerCallback, &timerContext);
-
- timerRunLoop = CFRunLoopGetCurrent();
- CFRunLoopAddTimer(timerRunLoop, timer, CFSTR("PtTimeMode"));
-
- /* run until we're told to stop by Pt_Stop() */
- CFRunLoopRunInMode(CFSTR("PtTimeMode"), LONG_TIME, false);
-
- CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), timer, CFSTR("PtTimeMode"));
- CFRelease(timer);
- free(params);
-
- return NULL;
-}
-
-PtError Pt_Start(int resolution, PtCallback *callback, void *userData)
-{
- PtThreadParams *params = (PtThreadParams*)malloc(sizeof(PtThreadParams));
- pthread_t pthread_id;
-
- printf("Pt_Start() called\n");
-
- // /* make sure we're not already playing */
- if (time_started_flag) return ptAlreadyStarted;
- startTime = CFAbsoluteTimeGetCurrent();
-
- if (callback) {
-
- params->resolution = resolution;
- params->callback = callback;
- params->userData = userData;
-
- pthread_create(&pthread_id, NULL, Pt_Thread, params);
- }
-
- time_started_flag = TRUE;
- return ptNoError;
-}
-
-
-PtError Pt_Stop()
-{
- printf("Pt_Stop called\n");
-
- CFRunLoopStop(timerRunLoop);
- time_started_flag = FALSE;
- return ptNoError;
-}
-
-
-int Pt_Started()
-{
- return time_started_flag;
-}
-
-
-PtTimestamp Pt_Time()
-{
- CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
- return (PtTimestamp) ((now - startTime) * 1000.0);
-}
-
-
-void Pt_Sleep(int32_t duration)
-{
- usleep(duration * 1000);
-}
diff --git a/portmidi/porttime/ptmacosx_mach.c b/portmidi/porttime/ptmacosx_mach.c
deleted file mode 100755
index 1390af8..0000000
--- a/portmidi/porttime/ptmacosx_mach.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/* ptmacosx.c -- portable timer implementation for mac os x */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <CoreAudio/HostTime.h>
-
-#import <mach/mach.h>
-#import <mach/mach_error.h>
-#import <mach/mach_time.h>
-#import <mach/clock.h>
-#include <unistd.h>
-#include <AvailabilityMacros.h>
-
-#include "porttime.h"
-#include "sys/time.h"
-#include "pthread.h"
-
-#ifndef NSEC_PER_MSEC
-#define NSEC_PER_MSEC 1000000
-#endif
-#define THREAD_IMPORTANCE 63
-
-// QOS headers are available as of macOS 10.10
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
-#include "sys/qos.h"
-#define HAVE_APPLE_QOS 1
-#else
-#undef HAVE_APPLE_QOS
-#endif
-
-static int time_started_flag = FALSE;
-static UInt64 start_time;
-static pthread_t pt_thread_pid;
-
-/* note that this is static data -- we only need one copy */
-typedef struct {
- int id;
- int resolution;
- PtCallback *callback;
- void *userData;
-} pt_callback_parameters;
-
-static int pt_callback_proc_id = 0;
-
-static void *Pt_CallbackProc(void *p)
-{
- pt_callback_parameters *parameters = (pt_callback_parameters *) p;
- int mytime = 1;
-
- kern_return_t error;
- thread_extended_policy_data_t extendedPolicy;
- thread_precedence_policy_data_t precedencePolicy;
-
- extendedPolicy.timeshare = 0;
- error = thread_policy_set(mach_thread_self(), THREAD_EXTENDED_POLICY,
- (thread_policy_t)&extendedPolicy,
- THREAD_EXTENDED_POLICY_COUNT);
- if (error != KERN_SUCCESS) {
- mach_error("Couldn't set thread timeshare policy", error);
- }
-
- precedencePolicy.importance = THREAD_IMPORTANCE;
- error = thread_policy_set(mach_thread_self(), THREAD_PRECEDENCE_POLICY,
- (thread_policy_t)&precedencePolicy,
- THREAD_PRECEDENCE_POLICY_COUNT);
- if (error != KERN_SUCCESS) {
- mach_error("Couldn't set thread precedence policy", error);
- }
-
- // Most important, set real-time constraints.
-
- // Define the guaranteed and max fraction of time for the audio thread.
- // These "duty cycle" values can range from 0 to 1. A value of 0.5
- // means the scheduler would give half the time to the thread.
- // These values have empirically been found to yield good behavior.
- // Good means that audio performance is high and other threads won't starve.
- const double kGuaranteedAudioDutyCycle = 0.75;
- const double kMaxAudioDutyCycle = 0.85;
-
- // Define constants determining how much time the audio thread can
- // use in a given time quantum. All times are in milliseconds.
-
- // About 128 frames @44.1KHz
- const double kTimeQuantum = 2.9;
-
- // Time guaranteed each quantum.
- const double kAudioTimeNeeded = kGuaranteedAudioDutyCycle * kTimeQuantum;
-
- // Maximum time each quantum.
- const double kMaxTimeAllowed = kMaxAudioDutyCycle * kTimeQuantum;
-
- // Get the conversion factor from milliseconds to absolute time
- // which is what the time-constraints call needs.
- mach_timebase_info_data_t tb_info;
- mach_timebase_info(&tb_info);
- double ms_to_abs_time =
- ((double)tb_info.denom / (double)tb_info.numer) * 1000000;
-
- thread_time_constraint_policy_data_t time_constraints;
- time_constraints.period = (uint32_t)(kTimeQuantum * ms_to_abs_time);
- time_constraints.computation = (uint32_t)(kAudioTimeNeeded * ms_to_abs_time);
- time_constraints.constraint = (uint32_t)(kMaxTimeAllowed * ms_to_abs_time);
- time_constraints.preemptible = 0;
-
- error = thread_policy_set(mach_thread_self(),
- THREAD_TIME_CONSTRAINT_POLICY,
- (thread_policy_t)&time_constraints,
- THREAD_TIME_CONSTRAINT_POLICY_COUNT);
- if (error != KERN_SUCCESS) {
- mach_error("Couldn't set thread precedence policy", error);
- }
-
- /* to kill a process, just increment the pt_callback_proc_id */
- /* printf("pt_callback_proc_id %d, id %d\n", pt_callback_proc_id,
- parameters->id); */
- while (pt_callback_proc_id == parameters->id) {
- /* wait for a multiple of resolution ms */
- UInt64 wait_time;
- int delay = mytime++ * parameters->resolution - Pt_Time();
- PtTimestamp timestamp;
- if (delay < 0) delay = 0;
- wait_time = AudioConvertNanosToHostTime((UInt64)delay * NSEC_PER_MSEC);
- wait_time += AudioGetCurrentHostTime();
- mach_wait_until(wait_time);
- timestamp = Pt_Time();
- (*(parameters->callback))(timestamp, parameters->userData);
- }
- free(parameters);
- return NULL;
-}
-
-
-PtError Pt_Start(int resolution, PtCallback *callback, void *userData)
-{
- if (time_started_flag) return ptAlreadyStarted;
- start_time = AudioGetCurrentHostTime();
-
- if (callback) {
- int res;
- pt_callback_parameters *parms;
-
- parms = (pt_callback_parameters *) malloc(sizeof(pt_callback_parameters));
- if (!parms) return ptInsufficientMemory;
- parms->id = pt_callback_proc_id;
- parms->resolution = resolution;
- parms->callback = callback;
- parms->userData = userData;
-
-#ifdef HAVE_APPLE_QOS
- pthread_attr_t qosAttribute;
- pthread_attr_init(&qosAttribute);
- pthread_attr_set_qos_class_np(&qosAttribute,
- QOS_CLASS_USER_INTERACTIVE, 0);
-
- res = pthread_create(&pt_thread_pid, &qosAttribute, Pt_CallbackProc,
- parms);
-#else
- res = pthread_create(&pt_thread_pid, NULL, Pt_CallbackProc, parms);
-#endif
-
- struct sched_param sp;
- memset(&sp, 0, sizeof(struct sched_param));
- sp.sched_priority = sched_get_priority_max(SCHED_RR);
- if (pthread_setschedparam(pthread_self(), SCHED_RR, &sp) == -1) {
- return ptHostError;
- }
-
- if (res != 0) return ptHostError;
- }
-
- time_started_flag = TRUE;
- return ptNoError;
-}
-
-
-PtError Pt_Stop(void)
-{
- /* printf("Pt_Stop called\n"); */
- pt_callback_proc_id++;
- pthread_join(pt_thread_pid, NULL);
- time_started_flag = FALSE;
- return ptNoError;
-}
-
-
-int Pt_Started(void)
-{
- return time_started_flag;
-}
-
-
-PtTimestamp Pt_Time(void)
-{
- UInt64 clock_time, nsec_time;
- clock_time = AudioGetCurrentHostTime() - start_time;
- nsec_time = AudioConvertHostTimeToNanos(clock_time);
- return (PtTimestamp)(nsec_time / NSEC_PER_MSEC);
-}
-
-
-void Pt_Sleep(int32_t duration)
-{
- usleep(duration * 1000);
-}
diff --git a/portmidi/porttime/ptwinmm.c b/portmidi/porttime/ptwinmm.c
deleted file mode 100755
index 5204659..0000000
--- a/portmidi/porttime/ptwinmm.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* ptwinmm.c -- portable timer implementation for win32 */
-
-
-#include "porttime.h"
-#include "windows.h"
-#include "time.h"
-
-
-TIMECAPS caps;
-
-static long time_offset = 0;
-static int time_started_flag = FALSE;
-static long time_resolution;
-static MMRESULT timer_id;
-static PtCallback *time_callback;
-
-void CALLBACK winmm_time_callback(UINT uID, UINT uMsg, DWORD_PTR dwUser,
- DWORD_PTR dw1, DWORD_PTR dw2)
-{
- (*time_callback)(Pt_Time(), (void *) dwUser);
-}
-
-
-PMEXPORT PtError Pt_Start(int resolution, PtCallback *callback, void *userData)
-{
- if (time_started_flag) return ptAlreadyStarted;
- timeBeginPeriod(resolution);
- time_resolution = resolution;
- time_offset = timeGetTime();
- time_started_flag = TRUE;
- time_callback = callback;
- if (callback) {
- timer_id = timeSetEvent(resolution, 1, winmm_time_callback,
- (DWORD_PTR) userData, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
- if (!timer_id) return ptHostError;
- }
- return ptNoError;
-}
-
-
-PMEXPORT PtError Pt_Stop()
-{
- if (!time_started_flag) return ptAlreadyStopped;
- if (time_callback && timer_id) {
- timeKillEvent(timer_id);
- time_callback = NULL;
- timer_id = 0;
- }
- time_started_flag = FALSE;
- timeEndPeriod(time_resolution);
- return ptNoError;
-}
-
-
-PMEXPORT int Pt_Started()
-{
- return time_started_flag;
-}
-
-
-PMEXPORT PtTimestamp Pt_Time()
-{
- return timeGetTime() - time_offset;
-}
-
-
-PMEXPORT void Pt_Sleep(int32_t duration)
-{
- Sleep(duration);
-}