peter1138@2743: /* $Id$ */ peter1138@2743: peter1138@2953: /***************************************************************************** peter1138@2953: * Cocoa sound driver * peter1138@2953: * Known things left to do: * peter1138@2953: * - Might need to do endian checking for it to work on both ppc and x86 * peter1138@2953: *****************************************************************************/ bjarni@2736: bjarni@2736: #ifdef WITH_COCOA bjarni@2736: bjarni@2736: #include bjarni@2736: bjarni@2736: /* Name conflict */ peter1138@2953: #define Rect OTTDRect peter1138@2953: #define Point OTTDPoint peter1138@2953: #define WindowClass OTTDWindowClass bjarni@2736: /* Defined in stdbool.h */ bjarni@2736: #ifndef __cplusplus bjarni@2736: # ifndef __BEOS__ bjarni@2736: # undef bool bjarni@2736: # undef false bjarni@2736: # undef true bjarni@2736: # endif bjarni@2736: #endif bjarni@2736: bjarni@2736: #include "../stdafx.h" bjarni@2736: #include "../openttd.h" bjarni@2736: #include "../debug.h" bjarni@2736: #include "../driver.h" bjarni@2736: #include "../mixer.h" bjarni@2736: #include "../sdl.h" bjarni@2736: bjarni@2736: #include "cocoa_s.h" bjarni@2736: bjarni@2736: #undef WindowClass bjarni@2736: #undef Point bjarni@2736: #undef Rect bjarni@2736: bjarni@2736: bjarni@2736: static AudioUnit _outputAudioUnit; bjarni@2736: bjarni@2736: /* The CoreAudio callback */ peter1138@2953: static OSStatus audioCallback(void *inRefCon, AudioUnitRenderActionFlags inActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, AudioBuffer *ioData) bjarni@2736: { tron@2977: MxMixSamples(ioData->mData, ioData->mDataByteSize / 4); bjarni@2736: bjarni@2736: return noErr; bjarni@2736: } bjarni@2736: bjarni@2736: bjarni@2736: static const char *CocoaSoundStart(const char * const *parm) bjarni@2736: { bjarni@2736: Component comp; bjarni@2736: ComponentDescription desc; bjarni@2736: struct AudioUnitInputCallback callback; bjarni@2736: AudioStreamBasicDescription requestedDesc; bjarni@2736: bjarni@2736: DEBUG(driver, 1)("cocoa_s: CocoaSoundStart"); bjarni@2736: bjarni@2736: /* Setup a AudioStreamBasicDescription with the requested format */ bjarni@2736: requestedDesc.mFormatID = kAudioFormatLinearPCM; bjarni@2736: requestedDesc.mFormatFlags = kLinearPCMFormatFlagIsPacked; bjarni@2736: requestedDesc.mChannelsPerFrame = 2; bjarni@2736: requestedDesc.mSampleRate = GetDriverParamInt(parm, "hz", 11025); bjarni@2736: bjarni@2736: requestedDesc.mBitsPerChannel = 16; bjarni@2736: requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger; bjarni@2837: bjarni@2837: #ifdef TTD_BIG_ENDIAN bjarni@2736: requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; bjarni@2736: #endif bjarni@2736: bjarni@2736: requestedDesc.mFramesPerPacket = 1; bjarni@2736: requestedDesc.mBytesPerFrame = requestedDesc.mBitsPerChannel * requestedDesc.mChannelsPerFrame / 8; bjarni@2736: requestedDesc.mBytesPerPacket = requestedDesc.mBytesPerFrame * requestedDesc.mFramesPerPacket; bjarni@2736: bjarni@2736: bjarni@2736: /* Locate the default output audio unit */ bjarni@2736: desc.componentType = kAudioUnitComponentType; bjarni@2736: desc.componentSubType = kAudioUnitSubType_Output; bjarni@2736: desc.componentManufacturer = kAudioUnitID_DefaultOutput; bjarni@2736: desc.componentFlags = 0; bjarni@2736: desc.componentFlagsMask = 0; bjarni@2736: bjarni@2736: comp = FindNextComponent (NULL, &desc); bjarni@2736: if (comp == NULL) bjarni@2736: return "cocoa_s: Failed to start CoreAudio: FindNextComponent returned NULL"; bjarni@2736: bjarni@2736: /* Open & initialize the default output audio unit */ peter1138@2953: if (OpenAComponent(comp, &_outputAudioUnit) != noErr) bjarni@2736: return "cocoa_s: Failed to start CoreAudio: OpenAComponent"; bjarni@2736: peter1138@2953: if (AudioUnitInitialize(_outputAudioUnit) != noErr) bjarni@2736: return "cocoa_s: Failed to start CoreAudio: AudioUnitInitialize"; bjarni@2736: bjarni@2736: /* Set the input format of the audio unit. */ peter1138@2953: if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &requestedDesc, sizeof(requestedDesc)) != noErr) peter1138@2953: return "cocoa_s: Failed to start CoreAudio: AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)"; bjarni@2736: bjarni@2736: /* Set the audio callback */ bjarni@2736: callback.inputProc = audioCallback; bjarni@2736: callback.inputProcRefCon = NULL; peter1138@2953: if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_SetInputCallback, kAudioUnitScope_Input, 0, &callback, sizeof(callback)) != noErr) bjarni@2736: return "cocoa_s: Failed to start CoreAudio: AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)"; bjarni@2736: bjarni@2736: /* Finally, start processing of the audio unit */ peter1138@2953: if (AudioOutputUnitStart(_outputAudioUnit) != noErr) bjarni@2736: return "cocoa_s: Failed to start CoreAudio: AudioOutputUnitStart"; bjarni@2736: bjarni@2736: /* We're running! */ bjarni@2736: return NULL; bjarni@2736: } bjarni@2736: bjarni@2736: bjarni@2736: static void CocoaSoundStop(void) bjarni@2736: { bjarni@2736: struct AudioUnitInputCallback callback; bjarni@2736: bjarni@2736: DEBUG(driver, 1)("cocoa_s: CocoaSoundStop"); bjarni@2736: bjarni@2736: /* stop processing the audio unit */ bjarni@2736: if(AudioOutputUnitStop(_outputAudioUnit) != noErr) { bjarni@2736: DEBUG(driver, 1)("cocoa_s: Core_CloseAudio: AudioOutputUnitStop failed"); bjarni@2736: return; bjarni@2736: } bjarni@2736: bjarni@2736: /* Remove the input callback */ bjarni@2736: callback.inputProc = 0; bjarni@2736: callback.inputProcRefCon = 0; peter1138@2953: if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_SetInputCallback, kAudioUnitScope_Input, 0, &callback, sizeof(callback)) != noErr) { bjarni@2736: DEBUG(driver, 1)("cocoa_s: Core_CloseAudio: AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback) failed"); bjarni@2736: return; bjarni@2736: } bjarni@2736: bjarni@2736: if (CloseComponent(_outputAudioUnit) != noErr) { bjarni@2736: DEBUG(driver, 1)("cocoa_s: Core_CloseAudio: CloseComponent failed"); bjarni@2736: return; bjarni@2736: } bjarni@2736: } bjarni@2736: bjarni@2736: bjarni@2736: const HalSoundDriver _cocoa_sound_driver = { bjarni@2736: CocoaSoundStart, bjarni@2736: CocoaSoundStop, bjarni@2736: }; bjarni@2736: bjarni@2736: #endif /* WITH_COCOA */