# cocoa_s.cpp

Go to the documentation of this file.

    00001 /* $Id: cocoa_s.cpp 16804 2009-07-13 10:16:50Z rubidium $ */
    00002
    00005 /*****************************************************************************
    00006  *                             Cocoa sound driver                            *
    00007  * Known things left to do:                                                  *
    00008  * - Might need to do endian checking for it to work on both ppc and x86     *
    00009  *****************************************************************************/
    00010
    00011 #ifdef WITH_COCOA
    00012
    00013 #define MAC_OS_X_VERSION_MIN_REQUIRED    MAC_OS_X_VERSION_10_3
    00014 #include <AvailabilityMacros.h>
    00015
    00016 #include <AudioUnit/AudioUnit.h>
    00017
    00018 /* Name conflict */
    00019 #define Rect        OTTDRect
    00020 #define Point       OTTDPoint
    00021 #define WindowClass OTTDWindowClass
    00022
    00023 #include "../stdafx.h"
    00024 #include "../debug.h"
    00025 #include "../driver.h"
    00026 #include "../mixer.h"
    00027 #include "../core/endian_type.hpp"
    00028
    00029 #include "cocoa_s.h"
    00030
    00031 #undef WindowClass
    00032 #undef Point
    00033 #undef Rect
    00034
    00035 static FSoundDriver_Cocoa iFSoundDriver_Cocoa;
    00036
    00037 static AudioUnit _outputAudioUnit;
    00038
    00039 /* The CoreAudio callback */
    00040 static OSStatus audioCallback(void *inRefCon, AudioUnitRenderActionFlags *inActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList * ioData)
    00041 {
    00042   MxMixSamples(ioData->mBuffers[0].mData, ioData->mBuffers[0].mDataByteSize / 4);
    00043
    00044   return noErr;
    00045 }
    00046
    00047
    00048 const char *SoundDriver_Cocoa::Start(const char * const *parm)
    00049 {
    00050   Component comp;
    00051   ComponentDescription desc;
    00052   struct AURenderCallbackStruct callback;
    00053   AudioStreamBasicDescription requestedDesc;
    00054
    00055   /* Setup a AudioStreamBasicDescription with the requested format */
    00056   requestedDesc.mFormatID = kAudioFormatLinearPCM;
    00057   requestedDesc.mFormatFlags = kLinearPCMFormatFlagIsPacked;
    00058   requestedDesc.mChannelsPerFrame = 2;
    00059   requestedDesc.mSampleRate = GetDriverParamInt(parm, "hz", 11025);
    00060
    00061   requestedDesc.mBitsPerChannel = 16;
    00062   requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
    00063
    00064 #if TTD_ENDIAN == TTD_BIG_ENDIAN
    00065   requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
    00066 #endif /* TTD_ENDIAN == TTD_BIG_ENDIAN */
    00067
    00068   requestedDesc.mFramesPerPacket = 1;
    00069   requestedDesc.mBytesPerFrame = requestedDesc.mBitsPerChannel * requestedDesc.mChannelsPerFrame / 8;
    00070   requestedDesc.mBytesPerPacket = requestedDesc.mBytesPerFrame * requestedDesc.mFramesPerPacket;
    00071
    00072   MxInitialize(requestedDesc.mSampleRate);
    00073
    00074   /* Locate the default output audio unit */
    00075   desc.componentType = kAudioUnitType_Output;
    00076   desc.componentSubType = kAudioUnitSubType_HALOutput;
    00077   desc.componentManufacturer = kAudioUnitManufacturer_Apple;
    00078   desc.componentFlags = 0;
    00079   desc.componentFlagsMask = 0;
    00080
    00081   comp = FindNextComponent (NULL, &desc);
    00082   if (comp == NULL) {
    00083     return "cocoa_s: Failed to start CoreAudio: FindNextComponent returned NULL";
    00084   }
    00085
    00086   /* Open & initialize the default output audio unit */
    00087   if (OpenAComponent(comp, &_outputAudioUnit) != noErr) {
    00088     return "cocoa_s: Failed to start CoreAudio: OpenAComponent";
    00089   }
    00090
    00091   if (AudioUnitInitialize(_outputAudioUnit) != noErr) {
    00092     return "cocoa_s: Failed to start CoreAudio: AudioUnitInitialize";
    00093   }
    00094
    00095   /* Set the input format of the audio unit. */
    00096   if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &requestedDesc, sizeof(requestedDesc)) != noErr) {
    00097     return "cocoa_s: Failed to start CoreAudio: AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)";
    00098   }
    00099
    00100   /* Set the audio callback */
    00101   callback.inputProc = audioCallback;
    00102   callback.inputProcRefCon = NULL;
    00103   if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callback, sizeof(callback)) != noErr) {
    00104     return "cocoa_s: Failed to start CoreAudio: AudioUnitSetProperty (kAudioUnitProperty_SetRenderCallback)";
    00105   }
    00106
    00107   /* Finally, start processing of the audio unit */
    00108   if (AudioOutputUnitStart(_outputAudioUnit) != noErr) {
    00109     return "cocoa_s: Failed to start CoreAudio: AudioOutputUnitStart";
    00110   }
    00111
    00112   /* We're running! */
    00113   return NULL;
    00114 }
    00115
    00116
    00117 void SoundDriver_Cocoa::Stop()
    00118 {
    00119   struct AURenderCallbackStruct callback;
    00120
    00121   /* stop processing the audio unit */
    00122   if (AudioOutputUnitStop(_outputAudioUnit) != noErr) {
    00123     DEBUG(driver, 0, "cocoa_s: Core_CloseAudio: AudioOutputUnitStop failed");
    00124     return;
    00125   }
    00126
    00127   /* Remove the input callback */
    00128   callback.inputProc = 0;
    00129   callback.inputProcRefCon = 0;
    00130   if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callback, sizeof(callback)) != noErr) {
    00131     DEBUG(driver, 0, "cocoa_s: Core_CloseAudio: AudioUnitSetProperty (kAudioUnitProperty_SetRenderCallback) failed");
    00132     return;
    00133   }
    00134
    00135   if (CloseComponent(_outputAudioUnit) != noErr) {
    00136     DEBUG(driver, 0, "cocoa_s: Core_CloseAudio: CloseComponent failed");
    00137     return;
    00138   }
    00139 }
    00140
    00141 #endif /* WITH_COCOA */