gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

ptmacosx_cf.c (3669B)


      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 
     18 static int time_started_flag = FALSE;
     19 static CFAbsoluteTime startTime = 0.0;
     20 static CFRunLoopRef timerRunLoop;
     21 
     22 typedef struct {
     23     int resolution;
     24     PtCallback *callback;
     25     void *userData;
     26 } PtThreadParams;
     27 
     28 
     29 void Pt_CFTimerCallback(CFRunLoopTimerRef timer, void *info)
     30 {
     31     PtThreadParams *params = (PtThreadParams*)info;
     32     (*params->callback)(Pt_Time(), params->userData);
     33 }
     34 
     35 static 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 
     89 PtError 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 
    114 PtError Pt_Stop()
    115 {
    116     printf("Pt_Stop called\n");
    117 
    118     CFRunLoopStop(timerRunLoop);
    119     time_started_flag = FALSE;
    120     return ptNoError;
    121 }
    122 
    123 
    124 int Pt_Started()
    125 {
    126     return time_started_flag;
    127 }
    128 
    129 
    130 PtTimestamp Pt_Time()
    131 {
    132     CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
    133     return (PtTimestamp) ((now - startTime) * 1000.0);
    134 }
    135 
    136 
    137 void Pt_Sleep(int32_t duration)
    138 {
    139     usleep(duration * 1000);
    140 }