mirror of
				https://github.com/cookiengineer/audacity
				synced 2025-11-04 16:14:00 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			141 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			141 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* 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);
 | 
						|
}
 |