#include #import #import /* TODO: Can we have even lower level API than AppKit? */ static float volume = 0; static NSCache *audio_cache = nil; /* For sound finish delegate memory safety */ @interface ClakMacSound : NSObject @end @implementation ClakMacSound - (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)flag { [sound release]; } @end static ClakMacSound *clak_mac_sound = nil; bool macos_sound_init(float _volume) { volume = _volume; /* Bring up NSCache for storing NSData */ audio_cache = [[NSCache alloc] init]; if (audio_cache == nil) { printf("ERROR: Could not initialise audio cache!\n"); return false; } /* Prepare sound delegate for memory safety */ clak_mac_sound = [[ClakMacSound alloc] init]; return true; } void macos_sound_play(unsigned char *buffer, unsigned int buffer_len) { /* Get buffer's pointer for use as dictionary key in cache */ NSValue *ptr_key = [NSValue valueWithPointer:buffer]; /* If no cached, set up the data */ NSData *buffer_ns = [audio_cache objectForKey:ptr_key]; if (buffer_ns == nil) { /* Set up data, reusing the static buffer */ buffer_ns = [NSData dataWithBytesNoCopy:(void *)buffer length:(NSUInteger)buffer_len freeWhenDone:NO]; /* Cache it */ [audio_cache setObject:buffer_ns forKey:ptr_key]; } NSSound *sound = [[NSSound alloc] initWithData:buffer_ns]; sound.delegate = clak_mac_sound; [sound play]; }