# cocoa_s.cpp

Go to the documentation of this file.

    00001 /* $Id: cocoa_s.cpp 13552 2008-06-17 19:38:00Z smatz $ */
    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
    00073   /* Locate the default output audio unit */
    00074   desc.componentType = kAudioUnitType_Output;
    00075   desc.componentSubType = kAudioUnitSubType_HALOutput;
    00076   desc.componentManufacturer = kAudioUnitManufacturer_Apple;
    00077   desc.componentFlags = 0;
    00078   desc.componentFlagsMask = 0;
    00079
    00080   comp = FindNextComponent (NULL, &desc);
    00081   if (comp == NULL) {
    00082     return "cocoa_s: Failed to start CoreAudio: FindNextComponent returned NULL";
    00083   }
    00084
    00085   /* Open & initialize the default output audio unit */
    00086   if (OpenAComponent(comp, &_outputAudioUnit) != noErr) {
    00087     return "cocoa_s: Failed to start CoreAudio: OpenAComponent";
    00088   }
    00089
    00090   if (AudioUnitInitialize(_outputAudioUnit) != noErr) {
    00091     return "cocoa_s: Failed to start CoreAudio: AudioUnitInitialize";
    00092   }
    00093
    00094   /* Set the input format of the audio unit. */
    00095   if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &requestedDesc, sizeof(requestedDesc)) != noErr) {
    00096     return "cocoa_s: Failed to start CoreAudio: AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)";
    00097   }
    00098
    00099   /* Set the audio callback */
    00100   callback.inputProc = audioCallback;
    00101   callback.inputProcRefCon = NULL;
    00102   if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callback, sizeof(callback)) != noErr) {
    00103     return "cocoa_s: Failed to start CoreAudio: AudioUnitSetProperty (kAudioUnitProperty_SetRenderCallback)";
    00104   }
    00105
    00106   /* Finally, start processing of the audio unit */
    00107   if (AudioOutputUnitStart(_outputAudioUnit) != noErr) {
    00108     return "cocoa_s: Failed to start CoreAudio: AudioOutputUnitStart";
    00109   }
    00110
    00111   /* We're running! */
    00112   return NULL;
    00113 }
    00114
    00115
    00116 void SoundDriver_Cocoa::Stop()
    00117 {
    00118   struct AURenderCallbackStruct callback;
    00119
    00120   /* stop processing the audio unit */
    00121   if (AudioOutputUnitStop(_outputAudioUnit) != noErr) {
    00122     DEBUG(driver, 0, "cocoa_s: Core_CloseAudio: AudioOutputUnitStop failed");
    00123     return;
    00124   }
    00125
    00126   /* Remove the input callback */
    00127   callback.inputProc = 0;
    00128   callback.inputProcRefCon = 0;
    00129   if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callback, sizeof(callback)) != noErr) {
    00130     DEBUG(driver, 0, "cocoa_s: Core_CloseAudio: AudioUnitSetProperty (kAudioUnitProperty_SetRenderCallback) failed");
    00131     return;
    00132   }
    00133
    00134   if (CloseComponent(_outputAudioUnit) != noErr) {
    00135     DEBUG(driver, 0, "cocoa_s: Core_CloseAudio: CloseComponent failed");
    00136     return;
    00137   }
    00138 }
    00139
    00140 #endif /* WITH_COCOA */