src/sound/cocoa_s.cpp
branchcustombridgeheads
changeset 5649 55c8267c933f
parent 5643 3778051e8095
child 6298 c30fe89622df
equal deleted inserted replaced
5648:1608018c5ff2 5649:55c8267c933f
       
     1 /* $Id$ */
       
     2 
       
     3 /*****************************************************************************
       
     4  *                             Cocoa sound driver                            *
       
     5  * Known things left to do:                                                  *
       
     6  * - Might need to do endian checking for it to work on both ppc and x86     *
       
     7  *****************************************************************************/
       
     8 
       
     9 #ifdef WITH_COCOA
       
    10 
       
    11 #include <AudioUnit/AudioUnit.h>
       
    12 
       
    13 /* Name conflict */
       
    14 #define Rect        OTTDRect
       
    15 #define Point       OTTDPoint
       
    16 #define WindowClass OTTDWindowClass
       
    17 /* Defined in stdbool.h */
       
    18 #ifndef __cplusplus
       
    19 # ifndef __BEOS__
       
    20 #  undef bool
       
    21 #  undef false
       
    22 #  undef true
       
    23 # endif
       
    24 #endif
       
    25 
       
    26 #include "../stdafx.h"
       
    27 #include "../openttd.h"
       
    28 #include "../debug.h"
       
    29 #include "../driver.h"
       
    30 #include "../mixer.h"
       
    31 #include "../sdl.h"
       
    32 
       
    33 #include "cocoa_s.h"
       
    34 
       
    35 #undef WindowClass
       
    36 #undef Point
       
    37 #undef Rect
       
    38 
       
    39 
       
    40 static AudioUnit _outputAudioUnit;
       
    41 
       
    42 /* The CoreAudio callback */
       
    43 static OSStatus audioCallback(void *inRefCon, AudioUnitRenderActionFlags inActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, AudioBuffer *ioData)
       
    44 {
       
    45 	MxMixSamples(ioData->mData, ioData->mDataByteSize / 4);
       
    46 
       
    47 	return noErr;
       
    48 }
       
    49 
       
    50 
       
    51 static const char *CocoaSoundStart(const char * const *parm)
       
    52 {
       
    53 	Component comp;
       
    54 	ComponentDescription desc;
       
    55 	struct AudioUnitInputCallback callback;
       
    56 	AudioStreamBasicDescription requestedDesc;
       
    57 
       
    58 	/* Setup a AudioStreamBasicDescription with the requested format */
       
    59 	requestedDesc.mFormatID = kAudioFormatLinearPCM;
       
    60 	requestedDesc.mFormatFlags = kLinearPCMFormatFlagIsPacked;
       
    61 	requestedDesc.mChannelsPerFrame = 2;
       
    62 	requestedDesc.mSampleRate = GetDriverParamInt(parm, "hz", 11025);
       
    63 
       
    64 	requestedDesc.mBitsPerChannel = 16;
       
    65 	requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
       
    66 
       
    67 #ifdef TTD_BIG_ENDIAN
       
    68 	requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
       
    69 #endif
       
    70 
       
    71 	requestedDesc.mFramesPerPacket = 1;
       
    72 	requestedDesc.mBytesPerFrame = requestedDesc.mBitsPerChannel * requestedDesc.mChannelsPerFrame / 8;
       
    73 	requestedDesc.mBytesPerPacket = requestedDesc.mBytesPerFrame * requestedDesc.mFramesPerPacket;
       
    74 
       
    75 
       
    76 	/* Locate the default output audio unit */
       
    77 	desc.componentType = kAudioUnitComponentType;
       
    78 	desc.componentSubType = kAudioUnitSubType_Output;
       
    79 	desc.componentManufacturer = kAudioUnitID_DefaultOutput;
       
    80 	desc.componentFlags = 0;
       
    81 	desc.componentFlagsMask = 0;
       
    82 
       
    83 	comp = FindNextComponent (NULL, &desc);
       
    84 	if (comp == NULL) {
       
    85 		return "cocoa_s: Failed to start CoreAudio: FindNextComponent returned NULL";
       
    86 	}
       
    87 
       
    88 	/* Open & initialize the default output audio unit */
       
    89 	if (OpenAComponent(comp, &_outputAudioUnit) != noErr) {
       
    90 		return "cocoa_s: Failed to start CoreAudio: OpenAComponent";
       
    91 	}
       
    92 
       
    93 	if (AudioUnitInitialize(_outputAudioUnit) != noErr) {
       
    94 		return "cocoa_s: Failed to start CoreAudio: AudioUnitInitialize";
       
    95 	}
       
    96 
       
    97 	/* Set the input format of the audio unit. */
       
    98 	if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &requestedDesc, sizeof(requestedDesc)) != noErr) {
       
    99 		return "cocoa_s: Failed to start CoreAudio: AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)";
       
   100 	}
       
   101 
       
   102 	/* Set the audio callback */
       
   103 	callback.inputProc = audioCallback;
       
   104 	callback.inputProcRefCon = NULL;
       
   105 	if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_SetInputCallback, kAudioUnitScope_Input, 0, &callback, sizeof(callback)) != noErr) {
       
   106 		return "cocoa_s: Failed to start CoreAudio: AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)";
       
   107 	}
       
   108 
       
   109 	/* Finally, start processing of the audio unit */
       
   110 	if (AudioOutputUnitStart(_outputAudioUnit) != noErr) {
       
   111 		return "cocoa_s: Failed to start CoreAudio: AudioOutputUnitStart";
       
   112 	}
       
   113 
       
   114 	/* We're running! */
       
   115 	return NULL;
       
   116 }
       
   117 
       
   118 
       
   119 static void CocoaSoundStop(void)
       
   120 {
       
   121 	struct AudioUnitInputCallback callback;
       
   122 
       
   123 	/* stop processing the audio unit */
       
   124 	if (AudioOutputUnitStop(_outputAudioUnit) != noErr) {
       
   125 		DEBUG(driver, 0, "cocoa_s: Core_CloseAudio: AudioOutputUnitStop failed");
       
   126 		return;
       
   127 	}
       
   128 
       
   129 	/* Remove the input callback */
       
   130 	callback.inputProc = 0;
       
   131 	callback.inputProcRefCon = 0;
       
   132 	if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_SetInputCallback, kAudioUnitScope_Input, 0, &callback, sizeof(callback)) != noErr) {
       
   133 		DEBUG(driver, 0, "cocoa_s: Core_CloseAudio: AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback) failed");
       
   134 		return;
       
   135 	}
       
   136 
       
   137 	if (CloseComponent(_outputAudioUnit) != noErr) {
       
   138 		DEBUG(driver, 0, "cocoa_s: Core_CloseAudio: CloseComponent failed");
       
   139 		return;
       
   140 	}
       
   141 }
       
   142 
       
   143 
       
   144 const HalSoundDriver _cocoa_sound_driver = {
       
   145 	CocoaSoundStart,
       
   146 	CocoaSoundStop,
       
   147 };
       
   148 
       
   149 #endif /* WITH_COCOA */