aboutsummaryrefslogtreecommitdiff
path: root/portmidi/porttime/ptmacosx_cf.c
diff options
context:
space:
mode:
Diffstat (limited to 'portmidi/porttime/ptmacosx_cf.c')
-rwxr-xr-xportmidi/porttime/ptmacosx_cf.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/portmidi/porttime/ptmacosx_cf.c b/portmidi/porttime/ptmacosx_cf.c
new file mode 100755
index 0000000..a174c86
--- /dev/null
+++ b/portmidi/porttime/ptmacosx_cf.c
@@ -0,0 +1,140 @@
1/* ptmacosx.c -- portable timer implementation for mac os x */
2
3#include <stdlib.h>
4#include <stdio.h>
5#include <pthread.h>
6#include <CoreFoundation/CoreFoundation.h>
7
8#import <mach/mach.h>
9#import <mach/mach_error.h>
10#import <mach/mach_time.h>
11#import <mach/clock.h>
12
13#include "porttime.h"
14
15#define THREAD_IMPORTANCE 30
16#define LONG_TIME 1000000000.0
17
18static int time_started_flag = FALSE;
19static CFAbsoluteTime startTime = 0.0;
20static CFRunLoopRef timerRunLoop;
21
22typedef struct {
23 int resolution;
24 PtCallback *callback;
25 void *userData;
26} PtThreadParams;
27
28
29void Pt_CFTimerCallback(CFRunLoopTimerRef timer, void *info)
30{
31 PtThreadParams *params = (PtThreadParams*)info;
32 (*params->callback)(Pt_Time(), params->userData);
33}
34
35static void* Pt_Thread(void *p)
36{
37 CFTimeInterval timerInterval;
38 CFRunLoopTimerContext timerContext;
39 CFRunLoopTimerRef timer;
40 PtThreadParams *params = (PtThreadParams*)p;
41 //CFTimeInterval timeout;
42
43 /* raise the thread's priority */
44 kern_return_t error;
45 thread_extended_policy_data_t extendedPolicy;
46 thread_precedence_policy_data_t precedencePolicy;
47
48 extendedPolicy.timeshare = 0;
49 error = thread_policy_set(mach_thread_self(), THREAD_EXTENDED_POLICY,
50 (thread_policy_t)&extendedPolicy,
51 THREAD_EXTENDED_POLICY_COUNT);
52 if (error != KERN_SUCCESS) {
53 mach_error("Couldn't set thread timeshare policy", error);
54 }
55
56 precedencePolicy.importance = THREAD_IMPORTANCE;
57 error = thread_policy_set(mach_thread_self(), THREAD_PRECEDENCE_POLICY,
58 (thread_policy_t)&precedencePolicy,
59 THREAD_PRECEDENCE_POLICY_COUNT);
60 if (error != KERN_SUCCESS) {
61 mach_error("Couldn't set thread precedence policy", error);
62 }
63
64 /* set up the timer context */
65 timerContext.version = 0;
66 timerContext.info = params;
67 timerContext.retain = NULL;
68 timerContext.release = NULL;
69 timerContext.copyDescription = NULL;
70
71 /* create a new timer */
72 timerInterval = (double)params->resolution / 1000.0;
73 timer = CFRunLoopTimerCreate(NULL, startTime+timerInterval, timerInterval,
74 0, 0, Pt_CFTimerCallback, &timerContext);
75
76 timerRunLoop = CFRunLoopGetCurrent();
77 CFRunLoopAddTimer(timerRunLoop, timer, CFSTR("PtTimeMode"));
78
79 /* run until we're told to stop by Pt_Stop() */
80 CFRunLoopRunInMode(CFSTR("PtTimeMode"), LONG_TIME, false);
81
82 CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), timer, CFSTR("PtTimeMode"));
83 CFRelease(timer);
84 free(params);
85
86 return NULL;
87}
88
89PtError Pt_Start(int resolution, PtCallback *callback, void *userData)
90{
91 PtThreadParams *params = (PtThreadParams*)malloc(sizeof(PtThreadParams));
92 pthread_t pthread_id;
93
94 printf("Pt_Start() called\n");
95
96 // /* make sure we're not already playing */
97 if (time_started_flag) return ptAlreadyStarted;
98 startTime = CFAbsoluteTimeGetCurrent();
99
100 if (callback) {
101
102 params->resolution = resolution;
103 params->callback = callback;
104 params->userData = userData;
105
106 pthread_create(&pthread_id, NULL, Pt_Thread, params);
107 }
108
109 time_started_flag = TRUE;
110 return ptNoError;
111}
112
113
114PtError Pt_Stop()
115{
116 printf("Pt_Stop called\n");
117
118 CFRunLoopStop(timerRunLoop);
119 time_started_flag = FALSE;
120 return ptNoError;
121}
122
123
124int Pt_Started()
125{
126 return time_started_flag;
127}
128
129
130PtTimestamp Pt_Time()
131{
132 CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
133 return (PtTimestamp) ((now - startTime) * 1000.0);
134}
135
136
137void Pt_Sleep(int32_t duration)
138{
139 usleep(duration * 1000);
140}