summaryrefslogtreecommitdiff
path: root/libs/appleutility
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2015-10-17 20:46:58 -0400
committerRobin Gareus <robin@gareus.org>2015-10-18 23:03:13 +0200
commit66704eefcbe132eac0415434340f788808c40302 (patch)
tree2d4b596265f2fd801244862cef8bb79a63eea289 /libs/appleutility
parentf7e3117c3b3f09cc10cb10434660accf4ef49fc8 (diff)
alternative new version of the AppleUtility library
Diffstat (limited to 'libs/appleutility')
-rw-r--r--libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.cpp580
-rw-r--r--libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.h147
-rw-r--r--libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.cpp329
-rw-r--r--libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.h115
-rw-r--r--libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodecDispatchTypes.h259
-rw-r--r--libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACComponentResources.r196
-rw-r--r--libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACConditionalMacros.h73
-rw-r--r--libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.cpp283
-rw-r--r--libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.h88
-rw-r--r--libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.cpp364
-rw-r--r--libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.h105
-rw-r--r--libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.cpp76
-rw-r--r--libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.h60
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.cpp1040
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.h311
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.cpp71
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.h125
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.cpp1966
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.h667
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp216
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.h186
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.cpp689
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.h372
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.cpp2393
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.h1048
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.cpp438
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.h82
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.cpp151
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.h119
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp62
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.h66
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.cpp669
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.h144
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUResources.r140
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp565
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.h553
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.cpp370
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.h353
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp403
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h188
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp710
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h230
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp125
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp359
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h90
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp90
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h71
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp843
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h269
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h168
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/MIDIControlHandler.h92
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp419
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h227
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h145
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp140
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h187
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp93
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h232
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h88
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp466
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.h377
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp495
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h213
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp164
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h104
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp76
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.h82
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp706
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.h272
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp354
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h126
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp125
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.h75
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.cpp219
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.h267
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h155
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUMIDIDefs.h138
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUSilentTimeout.h93
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp203
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h163
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.cpp169
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.h118
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.cpp139
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.h112
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.cpp227
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.h541
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.cpp233
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.h102
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.cpp400
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.h191
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.cpp707
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.h293
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAtomic.h305
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAtomicStack.h239
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp239
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.h108
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.cpp153
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.h199
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayoutObject.cpp210
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.cpp424
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.h149
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.cpp135
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.h97
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.cpp1421
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.h439
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAudioUnitOutputCapturer.h143
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.cpp262
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.h121
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAAutoDisposer.h508
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CABitOperations.h206
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CABool.h89
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CABufferList.cpp259
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CABufferList.h324
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.cpp84
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.h69
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAByteOrder.h161
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFArray.cpp821
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFArray.h195
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFData.h108
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.cpp581
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.h176
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.cpp107
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.h73
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.cpp168
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.h95
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.cpp163
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.h119
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFNumber.cpp83
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFNumber.h151
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFObject.h138
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFPlugIn.h101
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.cpp287
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.h92
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFString.cpp110
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CACFString.h196
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAComponent.cpp182
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAComponent.h121
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.cpp110
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.h145
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.cpp90
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.h581
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.cpp89
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.h115
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CADebugger.cpp103
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CADebugger.h69
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAException.h83
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h300
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.cpp188
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.h70
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAGuard.cpp343
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAGuard.h133
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.cpp1156
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.h238
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.cpp370
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.h155
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.cpp182
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.h94
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.cpp181
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.h90
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.cpp99
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.h234
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CALogMacros.h140
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAMath.h68
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAMixMap.h157
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAMutex.cpp345
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAMutex.h163
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAPThread.cpp450
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAPThread.h191
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAPersistence.cpp468
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAProcess.cpp92
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAProcess.h75
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAPropertyAddress.h312
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAReferenceCounted.h97
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.cpp319
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.h126
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.cpp737
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.h128
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.cpp118
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.h64
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.cpp376
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.h146
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.cpp879
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h424
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.cpp183
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.h140
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAThreadSafeList.h233
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CATink.h146
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CATokenMap.h212
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.cpp195
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.h101
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAVectorUnitTypes.h60
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.cpp482
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.h178
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAXException.cpp49
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/CAXException.h361
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.cpp149
-rw-r--r--libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.h71
-rw-r--r--libs/appleutility/CoreAudio105/AUOutputBL.cpp (renamed from libs/appleutility/AUOutputBL.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/AUOutputBL.h (renamed from libs/appleutility/AUOutputBL.h)0
-rw-r--r--libs/appleutility/CoreAudio105/AUParamInfo.cpp (renamed from libs/appleutility/AUParamInfo.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/AUParamInfo.h (renamed from libs/appleutility/AUParamInfo.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CAAUParameter.cpp (renamed from libs/appleutility/CAAUParameter.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/CAAUParameter.h (renamed from libs/appleutility/CAAUParameter.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CAAudioChannelLayout.cpp (renamed from libs/appleutility/CAAudioChannelLayout.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/CAAudioChannelLayout.h (renamed from libs/appleutility/CAAudioChannelLayout.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CAAudioChannelLayoutObject.cpp (renamed from libs/appleutility/CAAudioChannelLayoutObject.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/CAAudioFile.cpp (renamed from libs/appleutility/CAAudioFile.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/CAAudioFile.h (renamed from libs/appleutility/CAAudioFile.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CAAudioUnit.cpp (renamed from libs/appleutility/CAAudioUnit.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/CAAudioUnit.h (renamed from libs/appleutility/CAAudioUnit.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CABufferList.cpp (renamed from libs/appleutility/CABufferList.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/CABufferList.h (renamed from libs/appleutility/CABufferList.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CACFDictionary.cpp (renamed from libs/appleutility/CACFDictionary.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/CACFDictionary.h (renamed from libs/appleutility/CACFDictionary.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CACFNumber.cpp (renamed from libs/appleutility/CACFNumber.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/CACFNumber.h (renamed from libs/appleutility/CACFNumber.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CACFString.cpp (renamed from libs/appleutility/CACFString.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/CACFString.h (renamed from libs/appleutility/CACFString.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CAComponent.cpp (renamed from libs/appleutility/CAComponent.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/CAComponent.h (renamed from libs/appleutility/CAComponent.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CAComponentDescription.cpp (renamed from libs/appleutility/CAComponentDescription.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/CAComponentDescription.h (renamed from libs/appleutility/CAComponentDescription.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CAConditionalMacros.h (renamed from libs/appleutility/CAConditionalMacros.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CADebugMacros.cpp (renamed from libs/appleutility/CADebugMacros.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/CADebugMacros.h (renamed from libs/appleutility/CADebugMacros.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CAMath.h (renamed from libs/appleutility/CAMath.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CAReferenceCounted.h (renamed from libs/appleutility/CAReferenceCounted.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CAStreamBasicDescription.cpp (renamed from libs/appleutility/CAStreamBasicDescription.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/CAStreamBasicDescription.h (renamed from libs/appleutility/CAStreamBasicDescription.h)0
-rw-r--r--libs/appleutility/CoreAudio105/CAXException.cpp (renamed from libs/appleutility/CAXException.cpp)0
-rw-r--r--libs/appleutility/CoreAudio105/CAXException.h (renamed from libs/appleutility/CAXException.h)0
-rw-r--r--libs/appleutility/wscript20
232 files changed, 52826 insertions, 3 deletions
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.cpp b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.cpp
new file mode 100644
index 0000000000..f1ffdf7f1b
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.cpp
@@ -0,0 +1,580 @@
+/*
+ File: ACBaseCodec.cpp
+ Abstract: ACBaseCodec.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+#include <algorithm>
+#include "ACBaseCodec.h"
+
+#include "CABundleLocker.h"
+
+#if TARGET_OS_WIN32
+ #include "CAWin32StringResources.h"
+#endif
+
+//=============================================================================
+// ACBaseCodec
+//=============================================================================
+
+ACBaseCodec::ACBaseCodec( AudioComponentInstance inInstance )
+:
+ ACCodec(inInstance),
+ mIsInitialized(false),
+ mInputFormatList(),
+ mInputFormat(),
+ mOutputFormatList(),
+ mOutputFormat()
+{
+ mCodecSubType = 0;
+ if (inInstance) GetSubType();
+}
+
+ACBaseCodec::~ACBaseCodec()
+{
+}
+
+void ACBaseCodec::GetPropertyInfo(AudioCodecPropertyID inPropertyID, UInt32& outPropertyDataSize, Boolean& outWritable)
+{
+ switch(inPropertyID)
+ {
+#if BUILD_ADEC_LIB
+ case kAudioCodecPropertyNameCFString:
+ case kAudioCodecPropertyFormatCFString:
+ case kAudioCodecPropertyManufacturerCFString:
+ outPropertyDataSize = 0;
+ outWritable = false;
+ break;
+#else
+ case kAudioCodecPropertyNameCFString:
+ outPropertyDataSize = SizeOf32(CFStringRef);
+ outWritable = false;
+ break;
+
+ case kAudioCodecPropertyManufacturerCFString:
+ outPropertyDataSize = SizeOf32(CFStringRef);
+ outWritable = false;
+ break;
+
+ case kAudioCodecPropertyFormatCFString:
+ outPropertyDataSize = SizeOf32(CFStringRef);
+ outWritable = false;
+ break;
+#endif
+ case kAudioCodecPropertyRequiresPacketDescription:
+ outPropertyDataSize = SizeOf32(UInt32);
+ outWritable = false;
+ break;
+
+ case kAudioCodecPropertyMinimumNumberInputPackets :
+ outPropertyDataSize = SizeOf32(UInt32);
+ outWritable = false;
+ break;
+
+ case kAudioCodecPropertyMinimumNumberOutputPackets :
+ outPropertyDataSize = SizeOf32(UInt32);
+ outWritable = false;
+ break;
+
+ case kAudioCodecPropertyCurrentInputFormat:
+ outPropertyDataSize = SizeOf32(AudioStreamBasicDescription);
+ outWritable = true;
+ break;
+
+ case kAudioCodecPropertySupportedInputFormats:
+ case kAudioCodecPropertyInputFormatsForOutputFormat:
+ outPropertyDataSize = GetNumberSupportedInputFormats() * SizeOf32(AudioStreamBasicDescription);
+ outWritable = false;
+ break;
+
+ case kAudioCodecPropertyCurrentOutputFormat:
+ outPropertyDataSize = SizeOf32(AudioStreamBasicDescription);
+ outWritable = true;
+ break;
+
+ case kAudioCodecPropertySupportedOutputFormats:
+ case kAudioCodecPropertyOutputFormatsForInputFormat:
+ outPropertyDataSize = GetNumberSupportedOutputFormats() * SizeOf32(AudioStreamBasicDescription);
+ outWritable = false;
+ break;
+
+ case kAudioCodecPropertyMagicCookie:
+ outPropertyDataSize = GetMagicCookieByteSize();
+ outWritable = true;
+ break;
+
+ case kAudioCodecPropertyInputBufferSize:
+ outPropertyDataSize = SizeOf32(UInt32);
+ outWritable = false;
+ break;
+
+ case kAudioCodecPropertyUsedInputBufferSize:
+ outPropertyDataSize = SizeOf32(UInt32);
+ outWritable = false;
+ break;
+
+ case kAudioCodecPropertyIsInitialized:
+ outPropertyDataSize = SizeOf32(UInt32);
+ outWritable = false;
+ break;
+
+ case kAudioCodecPropertyAvailableNumberChannels:
+ outPropertyDataSize = SizeOf32(UInt32) * 2; // Mono, stereo
+ outWritable = false;
+ break;
+
+ case kAudioCodecPropertyPrimeMethod:
+ outPropertyDataSize = SizeOf32(UInt32);
+ outWritable = false;
+ break;
+
+ case kAudioCodecPropertyPrimeInfo:
+ outPropertyDataSize = SizeOf32(AudioCodecPrimeInfo);
+ outWritable = false;
+ break;
+
+ case kAudioCodecPropertyDoesSampleRateConversion:
+ outPropertyDataSize = SizeOf32(UInt32);
+ outWritable = false;
+ break;
+
+ default:
+ CODEC_THROW(kAudioCodecUnknownPropertyError);
+ break;
+
+ };
+}
+
+void ACBaseCodec::GetProperty(AudioCodecPropertyID inPropertyID, UInt32& ioPropertyDataSize, void* outPropertyData)
+{
+ UInt32 thePacketsToGet;
+
+ switch(inPropertyID)
+ {
+#if !BUILD_ADEC_LIB
+ case kAudioCodecPropertyNameCFString:
+ {
+ if (ioPropertyDataSize != SizeOf32(CFStringRef)) CODEC_THROW(kAudioCodecBadPropertySizeError);
+
+ CABundleLocker lock;
+ CFStringRef name = CFCopyLocalizedStringFromTableInBundle(CFSTR("unknown codec"), CFSTR("CodecNames"), GetCodecBundle(), CFSTR(""));
+ *(CFStringRef*)outPropertyData = name;
+ break;
+ }
+
+ case kAudioCodecPropertyManufacturerCFString:
+ {
+ if (ioPropertyDataSize != SizeOf32(CFStringRef)) CODEC_THROW(kAudioCodecBadPropertySizeError);
+
+ CABundleLocker lock;
+ CFStringRef name = CFCopyLocalizedStringFromTableInBundle(CFSTR("Apple, Inc."), CFSTR("CodecNames"), GetCodecBundle(), CFSTR(""));
+ *(CFStringRef*)outPropertyData = name;
+ break;
+ }
+#else
+ // If called on the device these should return nothing but 0
+ case kAudioCodecPropertyNameCFString:
+ case kAudioCodecPropertyFormatCFString:
+ case kAudioCodecPropertyManufacturerCFString:
+ ioPropertyDataSize = 0;
+ outPropertyData = 0;
+ break;
+#endif
+ case kAudioCodecPropertyRequiresPacketDescription:
+ if(ioPropertyDataSize == SizeOf32(UInt32))
+ {
+ *reinterpret_cast<UInt32*>(outPropertyData) = 0;
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecBadPropertySizeError);
+ }
+ break;
+
+ case kAudioCodecPropertyMinimumNumberInputPackets :
+ if(ioPropertyDataSize != SizeOf32(UInt32)) CODEC_THROW(kAudioCodecBadPropertySizeError);
+ *(UInt32*)outPropertyData = 1;
+ break;
+
+ case kAudioCodecPropertyMinimumNumberOutputPackets :
+ if(ioPropertyDataSize != SizeOf32(UInt32)) CODEC_THROW(kAudioCodecBadPropertySizeError);
+ *(UInt32*)outPropertyData = 1;
+ break;
+
+ case kAudioCodecPropertyCurrentInputFormat:
+ if(ioPropertyDataSize == SizeOf32(AudioStreamBasicDescription))
+ {
+ GetCurrentInputFormat(*reinterpret_cast<AudioStreamBasicDescription*>(outPropertyData));
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecBadPropertySizeError);
+ }
+ break;
+
+ case kAudioCodecPropertySupportedInputFormats:
+ case kAudioCodecPropertyInputFormatsForOutputFormat:
+ thePacketsToGet = ioPropertyDataSize / SizeOf32(AudioStreamBasicDescription);
+ GetSupportedInputFormats(reinterpret_cast<AudioStreamBasicDescription*>(outPropertyData), thePacketsToGet);
+ ioPropertyDataSize = thePacketsToGet * SizeOf32(AudioStreamBasicDescription);
+ break;
+
+ case kAudioCodecPropertyCurrentOutputFormat:
+ if(ioPropertyDataSize == SizeOf32(AudioStreamBasicDescription))
+ {
+ GetCurrentOutputFormat(*reinterpret_cast<AudioStreamBasicDescription*>(outPropertyData));
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecBadPropertySizeError);
+ }
+ break;
+
+ case kAudioCodecPropertySupportedOutputFormats:
+ case kAudioCodecPropertyOutputFormatsForInputFormat:
+ thePacketsToGet = ioPropertyDataSize / SizeOf32(AudioStreamBasicDescription);
+ GetSupportedOutputFormats(reinterpret_cast<AudioStreamBasicDescription*>(outPropertyData), thePacketsToGet);
+ ioPropertyDataSize = thePacketsToGet * SizeOf32(AudioStreamBasicDescription);
+ break;
+
+ case kAudioCodecPropertyMagicCookie:
+ if(ioPropertyDataSize >= GetMagicCookieByteSize())
+ {
+ GetMagicCookie(outPropertyData, ioPropertyDataSize);
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecBadPropertySizeError);
+ }
+ break;
+
+ case kAudioCodecPropertyInputBufferSize:
+ if(ioPropertyDataSize == SizeOf32(UInt32))
+ {
+ *reinterpret_cast<UInt32*>(outPropertyData) = GetInputBufferByteSize();
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecBadPropertySizeError);
+ }
+ break;
+
+ case kAudioCodecPropertyUsedInputBufferSize:
+ if(ioPropertyDataSize == SizeOf32(UInt32))
+ {
+ *reinterpret_cast<UInt32*>(outPropertyData) = GetUsedInputBufferByteSize();
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecBadPropertySizeError);
+ }
+ break;
+
+ case kAudioCodecPropertyIsInitialized:
+ if(ioPropertyDataSize == SizeOf32(UInt32))
+ {
+ *reinterpret_cast<UInt32*>(outPropertyData) = IsInitialized() ? 1 : 0;
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecBadPropertySizeError);
+ }
+ break;
+
+ case kAudioCodecPropertyAvailableNumberChannels:
+ if(ioPropertyDataSize == SizeOf32(UInt32) * 2)
+ {
+ (reinterpret_cast<UInt32*>(outPropertyData))[0] = 1;
+ (reinterpret_cast<UInt32*>(outPropertyData))[1] = 2;
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecBadPropertySizeError);
+ }
+ break;
+
+ case kAudioCodecPropertyPrimeMethod:
+ if(ioPropertyDataSize == SizeOf32(UInt32))
+ {
+ *reinterpret_cast<UInt32*>(outPropertyData) = (UInt32)kAudioCodecPrimeMethod_None;
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecBadPropertySizeError);
+ }
+ break;
+
+ case kAudioCodecPropertyPrimeInfo:
+ if(ioPropertyDataSize == SizeOf32(AudioCodecPrimeInfo) )
+ {
+ (reinterpret_cast<AudioCodecPrimeInfo*>(outPropertyData))->leadingFrames = 0;
+ (reinterpret_cast<AudioCodecPrimeInfo*>(outPropertyData))->trailingFrames = 0;
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecBadPropertySizeError);
+ }
+ break;
+
+ case kAudioCodecPropertyDoesSampleRateConversion:
+ if(ioPropertyDataSize == SizeOf32(UInt32))
+ {
+ *reinterpret_cast<UInt32*>(outPropertyData) = 0;
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecBadPropertySizeError);
+ }
+ break;
+
+ default:
+ CODEC_THROW(kAudioCodecUnknownPropertyError);
+ break;
+
+ };
+}
+
+void ACBaseCodec::SetProperty(AudioCodecPropertyID inPropertyID, UInt32 inPropertyDataSize, const void* inPropertyData)
+{
+ // No property can be set when the codec is initialized
+ if(mIsInitialized)
+ {
+ CODEC_THROW(kAudioCodecIllegalOperationError);
+ }
+
+ switch(inPropertyID)
+ {
+ case kAudioCodecPropertyCurrentInputFormat:
+ if(inPropertyDataSize == SizeOf32(AudioStreamBasicDescription))
+ {
+ SetCurrentInputFormat(*reinterpret_cast<const AudioStreamBasicDescription*>(inPropertyData));
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecBadPropertySizeError);
+ }
+ break;
+
+ case kAudioCodecPropertyCurrentOutputFormat:
+ if(inPropertyDataSize == SizeOf32(AudioStreamBasicDescription))
+ {
+ SetCurrentOutputFormat(*reinterpret_cast<const AudioStreamBasicDescription*>(inPropertyData));
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecBadPropertySizeError);
+ }
+ break;
+
+ case kAudioCodecPropertyMagicCookie:
+ SetMagicCookie(inPropertyData, inPropertyDataSize);
+ break;
+
+ case kAudioCodecPropertyMinimumNumberOutputPackets :
+ case kAudioCodecPropertyMinimumNumberInputPackets :
+ case kAudioCodecPropertyInputBufferSize:
+ case kAudioCodecPropertyNameCFString:
+ case kAudioCodecPropertyManufacturerCFString:
+ case kAudioCodecPropertyFormatCFString:
+ case kAudioCodecPropertySupportedInputFormats:
+ case kAudioCodecPropertySupportedOutputFormats:
+ case kAudioCodecPropertyUsedInputBufferSize:
+ case kAudioCodecPropertyIsInitialized:
+ case kAudioCodecPropertyAvailableNumberChannels:
+ case kAudioCodecPropertyPrimeMethod:
+ case kAudioCodecPropertyPrimeInfo:
+ case kAudioCodecPropertyOutputFormatsForInputFormat:
+ case kAudioCodecPropertyInputFormatsForOutputFormat:
+ case kAudioCodecPropertyDoesSampleRateConversion:
+ case kAudioCodecPropertyRequiresPacketDescription:
+ CODEC_THROW(kAudioCodecIllegalOperationError);
+ break;
+
+ default:
+ CODEC_THROW(kAudioCodecUnknownPropertyError);
+ break;
+ };
+}
+
+void ACBaseCodec::Initialize(const AudioStreamBasicDescription* /* inInputFormat */, const AudioStreamBasicDescription* /* inOutputFormat */, const void* /* inMagicCookie */, UInt32 /* inMagicCookieByteSize */)
+{
+ mIsInitialized = true;
+}
+
+void ACBaseCodec::Uninitialize()
+{
+ mIsInitialized = false;
+}
+
+void ACBaseCodec::Reset()
+{
+}
+
+UInt32 ACBaseCodec::GetNumberSupportedInputFormats() const
+{
+ return (UInt32)mInputFormatList.size();
+}
+
+void ACBaseCodec::GetSupportedInputFormats(AudioStreamBasicDescription* outInputFormats, UInt32& ioNumberInputFormats) const
+{
+ UInt32 theNumberFormats = (UInt32)mInputFormatList.size();
+ ioNumberInputFormats = (theNumberFormats < ioNumberInputFormats) ? theNumberFormats : ioNumberInputFormats;
+
+ FormatList::const_iterator theIterator = mInputFormatList.begin();
+ theNumberFormats = ioNumberInputFormats;
+ while((theNumberFormats > 0) && (theIterator != mInputFormatList.end()))
+ {
+ *outInputFormats = *theIterator;
+
+ ++outInputFormats;
+ --theNumberFormats;
+ std::advance(theIterator, 1);
+ }
+}
+
+void ACBaseCodec::GetCurrentInputFormat(AudioStreamBasicDescription& outInputFormat)
+{
+ outInputFormat = mInputFormat;
+}
+
+void ACBaseCodec::SetCurrentInputFormat(const AudioStreamBasicDescription& inInputFormat)
+{
+ if(!mIsInitialized)
+ {
+ mInputFormat = inInputFormat;
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecStateError);
+ }
+}
+
+UInt32 ACBaseCodec::GetNumberSupportedOutputFormats() const
+{
+ return (UInt32)mOutputFormatList.size();
+}
+
+void ACBaseCodec::GetSupportedOutputFormats(AudioStreamBasicDescription* outOutputFormats, UInt32& ioNumberOutputFormats) const
+{
+ UInt32 theNumberFormats = (UInt32)mOutputFormatList.size();
+ ioNumberOutputFormats = (theNumberFormats < ioNumberOutputFormats) ? theNumberFormats : ioNumberOutputFormats;
+
+ FormatList::const_iterator theIterator = mOutputFormatList.begin();
+ theNumberFormats = ioNumberOutputFormats;
+ while((theNumberFormats > 0) && (theIterator != mOutputFormatList.end()))
+ {
+ *outOutputFormats = *theIterator;
+
+ ++outOutputFormats;
+ --theNumberFormats;
+ std::advance(theIterator, 1);
+ }
+}
+
+void ACBaseCodec::GetCurrentOutputFormat(AudioStreamBasicDescription& outOutputFormat)
+{
+ outOutputFormat = mOutputFormat;
+}
+
+void ACBaseCodec::SetCurrentOutputFormat(const AudioStreamBasicDescription& inOutputFormat)
+{
+ if(!mIsInitialized)
+ {
+ mOutputFormat = inOutputFormat;
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecStateError);
+ }
+}
+
+UInt32 ACBaseCodec::GetMagicCookieByteSize() const
+{
+ return 0;
+}
+
+void ACBaseCodec::GetMagicCookie(void* /* outMagicCookieData */, UInt32& ioMagicCookieDataByteSize) const
+{
+ ioMagicCookieDataByteSize = 0;
+}
+
+void ACBaseCodec::SetMagicCookie(const void* /* outMagicCookieData */, UInt32 /* inMagicCookieDataByteSize */)
+{
+ if(mIsInitialized)
+ {
+ CODEC_THROW(kAudioCodecStateError);
+ }
+}
+
+void ACBaseCodec::AddInputFormat(const AudioStreamBasicDescription& inInputFormat)
+{
+ FormatList::iterator theIterator = std::find(mInputFormatList.begin(), mInputFormatList.end(), inInputFormat);
+ if(theIterator == mInputFormatList.end())
+ {
+ theIterator = std::lower_bound(mInputFormatList.begin(), mInputFormatList.end(), inInputFormat);
+ mInputFormatList.insert(theIterator, inInputFormat);
+ }
+}
+
+void ACBaseCodec::AddOutputFormat(const AudioStreamBasicDescription& inOutputFormat)
+{
+ FormatList::iterator theIterator = std::find(mOutputFormatList.begin(), mOutputFormatList.end(), inOutputFormat);
+ if(theIterator == mOutputFormatList.end())
+ {
+ theIterator = std::lower_bound(mOutputFormatList.begin(), mOutputFormatList.end(), inOutputFormat);
+ mOutputFormatList.insert(theIterator, inOutputFormat);
+ }
+}
+
+OSType ACBaseCodec::GetSubType()
+{
+ if (!mCodecSubType)
+ {
+ AudioComponentDescription desc = GetComponentDescription();
+ mCodecSubType = desc.componentSubType;
+ }
+ return mCodecSubType;
+}
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.h b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.h
new file mode 100644
index 0000000000..6689d91fbe
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.h
@@ -0,0 +1,147 @@
+/*
+ File: ACBaseCodec.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__ACBaseCodec_h__)
+#define __ACBaseCodec_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "ACCodec.h"
+#include "CAStreamBasicDescription.h"
+#include <vector>
+#include "GetCodecBundle.h"
+
+//=============================================================================
+// ACBaseCodec
+//
+// An abstract subclass of ACCodec that implements all the nuts and bolts
+// of the ACCodec interface, except for buffer handling. This class does
+// the proper dispatching of property requests and manages the list of
+// input and output formats.
+//=============================================================================
+
+class ACBaseCodec
+:
+ public ACCodec
+{
+
+// Construction/Destruction
+public:
+ ACBaseCodec( AudioComponentInstance inInstance );
+ virtual ~ACBaseCodec();
+
+// Property Management
+public:
+ virtual void GetPropertyInfo(AudioCodecPropertyID inPropertyID, UInt32& outPropertyDataSize, Boolean& outWritable);
+ virtual void GetProperty(AudioCodecPropertyID inPropertyID, UInt32& ioPropertyDataSize, void* outPropertyData);
+ virtual void SetProperty(AudioCodecPropertyID inPropertyID, UInt32 inPropertyDataSize, const void* inPropertyData);
+
+// Data Handling
+public:
+ bool IsInitialized() const { return mIsInitialized; }
+ virtual void Initialize(const AudioStreamBasicDescription* inInputFormat, const AudioStreamBasicDescription* inOutputFormat, const void* inMagicCookie, UInt32 inMagicCookieByteSize);
+ virtual void Uninitialize();
+ virtual void Reset();
+ virtual UInt32 GetInputBufferByteSize() const = 0;
+ virtual UInt32 GetUsedInputBufferByteSize() const = 0;
+
+protected:
+ virtual void ReallocateInputBuffer(UInt32 inInputBufferByteSize) = 0;
+
+ bool mIsInitialized;
+
+// Format Management
+public:
+ UInt32 GetNumberSupportedInputFormats() const;
+ void GetSupportedInputFormats(AudioStreamBasicDescription* outInputFormats, UInt32& ioNumberInputFormats) const;
+
+ void GetCurrentInputFormat(AudioStreamBasicDescription& outInputFormat);
+ virtual void SetCurrentInputFormat(const AudioStreamBasicDescription& inInputFormat);
+
+ UInt32 GetNumberSupportedOutputFormats() const;
+ void GetSupportedOutputFormats(AudioStreamBasicDescription* outOutputFormats, UInt32& ioNumberOutputFormats) const;
+
+ void GetCurrentOutputFormat(AudioStreamBasicDescription& outOutputFormat);
+ virtual void SetCurrentOutputFormat(const AudioStreamBasicDescription& inOutputFormat);
+
+ virtual UInt32 GetMagicCookieByteSize() const;
+ virtual void GetMagicCookie(void* outMagicCookieData, UInt32& ioMagicCookieDataByteSize) const;
+ virtual void SetMagicCookie(const void* outMagicCookieData, UInt32 inMagicCookieDataByteSize);
+
+ virtual bool ImplementsFeature(UInt32 /* feature */) const { return false; }
+ virtual void AppendInputBufferList(const AudioBufferList * /* ioBufferList */, UInt32& /* ioNumberPackets */, const AudioStreamPacketDescription * /* inPacketDescription */, UInt32 * /* outBytesConsumed */) { CODEC_THROW(-4); /*unimpErr*/ }
+ virtual UInt32 ProduceOutputBufferList(AudioBufferList * /* ioBufferList */, UInt32& /* ioNumberPackets */, AudioStreamPacketDescription * /* outPacketDescription */) { CODEC_THROW(-4); /*unimpErr*/ }
+protected:
+ void AddInputFormat(const AudioStreamBasicDescription& inInputFormat);
+ void AddOutputFormat(const AudioStreamBasicDescription& inOutputFormat);
+
+ OSType GetSubType();
+
+ typedef std::vector<CAStreamBasicDescription> FormatList;
+
+ FormatList mInputFormatList;
+#if TARGET_OS_WIN32
+ // VC 2005 screws up if this is not aligned to 8-byte boundaries
+ __declspec(align(8)) CAStreamBasicDescription mInputFormat;
+#else
+ CAStreamBasicDescription mInputFormat;
+#endif
+
+ FormatList mOutputFormatList;
+#if TARGET_OS_WIN32
+ // VC 2005 screws up if this is not aligned to 8-byte boundaries
+ __declspec(align(8)) CAStreamBasicDescription mOutputFormat;
+#else
+ CAStreamBasicDescription mOutputFormat;
+#endif
+ OSType mCodecSubType;
+ UInt32 mPadding[3]; // Align this with 16-byte boundaries
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.cpp b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.cpp
new file mode 100644
index 0000000000..512f93842a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.cpp
@@ -0,0 +1,329 @@
+/*
+ File: ACCodec.cpp
+ Abstract: ACCodec.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "ACCodec.h"
+
+//=============================================================================
+// ACCodec
+//=============================================================================
+
+ACCodec::ACCodec(AudioComponentInstance inInstance) : ComponentBase(inInstance)
+{
+}
+
+ACCodec::~ACCodec()
+{
+}
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY && !TARGET_OS_IPHONE
+
+#if TARGET_OS_MAC
+ #if __LP64__
+ // comp instance, parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)((void*)&inParameters->params[_index + 1]);
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)((void*)&inParameters->params[_nparams - 1 - _index]);
+ #endif
+#elif TARGET_OS_WIN32
+ // (no comp instance), parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&inParameters->params[_index];
+#endif
+
+OSStatus ACCodec::ComponentEntryDispatch(ComponentParameters *inParameters, ACCodec *inThis)
+{
+ OSStatus theError = kAudioCodecNoError;
+
+ try
+ {
+ switch (inParameters->what)
+ {
+ // these selectors don't use the object pointer
+
+ case kComponentOpenSelect:
+ case kComponentCloseSelect:
+ theError = ComponentBase::ComponentEntryDispatch(inParameters, inThis);
+ break;
+
+ case kComponentCanDoSelect:
+ {
+ switch (GetSelectorForCanDo(inParameters))
+ {
+ case kAudioCodecGetPropertyInfoSelect:
+ case kAudioCodecGetPropertySelect:
+ case kAudioCodecSetPropertySelect:
+ case kAudioCodecInitializeSelect:
+ case kAudioCodecUninitializeSelect: // was missing -- why?
+ case kAudioCodecAppendInputDataSelect:
+ case kAudioCodecProduceOutputDataSelect:
+ case kAudioCodecResetSelect:
+ theError = 1;
+ break;
+ default:
+ theError = ComponentBase::ComponentEntryDispatch(inParameters, inThis);
+ break;
+ }
+ }
+ break;
+
+ default:
+ // these selectors use the object pointer
+ if(inThis != NULL)
+ {
+ switch (inParameters->what)
+ {
+ case kComponentVersionSelect:
+ theError = inThis->Version();
+ break;
+
+ case kAudioCodecGetPropertyInfoSelect:
+ {
+ PARAM(AudioCodecPropertyID, inPropertyID, 0, 3);
+ PARAM(UInt32 *, outSize, 1, 3);
+ PARAM(Boolean *, outWritable, 2, 3);
+
+ UInt32 theSize = 0;
+ Boolean isWritable = false;
+
+ inThis->GetPropertyInfo(inPropertyID, theSize, isWritable);
+ if(outSize != NULL)
+ {
+ *outSize = theSize;
+ }
+ if(outWritable != NULL)
+ {
+ *outWritable = isWritable ? 1 : 0;
+ }
+ }
+ break;
+
+ case kAudioCodecGetPropertySelect:
+ {
+ PARAM(AudioCodecPropertyID, inPropertyID, 0, 3);
+ PARAM(UInt32 *, ioPropertyDataSize, 1, 3);
+ PARAM(void *, outPropertyData, 2, 3);
+
+ if((ioPropertyDataSize != NULL) && (outPropertyData != NULL))
+ {
+ inThis->GetProperty(inPropertyID, *ioPropertyDataSize, outPropertyData);
+ }
+ else
+ {
+ theError = kAudio_ParamError;
+ }
+ }
+ break;
+
+ case kAudioCodecSetPropertySelect:
+ {
+ PARAM(AudioCodecPropertyID, inPropertyID, 0, 3);
+ PARAM(UInt32, inPropertyDataSize, 1, 3);
+ PARAM(const void *, inPropertyData, 2, 3);
+
+ if(inPropertyData != NULL)
+ {
+ inThis->SetProperty(inPropertyID, inPropertyDataSize, inPropertyData);
+ }
+ else
+ {
+ theError = kAudio_ParamError;
+ }
+ }
+ break;
+
+ case kAudioCodecInitializeSelect:
+ {
+ PARAM(const AudioStreamBasicDescription *, inInputFormat, 0, 4);
+ PARAM(const AudioStreamBasicDescription *, inOutputFormat, 1, 4);
+ PARAM(const void *, inMagicCookie, 2, 4);
+ PARAM(UInt32, inMagicCookieByteSize, 3, 4);
+
+ inThis->Initialize(inInputFormat, inOutputFormat, inMagicCookie, inMagicCookieByteSize);
+ }
+ break;
+
+ case kAudioCodecUninitializeSelect:
+ {
+ inThis->Uninitialize();
+ }
+ break;
+
+ case kAudioCodecAppendInputDataSelect:
+ {
+ PARAM(const void *, inInputData, 0, 4);
+ PARAM(UInt32 *, ioInputDataByteSize, 1, 4);
+ PARAM(UInt32 *, ioNumberPackets, 2, 4);
+ PARAM(const AudioStreamPacketDescription *, inPacketDescription, 3, 4);
+
+ if((inInputData != NULL) && (ioInputDataByteSize != NULL))
+ {
+ if(ioNumberPackets != NULL)
+ {
+ inThis->AppendInputData(inInputData, *ioInputDataByteSize, *ioNumberPackets, inPacketDescription);
+ }
+ else
+ {
+ UInt32 theNumberPackets = 0;
+ inThis->AppendInputData(inInputData, *ioInputDataByteSize, theNumberPackets, inPacketDescription);
+ }
+ }
+ else
+ {
+ theError = kAudio_ParamError;
+ }
+ }
+ break;
+
+ case kAudioCodecProduceOutputDataSelect:
+ {
+ PARAM(void *, outOutputData, 0, 5);
+ PARAM(UInt32 *, ioOutputDataByteSize, 1, 5);
+ PARAM(UInt32 *, ioNumberPackets, 2, 5);
+ PARAM(AudioStreamPacketDescription *, outPacketDescription, 3, 5);
+ PARAM(UInt32 *, outStatus, 4, 5);
+
+ if((outOutputData != NULL) && (ioOutputDataByteSize != NULL) && (ioNumberPackets != NULL) && (outStatus != NULL))
+ {
+ *outStatus = inThis->ProduceOutputPackets(outOutputData, *ioOutputDataByteSize, *ioNumberPackets, outPacketDescription);
+ if(kAudioCodecProduceOutputPacketFailure == *outStatus)
+ {
+ theError = kAudio_ParamError;
+ }
+ }
+ else
+ {
+ theError = kAudio_ParamError;
+ }
+ }
+ break;
+
+#if AC_NON_INTERLEAVED_SUPPORT
+ case kAudioCodecAppendInputBufferListSelect:
+ {
+ PARAM(const AudioBufferList *, inBufferList, 0, 4);
+ PARAM(UInt32 *, ioNumberPackets, 1, 4);
+ PARAM(const AudioStreamPacketDescription *, inPacketDescription, 2, 4);
+ PARAM(UInt32 *, outBytesConsumed, 3, 4);
+
+ if((inBufferList != NULL) && (outBytesConsumed != NULL))
+ {
+ if(ioNumberPackets != NULL)
+ {
+ inThis->AppendInputBufferList(inBufferList, *ioNumberPackets, inPacketDescription, outBytesConsumed);
+ }
+ else
+ {
+ UInt32 theNumberPackets = 0;
+ inThis->AppendInputBufferList(inBufferList, theNumberPackets, inPacketDescription, outBytesConsumed);
+ }
+ }
+ else
+ {
+ theError = kAudio_ParamError;
+ }
+ }
+ break;
+
+ case kAudioCodecProduceOutputBufferListSelect:
+ {
+ PARAM(AudioBufferList *, ioBufferList, 0, 4);
+ PARAM(UInt32 *, ioNumberPackets, 1, 4);
+ PARAM(AudioStreamPacketDescription *, outPacketDescription, 2, 4);
+ PARAM(UInt32 *, outStatus, 3, 4);
+
+ if((ioBufferList != NULL) && (ioNumberPackets != NULL) && (outStatus != NULL))
+ {
+ *outStatus = inThis->ProduceOutputBufferList(ioBufferList, *ioNumberPackets, outPacketDescription);
+ if(kAudioCodecProduceOutputPacketFailure == *outStatus)
+ {
+ theError = kAudio_ParamError;
+ }
+ }
+ else
+ {
+ theError = kAudio_ParamError;
+ }
+ }
+ break;
+#endif // AC_NON_INTERLEAVED_SUPPORT
+
+ case kAudioCodecResetSelect:
+ {
+ inThis->Reset();
+ }
+ break;
+
+ default:
+ theError = badComponentSelector;
+ break;
+ };
+ }
+ else
+ {
+ theError = kAudio_ParamError;
+ }
+ break;
+ };
+ }
+ catch(OSStatus inErrorCode)
+ {
+ theError = inErrorCode;
+ }
+ catch(...)
+ {
+ theError = kAudioCodecUnspecifiedError;
+ }
+
+ return theError;
+}
+#endif // !CA_USE_AUDIO_PLUGIN_ONLY && !TARGET_OS_IPHONE
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.h b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.h
new file mode 100644
index 0000000000..b0d93165ab
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.h
@@ -0,0 +1,115 @@
+/*
+ File: ACCodec.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__ACCodec_h__)
+#define __ACCodec_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioCodec.h>
+#else
+ #include "AudioCodec.h"
+#endif
+
+#include "ComponentBase.h"
+
+//=============================================================================
+// ACCodec
+//
+// A totally abstract base class for implementing components that conform to
+// the AudioCodec API.
+//=============================================================================
+
+class ACCodec : public ComponentBase
+{
+
+// Construction/Destruction
+public:
+ ACCodec(AudioComponentInstance inInstance);
+ virtual ~ACCodec();
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY && !TARGET_OS_IPHONE
+ static OSStatus ComponentEntryDispatch(ComponentParameters *p, ACCodec *This);
+#endif
+
+// Property Management
+public:
+ virtual void GetPropertyInfo(AudioCodecPropertyID inPropertyID, UInt32& outSize, Boolean& outWritable) = 0;
+ virtual void GetProperty(AudioCodecPropertyID inPropertyID, UInt32& ioPropertyDataSize, void* outPropertyData) = 0;
+ virtual void SetProperty(AudioCodecPropertyID inPropertyID, UInt32 inPropertyDataSize, const void* inPropertyData) = 0;
+
+// Data Handling
+public:
+ virtual void Initialize(const AudioStreamBasicDescription* inInputFormat, const AudioStreamBasicDescription* inOutputFormat, const void* inMagicCookie, UInt32 inMagicCookieByteSize) = 0;
+ virtual void Uninitialize() = 0;
+ virtual void Reset() = 0;
+
+ virtual void AppendInputData(const void* inInputData, UInt32& ioInputDataByteSize, UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription) = 0;
+ virtual void AppendInputBufferList(const AudioBufferList *ioBufferList, UInt32& ioNumberPackets, const AudioStreamPacketDescription *inPacketDescription, UInt32 *outBytesConsumed) = 0;
+
+ virtual UInt32 ProduceOutputPackets(void* outOutputData, UInt32& ioOutputDataByteSize, UInt32& ioNumberPackets, AudioStreamPacketDescription* outPacketDescription) = 0;
+ virtual UInt32 ProduceOutputBufferList(AudioBufferList *ioBufferList, UInt32& ioNumberPackets, AudioStreamPacketDescription *outPacketDescription) = 0;
+
+// Component Support
+public:
+// used internally
+ virtual bool ImplementsFeature(UInt32 feature) const = 0;
+};
+
+// when throwing static_cast to OSStatus so the catch will grab the error code correctly
+#define CODEC_THROW(err) \
+ throw static_cast<OSStatus>(err)
+
+#define CODEC_THROW_IF(cond, err) \
+ if(bool(cond)) CODEC_THROW(err);
+
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodecDispatchTypes.h b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodecDispatchTypes.h
new file mode 100644
index 0000000000..42c2bc5ba6
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodecDispatchTypes.h
@@ -0,0 +1,259 @@
+/*
+ File: ACCodecDispatchTypes.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__ACCodecDispatchTypes_h__)
+#define __ACCodecDispatchTypes_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// note that AudioCodec.h needs to be included prior to including this file
+#if !defined(__AudioCodec_h__)
+ #error AudioCodec.h needs to be included prior to including this file
+#endif
+
+//=============================================================================
+// Parameter Blocks for AudioCodec Component Routines
+//
+// Note that the arguments for all the AudioCodec component routines are
+// 4 bytes in size (assuming pointers are 4 bytes). This means that even on
+// Windows (where all arguments are forced into SInt32s), we can get away with
+// mass casting the argument list through the appropriate paramblock structure.
+// This gets around the fact that the component glue passes the arguments in
+// a different order depending on the platform and therefore makes writing the
+// calling glue and the dispatcher much simpler.
+//=============================================================================
+
+#if PRAGMA_STRUCT_ALIGN
+ #pragma options align=mac68k
+#elif PRAGMA_STRUCT_PACKPUSH
+ #pragma pack(push, 2)
+#elif PRAGMA_STRUCT_PACK
+ #pragma pack(2)
+#endif
+
+#define AudioCodecStandardGluePBFields UInt8 componentFlags; UInt8 componentParamSize; SInt16 componentWhat
+
+#if !TARGET_OS_WIN32
+struct AudioCodecOpenGluePB {
+ AudioCodecStandardGluePBFields;
+ AudioCodec inCodec;
+ void* unused;
+};
+#else
+struct AudioCodecOpenGluePB {
+ AudioCodecStandardGluePBFields;
+ AudioCodec inCodec;
+};
+#endif
+typedef struct AudioCodecOpenGluePB AudioCodecOpenGluePB;
+
+#if !TARGET_OS_WIN32
+struct AudioCodecGetPropertyInfoGluePB
+{
+ AudioCodecStandardGluePBFields;
+ Boolean* outWritable;
+ UInt32* outSize;
+ AudioCodecPropertyID inPropertyID;
+ AudioCodec inCodec;
+};
+#else
+struct AudioCodecGetPropertyInfoGluePB
+{
+ AudioCodecStandardGluePBFields;
+ AudioCodecPropertyID inPropertyID;
+ UInt32* outSize;
+ Boolean* outWritable;
+};
+#endif
+typedef struct AudioCodecGetPropertyInfoGluePB AudioCodecGetPropertyInfoGluePB;
+
+#if !TARGET_OS_WIN32
+struct AudioCodecGetPropertyGluePB
+{
+ AudioCodecStandardGluePBFields;
+ void* outPropertyData;
+ UInt32* ioPropertyDataSize;
+ AudioCodecPropertyID inPropertyID;
+ AudioCodec inCodec;
+};
+#else
+struct AudioCodecGetPropertyGluePB
+{
+ AudioCodecStandardGluePBFields;
+ AudioCodecPropertyID inPropertyID;
+ UInt32* ioPropertyDataSize;
+ void* outPropertyData;
+};
+#endif
+typedef struct AudioCodecGetPropertyGluePB AudioCodecGetPropertyGluePB;
+
+#if !TARGET_OS_WIN32
+struct AudioCodecSetPropertyGluePB
+{
+ AudioCodecStandardGluePBFields;
+ const void* inPropertyData;
+ UInt32 inPropertyDataSize;
+ AudioCodecPropertyID inPropertyID;
+ AudioCodec inCodec;
+};
+#else
+struct AudioCodecSetPropertyGluePB
+{
+ AudioCodecStandardGluePBFields;
+ AudioCodecPropertyID inPropertyID;
+ UInt32 inPropertyDataSize;
+ const void* inPropertyData;
+};
+#endif
+typedef struct AudioCodecSetPropertyGluePB AudioCodecSetPropertyGluePB;
+
+#if !TARGET_OS_WIN32
+struct AudioCodecInitializeGluePB
+{
+ AudioCodecStandardGluePBFields;
+ UInt32 inMagicCookieByteSize;
+ const void* inMagicCookie;
+ const AudioStreamBasicDescription* inOutputFormat;
+ const AudioStreamBasicDescription* inInputFormat;
+ AudioCodec inCodec;
+};
+#else
+struct AudioCodecInitializeGluePB
+{
+ AudioCodecStandardGluePBFields;
+ const AudioStreamBasicDescription* inInputFormat;
+ const AudioStreamBasicDescription* inOutputFormat;
+ const void* inMagicCookie;
+ UInt32 inMagicCookieByteSize;
+};
+#endif
+typedef struct AudioCodecInitializeGluePB AudioCodecInitializeGluePB;
+
+#if !TARGET_OS_WIN32
+struct AudioCodecUninitializeGluePB
+{
+ AudioCodecStandardGluePBFields;
+ AudioCodec inCodec;
+};
+#else
+struct AudioCodecUninitializeGluePB
+{
+ AudioCodecStandardGluePBFields;
+};
+#endif
+typedef struct AudioCodecUninitializeGluePB AudioCodecUninitializeGluePB;
+
+#if !TARGET_OS_WIN32
+struct AudioCodecAppendInputDataGluePB
+{
+ AudioCodecStandardGluePBFields;
+ const AudioStreamPacketDescription* inPacketDescription;
+ UInt32* ioNumberPackets;
+ UInt32* ioInputDataByteSize;
+ const void* inInputData;
+ AudioCodec inCodec;
+};
+#else
+struct AudioCodecAppendInputDataGluePB
+{
+ AudioCodecStandardGluePBFields;
+ const void* inInputData;
+ UInt32* ioInputDataByteSize;
+ UInt32* ioNumberPackets;
+ const AudioStreamPacketDescription* inPacketDescription;
+};
+#endif
+typedef struct AudioCodecAppendInputDataGluePB AudioCodecAppendInputDataGluePB;
+
+#if !TARGET_OS_WIN32
+struct AudioCodecProduceOutputPacketsGluePB
+{
+ AudioCodecStandardGluePBFields;
+ UInt32* outStatus;
+ AudioStreamPacketDescription* outPacketDescription;
+ UInt32* ioNumberPackets;
+ UInt32* ioOutputDataByteSize;
+ void* outOutputData;
+ AudioCodec inCodec;
+};
+#else
+struct AudioCodecProduceOutputPacketsGluePB
+{
+ AudioCodecStandardGluePBFields;
+ void* outOutputData;
+ UInt32* ioOutputDataByteSize;
+ UInt32* ioNumberPackets;
+ AudioStreamPacketDescription* outPacketDescription;
+ UInt32* outStatus;
+};
+#endif
+typedef struct AudioCodecProduceOutputPacketsGluePB AudioCodecProduceOutputPacketsGluePB;
+
+#if !TARGET_OS_WIN32
+struct AudioCodecResetGluePB
+{
+ AudioCodecStandardGluePBFields;
+ AudioCodec inCodec;
+};
+#else
+struct AudioCodecResetGluePB
+{
+ AudioCodecStandardGluePBFields;
+};
+#endif
+typedef struct AudioCodecResetGluePB AudioCodecResetGluePB;
+
+#if PRAGMA_STRUCT_ALIGN
+ #pragma options align=reset
+#elif PRAGMA_STRUCT_PACKPUSH
+ #pragma pack(pop)
+#elif PRAGMA_STRUCT_PACK
+ #pragma pack()
+#endif
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACComponentResources.r b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACComponentResources.r
new file mode 100644
index 0000000000..a84fd11ad9
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACComponentResources.r
@@ -0,0 +1,196 @@
+/*
+ File: ACComponentResources.r
+ Abstract: ACComponentResources.r
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef GEN_MISSING
+ #define GEN_MISSING 0
+#endif
+
+#ifndef thng_RezTemplateVersion
+ #define thng_RezTemplateVersion 2
+#endif
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "ConditionalMacros.r"
+#include "MacTypes.r"
+#include "Components.r"
+
+//=============================================================================
+// Platform constants for the thng resources
+//=============================================================================
+
+#if TARGET_OS_MAC && TARGET_API_MAC_OSX
+ #define Target_PlatformType 1000
+ #define Target_CodeResType 'dlle'
+ #define kUseDLLEResource 1
+#elif TARGET_OS_WIN32
+ #define Target_PlatformType platformWin32
+ #define Target_CodeResType 'dlle'
+ #define kUseDLLEResource 1
+#else
+ #define Target_PlatformType platformPowerPC
+ #define Target_CodeResType 'tppc'
+ #define kUseDLLEResource 0
+#endif
+
+#if kComponentIsThreadSafe
+ #ifndef cmpThreadSafeOnMac // so we don't need Panther headers to build
+ #define cmpThreadSafeOnMac 0x10000000
+ #endif
+ #define COMPONENT_FLAGS cmpThreadSafeOnMac
+#else
+ #define COMPONENT_FLAGS 0
+#endif
+
+//=============================================================================
+// The thng and related resources
+//
+// The definitions below use the following macros, all of which must be
+// defined. Note that kPrimaryResourceID is used to define two 'STR '
+// resources with consecutive IDs so be sure to space them at least two'
+// apart. Here's a sample of how to do the defines:
+//
+// #define kPrimaryResourceID 128
+// #define kComponentType 'aenc'
+// #define kComponentSubtype 'ima4'
+// #define kComponentManufacturer 'appl'
+// #define kComponentFlags 0
+// #define kComponentVersion 0x00010000
+// #define kComponentName "Apple IMA4 Encoder"
+// #define kComponentInfo "An AudioCodec that encodes linear PCM data into IMA4"
+// #define kComponentEntryPoint "ACAppleIMA4EncoderEntry"
+// #define kComponentPublicResourceMapType 0
+// #define kComponentIsThreadSafe 1
+//=============================================================================
+
+#ifndef AC_LOCALIZED
+resource 'strn' (kPrimaryResourceID, purgeable)
+{
+ kComponentName
+};
+
+resource 'stri' (kPrimaryResourceID, purgeable)
+{
+ kComponentInfo
+};
+#endif
+
+#if !GEN_MISSING
+
+#if kUseDLLEResource
+
+ resource 'dlle' (kPrimaryResourceID)
+ {
+ kComponentEntryPoint
+ };
+
+#endif
+
+#define kComponentRegistrationFlags componentHasMultiplePlatforms | componentDoAutoVersion | componentLoadResident
+resource 'thng' (kPrimaryResourceID, kComponentName)
+{
+ kComponentType, // Component type
+ kComponentSubtype, // Component subtype
+ kComponentManufacturer, // Component manufacturer
+ kComponentFlags, // Component flags
+ 0, // Component flags mask
+ 0, 0, // Code type, Code ID
+ 'strn', kPrimaryResourceID, // Name resource type, resource ID
+ 'stri', kPrimaryResourceID, // Info resource type, resource ID
+ 0, 0, // Icon resource type, resource ID
+ kComponentVersion, // Component version
+ kComponentRegistrationFlags, // Registration flags
+ 0, // Icon family resource ID
+ { // Beginning of platform info
+ COMPONENT_FLAGS, // Component flags
+ Target_CodeResType, kPrimaryResourceID, // Code resource type, resource ID
+ Target_PlatformType, // Platform type
+ },
+#if thng_RezTemplateVersion >= 2
+ kComponentPublicResourceMapType, kPrimaryResourceID // Resource map type, resource map ID
+#endif
+};
+
+#else // GEN_MISSING
+
+resource 'thga' (kPrimaryResourceID) {
+ kComponentType, // Component type
+ kComponentSubtype, // Component subtype
+ kComponentManufacturer, // Component manufacturer
+ kComponentFlags, // Component flags
+ 0, // Component flags mask
+ 0, 0, // Code type, Code ID
+ 'strn', kPrimaryResourceID, // Name resource type, resource ID
+ 'stri', kPrimaryResourceID, // Info resource type, resource ID
+ 0, 0, // Icon resource type, resource ID
+ 'miss', // Alias component type
+ 'base', // Alias component subtype
+ 0, // Alias component manufacturer
+ 0, // Alias component flags
+ 0, // Alias component flags mask
+#if thng_RezTemplateVersion >= 2
+ kComponentPublicResourceMapType, kPrimaryResourceID, // Resource map type, resource map ID
+ cmpAliasNoFlags // Alias flags
+#endif
+};
+
+#endif // GEN_MISSING
+
+#undef kPrimaryResourceID
+#undef kComponentType
+#undef kComponentSubtype
+#undef kComponentManufacturer
+#undef kComponentVersion
+#undef kComponentRegistrationFlags
+#undef kComponentName
+#undef kComponentInfo
+#undef kComponentEntryPoint
+#undef kComponentPublicResourceMapType
+#undef Target_PlatformType
+#undef Target_CodeResType
+#undef kUseDLLEResource
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACConditionalMacros.h b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACConditionalMacros.h
new file mode 100644
index 0000000000..2cff483fde
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACConditionalMacros.h
@@ -0,0 +1,73 @@
+/*
+ File: ACConditionalMacros.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__ACConditionalMacros_h__)
+#define __ACConditionalMacros_h__
+
+//=============================================================================
+// This file exists to make figuring out how to include system headers
+// easier. We throw in an include of the standard ConditionalMacros too.
+//=============================================================================
+
+// TargetConditionals.h defines the bare minimum we need
+#include "TargetConditionals.h"
+
+// Determine whether or not to use framework style includes for system headers
+#if !defined(AC_Use_Framework_Includes)
+ #if TARGET_OS_MAC && TARGET_RT_MAC_MACHO
+ #define AC_Use_Framework_Includes 1
+ #else
+ #define AC_Use_Framework_Includes 0
+ #endif
+#endif
+
+#if AC_Use_Framework_Includes
+ #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/ConditionalMacros.h>
+#else
+ #include "ConditionalMacros.h"
+#endif
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.cpp b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.cpp
new file mode 100644
index 0000000000..de9599b186
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.cpp
@@ -0,0 +1,283 @@
+/*
+ File: ACPlugInDispatch.cpp
+ Abstract: ACPlugInDispatch.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if AUDIOCODECS_SUPPORT_PLUGINS
+#include "ACPlugInDispatch.h"
+#include "CAXException.h"
+#include "ACCodec.h"
+#include <new>
+
+#define ACPI ((AudioComponentPlugInInstance *)self)
+#define ACC ((ACCodec *)&ACPI->mInstanceStorage)
+
+static OSStatus GetPropertyInfo(void *self, AudioCodecPropertyID inPropertyID, UInt32 *outSize, Boolean *outWritable)
+{
+ OSStatus result = noErr;
+ try {
+ UInt32 size;
+ Boolean writable;
+ ACC->GetPropertyInfo(inPropertyID, size, writable);
+ if (outSize) *outSize = size;
+ if (outWritable) *outWritable = writable;
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus GetProperty(void *self, AudioCodecPropertyID inPropertyID, UInt32 *ioPropertyDataSize, void *outPropertyData)
+{
+ OSStatus result = noErr;
+ try {
+ ACC->GetProperty(inPropertyID, *ioPropertyDataSize, outPropertyData);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus SetProperty(void *self, AudioCodecPropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData)
+{
+ OSStatus result = noErr;
+ try {
+ ACC->SetProperty(inPropertyID, inPropertyDataSize, inPropertyData);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+
+static OSStatus Initialize(void *self, const AudioStreamBasicDescription *inInputFormat, const AudioStreamBasicDescription *inOutputFormat, const void *inMagicCookie, UInt32 inMagicCookieByteSize)
+{
+ OSStatus result = noErr;
+ try {
+ ACC->Initialize(inInputFormat, inOutputFormat, inMagicCookie, inMagicCookieByteSize);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus Uninitialize(void *self)
+{
+ OSStatus result = noErr;
+ try {
+ ACC->Uninitialize();
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AppendInputData(void *self, const void *inInputData, UInt32 *ioInputDataByteSize, UInt32 *ioNumberPackets, const AudioStreamPacketDescription *inPacketDescription)
+{
+ OSStatus result = noErr;
+ try {
+ UInt32 npackets = (ioNumberPackets != NULL) ? *ioNumberPackets : 0;
+ ACC->AppendInputData(inInputData, *ioInputDataByteSize, npackets, inPacketDescription);
+ if(ioNumberPackets != NULL)
+ *ioNumberPackets = npackets;
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus ProduceOutputPackets(void *self, void *outOutputData, UInt32 *ioOutputDataByteSize, UInt32 *ioNumberPackets, AudioStreamPacketDescription *outPacketDescription, UInt32 *outStatus)
+{
+ OSStatus result = noErr;
+ try {
+ *outStatus = ACC->ProduceOutputPackets(outOutputData, *ioOutputDataByteSize, *ioNumberPackets, outPacketDescription);
+ if (*outStatus == kAudioCodecProduceOutputPacketFailure)
+ result = kAudio_ParamError;
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus Reset(void *self)
+{
+ OSStatus result = noErr;
+ try {
+ ACC->Reset();
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+#if AC_NON_INTERLEAVED_SUPPORT
+static OSStatus AppendInputBufferList(void *self, const AudioBufferList *ioBufferList, UInt32 *inNumberPackets, const AudioStreamPacketDescription *inPacketDescription, UInt32 *outBytesConsumed)
+{
+ OSStatus result = noErr;
+ try {
+ if((ioBufferList != NULL) && (outBytesConsumed != NULL))
+ {
+ if(inNumberPackets != NULL)
+ {
+ ACC->AppendInputBufferList(ioBufferList, *inNumberPackets, inPacketDescription, outBytesConsumed);
+ }
+ else
+ {
+ UInt32 theNumberPackets = 0;
+ ACC->AppendInputBufferList(ioBufferList, theNumberPackets, inPacketDescription, outBytesConsumed);
+ }
+ }
+ else
+ {
+ result = kAudio_ParamError;
+ }
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus ProduceOutputBufferList(void *self, AudioBufferList *ioBufferList, UInt32 *ioNumberPackets, AudioStreamPacketDescription *outPacketDescription, UInt32 *outStatus)
+{
+ OSStatus result = noErr;
+ try {
+ if((ioBufferList != NULL) && (ioNumberPackets != NULL) && (outStatus != NULL))
+ {
+ *outStatus = ACC->ProduceOutputBufferList(ioBufferList, *ioNumberPackets, outPacketDescription);
+ if(kAudioCodecProduceOutputPacketFailure == *outStatus)
+ {
+ result = kAudio_ParamError;
+ }
+ }
+ else
+ {
+ result = kAudio_ParamError;
+ }
+ }
+ COMPONENT_CATCH
+ return result;
+}
+#endif
+
+#if TARGET_OS_IPHONE && AUDIOCONV_HAVE_AMC
+// The ACTransformerCodecBase class is the base for ALL hardware codecs.
+// No need to check for ImplementFeature...
+#include "ACTransformerManager.h"
+#define ACTM ((ACTransformerCodecBase*)&ACPI->mInstanceStorage)
+
+static OSStatus AcquireHardware(void *self)
+{
+ OSStatus result = noErr;
+ try {
+ ACTM->AcquireHardware();
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus ReleaseHardware(void *self)
+{
+ OSStatus result = noErr;
+ try {
+ ACTM->ReleaseHardware();
+ }
+ COMPONENT_CATCH
+ return result;
+}
+#endif // TARGET_OS_IPHONE && AUDIOCONV_HAVE_AMC
+
+
+AudioComponentMethod AudioCodecLookup::Lookup (SInt16 selector)
+{
+ switch (selector) {
+ case kAudioCodecGetPropertyInfoSelect: return (AudioComponentMethod)GetPropertyInfo;
+ case kAudioCodecGetPropertySelect: return (AudioComponentMethod)GetProperty;
+ case kAudioCodecSetPropertySelect: return (AudioComponentMethod)SetProperty;
+ case kAudioCodecInitializeSelect: return (AudioComponentMethod)Initialize;
+ case kAudioCodecUninitializeSelect: return (AudioComponentMethod)Uninitialize;
+ case kAudioCodecAppendInputDataSelect: return (AudioComponentMethod)AppendInputData;
+ case kAudioCodecProduceOutputDataSelect: return (AudioComponentMethod)ProduceOutputPackets;
+ case kAudioCodecResetSelect: return (AudioComponentMethod)Reset;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+#if AC_NON_INTERLEAVED_SUPPORT
+AudioComponentMethod AudioCodecNonInterleavedEncoderLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AudioCodecLookup::Lookup(selector);
+ if (method)
+ return method;
+
+ if (selector == kAudioCodecAppendInputBufferListSelect)
+ return (AudioComponentMethod)AppendInputBufferList;
+
+ return NULL;
+}
+
+AudioComponentMethod AudioCodecNonInterleavedDecoderLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AudioCodecLookup::Lookup(selector);
+ if (method)
+ return method;
+
+ if (selector == kAudioCodecProduceOutputBufferListSelect)
+ return (AudioComponentMethod)ProduceOutputBufferList;
+
+ return NULL;
+}
+#endif
+
+#if TARGET_OS_IPHONE && AUDIOCONV_HAVE_AMC
+#include "AudioCodecPriv.h"
+
+AudioComponentMethod AudioCodecHWCodecLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AudioCodecLookup::Lookup(selector);
+ if (method) return method;
+
+ switch (selector) {
+ case kAudioCodecAcquireHardwareSelect: return (AudioComponentMethod)AcquireHardware;
+ case kAudioCodecReleaseHardwareSelect: return (AudioComponentMethod)ReleaseHardware;
+ default:
+ break;
+ }
+ return NULL;
+}
+#endif // TARGET_OS_IPHONE && AUDIOCONV_HAVE_AMC
+
+#endif // AUDIOCODECS_SUPPORT_PLUGINS
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.h b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.h
new file mode 100644
index 0000000000..252a4af0aa
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.h
@@ -0,0 +1,88 @@
+/*
+ File: ACPlugInDispatch.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __ACPlugInDispatch_h__
+#define __ACPlugInDispatch_h__
+
+#include "ComponentBase.h"
+
+struct AudioCodecLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AudioCodecFactory : public APFactory<AudioCodecLookup, Implementor>
+{
+};
+
+#if AC_NON_INTERLEAVED_SUPPORT
+struct AudioCodecNonInterleavedEncoderLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AudioCodecNonInterleavedEncoderFactory : public APFactory<AudioCodecNonInterleavedEncoderLookup, Implementor>
+{
+};
+
+struct AudioCodecNonInterleavedDecoderLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AudioCodecNonInterleavedDecoderFactory : public APFactory<AudioCodecNonInterleavedDecoderLookup, Implementor>
+{
+};
+#endif
+
+#if TARGET_OS_IPHONE
+struct AudioCodecHWCodecLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AudioCodecHWCodecFactory : public APFactory<AudioCodecHWCodecLookup, Implementor>
+{
+};
+#endif // TARGET_OS_IPHONE
+
+#endif // __ACPlugInDispatch_h__
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.cpp b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.cpp
new file mode 100644
index 0000000000..b10add9dac
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.cpp
@@ -0,0 +1,364 @@
+/*
+ File: ACSimpleCodec.cpp
+ Abstract: ACSimpleCodec.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "ACSimpleCodec.h"
+#include <string.h>
+
+//=============================================================================
+// ACSimpleCodec
+//=============================================================================
+
+static const UInt32 kBufferPad = 64; // this is used to prevent end from passing start.
+
+ACSimpleCodec::ACSimpleCodec(UInt32 inInputBufferByteSize, AudioComponentInstance inInstance)
+:
+ ACBaseCodec(inInstance),
+ mInputBuffer(NULL),
+ mInputBufferByteSize(inInputBufferByteSize+kBufferPad),
+ mInputBufferStart(0),
+ mInputBufferEnd(0)
+{
+}
+
+ACSimpleCodec::~ACSimpleCodec()
+{
+ delete[] mInputBuffer;
+}
+
+void ACSimpleCodec::Initialize(const AudioStreamBasicDescription* inInputFormat, const AudioStreamBasicDescription* inOutputFormat, const void* inMagicCookie, UInt32 inMagicCookieByteSize)
+{
+ ReallocateInputBuffer(mInputBufferByteSize - kBufferPad);
+
+ // By definition CBR has this greater than 0. We must avoid a div by 0 error in AppendInputData()
+ // Note this will cause us to fail initialization which is intended
+ if (mInputFormat.mBytesPerPacket == 0)
+ {
+ CODEC_THROW(kAudioCodecUnsupportedFormatError);
+ }
+
+ ACBaseCodec::Initialize(inInputFormat, inOutputFormat, inMagicCookie, inMagicCookieByteSize);
+}
+
+void ACSimpleCodec::Uninitialize()
+{
+ // get rid of the buffer
+ delete[] mInputBuffer;
+ mInputBuffer = NULL;
+
+ // reset the ring buffer state
+ mInputBufferStart = 0;
+ mInputBufferEnd = 0;
+
+ ACBaseCodec::Uninitialize();
+}
+
+void ACSimpleCodec::Reset()
+{
+ // clear the entire input buffer
+ if (mInputBuffer) { // could be called before allocated.
+ memset(mInputBuffer, 0, mInputBufferByteSize);
+ }
+
+ // reset the ring buffer state
+ mInputBufferStart = 0;
+ mInputBufferEnd = 0;
+
+ ACBaseCodec::Reset();
+}
+
+UInt32 ACSimpleCodec::GetInputBufferByteSize() const
+{
+ return mInputBufferByteSize - kBufferPad; // minus kBufferPad to prevent end moving past start
+}
+
+UInt32 ACSimpleCodec::GetUsedInputBufferByteSize() const
+{
+ UInt32 theAnswer = 0;
+
+ // this object uses a ring buffer
+ if(mInputBufferStart <= mInputBufferEnd)
+ {
+ // the active region is contiguous
+ theAnswer = mInputBufferEnd - mInputBufferStart;
+ }
+ else
+ {
+ // the active region wraps around
+ theAnswer = (mInputBufferByteSize - mInputBufferStart) + mInputBufferEnd;
+ }
+
+ return theAnswer;
+}
+
+
+void ACSimpleCodec::AppendInputData(const void* inInputData, UInt32& ioInputDataByteSize, UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription)
+{
+ // this buffer handling code doesn't care about such things as the packet descriptions
+ if(!mIsInitialized) CODEC_THROW(kAudioCodecStateError);
+
+ // this is a ring buffer we're dealing with, so we need to set up a few things
+ UInt32 theUsedByteSize = GetUsedInputBufferByteSize();
+ UInt32 theAvailableByteSize = GetInputBufferByteSize() - theUsedByteSize;
+
+ UInt32 theMaxAvailableInputBytes = ioInputDataByteSize; // we can't consume more than we get
+
+ const Byte* theInputData = static_cast<const Byte*>(inInputData);
+
+ // >>jamesmcc: added this because ioNumberPackets was not being updated if less was taken than given.
+ // THIS ASSUMES CBR!
+ UInt32 bytesPerPacketOfInput = mInputFormat.mBytesPerPacket;
+ UInt32 theAvailablePacketSize = theAvailableByteSize / bytesPerPacketOfInput;
+
+ UInt32 minPacketSize = ioNumberPackets < theAvailablePacketSize ? ioNumberPackets : theAvailablePacketSize;
+ UInt32 minByteSize = minPacketSize * bytesPerPacketOfInput;
+
+ // we can copy only as much data as there is or up to how much space is availiable
+ ioNumberPackets = minPacketSize;
+ ioInputDataByteSize = minByteSize;
+
+ // ioInputDataByteSize had better be <= to theMaxAvailableInputBytes or we're screwed
+ if (ioInputDataByteSize > theMaxAvailableInputBytes)
+ {
+ CODEC_THROW(kAudioCodecStateError);
+ }
+ // <<jamesmcc
+
+ // now we have to copy the data taking into account the wrap around and where the start is
+ if(mInputBufferEnd + ioInputDataByteSize < mInputBufferByteSize)
+ {
+ // no wrap around here
+ memcpy(mInputBuffer + mInputBufferEnd, theInputData, ioInputDataByteSize);
+
+ // adjust the end point
+ mInputBufferEnd += ioInputDataByteSize;
+ }
+ else
+ {
+ // the copy will wrap
+
+ // copy the first part
+ UInt32 theBeforeWrapByteSize = mInputBufferByteSize - mInputBufferEnd;
+ memcpy(mInputBuffer + mInputBufferEnd, theInputData, theBeforeWrapByteSize);
+
+ // and the rest
+ UInt32 theAfterWrapByteSize = ioInputDataByteSize - theBeforeWrapByteSize;
+ memcpy(mInputBuffer, theInputData + theBeforeWrapByteSize, theAfterWrapByteSize);
+
+ // adjust the end point
+ mInputBufferEnd = theAfterWrapByteSize;
+ }
+
+}
+
+
+void ACSimpleCodec::ZeroPadInputData(UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription)
+{
+ // this buffer handling code doesn't care about such things as the packet descriptions
+ if(!mIsInitialized) CODEC_THROW(kAudioCodecStateError);
+
+
+ // this is a ring buffer we're dealing with, so we need to set up a few things
+ UInt32 theUsedByteSize = GetUsedInputBufferByteSize();
+ UInt32 theAvailableByteSize = GetInputBufferByteSize() - theUsedByteSize;
+
+ // >>jamesmcc: added this because ioNumberPackets was not being updated if less was taken than given.
+ // THIS ASSUMES CBR!
+ UInt32 bytesPerPacketOfInput = mInputFormat.mBytesPerPacket;
+ UInt32 theAvailablePacketSize = theAvailableByteSize / bytesPerPacketOfInput;
+
+ UInt32 minPacketSize = ioNumberPackets < theAvailablePacketSize ? ioNumberPackets : theAvailablePacketSize;
+ UInt32 minByteSize = minPacketSize * bytesPerPacketOfInput;
+
+ // we can copy only as much data as there is or up to how much space is availiable
+ ioNumberPackets = minPacketSize;
+
+ // <<jamesmcc
+
+ // now we have to copy the data taking into account the wrap around and where the start is
+ if(mInputBufferEnd + minByteSize < mInputBufferByteSize)
+ {
+ // no wrap around here
+ memset(mInputBuffer + mInputBufferEnd, 0, minByteSize);
+
+ // adjust the end point
+ mInputBufferEnd += minByteSize;
+ }
+ else
+ {
+ // the copy will wrap
+
+ // copy the first part
+ UInt32 theBeforeWrapByteSize = mInputBufferByteSize - mInputBufferEnd;
+ memset(mInputBuffer + mInputBufferEnd, 0, theBeforeWrapByteSize);
+
+ // and the rest
+ UInt32 theAfterWrapByteSize = minByteSize - theBeforeWrapByteSize;
+ memset(mInputBuffer, 0, theAfterWrapByteSize);
+
+ // adjust the end point
+ mInputBufferEnd = theAfterWrapByteSize;
+ }
+}
+
+
+void ACSimpleCodec::ConsumeInputData(UInt32 inConsumedByteSize)
+{
+ // this is a convenience routine to make maintaining the ring buffer state easy
+ UInt32 theContiguousRange = GetInputBufferContiguousByteSize();
+
+ if(inConsumedByteSize > GetUsedInputBufferByteSize()) CODEC_THROW(kAudioCodecUnspecifiedError);
+
+ if(inConsumedByteSize <= theContiguousRange)
+ {
+ // the region to consume doesn't wrap
+
+ // figure out how much to consume
+ inConsumedByteSize = (theContiguousRange < inConsumedByteSize) ? theContiguousRange : inConsumedByteSize;
+
+ // clear the consumed bits
+ memset(mInputBuffer + mInputBufferStart, 0, inConsumedByteSize);
+
+ // adjust the start
+ mInputBufferStart += inConsumedByteSize;
+ }
+ else
+ {
+ // the region to consume will wrap
+
+ // clear the bits to the end of the buffer
+ memset(mInputBuffer + mInputBufferStart, 0, theContiguousRange);
+
+ // now clear the bits left from the start
+ memset(mInputBuffer, 0, inConsumedByteSize - theContiguousRange);
+
+ // adjust the start
+ mInputBufferStart = inConsumedByteSize - theContiguousRange;
+ }
+}
+
+
+Byte* ACSimpleCodec::GetBytes(UInt32& ioNumberBytes) const
+{
+ // if a client's algorithm has to have contiguous data and mInputBuffer wraps, then someone has to make a copy.
+ // I can do it more efficiently than the client.
+
+ if(!mIsInitialized) CODEC_THROW(kAudioCodecStateError);
+
+ UInt32 theUsedByteSize = GetUsedInputBufferByteSize();
+ //UInt32 theAvailableByteSize = GetInputBufferByteSize() - theUsedByteSize;
+
+ if (ioNumberBytes > theUsedByteSize) ioNumberBytes = theUsedByteSize;
+
+ SInt32 leftOver = mInputBufferStart + ioNumberBytes - mInputBufferByteSize;
+
+ if(leftOver > 0)
+ {
+ // need to copy beginning of buffer to the end.
+ // We cleverly over allocated our buffer space to make this possible.
+ memmove(mInputBuffer + mInputBufferByteSize, mInputBuffer, leftOver);
+ }
+
+ return GetInputBufferStart();
+}
+
+
+void ACSimpleCodec::ReallocateInputBuffer(UInt32 inInputBufferByteSize)
+{
+ mInputBufferByteSize = inInputBufferByteSize + kBufferPad;
+
+ // toss the old buffer
+ delete[] mInputBuffer;
+ mInputBuffer = NULL;
+
+ // allocate the new one
+ // allocate extra in order to allow making contiguous data.
+ UInt32 allocSize = 2*inInputBufferByteSize + kBufferPad;
+ mInputBuffer = new Byte[allocSize];
+ memset(mInputBuffer, 0, allocSize);
+
+ // reset the ring buffer state
+ mInputBufferStart = 0;
+ mInputBufferEnd = 0;
+}
+
+void ACSimpleCodec::GetPropertyInfo(AudioCodecPropertyID inPropertyID, UInt32& outPropertyDataSize, Boolean& outWritable)
+{
+ switch(inPropertyID)
+ {
+ case kAudioCodecPropertyInputBufferSize:
+ outPropertyDataSize = SizeOf32(UInt32);
+ outWritable = true;
+ break;
+ default:
+ ACBaseCodec::GetPropertyInfo(inPropertyID, outPropertyDataSize, outWritable);
+ break;
+ }
+
+}
+
+void ACSimpleCodec::SetProperty(AudioCodecPropertyID inPropertyID, UInt32 inPropertyDataSize, const void* inPropertyData)
+{
+ switch(inPropertyID)
+ {
+ case kAudioCodecPropertyInputBufferSize:
+ if(inPropertyDataSize == sizeof(UInt32))
+ {
+ ReallocateInputBuffer(*reinterpret_cast<const UInt32*>(inPropertyData));
+ }
+ else
+ {
+ CODEC_THROW(kAudioCodecBadPropertySizeError);
+ }
+ break;
+ default:
+ ACBaseCodec::SetProperty(inPropertyID, inPropertyDataSize, inPropertyData);
+ break;
+ }
+}
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.h b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.h
new file mode 100644
index 0000000000..f41fe54b93
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.h
@@ -0,0 +1,105 @@
+/*
+ File: ACSimpleCodec.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__ACSimpleCodec_h__)
+#define __ACSimpleCodec_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "ACBaseCodec.h"
+
+//=============================================================================
+// ACSimpleCodec
+//
+// This extension of ACBaseCodec provides for a simple ring buffer to handle
+// input data.
+//=============================================================================
+
+class ACSimpleCodec
+:
+ public ACBaseCodec
+{
+
+// Construction/Destruction
+public:
+ ACSimpleCodec(UInt32 inInputBufferByteSize, AudioComponentInstance inInstance);
+ virtual ~ACSimpleCodec();
+
+// Data Handling
+public:
+ virtual void Initialize(const AudioStreamBasicDescription* inInputFormat, const AudioStreamBasicDescription* inOutputFormat, const void* inMagicCookie, UInt32 inMagicCookieByteSize) = 0;
+ virtual void Uninitialize();
+ virtual void Reset();
+
+ virtual void AppendInputData(const void* inInputData, UInt32& ioInputDataByteSize, UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription);
+ virtual void ZeroPadInputData(UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription);
+ virtual UInt32 GetInputBufferByteSize() const;
+ virtual UInt32 GetUsedInputBufferByteSize() const;
+ virtual void GetPropertyInfo(AudioCodecPropertyID inPropertyID, UInt32& outPropertyDataSize, Boolean& outWritable);
+ virtual void SetProperty(AudioCodecPropertyID inPropertyID, UInt32 inPropertyDataSize, const void* inPropertyData);
+
+protected:
+ void ConsumeInputData(UInt32 inConsumedByteSize);
+ Byte* GetInputBufferStart() const { return mInputBuffer + mInputBufferStart; }
+ UInt32 GetInputBufferContiguousByteSize() const { return (mInputBufferStart <= mInputBufferEnd) ? (mInputBufferEnd - mInputBufferStart) : (mInputBufferByteSize - mInputBufferStart); }
+ virtual void ReallocateInputBuffer(UInt32 inInputBufferByteSize);
+
+ // returns a pointer to contiguous bytes.
+ // will do some copying if the request wraps around the internal buffer.
+ // request must be less than available bytes
+ Byte* GetBytes(UInt32& ioNumberBytes) const;
+
+private:
+ Byte* mInputBuffer;
+ UInt32 mInputBufferByteSize;
+ UInt32 mInputBufferStart;
+ UInt32 mInputBufferEnd;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.cpp b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.cpp
new file mode 100644
index 0000000000..8954c8dd56
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.cpp
@@ -0,0 +1,76 @@
+/*
+ File: GetCodecBundle.cpp
+ Abstract: GetCodecBundle.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "GetCodecBundle.h"
+
+#if TARGET_OS_WIN32
+ #include "CAWin32StringResources.h"
+#endif
+
+#if TARGET_OS_WIN32
+#define kCodecBundleID "com.apple.audio.codecs.Components"
+#else
+const CFStringRef kCodecBundleID = CFSTR("com.apple.audio.codecs.Components");
+#endif
+
+CFBundleRef GetCodecBundle()
+{
+ static CFBundleRef sAudioCodecBundle = 0;
+ if (!sAudioCodecBundle)
+ {
+ #if TARGET_OS_WIN32
+ sAudioCodecBundle = CFBundleGetBundleWithIdentifier(CFSTR(kCodecBundleID));
+ #else
+ sAudioCodecBundle = CFBundleGetBundleWithIdentifier(kCodecBundleID);
+ #endif
+ if (sAudioCodecBundle)
+ {
+ CFRetain(sAudioCodecBundle);
+ }
+ }
+ return sAudioCodecBundle;
+}
+
diff --git a/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.h b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.h
new file mode 100644
index 0000000000..96e3d9e2b4
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.h
@@ -0,0 +1,60 @@
+/*
+ File: GetCodecBundle.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef _GetCodecBundle_
+#define _GetCodecBundle_
+
+#include <TargetConditionals.h>
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CFBundle.h>
+#else
+ #include "CFBundle.h"
+#endif
+
+CFBundleRef GetCodecBundle();
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.cpp
new file mode 100644
index 0000000000..053da0a5d0
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.cpp
@@ -0,0 +1,1040 @@
+/*
+ File: AudioFileComponentBase.cpp
+ Abstract: AudioFileComponentBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioToolbox/AudioFileComponent.h>
+#else
+ #include "AudioFileComponent.h"
+#endif
+
+#include "AudioFileComponentBase.h"
+
+#if TARGET_OS_MAC
+ #if __LP64__
+ // comp instance, parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index + 1];
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
+ #endif
+#elif TARGET_OS_WIN32
+ // (no comp instance), parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index];
+#endif
+
+#define ACPI ((AudioComponentPlugInInstance *)self)
+#define AFC ((AudioFileComponentBase *)&ACPI->mInstanceStorage)
+
+//----------------------------------------------------------------------------------------
+
+static OSStatus CreateURL(
+ void * self,
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ return AFC->AFAPI_CreateURL(inFileRef, inFormat, inFlags);
+}
+
+static OSStatus OpenURL(
+ void * self,
+ CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFileDescriptor)
+{
+ return AFC->AFAPI_OpenURL(inFileRef, inPermissions, inFileDescriptor);
+}
+
+static OSStatus OpenWithCallbacks(
+ void * self,
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc)
+{
+ return AFC->AFAPI_OpenWithCallbacks(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc);
+}
+
+static OSStatus InitializeWithCallbacks(
+ void * self,
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc,
+ UInt32 inFileType,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ return AFC->AFAPI_InitializeWithCallbacks(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc, inFileType, inFormat, inFlags);
+}
+
+static OSStatus Close(
+ void * self)
+{
+ return AFC->AFAPI_Close();
+}
+
+static OSStatus Optimize(
+ void * self)
+{
+ return AFC->AFAPI_Optimize();
+}
+
+static OSStatus ReadBytes(
+ void * self,
+ Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ void *outBuffer)
+{
+ return AFC->AFAPI_ReadBytes(inUseCache, inStartingByte, ioNumBytes, outBuffer);
+}
+
+
+static OSStatus WriteBytes(
+ void * self,
+ Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ const void *inBuffer)
+{
+ return AFC->AFAPI_WriteBytes(inUseCache, inStartingByte, ioNumBytes, inBuffer);
+}
+
+
+static OSStatus ReadPackets(
+ void * self,
+ Boolean inUseCache,
+ UInt32 *outNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ return AFC->AFAPI_ReadPackets(inUseCache, outNumBytes, outPacketDescriptions,
+ inStartingPacket, ioNumPackets, outBuffer);
+}
+
+static OSStatus ReadPacketData(
+ void * self,
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ return AFC->AFAPI_ReadPacketData(inUseCache, ioNumBytes, outPacketDescriptions,
+ inStartingPacket, ioNumPackets, outBuffer);
+}
+
+#if COREAUDIOTYPES_VERSION < 1050
+static OSStatus WritePackets(
+ void * self,
+ Boolean inUseCache,
+ UInt32 inNumBytes,
+ AudioStreamPacketDescription *inPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ const void *inBuffer)
+#else
+static OSStatus WritePackets(
+ void * self,
+ Boolean inUseCache,
+ UInt32 inNumBytes,
+ const AudioStreamPacketDescription *inPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ const void *inBuffer)
+#endif
+{
+ return AFC->AFAPI_WritePackets(inUseCache, inNumBytes,
+ (const AudioStreamPacketDescription *)inPacketDescriptions, // this should be const (and is in 10.5 headers)
+ inStartingPacket, ioNumPackets, inBuffer);
+}
+
+static OSStatus GetPropertyInfo(
+ void * self,
+ AudioFilePropertyID inPropertyID,
+ UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ return AFC->AFAPI_GetPropertyInfo(inPropertyID, outDataSize, isWritable);
+}
+
+static OSStatus GetProperty(
+ void * self,
+ AudioFilePropertyID inPropertyID,
+ UInt32 *ioDataSize,
+ void *ioData)
+{
+ return AFC->AFAPI_GetProperty(inPropertyID, ioDataSize, ioData);
+}
+
+
+static OSStatus SetProperty(
+ void * self,
+ AudioFilePropertyID inPropertyID,
+ UInt32 inDataSize,
+ const void *inData)
+{
+ return AFC->AFAPI_SetProperty(inPropertyID, inDataSize, inData);
+}
+
+static OSStatus CountUserData(
+ void * self,
+ UInt32 inUserDataID,
+ UInt32 *outNumberItems)
+{
+ return AFC->AFAPI_CountUserData(inUserDataID, outNumberItems);
+}
+
+static OSStatus GetUserDataSize(
+ void * self,
+ UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *outDataSize)
+{
+ return AFC->AFAPI_GetUserDataSize(inUserDataID, inIndex, outDataSize);
+}
+
+static OSStatus GetUserData(
+ void * self,
+ UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *ioUserDataSize,
+ void *outUserData)
+{
+ return AFC->AFAPI_GetUserData(inUserDataID, inIndex, ioUserDataSize, outUserData);
+}
+
+static OSStatus SetUserData(
+ void * self,
+ UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 inUserDataSize,
+ const void *inUserData)
+{
+ return AFC->AFAPI_SetUserData(inUserDataID, inIndex, inUserDataSize, inUserData);
+}
+
+static OSStatus RemoveUserData(
+ void * self,
+ UInt32 inUserDataID,
+ UInt32 inIndex)
+{
+ return AFC->AFAPI_RemoveUserData(inUserDataID, inIndex);
+}
+
+static OSStatus ExtensionIsThisFormat(
+ void * self,
+ CFStringRef inExtension,
+ UInt32 *outResult)
+{
+ AudioFileFormatBase* aff = AFC->GetAudioFileFormatBase();
+ if (!aff) return kAudio_ParamError;
+
+ UInt32 res = aff->ExtensionIsThisFormat(inExtension);
+ if (outResult) *outResult = res;
+ return noErr;
+}
+
+static OSStatus FileDataIsThisFormat(
+ void * self,
+ UInt32 inDataByteSize,
+ const void* inData,
+ UInt32 *outResult)
+{
+ AudioFileFormatBase* aff = AFC->GetAudioFileFormatBase();
+ if (!aff) return kAudio_ParamError;
+
+ UncertainResult res = aff->FileDataIsThisFormat(inDataByteSize, inData);
+ if (outResult) *outResult = res;
+ return noErr;
+}
+
+static OSStatus GetGlobalInfoSize(
+ void * self,
+ AudioFilePropertyID inPropertyID,
+ UInt32 inSpecifierSize,
+ const void* inSpecifier,
+ UInt32 *outPropertySize)
+{
+ return AFC->AFAPI_GetGlobalInfoSize(inPropertyID, inSpecifierSize, inSpecifier, outPropertySize);
+}
+
+static OSStatus GetGlobalInfo(
+ void * self,
+ AudioFilePropertyID inPropertyID,
+ UInt32 inSpecifierSize,
+ const void* inSpecifier,
+ UInt32 *ioPropertySize,
+ void *ioPropertyData)
+{
+ return AFC->AFAPI_GetGlobalInfo(inPropertyID, inSpecifierSize, inSpecifier, ioPropertySize, ioPropertyData);
+}
+
+//----------------------------------------------------------------------------------------
+
+
+AudioFileComponentBase::AudioFileComponentBase(AudioComponentInstance inInstance)
+ : ComponentBase(inInstance)
+{
+}
+
+AudioFileComponentBase::~AudioFileComponentBase()
+{
+}
+
+AudioFileObjectComponentBase::AudioFileObjectComponentBase(AudioComponentInstance inInstance)
+ : AudioFileComponentBase(inInstance), mAudioFileObject(0)
+{
+ // derived class should create an AudioFileObject here and if NULL, the AudioFormat as well.
+}
+
+AudioFileObjectComponentBase::~AudioFileObjectComponentBase()
+{
+ delete mAudioFileObject;
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_CreateURL(
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+
+ OSStatus result = mAudioFileObject->DoCreate (inFileRef, inFormat, inFlags);
+ return result;
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_OpenURL(
+ CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFD)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+
+ OSStatus result = mAudioFileObject->DoOpen(inFileRef, inPermissions, inFD);
+ return result;
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_OpenWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->DoOpenWithCallbacks(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc);
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_InitializeWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc,
+ UInt32 inFileType,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->DoInitializeWithCallbacks(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc,
+ inFileType, inFormat, inFlags);
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_Close()
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->DoClose();
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_Optimize()
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->DoOptimize();
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_ReadBytes(
+ Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ void *outBuffer)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->ReadBytes(inUseCache, inStartingByte, ioNumBytes, outBuffer);
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_WriteBytes(
+ Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ const void *inBuffer)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->WriteBytes(inUseCache, inStartingByte, ioNumBytes, inBuffer);
+}
+
+
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_ReadPackets(
+ Boolean inUseCache,
+ UInt32 *outNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->ReadPackets(inUseCache, outNumBytes, outPacketDescriptions,
+ inStartingPacket, ioNumPackets, outBuffer);
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_ReadPacketData(
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->ReadPacketData(inUseCache, ioNumBytes, outPacketDescriptions,
+ inStartingPacket, ioNumPackets, outBuffer);
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_WritePackets(
+ Boolean inUseCache,
+ UInt32 inNumBytes,
+ const AudioStreamPacketDescription *inPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ const void *inBuffer)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->WritePackets(inUseCache, inNumBytes, inPacketDescriptions,
+ inStartingPacket, ioNumPackets, inBuffer);
+}
+
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_GetPropertyInfo(
+ AudioFilePropertyID inPropertyID,
+ UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->GetPropertyInfo(inPropertyID, outDataSize, isWritable);
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_GetProperty(
+ AudioFilePropertyID inPropertyID,
+ UInt32 *ioPropertySize,
+ void *ioPropertyData)
+{
+ OSStatus err = noErr;
+
+ if (!ioPropertyData) return kAudio_ParamError;
+
+ if (!mAudioFileObject) return kAudio_ParamError;
+ err = mAudioFileObject->GetProperty(inPropertyID, ioPropertySize, ioPropertyData);
+ return err;
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_SetProperty(
+ AudioFilePropertyID inPropertyID,
+ UInt32 inPropertySize,
+ const void *inPropertyData)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->SetProperty(inPropertyID, inPropertySize, inPropertyData);
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_CountUserData(
+ UInt32 inUserDataID,
+ UInt32 *outNumberItems)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->CountUserData(inUserDataID, outNumberItems);
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_GetUserDataSize(
+ UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *outUserDataSize)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->GetUserDataSize(inUserDataID, inIndex, outUserDataSize);
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_GetUserData(
+ UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *ioUserDataSize,
+ void *outUserData)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->GetUserData(inUserDataID, inIndex, ioUserDataSize, outUserData);
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_SetUserData(
+ UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 inUserDataSize,
+ const void *inUserData)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->SetUserData(inUserDataID, inIndex, inUserDataSize, inUserData);
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_RemoveUserData(
+ UInt32 inUserDataID,
+ UInt32 inIndex)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->RemoveUserData(inUserDataID, inIndex);
+}
+
+
+OSStatus AudioFileComponentBase::AFAPI_GetGlobalInfoSize(
+ AudioFilePropertyID inPropertyID,
+ UInt32 inSpecifierSize,
+ const void* inSpecifier,
+ UInt32 *outPropertySize)
+{
+ OSStatus err = noErr;
+
+ switch (inPropertyID)
+ {
+ case kAudioFileComponent_CanRead :
+ case kAudioFileComponent_CanWrite :
+ *outPropertySize = sizeof(UInt32);
+ break;
+
+ case kAudioFileComponent_FileTypeName :
+ *outPropertySize = sizeof(CFStringRef);
+ break;
+
+ case kAudioFileComponent_ExtensionsForType :
+ *outPropertySize = sizeof(CFArrayRef);
+ break;
+
+ case kAudioFileComponent_UTIsForType :
+ *outPropertySize = sizeof(CFArrayRef);
+ break;
+
+ case kAudioFileComponent_MIMETypesForType :
+ *outPropertySize = sizeof(CFArrayRef);
+ break;
+
+ case kAudioFileComponent_AvailableFormatIDs :
+ {
+ UInt32 size = 0xFFFFFFFF;
+ err = GetAudioFileFormatBase()->GetAvailableFormatIDs(&size, NULL);
+ if (!err) *outPropertySize = size;
+ break;
+ }
+ case kAudioFileComponent_HFSTypeCodesForType :
+ {
+ UInt32 size = 0xFFFFFFFF;
+ err = GetAudioFileFormatBase()->GetHFSCodes(&size, NULL);
+ if (!err) *outPropertySize = size;
+ break;
+ }
+ case kAudioFileComponent_AvailableStreamDescriptionsForFormat :
+ {
+ if (inSpecifierSize != sizeof(UInt32)) return kAudioFileBadPropertySizeError;
+ UInt32 inFormatID = *(UInt32*)inSpecifier;
+ err = GetAudioFileFormatBase()->GetAvailableStreamDescriptions(inFormatID, outPropertySize, NULL);
+ }
+ break;
+
+ default:
+ err = kAudioFileUnsupportedPropertyError;
+ }
+ return err;
+}
+
+
+OSStatus AudioFileComponentBase::AFAPI_GetGlobalInfo(
+ AudioFilePropertyID inPropertyID,
+ UInt32 inSpecifierSize,
+ const void* inSpecifier,
+ UInt32 *ioPropertySize,
+ void *ioPropertyData)
+{
+ OSStatus err = noErr;
+
+ if (!ioPropertyData || !ioPropertySize) return kAudio_ParamError;
+
+ switch (inPropertyID)
+ {
+ case kAudioFileComponent_CanRead :
+ {
+ if (*ioPropertySize != sizeof(UInt32)) return kAudioFileBadPropertySizeError;
+ UInt32* flag = (UInt32*)ioPropertyData;
+ *flag = GetAudioFileFormatBase()->CanRead();
+ }
+ break;
+
+ case kAudioFileComponent_CanWrite :
+ {
+ if (*ioPropertySize != sizeof(UInt32)) return kAudioFileBadPropertySizeError;
+ UInt32* flag = (UInt32*)ioPropertyData;
+ *flag = GetAudioFileFormatBase()->CanWrite();
+ }
+ break;
+
+ case kAudioFileComponent_FileTypeName :
+ {
+ if (*ioPropertySize != sizeof(CFStringRef)) return kAudioFileBadPropertySizeError;
+ CFStringRef* name = (CFStringRef*)ioPropertyData;
+ GetAudioFileFormatBase()->GetFileTypeName(name);
+ }
+ break;
+
+ case kAudioFileComponent_ExtensionsForType :
+ {
+ if (*ioPropertySize != sizeof(CFArrayRef)) return kAudioFileBadPropertySizeError;
+ CFArrayRef* array = (CFArrayRef*)ioPropertyData;
+ GetAudioFileFormatBase()->GetExtensions(array);
+ }
+ break;
+
+ case kAudioFileComponent_UTIsForType :
+ {
+ if (*ioPropertySize != sizeof(CFArrayRef)) return kAudioFileBadPropertySizeError;
+ CFArrayRef* array = (CFArrayRef*)ioPropertyData;
+ GetAudioFileFormatBase()->GetUTIs(array);
+ }
+ break;
+
+ case kAudioFileComponent_MIMETypesForType :
+ {
+ if (*ioPropertySize != sizeof(CFArrayRef)) return kAudioFileBadPropertySizeError;
+ CFArrayRef* array = (CFArrayRef*)ioPropertyData;
+ GetAudioFileFormatBase()->GetMIMETypes(array);
+ }
+ break;
+
+ case kAudioFileComponent_HFSTypeCodesForType :
+ {
+ err = GetAudioFileFormatBase()->GetHFSCodes(ioPropertySize, ioPropertyData);
+ }
+ break;
+
+ case kAudioFileComponent_AvailableFormatIDs :
+ {
+ err = GetAudioFileFormatBase()->GetAvailableFormatIDs(ioPropertySize, ioPropertyData);
+ }
+ break;
+
+ case kAudioFileComponent_AvailableStreamDescriptionsForFormat :
+ {
+ if (inSpecifierSize != sizeof(UInt32)) return kAudioFileBadPropertySizeError;
+ UInt32 inFormatID = *(UInt32*)inSpecifier;
+ err = GetAudioFileFormatBase()->GetAvailableStreamDescriptions(inFormatID, ioPropertySize, ioPropertyData);
+ }
+ break;
+
+ default:
+ err = kAudioFileUnsupportedPropertyError;
+ }
+ return err;
+}
+
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+OSStatus AudioFileComponentBase::ComponentEntryDispatch(ComponentParameters* params, AudioFileComponentBase* inThis)
+{
+ OSStatus result = noErr;
+ if (inThis == NULL) return kAudio_ParamError;
+
+ try
+ {
+ switch (params->what)
+ {
+ case kComponentCanDoSelect:
+ switch (GetSelectorForCanDo(params))
+ {
+ case kAudioFileCreateURLSelect:
+ case kAudioFileOpenURLSelect:
+ case kAudioFileOpenWithCallbacksSelect:
+ case kAudioFileInitializeWithCallbacksSelect:
+ case kAudioFileCloseSelect:
+ case kAudioFileOptimizeSelect:
+ case kAudioFileReadBytesSelect:
+ case kAudioFileWriteBytesSelect:
+ case kAudioFileReadPacketsSelect:
+ case kAudioFileWritePacketsSelect:
+ case kAudioFileGetPropertyInfoSelect:
+ case kAudioFileGetPropertySelect:
+ case kAudioFileSetPropertySelect:
+ case kAudioFileExtensionIsThisFormatSelect:
+ case kAudioFileFileDataIsThisFormatSelect:
+ case kAudioFileGetGlobalInfoSizeSelect:
+ case kAudioFileGetGlobalInfoSelect:
+
+ case kAudioFileCountUserDataSelect:
+ case kAudioFileGetUserDataSizeSelect:
+ case kAudioFileGetUserDataSelect:
+ case kAudioFileSetUserDataSelect:
+ case kAudioFileRemoveUserDataSelect:
+ result = 1;
+ break;
+ default:
+ // these are no longer supported
+/* case kAudioFileCreateSelect:
+ case kAudioFileOpenSelect:
+ case kAudioFileInitializeSelect:
+*/ result = ComponentBase::ComponentEntryDispatch(params, inThis);
+ };
+ break;
+
+ case kAudioFileCreateURLSelect:
+ {
+ PARAM(CFURLRef, inFileRef, 0, 3);
+ PARAM(const AudioStreamBasicDescription*, inFormat, 1, 3);
+ PARAM(UInt32, inFlags, 2, 3);
+
+ result = inThis->AFAPI_CreateURL(inFileRef, inFormat, inFlags);
+ }
+ break;
+ case kAudioFileOpenURLSelect:
+ {
+ PARAM(CFURLRef, inFileRef, 0, 3);
+ PARAM(SInt32, inPermissions, 1, 3);
+ PARAM(int, inFileDescriptor, 2, 3);
+
+ result = inThis->AFAPI_OpenURL(inFileRef, inPermissions, inFileDescriptor);
+ }
+ break;
+ case kAudioFileOpenWithCallbacksSelect:
+ {
+ PARAM(void*, inRefCon, 0, 5);
+ PARAM(AudioFile_ReadProc, inReadFunc, 1, 5);
+ PARAM(AudioFile_WriteProc, inWriteFunc, 2, 5);
+ PARAM(AudioFile_GetSizeProc, inGetSizeFunc, 3, 5);
+ PARAM(AudioFile_SetSizeProc, inSetSizeFunc, 4, 5);
+
+ result = inThis->AFAPI_OpenWithCallbacks(inRefCon, inReadFunc, inWriteFunc,
+ inGetSizeFunc, inSetSizeFunc);
+ }
+ break;
+ case kAudioFileInitializeWithCallbacksSelect:
+ {
+ PARAM(void*, inRefCon, 0, 8);
+ PARAM(AudioFile_ReadProc, inReadFunc, 1, 8);
+ PARAM(AudioFile_WriteProc, inWriteFunc, 2, 8);
+ PARAM(AudioFile_GetSizeProc, inGetSizeFunc, 3, 8);
+ PARAM(AudioFile_SetSizeProc, inSetSizeFunc, 4, 8);
+ PARAM(UInt32, inFileType, 5, 8);
+ PARAM(const AudioStreamBasicDescription*, inFormat, 6, 8);
+ PARAM(UInt32, inFlags, 7, 8);
+
+ result = inThis->AFAPI_InitializeWithCallbacks(inRefCon, inReadFunc, inWriteFunc,
+ inGetSizeFunc, inSetSizeFunc,
+ inFileType, inFormat, inFlags);
+ }
+ break;
+ case kAudioFileCloseSelect:
+ {
+ result = inThis->AFAPI_Close();
+ }
+ break;
+ case kAudioFileOptimizeSelect:
+ {
+ result = inThis->AFAPI_Optimize();
+ }
+ break;
+ case kAudioFileReadBytesSelect:
+ {
+ PARAM(UInt32, inUseCache, 0, 4);
+ PARAM(SInt64*, inStartingByte, 1, 4);
+ PARAM(UInt32*, ioNumBytes, 2, 4);
+ PARAM(void*, outBuffer, 3, 4);
+
+ result = inThis->AFAPI_ReadBytes(inUseCache, *inStartingByte, ioNumBytes,
+ outBuffer);
+ }
+ break;
+ case kAudioFileWriteBytesSelect:
+ {
+ PARAM(UInt32, inUseCache, 0, 4);
+ PARAM(SInt64*, inStartingByte, 1, 4);
+ PARAM(UInt32*, ioNumBytes, 2, 4);
+ PARAM(const void*, inBuffer, 3, 4);
+
+ result = inThis->AFAPI_WriteBytes(inUseCache, *inStartingByte, ioNumBytes,
+ inBuffer);
+ }
+ break;
+ case kAudioFileReadPacketsSelect:
+ {
+ PARAM(UInt32, inUseCache, 0, 6);
+ PARAM(UInt32*, outNumBytes, 1, 6);
+ PARAM(AudioStreamPacketDescription*, outPacketDescriptions, 2, 6);
+ PARAM(SInt64*, inStartingPacket, 3, 6);
+ PARAM(UInt32*, ioNumPackets, 4, 6);
+ PARAM(void*, outBuffer, 5, 6);
+
+ result = inThis->AFAPI_ReadPackets(inUseCache, outNumBytes, outPacketDescriptions,
+ *inStartingPacket, ioNumPackets, outBuffer);
+ }
+ break;
+ case kAudioFileWritePacketsSelect:
+ {
+ PARAM(UInt32, inUseCache, 0, 6);
+ PARAM(UInt32, inNumBytes, 1, 6);
+ PARAM(const AudioStreamPacketDescription*, inPacketDescriptions, 2, 6);
+ PARAM(SInt64*, inStartingPacket, 3, 6);
+ PARAM(UInt32*, ioNumPackets, 4, 6);
+ PARAM(const void*, inBuffer, 5, 6);
+
+ result = inThis->AFAPI_WritePackets(inUseCache, inNumBytes, inPacketDescriptions,
+ *inStartingPacket, ioNumPackets, inBuffer);
+ }
+ break;
+
+ case kAudioFileGetPropertyInfoSelect:
+ {
+ PARAM(AudioFileComponentPropertyID, inPropertyID, 0, 3);
+ PARAM(UInt32*, outPropertySize, 1, 3);
+ PARAM(UInt32*, outWritable, 2, 3);
+
+ result = inThis->AFAPI_GetPropertyInfo(inPropertyID, outPropertySize, outWritable);
+ }
+ break;
+
+ case kAudioFileGetPropertySelect:
+ {
+ PARAM(AudioFileComponentPropertyID, inPropertyID, 0, 3);
+ PARAM(UInt32*, ioPropertyDataSize, 1, 3);
+ PARAM(void*, outPropertyData, 2, 3);
+
+ result = inThis->AFAPI_GetProperty(inPropertyID, ioPropertyDataSize, outPropertyData);
+ }
+ break;
+ case kAudioFileSetPropertySelect:
+ {
+ PARAM(AudioFileComponentPropertyID, inPropertyID, 0, 3);
+ PARAM(UInt32, inPropertyDataSize, 1, 3);
+ PARAM(const void*, inPropertyData, 2, 3);
+
+ result = inThis->AFAPI_SetProperty(inPropertyID, inPropertyDataSize, inPropertyData);
+ }
+ break;
+
+ case kAudioFileGetGlobalInfoSizeSelect:
+ {
+ PARAM(AudioFileComponentPropertyID, inPropertyID, 0, 4);
+ PARAM(UInt32, inSpecifierSize, 1, 4);
+ PARAM(const void*, inSpecifier, 2, 4);
+ PARAM(UInt32*, outPropertyDataSize, 3, 4);
+
+ result = inThis->AFAPI_GetGlobalInfoSize(inPropertyID, inSpecifierSize, inSpecifier,
+ outPropertyDataSize);
+ }
+ break;
+ case kAudioFileGetGlobalInfoSelect:
+ {
+ PARAM(AudioFileComponentPropertyID, inPropertyID, 0, 5);
+ PARAM(UInt32, inSpecifierSize, 1, 5);
+ PARAM(const void*, inSpecifier, 2, 5);
+ PARAM(UInt32*, ioPropertyDataSize, 3, 5);
+ PARAM(void*, outPropertyData, 4, 5);
+
+ result = inThis->AFAPI_GetGlobalInfo(inPropertyID, inSpecifierSize, inSpecifier,
+ ioPropertyDataSize, outPropertyData);
+ }
+ break;
+
+ case kAudioFileExtensionIsThisFormatSelect:
+ {
+ PARAM(CFStringRef, inExtension, 0, 2);
+ PARAM(UInt32*, outResult, 1, 2);
+
+ AudioFileFormatBase* aff = inThis->GetAudioFileFormatBase();
+ if (!aff) return kAudio_ParamError;
+
+ UInt32 res = aff->ExtensionIsThisFormat(inExtension);
+ if (outResult) *outResult = res;
+ }
+ break;
+
+ case kAudioFileFileDataIsThisFormatSelect:
+ {
+ PARAM(UInt32, inDataByteSize, 0, 3);
+ PARAM(const void*, inData, 1, 3);
+ PARAM(UInt32*, outResult, 2, 3);
+
+ AudioFileFormatBase* aff = inThis->GetAudioFileFormatBase();
+ if (!aff) return kAudio_ParamError;
+
+ UncertainResult res = aff->FileDataIsThisFormat(inDataByteSize, inData);
+ if (outResult) *outResult = res;
+ }
+ break;
+
+ case kAudioFileCountUserDataSelect:
+ {
+ PARAM(UInt32, inUserDataID, 0, 2);
+ PARAM(UInt32*, outNumberItems, 1, 2);
+
+ result = inThis->AFAPI_CountUserData(inUserDataID, outNumberItems);
+ }
+ break;
+
+ case kAudioFileGetUserDataSizeSelect:
+ {
+ PARAM(UInt32, inUserDataID, 0, 3);
+ PARAM(UInt32, inIndex, 1, 3);
+ PARAM(UInt32*, outUserDataSize, 2, 3);
+
+ result = inThis->AFAPI_GetUserDataSize(inUserDataID, inIndex, outUserDataSize);
+ }
+ break;
+
+ case kAudioFileGetUserDataSelect:
+ {
+ PARAM(UInt32, inUserDataID, 0, 4);
+ PARAM(UInt32, inIndex, 1, 4);
+ PARAM(UInt32*, ioUserDataSize, 2, 4);
+ PARAM(void*, outUserData, 3, 4);
+
+ result = inThis->AFAPI_GetUserData(inUserDataID, inIndex,
+ ioUserDataSize, outUserData);
+ }
+ break;
+
+ case kAudioFileSetUserDataSelect:
+ {
+ PARAM(UInt32, inUserDataID, 0, 4);
+ PARAM(UInt32, inIndex, 1, 4);
+ PARAM(UInt32, inUserDataSize, 2, 4);
+ PARAM(const void*, inUserData, 3, 4);
+
+ result = inThis->AFAPI_SetUserData(inUserDataID, inIndex,
+ inUserDataSize, inUserData);
+ }
+ break;
+
+ case kAudioFileRemoveUserDataSelect:
+ {
+ PARAM(UInt32, inUserDataID, 0, 2);
+ PARAM(UInt32, inIndex, 1, 2);
+
+ result = inThis->AFAPI_RemoveUserData(inUserDataID, inIndex);
+ }
+ break;
+
+
+ default:
+ result = ComponentBase::ComponentEntryDispatch(params, inThis);
+ break;
+ }
+ }
+ COMPONENT_CATCH
+ return result;
+}
+#endif
+
+AudioComponentMethod AudioFileComponentLookup::Lookup (SInt16 selector)
+{
+ switch (selector) {
+
+#define DefCase(NAME) case kAudioFile##NAME##Select: return (AudioComponentMethod)NAME
+
+ DefCase(OpenWithCallbacks);
+ DefCase(InitializeWithCallbacks);
+ DefCase(Close);
+ DefCase(Optimize);
+ DefCase(ReadBytes);
+ DefCase(WriteBytes);
+ DefCase(ReadPackets);
+ DefCase(WritePackets);
+ DefCase(GetPropertyInfo);
+ DefCase(GetProperty);
+ DefCase(SetProperty);
+
+ DefCase(ExtensionIsThisFormat);
+ DefCase(GetGlobalInfoSize);
+ DefCase(GetGlobalInfo);
+
+ DefCase(CountUserData);
+ DefCase(GetUserDataSize);
+ DefCase(GetUserData);
+ DefCase(SetUserData);
+ DefCase(RemoveUserData);
+ DefCase(CreateURL);
+ DefCase(OpenURL);
+ DefCase(FileDataIsThisFormat);
+ DefCase(ReadPacketData);
+
+ // These selectors are deprecated and do not appear: Create, Open, Initialize, FileIsThisFormat, DataIsThisFormat.
+
+ default:
+ break;
+ }
+ return NULL;
+}
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.h b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.h
new file mode 100644
index 0000000000..5a11934e76
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.h
@@ -0,0 +1,311 @@
+/*
+ File: AudioFileComponentBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AudioFileComponentBase_h__
+#define __AudioFileComponentBase_h__
+
+#include "ComponentBase.h"
+#include "AudioFileFormat.h"
+
+struct AudioFileComponentLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AudioFileComponentFactory : public APFactory<AudioFileComponentLookup, Implementor>
+{
+};
+
+/* subclass, override AudioFileComponentBase() and GetAudioFormat() and that's it. */
+
+class AudioFileComponentBase : public ComponentBase
+{
+public:
+ AudioFileComponentBase(AudioComponentInstance inInstance);
+ virtual ~AudioFileComponentBase();
+
+ virtual AudioFileFormatBase* GetAudioFileFormatBase() const = 0;
+
+ /* Public API Function Support */
+ virtual OSStatus AFAPI_CreateURL(
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags) { return kAudio_UnimplementedError; }
+
+ virtual OSStatus AFAPI_OpenURL(
+ CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFD) { return kAudio_UnimplementedError; }
+
+
+ virtual OSStatus AFAPI_Create(
+ const FSRef *inParentRef,
+ CFStringRef inFileName,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags,
+ FSRef *outNewFileRef) { return kAudio_UnimplementedError; }
+
+ virtual OSStatus AFAPI_Initialize(
+ const FSRef *inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags) { return kAudio_UnimplementedError; }
+
+ virtual OSStatus AFAPI_Open(
+ const FSRef *inFileRef,
+ SInt8 inPermissions,
+ SInt16 inRefNum) { return kAudio_UnimplementedError; }
+
+ virtual OSStatus AFAPI_OpenWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc)=0;
+
+ virtual OSStatus AFAPI_InitializeWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc,
+ UInt32 inFileType,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)=0;
+
+ virtual OSStatus AFAPI_Close()=0;
+ virtual OSStatus AFAPI_Optimize()=0;
+ virtual OSStatus AFAPI_ReadBytes( Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ void *outBuffer)=0;
+
+ virtual OSStatus AFAPI_WriteBytes( Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ const void *inBuffer)=0;
+
+ virtual OSStatus AFAPI_ReadPackets( Boolean inUseCache,
+ UInt32 *outNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)=0;
+
+ virtual OSStatus AFAPI_ReadPacketData( Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)=0;
+
+ virtual OSStatus AFAPI_WritePackets( Boolean inUseCache,
+ UInt32 inNumBytes,
+ const AudioStreamPacketDescription *inPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ const void *inBuffer)=0;
+
+ virtual OSStatus AFAPI_GetPropertyInfo( AudioFilePropertyID inPropertyID,
+ UInt32 *outDataSize,
+ UInt32 *isWritable)=0;
+
+ virtual OSStatus AFAPI_GetProperty( AudioFilePropertyID inPropertyID,
+ UInt32 *ioDataSize,
+ void *ioPropertyData)=0;
+
+ virtual OSStatus AFAPI_SetProperty( AudioFilePropertyID inPropertyID,
+ UInt32 inDataSize,
+ const void *inPropertyData)=0;
+ virtual OSStatus AFAPI_GetGlobalInfoSize(
+ AudioFilePropertyID inPropertyID,
+ UInt32 inSpecifierSize,
+ const void* inSpecifier,
+ UInt32 *outPropertySize);
+
+ virtual OSStatus AFAPI_GetGlobalInfo(
+ AudioFilePropertyID inPropertyID,
+ UInt32 inSpecifierSize,
+ const void* inSpecifier,
+ UInt32 *ioPropertySize,
+ void *ioPropertyData);
+
+ virtual OSStatus AFAPI_CountUserData( UInt32 inUserDataID,
+ UInt32 *outNumberItems)=0;
+
+ virtual OSStatus AFAPI_GetUserDataSize( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *outDataSize)=0;
+
+ virtual OSStatus AFAPI_GetUserData( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *ioDataSize,
+ void *ioUserData)=0;
+
+ virtual OSStatus AFAPI_SetUserData( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 inDataSize,
+ const void *inUserData)=0;
+
+ virtual OSStatus AFAPI_RemoveUserData( UInt32 inUserDataID,
+ UInt32 inIndex)=0;
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ static OSStatus ComponentEntryDispatch(ComponentParameters *p, AudioFileComponentBase *This);
+#endif
+
+protected:
+};
+
+
+
+class AudioFileObjectComponentBase : public AudioFileComponentBase
+{
+public:
+ AudioFileObjectComponentBase(AudioComponentInstance inInstance);
+ virtual ~AudioFileObjectComponentBase();
+
+ virtual AudioFileFormat* GetAudioFormat() const = 0;
+ virtual AudioFileFormatBase* GetAudioFileFormatBase() const { return GetAudioFormat(); }
+
+ void SetAudioFileObject(AudioFileObject* inObject) { mAudioFileObject = inObject; }
+
+ /* Public API Function Support */
+
+ virtual OSStatus AFAPI_CreateURL(
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags);
+
+ virtual OSStatus AFAPI_OpenURL(
+ CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFD);
+
+ virtual OSStatus AFAPI_OpenWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc);
+
+ virtual OSStatus AFAPI_InitializeWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc,
+ UInt32 inFileType,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags);
+
+ virtual OSStatus AFAPI_Close();
+ virtual OSStatus AFAPI_Optimize();
+ virtual OSStatus AFAPI_ReadBytes( Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ void *outBuffer);
+
+ virtual OSStatus AFAPI_WriteBytes( Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ const void *inBuffer);
+
+ virtual OSStatus AFAPI_ReadPackets( Boolean inUseCache,
+ UInt32 *outNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer);
+
+ virtual OSStatus AFAPI_ReadPacketData( Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer);
+
+ virtual OSStatus AFAPI_WritePackets( Boolean inUseCache,
+ UInt32 inNumBytes,
+ const AudioStreamPacketDescription *inPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ const void *inBuffer);
+
+ virtual OSStatus AFAPI_GetPropertyInfo( AudioFilePropertyID inPropertyID,
+ UInt32 *outDataSize,
+ UInt32 *isWritable);
+
+ virtual OSStatus AFAPI_GetProperty( AudioFilePropertyID inPropertyID,
+ UInt32 *ioDataSize,
+ void *ioPropertyData);
+
+ virtual OSStatus AFAPI_SetProperty( AudioFilePropertyID inPropertyID,
+ UInt32 inDataSize,
+ const void *inPropertyData);
+
+ virtual OSStatus AFAPI_CountUserData( UInt32 inUserDataID,
+ UInt32 *outNumberItems);
+
+ virtual OSStatus AFAPI_GetUserDataSize( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *outDataSize);
+
+ virtual OSStatus AFAPI_GetUserData( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *ioDataSize,
+ void *ioUserData);
+
+ virtual OSStatus AFAPI_SetUserData( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 inDataSize,
+ const void *inUserData);
+
+ virtual OSStatus AFAPI_RemoveUserData( UInt32 inUserDataID,
+ UInt32 inIndex);
+
+protected:
+ AudioFileObject* mAudioFileObject;
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.cpp
new file mode 100644
index 0000000000..ee6bedd593
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.cpp
@@ -0,0 +1,71 @@
+/*
+ File: AudioFileFormat.cpp
+ Abstract: AudioFileFormat.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AudioFileFormat.h"
+#include "DataSource.h"
+
+AudioFileFormatBase::AudioFileFormatBase(UInt32 inFileType)
+ : mFileType(inFileType)
+{
+}
+
+AudioFileFormatBase::~AudioFileFormatBase()
+{
+}
+
+OSStatus AudioFileFormatBase::GetHFSCodes(UInt32* ioDataSize, void* outPropertyData)
+{
+ return kAudioFileUnsupportedPropertyError;
+}
+
+AudioFileFormat::AudioFileFormat(UInt32 inFileType)
+ : AudioFileFormatBase(inFileType)
+{
+}
+
+AudioFileFormat::~AudioFileFormat()
+{
+}
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.h b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.h
new file mode 100644
index 0000000000..9436199569
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.h
@@ -0,0 +1,125 @@
+/*
+ File: AudioFileFormat.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef _AudioFileFormat_H_
+#define _AudioFileFormat_H_
+
+#include "AudioFileObject.h"
+
+// AudioFileFormat is a factory class for AudioFileObjects.
+
+// UncertainResult is needed for DataIsThisFormat.
+// In the case of SoundDesigner 2 we can't determine if the data is SoundDesigner 2 or not.
+
+typedef int UncertainResult;
+
+enum {
+ kFalse = 0,
+ kTrue = 1,
+ kCantDetermine = -1
+};
+
+class AudioFileHandle;
+class AudioFileFormat;
+class AudioFileFormatComponent;
+
+class AudioFileFormatBase
+{
+public:
+ AudioFileFormatBase(UInt32 inFileType);
+ virtual ~AudioFileFormatBase();
+
+ // return true if extension is of this format type
+ virtual Boolean ExtensionIsThisFormat(CFStringRef inExtension) = 0;
+
+ virtual UncertainResult FileDataIsThisFormat(
+ UInt32 /*inDataByteSize*/,
+ const void* /*inData*/) = 0;
+
+ // support SoundDesigner II files while minimizing opening and closing files.
+ virtual Boolean ResourceIsThisFormat(const FSRef* /*inRef*/) { return false; }
+
+ UInt32 GetFileType() const { return mFileType; }
+
+ virtual UInt32 CanRead() const { return 1; }
+ virtual UInt32 CanWrite() const { return 1; }
+ virtual UInt32 HasResourceFork() const { return 0; }
+
+ virtual void GetExtensions(CFArrayRef *outArray) = 0;
+ virtual void GetUTIs(CFArrayRef *outArray) {}
+ virtual void GetMIMETypes(CFArrayRef *outArray) {}
+ virtual void GetFileTypeName(CFStringRef *outName) = 0;
+ virtual OSStatus GetAvailableFormatIDs(UInt32* ioDataSize, void* outPropertyData) = 0;
+ virtual OSStatus GetAvailableStreamDescriptions(UInt32 inFormatID, UInt32* ioDataSize, void* outPropertyData) = 0;
+ virtual OSStatus GetHFSCodes(UInt32* ioDataSize, void* outPropertyData);
+
+ virtual AudioFileFormat* AsAudioFileFormat() { return NULL; }
+ virtual AudioFileFormatComponent* AsAudioFileFormatComponent() { return NULL; }
+
+private:
+ UInt32 mFileType;
+};
+
+class AudioFileStreamObject;
+
+class AudioFileFormat : public AudioFileFormatBase
+{
+public:
+ AudioFileFormat(UInt32 inFileType);
+ virtual ~AudioFileFormat();
+
+ // create an AudioFileObject for this format type.
+ virtual AudioFileObject* New() = 0;
+ virtual AudioFileStreamObject* NewStream() { return NULL; }
+
+ // return true if file is of this format type
+ virtual UncertainResult FileDataIsThisFormat(UInt32 inDataByteSize, const void* inData) = 0;
+
+ virtual AudioFileFormat* AsAudioFileFormat() { return this; }
+};
+
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.cpp
new file mode 100644
index 0000000000..1a00f96251
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.cpp
@@ -0,0 +1,1966 @@
+/*
+ File: AudioFileObject.cpp
+ Abstract: AudioFileObject.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AudioFileObject.h"
+#include "CADebugMacros.h"
+#include <algorithm>
+#include <sys/stat.h>
+
+#define kAudioFileNoCacheMask 0x20
+
+const SInt64 kScanToEnd = 0x7fffFFFFffffFFFFLL;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+AudioFileObject::~AudioFileObject()
+{
+ delete mDataSource;
+ DeletePacketTable();
+ SetURL(NULL);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoCreate(
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ // common prologue
+ if (!IsDataFormatValid(inFormat))
+ return kAudioFileUnsupportedDataFormatError;
+
+ if (!IsDataFormatSupported(inFormat))
+ return kAudioFileUnsupportedDataFormatError;
+
+ SetPermissions(kAudioFileReadWritePermission);
+
+ SetAlignDataWithFillerChunks(!(inFlags & 2 /* kAudioFileFlags_DontPageAlignAudioData */ ));
+
+ // call virtual method for particular format.
+ return Create(inFileRef, inFormat);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::Create(
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat)
+{
+ int fileD;
+ OSStatus err = CreateDataFile (inFileRef, fileD);
+ FailIf (err != noErr, Bail, "CreateDataFile failed");
+
+ SetURL (inFileRef);
+
+ err = OpenFile(kAudioFileReadWritePermission, fileD);
+ FailIf (err != noErr, Bail, "OpenFile failed");
+
+ err = SetDataFormat(inFormat);
+ FailIf (err != noErr, Bail, "SetDataFormat failed");
+
+ mIsInitialized = false;
+
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoOpen(
+ CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFD)
+{
+ OSStatus err = noErr;
+ SetPermissions(inPermissions);
+
+ err = Open(inFileRef, inPermissions, inFD);
+ FailIf (err != noErr, Bail, "Open failed");
+
+ err = ValidateFormatAndData();
+ FailIf (err != noErr, Bail, "ValidateFormatAndData failed");
+
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::Open(
+ CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFD)
+{
+ if (!(inPermissions & kAudioFileReadPermission))
+ return kAudioFilePermissionsError; // file must have read permissions
+
+ SetURL(inFileRef);
+
+ OSStatus err = OpenFile(inPermissions, inFD);
+ FailIf (err != noErr, Bail, "OpenFile failed");
+
+ err = OpenFromDataSource();
+ FailIf (err != noErr, Bail, "OpenFromDataSource failed");
+
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ValidateFormatAndData()
+{
+
+
+ AudioStreamBasicDescription asbd = GetDataFormat();
+
+ if (!IsDataFormatValid(&asbd))
+ return kAudioFileInvalidFileError;
+
+ if (asbd.mFormatID == kAudioFormatLinearPCM)
+ {
+ SInt64 maxPackets = GetNumBytes() / asbd.mBytesPerPacket;
+ if (GetNumPackets() > maxPackets)
+ return kAudioFileInvalidFileError;
+ }
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoOpenWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc)
+{
+ SInt8 perms = (inSetSizeFunc || inWriteFunc) ? kAudioFileReadWritePermission : kAudioFileReadPermission;
+ SetPermissions(perms);
+
+ DataSource* dataSource = new Seekable_DataSource(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc);
+ SetDataSource(dataSource);
+ return OpenFromDataSource();
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::OpenFromDataSource(void)
+{
+ return noErr;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoInitializeWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc,
+ UInt32 inFileType,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ DataSource* dataSource = new Seekable_DataSource(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc);
+ if (!dataSource->CanWrite()) return -54/*permErr*/;
+ dataSource->SetSize(0);
+ SetDataSource(dataSource);
+ SetPermissions(kAudioFileReadWritePermission);
+
+ SetAlignDataWithFillerChunks(!(inFlags & 2 /* kAudioFileFlags_DontPageAlignAudioData */ ));
+
+ OSStatus err = SetDataFormat(inFormat);
+ if (err) return err;
+
+ return InitializeDataSource(inFormat, inFlags);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoInitialize(
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ SetURL (inFileRef);
+ SetPermissions(kAudioFileReadWritePermission);
+
+ SetAlignDataWithFillerChunks(!(inFlags & 2 /* kAudioFileFlags_DontPageAlignAudioData */ ));
+
+ return Initialize(inFileRef, inFormat, inFlags);
+}
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::Initialize(
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ OSStatus err = noErr;
+
+ UInt8 fPath[FILENAME_MAX];
+ if (!CFURLGetFileSystemRepresentation (inFileRef, true, fPath, FILENAME_MAX))
+ return kAudio_FileNotFoundError;
+
+#if TARGET_OS_WIN32
+ int filePerms = 0;
+ int flags = O_TRUNC | O_RDWR | O_BINARY;
+#else
+ mode_t filePerms = 0;
+ int flags = O_TRUNC | O_RDWR;
+#endif
+
+ int fileD = open((const char*)fPath, flags, filePerms);
+ if (fileD < 0)
+ return AudioFileTranslateErrno(errno);
+
+ err = OpenFile(kAudioFileReadWritePermission, fileD);
+ FailIf (err != noErr, Bail, "OpenFile failed");
+
+ // don't need to do this as open has an option to truncate the file
+// GetDataSource()->SetSize(0);
+
+ err = SetDataFormat(inFormat);
+ FailIf (err != noErr, Bail, "SetDataFormat failed");
+
+ InitializeDataSource(inFormat, inFlags);
+
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::InitializeDataSource(const AudioStreamBasicDescription *inFormat, UInt32 /*inFlags*/)
+{
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoClose()
+{
+ OSStatus err = UpdateSizeIfNeeded();
+ if (err) return err;
+
+ return Close();
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::Close()
+{
+ try {
+ delete mDataSource;
+ mDataSource = 0;
+ } catch (OSStatus err) {
+ return err;
+ } catch (...) {
+ return kAudioFileUnspecifiedError;
+ }
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+OSStatus AudioFileObject::Optimize()
+{
+ // default is that nothing needs to be done. This happens to be true for Raw, SD2 and NeXT/Sun types.
+ SetIsOptimized(true);
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+OSStatus AudioFileObject::DoOptimize()
+{
+ if (!CanWrite()) return kAudioFilePermissionsError;
+
+ OSStatus err = UpdateSizeIfNeeded();
+ if (err) return err;
+
+ if (IsOptimized()) return noErr;
+
+ err = Optimize();
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::UpdateNumBytes(SInt64 inNumBytes)
+{
+ OSStatus err = noErr;
+ if (inNumBytes != GetNumBytes()) {
+ SetNumBytes(inNumBytes);
+
+ // #warning " this will not work for vbr formats"
+ SetNumPackets(GetNumBytes() / mDataFormat.mBytesPerPacket);
+ SizeChanged();
+ }
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::UpdateNumPackets(SInt64 inNumPackets)
+{
+ OSStatus err = noErr;
+ if (inNumPackets != GetNumPackets()) {
+ // sync current state.
+ SetNeedsSizeUpdate(true);
+ UpdateSizeIfNeeded();
+ SetNumPackets(inNumPackets);
+
+ // #warning " this will not work for vbr formats"
+ SetNumBytes(GetNumPackets() * mDataFormat.mBytesPerFrame);
+ SizeChanged();
+ }
+ return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::PacketToFrame(SInt64 inPacket, SInt64& outFirstFrameInPacket)
+{
+ if (mDataFormat.mFramesPerPacket == 0)
+ {
+ OSStatus err = ScanForPackets(inPacket+1); // the packet count must be one greater than the packet index
+ if (err) return err;
+
+ SInt64 packetTableSize = GetPacketTableSize();
+
+ if (mPacketTable && inPacket >= packetTableSize)
+ return kAudioFileEndOfFileError;
+
+ CompressedPacketTable* packetTable = GetPacketTable();
+ if (!packetTable)
+ return kAudioFileInvalidPacketOffsetError;
+
+ if (inPacket < 0 || inPacket >= packetTableSize)
+ return kAudioFileInvalidPacketOffsetError;
+
+ outFirstFrameInPacket = (*packetTable)[(size_t)inPacket].mFrameOffset;
+ }
+ else
+ {
+ outFirstFrameInPacket = inPacket * mDataFormat.mFramesPerPacket;
+ }
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::FrameToPacket(SInt64 inFrame, SInt64& outPacket, UInt32& outFrameOffsetInPacket)
+{
+ if (mDataFormat.mFramesPerPacket == 0)
+ {
+ CompressedPacketTable* packetTable = GetPacketTable();
+ if (!packetTable)
+ return kAudioFileInvalidPacketOffsetError;
+
+ // search packet table
+ AudioStreamPacketDescriptionExtended pext;
+ memset(&pext, 0, sizeof(pext));
+ pext.mFrameOffset = inFrame;
+ CompressedPacketTable::iterator iter = std::lower_bound(packetTable->begin(), packetTable->end(), pext);
+
+ if (iter == packetTable->end())
+ return kAudioFileInvalidPacketOffsetError;
+
+ if (iter > packetTable->begin()) --iter;
+
+ outPacket = iter - packetTable->begin();
+ outFrameOffsetInPacket = (UInt32)(inFrame - iter->mFrameOffset);
+ }
+ else
+ {
+ outPacket = inFrame / mDataFormat.mFramesPerPacket;
+ outFrameOffsetInPacket = (UInt32)(inFrame % mDataFormat.mFramesPerPacket);
+ }
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::PacketToByte(AudioBytePacketTranslation* abpt)
+{
+ if (abpt->mPacket < 0)
+ return kAudioFileInvalidPacketOffsetError;
+
+ if (mDataFormat.mBytesPerPacket == 0)
+ {
+ CompressedPacketTable* packetTable = GetPacketTable();
+ if (!packetTable)
+ return kAudioFileInvalidPacketOffsetError;
+
+ if (abpt->mPacket < GetPacketTableSize()) {
+ abpt->mByte = (*packetTable)[(int)abpt->mPacket].mStartOffset;
+ abpt->mFlags = 0;
+ } else {
+ SInt64 numPackets = packetTable->size();
+ if (numPackets < 8)
+ return 'more' /*kAudioFileStreamError_DataUnavailable*/ ;
+
+ const AudioStreamPacketDescriptionExtended lastPacket = (*packetTable)[numPackets - 1];
+ SInt64 bytesReadSoFar = lastPacket.mStartOffset + lastPacket.mDataByteSize;
+ double averageBytesPerPacket = (double)(bytesReadSoFar - GetDataOffset()) / (double)numPackets;
+ abpt->mByte = (SInt64)floor((double)abpt->mPacket * averageBytesPerPacket);
+ abpt->mFlags = kBytePacketTranslationFlag_IsEstimate;
+ }
+ }
+ else
+ {
+ abpt->mByte = abpt->mPacket * mDataFormat.mBytesPerPacket;
+ abpt->mFlags = 0;
+ }
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+inline bool byte_less_than (const AudioStreamPacketDescriptionExtended& a, const AudioStreamPacketDescriptionExtended& b)
+{
+ return a.mStartOffset < b.mStartOffset;
+}
+
+OSStatus AudioFileObject::ByteToPacket(AudioBytePacketTranslation* abpt)
+{
+ if (abpt->mByte < 0)
+ return kAudioFileInvalidPacketOffsetError;
+
+ if (mDataFormat.mBytesPerPacket == 0)
+ {
+ CompressedPacketTable* packetTable = GetPacketTable();
+ if (!packetTable)
+ return kAudioFileInvalidPacketOffsetError;
+ // search packet table
+ AudioStreamPacketDescriptionExtended pext;
+ memset(&pext, 0, sizeof(pext));
+ pext.mStartOffset = abpt->mByte;
+ CompressedPacketTable::iterator iter = std::lower_bound(packetTable->begin(), packetTable->end(), pext, byte_less_than);
+
+ if (iter == packetTable->end()) {
+ SInt64 numPackets = packetTable->size();
+ if (numPackets < 8)
+ return 'more' /*kAudioFileStreamError_DataUnavailable*/ ;
+
+ const AudioStreamPacketDescriptionExtended lastPacket = (*packetTable)[numPackets - 1];
+ SInt64 bytesReadSoFar = lastPacket.mStartOffset + lastPacket.mDataByteSize;
+ double averageBytesPerPacket = (double)(bytesReadSoFar - GetDataOffset()) / (double)numPackets;
+
+ double fpacket = (double)abpt->mByte / averageBytesPerPacket;
+ abpt->mPacket = (SInt64)floor(fpacket);
+ abpt->mByteOffsetInPacket = (UInt32)floor((fpacket - (double)abpt->mPacket) * averageBytesPerPacket);
+ abpt->mFlags = kBytePacketTranslationFlag_IsEstimate;
+
+ } else {
+ if (iter > packetTable->begin()) --iter;
+ abpt->mPacket = iter - packetTable->begin();
+ abpt->mByteOffsetInPacket = (UInt32)(abpt->mByte - iter->mStartOffset);
+ abpt->mFlags = 0;
+ }
+ }
+ else
+ {
+ abpt->mPacket = abpt->mByte / mDataFormat.mBytesPerPacket;
+ abpt->mByteOffsetInPacket = (UInt32)(abpt->mByte % mDataFormat.mBytesPerPacket);
+ abpt->mFlags = 0;
+ }
+ return noErr;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ReadBytes(
+ Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ void *outBuffer)
+{
+ OSStatus err = noErr;
+ UInt16 mode = SEEK_SET;
+ SInt64 fileOffset = mDataOffset + inStartingByte;
+ bool readingPastEnd = false;
+
+ FailWithAction((ioNumBytes == NULL) || (outBuffer == NULL), err = kAudio_ParamError,
+ Bail, "invalid num bytes parameter");
+
+ //printf("inStartingByte %lld GetNumBytes %lld\n", inStartingByte, GetNumBytes());
+
+ if (inStartingByte >= GetNumBytes())
+ {
+ *ioNumBytes = 0;
+ return kAudioFileEndOfFileError;
+ }
+
+ if ((fileOffset + *ioNumBytes) > (GetNumBytes() + mDataOffset))
+ {
+ *ioNumBytes = (UInt32)(GetNumBytes() + mDataOffset - fileOffset);
+ readingPastEnd = true;
+ }
+ //printf("fileOffset %lld mDataOffset %lld readingPastEnd %d\n", fileOffset, mDataOffset, readingPastEnd);
+
+ if (!inUseCache)
+ mode |= kAudioFileNoCacheMask;
+
+ err = GetDataSource()->ReadBytes(mode, fileOffset, *ioNumBytes, outBuffer, ioNumBytes);
+
+ if (readingPastEnd && err == noErr)
+ err = kAudioFileEndOfFileError;
+
+Bail:
+ return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::WriteBytes(
+ Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ const void *inBuffer)
+{
+ OSStatus err = noErr;
+ UInt16 mode = SEEK_SET;
+ bool extendingTheAudioData;
+
+ if (!CanWrite()) return kAudioFilePermissionsError;
+
+ FailWithAction((ioNumBytes == NULL) || (inBuffer == NULL), err = kAudioFileUnspecifiedError, Bail, "invalid parameters");
+
+ // Do not try to write to a postion greater than 32 bits for some file types
+ // see if starting byte + ioNumBytes is greater than 32 bits
+ // if so, see if file type supports this and bail if not
+ err = IsValidFilePosition(inStartingByte + *ioNumBytes);
+ FailIf(err != noErr, Bail, "invalid file position");
+
+ extendingTheAudioData = inStartingByte + *ioNumBytes > GetNumBytes();
+
+ // if file is not optimized, then do not write data that would overwrite chunks following the sound data chunk
+ FailWithAction( extendingTheAudioData && !IsOptimized(),
+ err = kAudioFileNotOptimizedError, Bail, "Can't write more data until the file is optimized");
+
+ if (!inUseCache)
+ mode |= kAudioFileNoCacheMask;
+
+ err = GetDataSource()->WriteBytes(mode, mDataOffset + inStartingByte, *ioNumBytes,
+ inBuffer, ioNumBytes);
+
+ FailIf(err != noErr, Bail, "couldn't write new data");
+
+ if (extendingTheAudioData) {
+ SInt64 nuEOF; // Get the total bytes of audio data
+ SInt64 nuByteTotal;
+
+ err = GetDataSource()->GetSize(nuEOF);
+ FailIf(err != noErr, Bail, "GetSize failed");
+
+ nuByteTotal = nuEOF - mDataOffset;
+ err = UpdateNumBytes(nuByteTotal);
+ }
+
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ReadPackets(
+ Boolean inUseCache,
+ UInt32 *outNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ // This only works with CBR. To suppport VBR you must override.
+ OSStatus err = noErr;
+
+ FailWithAction(outBuffer == NULL, err = kAudio_ParamError, Bail, "NULL buffer");
+
+ FailWithAction((ioNumPackets == NULL) || (*ioNumPackets < 1), err = kAudio_ParamError, Bail, "invalid num packets parameter");
+
+ {
+ UInt32 byteCount = *ioNumPackets * mDataFormat.mBytesPerPacket;
+ SInt64 startingByte = inStartingPacket * mDataFormat.mBytesPerPacket;
+
+ err = ReadBytes (inUseCache, startingByte, &byteCount, outBuffer);
+ if ((err == noErr) || (err == kAudioFileEndOfFileError))
+ {
+ if (byteCount != (*ioNumPackets * mDataFormat.mBytesPerPacket))
+ {
+ *ioNumPackets = byteCount / mDataFormat.mBytesPerPacket;
+ byteCount = *ioNumPackets * mDataFormat.mBytesPerPacket;
+ }
+
+ if (outNumBytes)
+ *outNumBytes = byteCount;
+
+ if (err == kAudioFileEndOfFileError)
+ err = noErr;
+ }
+ }
+Bail:
+ return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ReadPacketData(
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ OSStatus err = noErr;
+ FailWithAction(ioNumPackets == NULL || *ioNumPackets < 1, err = kAudio_ParamError, Bail, "invalid ioNumPackets parameter");
+ FailWithAction(ioNumBytes == NULL || *ioNumBytes < 1, err = kAudio_ParamError, Bail, "invalid ioNumBytes parameter");
+ if (mDataFormat.mBytesPerPacket) {
+ // CBR
+ FailWithAction(outBuffer == NULL, err = kAudio_ParamError, Bail, "NULL buffer");
+ UInt32 maxPackets = *ioNumBytes / mDataFormat.mBytesPerPacket;
+ if (*ioNumPackets > maxPackets) *ioNumPackets = maxPackets;
+
+ if (outBuffer) {
+ UInt32 byteCount = *ioNumPackets * mDataFormat.mBytesPerPacket;
+ SInt64 startingByte = inStartingPacket * mDataFormat.mBytesPerPacket;
+ err = ReadBytes (inUseCache, startingByte, &byteCount, outBuffer);
+ if (err == noErr || err == kAudioFileEndOfFileError) {
+ if (byteCount != (*ioNumPackets * mDataFormat.mBytesPerPacket)) {
+ *ioNumPackets = byteCount / mDataFormat.mBytesPerPacket;
+ byteCount = *ioNumPackets * mDataFormat.mBytesPerPacket;
+ }
+ *ioNumBytes = byteCount;
+ }
+ }
+ } else {
+ FailWithAction(outPacketDescriptions == NULL, err = kAudio_ParamError, Bail, "invalid outPacketDescriptions parameter");
+ err = ReadPacketDataVBR(inUseCache, ioNumBytes, outPacketDescriptions, inStartingPacket, ioNumPackets, outBuffer);
+ }
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ReadPacketDataVBR(
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ OSStatus err = ScanForPackets(inStartingPacket+1); // need to scan packets up to start
+ if (err && err != kAudioFileEndOfFileError)
+ return err;
+
+ SInt64 dataOffset = GetDataOffset();
+
+ CompressedPacketTable* packetTable = GetPacketTable();
+ if (!packetTable)
+ return kAudioFileInvalidFileError;
+
+ SInt64 packetTableSize = GetPacketTableSize();
+
+ if (inStartingPacket >= packetTableSize) {
+ *ioNumBytes = 0;
+ *ioNumPackets = 0;
+ return kAudioFileEndOfFileError;
+ }
+
+ if (inStartingPacket + *ioNumPackets <= packetTableSize) {
+ err = ReadPacketDataVBR_InTable(inUseCache, ioNumBytes, outPacketDescriptions, inStartingPacket, ioNumPackets, outBuffer);
+ } else {
+
+ AudioStreamPacketDescription firstPacket = (*packetTable)[inStartingPacket];
+ SInt64 firstPacketOffset = firstPacket.mStartOffset;
+ UInt32 bytesRead = *ioNumBytes;
+ SInt64 fileSize = 0;
+ GetDataSource()->GetSize(fileSize);
+ SInt64 remainingBytesInFile = fileSize - firstPacketOffset - dataOffset;
+ if (bytesRead > remainingBytesInFile)
+ bytesRead = (UInt32)remainingBytesInFile;
+
+ err = ReadBytes (inUseCache, firstPacketOffset, &bytesRead, outBuffer);
+ if (err && err != kAudioFileEndOfFileError) {
+ *ioNumBytes = 0;
+ *ioNumPackets = 0;
+ return err;
+ }
+
+ Buffer_DataSource bufSrc(bytesRead, outBuffer, dataOffset + firstPacketOffset);
+
+ OSStatus scanErr = ScanForPackets(kScanToEnd, &bufSrc, false);
+ if (scanErr && scanErr != kAudioFileEndOfFileError)
+ return scanErr;
+ packetTableSize = packetTable->size();
+
+ UInt32 numPacketsRead = 0;
+ UInt32 endOfData = 0;
+ SInt64 packetNumber = inStartingPacket;
+ for (; numPacketsRead < *ioNumPackets && packetNumber < packetTableSize; ++numPacketsRead, ++packetNumber) {
+ AudioStreamPacketDescription curPacket = (*packetTable)[numPacketsRead + inStartingPacket];
+ SInt64 curPacketOffset = curPacket.mStartOffset - firstPacketOffset;
+ SInt64 endOfPacket = curPacketOffset + curPacket.mDataByteSize;
+ if (endOfPacket > bytesRead) break;
+ endOfData = (UInt32)endOfPacket;
+ outPacketDescriptions[numPacketsRead] = curPacket;
+ outPacketDescriptions[numPacketsRead].mStartOffset = curPacketOffset;
+ }
+
+ *ioNumBytes = endOfData;
+ *ioNumPackets = numPacketsRead;
+ }
+ return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+OSStatus AudioFileObject::HowManyPacketsCanBeReadIntoBuffer(UInt32* ioNumBytes, SInt64 inStartingPacket, UInt32 *ioNumPackets)
+{
+ CompressedPacketTable* packetTable = GetPacketTable();
+ SInt64 packetTableSize = GetPacketTableSize();
+
+ if (inStartingPacket + *ioNumPackets > (SInt64)packetTableSize) {
+ *ioNumPackets = (UInt32)(packetTableSize - inStartingPacket);
+ }
+
+ AudioStreamPacketDescription firstPacket = (*packetTable)[inStartingPacket];
+
+ if (*ioNumBytes < firstPacket.mDataByteSize) {
+ *ioNumBytes = 0;
+ *ioNumPackets = 0;
+ return kAudio_ParamError;
+ }
+
+ SInt64 lastPacketIndex = inStartingPacket + *ioNumPackets - 1;
+ if (lastPacketIndex >= packetTableSize)
+ lastPacketIndex = packetTableSize - 1;
+
+ AudioStreamPacketDescription lastPacket = (*packetTable)[lastPacketIndex];
+
+ SInt64 readBytes = lastPacket.mStartOffset + lastPacket.mDataByteSize - firstPacket.mStartOffset;
+ if (readBytes <= *ioNumBytes) {
+ *ioNumBytes = (UInt32)readBytes;
+ return noErr;
+ }
+
+ SInt64 lowBound = inStartingPacket;
+ SInt64 highBound = lastPacketIndex + 1;
+ SInt64 okIndex = lowBound;
+ while (highBound >= lowBound) {
+ SInt64 tryBound = (lowBound + highBound) >> 1;
+ if (tryBound > lastPacketIndex)
+ break;
+ AudioStreamPacketDescription tryPacket = (*packetTable)[tryBound];
+
+ SInt64 readBytes = tryPacket.mStartOffset + tryPacket.mDataByteSize - firstPacket.mStartOffset;
+
+ if (readBytes > (SInt64)*ioNumBytes) {
+ highBound = tryBound - 1;
+ } else if (readBytes < (SInt64)*ioNumBytes) {
+ okIndex = tryBound;
+ lowBound = tryBound + 1;
+ } else {
+ okIndex = tryBound;
+ break;
+ }
+ }
+
+ SInt64 numPackets = okIndex - inStartingPacket + 1;
+ if (numPackets > *ioNumPackets) {
+ numPackets = *ioNumPackets;
+ okIndex = inStartingPacket + numPackets - 1;
+ }
+
+ AudioStreamPacketDescription packet = (*packetTable)[okIndex];
+ *ioNumBytes = (UInt32)(packet.mStartOffset + packet.mDataByteSize - firstPacket.mStartOffset);
+ *ioNumPackets = (UInt32)numPackets;
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ReadPacketDataVBR_InTable(
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ CompressedPacketTable* packetTable = GetPacketTable();
+ if (!packetTable)
+ return kAudioFileInvalidFileError;
+
+ OSStatus err = HowManyPacketsCanBeReadIntoBuffer(ioNumBytes, inStartingPacket, ioNumPackets);
+ if (err) return err;
+
+ AudioStreamPacketDescription firstPacket = (*packetTable)[inStartingPacket];
+ SInt64 firstPacketOffset = firstPacket.mStartOffset;
+ UInt32 bytesRead = *ioNumBytes;
+
+ if (outBuffer) {
+ err = ReadBytes (inUseCache, firstPacketOffset, &bytesRead, outBuffer);
+ if (err && err != kAudioFileEndOfFileError) {
+ *ioNumBytes = 0;
+ *ioNumPackets = 0;
+ return err;
+ }
+ *ioNumBytes = bytesRead;
+ }
+
+ // fill out packet descriptions
+ if (outPacketDescriptions) {
+ for (UInt32 i = 0; i < *ioNumPackets; i++) {
+ AudioStreamPacketDescription curPacket = (*packetTable)[i + inStartingPacket];
+ outPacketDescriptions[i] = curPacket;
+ outPacketDescriptions[i].mStartOffset = curPacket.mStartOffset - firstPacketOffset;
+ }
+ }
+
+ return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::WritePackets(
+ Boolean inUseCache,
+ UInt32 inNumBytes,
+ const AudioStreamPacketDescription *inPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ const void *inBuffer)
+{
+ // This only works with CBR. To suppport VBR you must override.
+ OSStatus err = noErr;
+
+ FailWithAction(inStartingPacket > GetNumPackets(), err = kAudioFileInvalidPacketOffsetError, Bail, "write past end");
+ FailWithAction((ioNumPackets == NULL) || (inBuffer == NULL), err = kAudioFileUnspecifiedError, Bail, "invalid parameter");
+
+ {
+ UInt32 byteCount = *ioNumPackets * mDataFormat.mBytesPerPacket;
+ SInt64 startingByte = inStartingPacket * mDataFormat.mBytesPerPacket;
+
+ err = WriteBytes(inUseCache, startingByte, &byteCount, inBuffer);
+ FailIf (err != noErr, Bail, "Write Bytes Failed");
+
+ if (byteCount != (*ioNumPackets * mDataFormat.mBytesPerPacket))
+ *ioNumPackets = byteCount / mDataFormat.mBytesPerPacket;
+ }
+Bail:
+ return (err);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetBitRate( UInt32 *outBitRate)
+{
+
+ if (!outBitRate) return kAudioFileUnspecifiedError;
+
+ UInt32 bytesPerPacket = GetDataFormat().mBytesPerPacket;
+ UInt32 framesPerPacket = GetDataFormat().mFramesPerPacket;
+ Float64 sampleRate = GetDataFormat().mSampleRate;
+ const Float64 bitsPerByte = 8.;
+
+ if (bytesPerPacket && framesPerPacket) {
+ *outBitRate = (UInt32)(bitsPerByte * (Float64)bytesPerPacket * sampleRate / (Float64)framesPerPacket);
+ } else {
+ SInt64 numPackets = GetNumPackets();
+ SInt64 numBytes = GetNumBytes();
+ SInt64 numFrames = 0;
+
+ if (framesPerPacket) {
+ numFrames = numPackets * framesPerPacket;
+ } else {
+ // count frames
+ CompressedPacketTable* packetTable = GetPacketTable();
+ if (packetTable) {
+ if (packetTable->size() != numPackets) {
+ return kAudioFileInvalidFileError;
+ }
+#if !TARGET_OS_WIN32
+ for (ssize_t i = 0; i < numPackets; i++)
+#else
+ for (int i = 0; i < numPackets; i++)
+#endif
+ {
+ numFrames += (*packetTable)[i].mVariableFramesInPacket;
+ }
+ } else {
+ return kAudioFileUnsupportedPropertyError;
+ }
+ }
+
+ if (numFrames == 0 || (sampleRate == 0.)) {
+ *outBitRate = 0;
+ return noErr;
+ }
+ Float64 duration = (Float64)numFrames / sampleRate;
+ *outBitRate = (UInt32)(bitsPerByte * (Float64)numBytes / duration);
+ }
+
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetMagicCookieDataSize(
+ UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ if (outDataSize) *outDataSize = 0;
+ if (isWritable) *isWritable = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetMagicCookieData(
+ UInt32 *ioDataSize,
+ void *ioPropertyData)
+{
+ *ioDataSize = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetMagicCookieData( UInt32 /*inDataSize*/,
+ const void *inPropertyData)
+{
+ return kAudioFileInvalidChunkError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetMarkerListSize(
+ UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ if (outDataSize) *outDataSize = 0;
+ if (isWritable) *isWritable = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetMarkerList(
+ UInt32 *ioDataSize,
+ AudioFileMarkerList* /*ioPropertyData*/)
+{
+ *ioDataSize = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetMarkerList( UInt32 /*inDataSize*/,
+ const AudioFileMarkerList* /*inPropertyData*/)
+{
+ return kAudioFileUnsupportedPropertyError;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetRegionListSize(
+ UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ if (outDataSize) *outDataSize = 0;
+ if (isWritable) *isWritable = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetRegionList(
+ UInt32 *ioDataSize,
+ AudioFileRegionList *ioPropertyData)
+{
+ *ioDataSize = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetRegionList( UInt32 /*inDataSize*/,
+ const AudioFileRegionList* /*inPropertyData*/)
+{
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetChannelLayoutSize(
+ UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ if (outDataSize) *outDataSize = 0;
+ if (isWritable) *isWritable = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetChannelLayout(
+ UInt32 *ioDataSize,
+ AudioChannelLayout* /*ioPropertyData*/)
+{
+ *ioDataSize = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetChannelLayout( UInt32 /*inDataSize*/,
+ const AudioChannelLayout* /*inPropertyData*/)
+{
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetInfoDictionarySize( UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ if (outDataSize) *outDataSize = sizeof(CFDictionaryRef);
+ if (isWritable) *isWritable = 0;
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetInfoDictionary(CACFDictionary *infoDict)
+{
+ Float64 fl;
+ if (GetEstimatedDuration(&fl) == noErr)
+ return AddDurationToInfoDictionary(infoDict, fl);
+
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetInfoDictionary(CACFDictionary *infoDict)
+{
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+OSStatus AudioFileObject::GetEstimatedDuration(Float64* duration)
+{
+ // calculate duration
+ AudioStreamBasicDescription ASBD = GetDataFormat();
+
+ *duration = (ASBD.mFramesPerPacket != 0) ? (GetNumPackets() * ASBD.mFramesPerPacket) / ASBD.mSampleRate : 0.0;
+
+ /*
+ For now, assume that any ASBD that has zero in the frames per packet field has been subclassed for this
+ method. i.e. A CAF file has a frame count in one of it's chunks.
+
+ MP3 has been subclassed because it guesstimates a duration so the entire file does not
+ need to be parsed in order to calculate the total frames.
+ */
+
+ return noErr;
+
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetPropertyInfo (
+ AudioFilePropertyID inPropertyID,
+ UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ OSStatus err = noErr;
+ UInt32 writable = 0;
+
+ switch (inPropertyID)
+ {
+ case kAudioFilePropertyDeferSizeUpdates :
+ if (outDataSize) *outDataSize = sizeof(UInt32);
+ writable = 1;
+ break;
+
+ case kAudioFilePropertyFileFormat:
+ if (outDataSize) *outDataSize = sizeof(UInt32);
+ writable = 0;
+ break;
+
+ case kAudioFilePropertyDataFormat:
+ if (outDataSize) *outDataSize = sizeof(AudioStreamBasicDescription);
+ writable = 1;
+ break;
+
+ case kAudioFilePropertyFormatList:
+ err = GetFormatListInfo(*outDataSize, writable);
+ break;
+
+ case kAudioFilePropertyPacketSizeUpperBound:
+ case kAudioFilePropertyIsOptimized:
+ case kAudioFilePropertyMaximumPacketSize:
+ if (outDataSize) *outDataSize = sizeof(UInt32);
+ writable = 0;
+ break;
+
+ case kAudioFilePropertyAudioDataByteCount:
+ case kAudioFilePropertyAudioDataPacketCount:
+ writable = 1;
+ if (outDataSize) *outDataSize = sizeof(SInt64);
+ break;
+
+ case kAudioFilePropertyDataOffset:
+ writable = 0;
+ if (outDataSize) *outDataSize = sizeof(SInt64);
+ break;
+
+ case kAudioFilePropertyBitRate:
+ writable = 0;
+ if (outDataSize) *outDataSize = sizeof(UInt32);
+ break;
+
+ case kAudioFilePropertyMagicCookieData:
+ err = GetMagicCookieDataSize(outDataSize, &writable);
+ break;
+
+ case kAudioFilePropertyMarkerList :
+ err = GetMarkerListSize(outDataSize, &writable);
+ break;
+
+ case kAudioFilePropertyRegionList :
+ err = GetRegionListSize(outDataSize, &writable);
+ break;
+
+ case kAudioFilePropertyChannelLayout :
+ err = GetChannelLayoutSize(outDataSize, &writable);
+ break;
+
+ case kAudioFilePropertyPacketToFrame :
+ case kAudioFilePropertyFrameToPacket :
+ if (outDataSize) *outDataSize = sizeof(AudioFramePacketTranslation);
+ writable = 0;
+ break;
+
+ case kAudioFilePropertyPacketToByte :
+ case kAudioFilePropertyByteToPacket :
+ if (outDataSize) *outDataSize = sizeof(AudioBytePacketTranslation);
+ writable = 0;
+ break;
+
+ case kAudioFilePropertyInfoDictionary :
+ err = GetInfoDictionarySize(outDataSize, &writable);
+ break;
+
+ case kTEMPAudioFilePropertySoundCheckDictionary :
+ err = GetSoundCheckDictionarySize(outDataSize, &writable);
+ break;
+
+ case kTEMPAudioFilePropertyGenerateLoudnessInfo :
+ err = GetLoudnessInfoSize(outDataSize, &writable);
+ writable = 0;
+ break;
+
+ case kTEMPAudioFilePropertyLoudnessInfo :
+ err = GetLoudnessInfoSize(outDataSize, &writable);
+ break;
+
+ case kAudioFilePropertyEstimatedDuration :
+ if (outDataSize) *outDataSize = sizeof(Float64);
+ writable = 0;
+ break;
+
+ case 'LYRC':
+ if (outDataSize) *outDataSize = sizeof(CFStringRef);
+ if (isWritable) *isWritable = 0;
+ break;
+
+ case 'eof?':
+ if (outDataSize) *outDataSize = sizeof(UInt32);
+ if (isWritable) *isWritable = 0;
+ break;
+
+ case 'sbtd' /*kAudioFilePropertySourceBitDepth*/ :
+ if (outDataSize) *outDataSize = sizeof(SInt32);
+ if (isWritable) *isWritable = CanWrite();
+ break;
+
+ default:
+ writable = 0;
+ err = kAudioFileUnsupportedPropertyError;
+ break;
+ }
+
+ if (isWritable)
+ *isWritable = writable;
+ return (err);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetProperty(
+ AudioFilePropertyID inPropertyID,
+ UInt32 *ioDataSize,
+ void *ioPropertyData)
+{
+ OSStatus err = noErr;
+ UInt32 neededSize;
+ UInt32 writable;
+
+ switch (inPropertyID)
+ {
+ case kAudioFilePropertyFileFormat:
+ FailWithAction(*ioDataSize != sizeof(UInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ *(UInt32 *) ioPropertyData = GetFileType();
+ break;
+
+ case kAudioFilePropertyFormatList:
+ err = GetFormatList(*ioDataSize, (AudioFormatListItem*)ioPropertyData);
+ break;
+
+ case kAudioFilePropertyDataFormat:
+ FailWithAction(*ioDataSize != sizeof(AudioStreamBasicDescription),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ memcpy(ioPropertyData, &mDataFormat, sizeof(AudioStreamBasicDescription));
+ break;
+ case kAudioFilePropertyDataOffset:
+ FailWithAction(*ioDataSize != sizeof(SInt64),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ *(SInt64 *) ioPropertyData = mDataOffset;
+ break;
+ case kAudioFilePropertyIsOptimized:
+ FailWithAction(*ioDataSize != sizeof(UInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ *(UInt32 *) ioPropertyData = mIsOptimized;
+ break;
+
+ case kAudioFilePropertyAudioDataByteCount:
+ FailWithAction(*ioDataSize != sizeof(SInt64),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ *(SInt64 *)ioPropertyData = GetNumBytes();
+ break;
+
+ case kAudioFilePropertyAudioDataPacketCount:
+ FailWithAction(*ioDataSize != sizeof(SInt64),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ *(SInt64 *)ioPropertyData = GetNumPackets();
+ break;
+
+ case kAudioFilePropertyPacketSizeUpperBound:
+ FailWithAction(*ioDataSize != sizeof(UInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ *(UInt32 *)ioPropertyData = GetPacketSizeUpperBound();
+ break;
+
+ case kAudioFilePropertyMaximumPacketSize:
+ FailWithAction(*ioDataSize != sizeof(UInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ *(UInt32 *)ioPropertyData = FindMaximumPacketSize();
+ break;
+
+
+ case kAudioFilePropertyBitRate:
+ FailWithAction(*ioDataSize != sizeof(UInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ err = GetBitRate((UInt32*)ioPropertyData);
+ break;
+
+ case kAudioFilePropertyMagicCookieData:
+
+ err = GetMagicCookieData(ioDataSize, ioPropertyData);
+ break;
+
+ case kAudioFilePropertyMarkerList :
+ err = GetMarkerList(ioDataSize, static_cast<AudioFileMarkerList*>(ioPropertyData));
+ break;
+
+ case kAudioFilePropertyRegionList :
+ memset(ioPropertyData, 0, *ioDataSize);
+ err = GetRegionList(ioDataSize, static_cast<AudioFileRegionList*>(ioPropertyData));
+ break;
+
+ case kAudioFilePropertyChannelLayout :
+ err = GetChannelLayoutSize(&neededSize, &writable);
+ FailIf(err, Bail, "GetChannelLayoutSize failed");
+ FailWithAction(*ioDataSize != neededSize, err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ err = GetChannelLayout(ioDataSize, static_cast<AudioChannelLayout*>(ioPropertyData));
+ break;
+
+ case kAudioFilePropertyDeferSizeUpdates :
+ FailWithAction(*ioDataSize != sizeof(UInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ *(UInt32 *) ioPropertyData = DeferSizeUpdates();
+ break;
+
+ case kAudioFilePropertyPacketToFrame :
+ {
+ FailWithAction(*ioDataSize != sizeof(AudioFramePacketTranslation),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ AudioFramePacketTranslation* afpt = (AudioFramePacketTranslation*)ioPropertyData;
+ err = PacketToFrame(afpt->mPacket, afpt->mFrame);
+ break;
+ }
+ case kAudioFilePropertyFrameToPacket :
+ {
+ FailWithAction(*ioDataSize != sizeof(AudioFramePacketTranslation),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ AudioFramePacketTranslation* afpt = (AudioFramePacketTranslation*)ioPropertyData;
+ err = FrameToPacket(afpt->mFrame, afpt->mPacket, afpt->mFrameOffsetInPacket);
+ break;
+ }
+
+ case kAudioFilePropertyPacketToByte :
+ {
+ FailWithAction(*ioDataSize != sizeof(AudioBytePacketTranslation),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ AudioBytePacketTranslation* abpt = (AudioBytePacketTranslation*)ioPropertyData;
+ err = PacketToByte(abpt);
+ break;
+ }
+ case kAudioFilePropertyByteToPacket :
+ {
+ FailWithAction(*ioDataSize != sizeof(AudioBytePacketTranslation),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ AudioBytePacketTranslation* abpt = (AudioBytePacketTranslation*)ioPropertyData;
+ err = ByteToPacket(abpt);
+ break;
+ }
+
+ case kAudioFilePropertyInfoDictionary :
+ {
+ FailWithAction(*ioDataSize != sizeof(CFDictionaryRef),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ CACFDictionary afInfoDictionary(true);
+
+ err = GetInfoDictionary(&afInfoDictionary);
+
+ if (!err)
+ {
+ *(CFMutableDictionaryRef *)ioPropertyData = afInfoDictionary.CopyCFMutableDictionary();
+ }
+ break;
+ }
+
+ case kTEMPAudioFilePropertySoundCheckDictionary :
+ {
+ FailWithAction(*ioDataSize != sizeof(CFDictionaryRef),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ CACFDictionary afInfoDictionary(true);
+
+ err = GetSoundCheckDictionary(&afInfoDictionary);
+ if (err) {
+ OSStatus err2 = GetSoundCheckDictionaryFromLoudnessInfo(&afInfoDictionary);
+ if (err2 == noErr) err = noErr; // else report original error from GetSoundCheckDictionary.
+ }
+
+ if (!err)
+ {
+ *(CFMutableDictionaryRef *)ioPropertyData = afInfoDictionary.CopyCFMutableDictionary();
+ }
+ break;
+ }
+
+ case kTEMPAudioFilePropertyLoudnessInfo :
+ {
+ FailWithAction(*ioDataSize != sizeof(CFDictionaryRef),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ CACFDictionary afInfoDictionary(true);
+
+ err = GetLoudnessInfo(&afInfoDictionary);
+ if (err) {
+ OSStatus err2 = GetLoudnessInfoFromSoundCheckDictionary(&afInfoDictionary);
+ if (err2 == noErr) err = noErr; // else report original error from GetLoudnessInfo.
+ }
+
+ if (!err)
+ {
+ *(CFMutableDictionaryRef *)ioPropertyData = afInfoDictionary.CopyCFMutableDictionary();
+ }
+ break;
+ }
+
+ case kTEMPAudioFilePropertyGenerateLoudnessInfo :
+ {
+ FailWithAction(*ioDataSize != sizeof(CFDictionaryRef),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ CACFDictionary afInfoDictionary(true);
+
+ err = GenerateLoudnessInfo(&afInfoDictionary);
+
+ if (!err)
+ {
+ *(CFMutableDictionaryRef *)ioPropertyData = afInfoDictionary.CopyCFMutableDictionary();
+ }
+ break;
+ }
+
+ case kAudioFilePropertyEstimatedDuration :
+ {
+ FailWithAction(*ioDataSize != sizeof(Float64),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ err = GetEstimatedDuration((Float64*)ioPropertyData);
+ break;
+ }
+
+ case 'LYRC' :
+ if (*ioDataSize < sizeof(CFStringRef))
+ return kAudioFileBadPropertySizeError;
+
+ *ioDataSize = sizeof(CFStringRef);
+ err = GetLyrics((CFStringRef*) ioPropertyData);
+ break;
+
+ case 'eof?' :
+ {
+ if (*ioDataSize != sizeof(UInt32))
+ return kAudioFileBadPropertySizeError;
+
+ SInt64 pos;
+ err = GetDataSource()->GetPos(pos);
+ if (err) break;
+
+ SInt64 endOfData = GetDataOffset() + GetNumBytes();
+ *(UInt32*)ioPropertyData = pos >= endOfData;
+
+ break;
+ }
+ case 'sbtd' /*kAudioFilePropertySourceBitDepth*/ :
+ {
+ if (*ioDataSize != sizeof(SInt32))
+ return kAudioFileBadPropertySizeError;
+
+ SInt32 outValue = 0;
+ err = GetSourceBitDepth(outValue);
+ if ((err || outValue == 0) && GetDataFormat().mFormatID == kAudioFormatLinearPCM) {
+ // if there was no stored source bit depth, and this file is LPCM, then report this file's bit depth.
+ err = noErr;
+ outValue = GetDataFormat().mBitsPerChannel;
+ if (GetDataFormat().mFormatFlags & kAudioFormatFlagIsFloat)
+ outValue = -outValue;
+ } else if (err)
+ break;
+
+ *(SInt32 *) ioPropertyData = outValue;
+
+ break;
+ }
+ default:
+ err = kAudioFileUnsupportedPropertyError;
+ break;
+ }
+
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetProperty(
+ AudioFilePropertyID inPropertyID,
+ UInt32 inDataSize,
+ const void *inPropertyData)
+{
+ OSStatus err = noErr;
+
+ switch (inPropertyID)
+ {
+ case kAudioFilePropertyDataFormat:
+ FailWithAction(inDataSize != sizeof(AudioStreamBasicDescription),
+ err = kAudioFileBadPropertySizeError, Bail, "Incorrect data size");
+ err = UpdateDataFormat((AudioStreamBasicDescription *) inPropertyData);
+ break;
+ case kAudioFilePropertyFormatList:
+ err = SetFormatList(inDataSize, (AudioFormatListItem*)inPropertyData);
+ break;
+
+ case kAudioFilePropertyAudioDataByteCount: {
+ FailWithAction(inDataSize != sizeof(SInt64), err = kAudioFileBadPropertySizeError, Bail, "Incorrect data size");
+ SInt64 numBytes = *(SInt64 *) inPropertyData;
+ if (numBytes > GetNumBytes()) {
+ // can't use this to increase data size.
+ return kAudioFileOperationNotSupportedError;
+ }
+ UInt32 saveDefer = DeferSizeUpdates();
+ SetDeferSizeUpdates(0); // force an update.
+ err = UpdateNumBytes(numBytes);
+ SetDeferSizeUpdates(saveDefer);
+ } break;
+
+ case kAudioFilePropertyAudioDataPacketCount: {
+ SInt64 numPackets = *(SInt64 *) inPropertyData;
+ if (numPackets > GetNumPackets()) {
+ // can't use this to increase data size.
+ return kAudioFileOperationNotSupportedError;
+ }
+ err = UpdateNumPackets(numPackets);
+ } break;
+
+ case kAudioFilePropertyMagicCookieData:
+ err = SetMagicCookieData(inDataSize, inPropertyData);
+ break;
+
+
+ case kAudioFilePropertyMarkerList :
+ err = SetMarkerList(inDataSize, static_cast<const AudioFileMarkerList*>(inPropertyData));
+ break;
+
+ case kAudioFilePropertyRegionList :
+ err = SetRegionList(inDataSize, static_cast<const AudioFileRegionList*>(inPropertyData));
+ break;
+
+ case kAudioFilePropertyChannelLayout :
+ err = SetChannelLayout(inDataSize, static_cast<const AudioChannelLayout*>(inPropertyData));
+ break;
+
+ case kAudioFilePropertyDeferSizeUpdates :
+ FailWithAction(inDataSize != sizeof(UInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ SetDeferSizeUpdates(*(UInt32 *) inPropertyData);
+ break;
+
+ case kAudioFilePropertyInfoDictionary :
+ {
+ FailWithAction(inDataSize != sizeof(CFDictionaryRef),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ // pass the SetInfoDictionary a CACFDictionary object made with the provided CFDictionaryRef
+ // Let the caller release their own CFObject so pass false for th erelease parameter
+ CACFDictionary afInfoDictionary(*(CFDictionaryRef *)inPropertyData, false);
+ err = SetInfoDictionary(&afInfoDictionary);
+
+ break;
+ }
+
+ case kTEMPAudioFilePropertySoundCheckDictionary :
+ {
+ FailWithAction(inDataSize != sizeof(CFDictionaryRef),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ // pass the SetInfoDictionary a CACFDictionary object made with the provided CFDictionaryRef
+ // Let the caller release their own CFObject so pass false for the release parameter
+ CACFDictionary afInfoDictionary(*(CFDictionaryRef *)inPropertyData, false);
+ err = SetSoundCheckDictionary(&afInfoDictionary);
+
+ break;
+ }
+
+ case kTEMPAudioFilePropertyLoudnessInfo :
+ {
+ FailWithAction(inDataSize != sizeof(CFDictionaryRef),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ // pass the SetInfoDictionary a CACFDictionary object made with the provided CFDictionaryRef
+ // Let the caller release their own CFObject so pass false for the release parameter
+ CACFDictionary afInfoDictionary(*(CFDictionaryRef *)inPropertyData, false);
+ err = SetLoudnessInfo(&afInfoDictionary);
+
+ break;
+ }
+
+ case 'sbtd' /*kAudioFilePropertySourceBitDepth*/ :
+ {
+ FailWithAction(inDataSize != sizeof(SInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ SInt32 inValue = *(SInt32 *)inPropertyData;
+ err = SetSourceBitDepth(inValue);
+
+ break;
+ }
+
+ default:
+ err = kAudioFileUnsupportedPropertyError;
+ break;
+ }
+
+Bail:
+ return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetDataFormat(const AudioStreamBasicDescription* inStreamFormat)
+{
+ OSStatus err = noErr;
+
+ if (!IsDataFormatValid(inStreamFormat))
+ return kAudioFileUnsupportedDataFormatError;
+
+ if (!IsDataFormatSupported(inStreamFormat))
+ return kAudioFileUnsupportedDataFormatError;
+
+ UInt32 prevBytesPerPacket = mDataFormat.mBytesPerPacket;
+
+ mDataFormat = *inStreamFormat;
+
+ // if CBR and bytes per packet changes, we need to change the number of packets we think we have.
+ if (mDataFormat.mBytesPerPacket && mDataFormat.mBytesPerPacket != prevBytesPerPacket)
+ {
+ SInt64 numPackets = GetNumBytes() / mDataFormat.mBytesPerPacket;
+ SetNumPackets(numPackets);
+ SetMaximumPacketSize(mDataFormat.mBytesPerPacket);
+
+ if (!mFirstSetFormat)
+ SizeChanged();
+ }
+
+ mFirstSetFormat = false;
+
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetFormatListInfo( UInt32 &outDataSize,
+ UInt32 &outWritable)
+{
+ // default implementation is to just return the data format
+ outDataSize = sizeof(AudioFormatListItem);
+ outWritable = false;
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetFormatList( UInt32 &ioDataSize,
+ AudioFormatListItem *ioPropertyData)
+{
+ // default implementation is to just return the data format
+ if (ioDataSize < sizeof(AudioFormatListItem))
+ return kAudioFileBadPropertySizeError;
+
+ AudioFormatListItem afli;
+ afli.mASBD = mDataFormat;
+ AudioChannelLayoutTag layoutTag = /*kAudioChannelLayoutTag_Unknown*/ 0xFFFF0000 | mDataFormat.mChannelsPerFrame;
+ UInt32 layoutSize, isWritable;
+ OSStatus err = GetChannelLayoutSize(&layoutSize, &isWritable);
+ if (err == noErr)
+ {
+ CAAutoFree<AudioChannelLayout> layout;
+ layout.allocBytes(layoutSize);
+ err = GetChannelLayout(&layoutSize, layout());
+ if (err == noErr) {
+ layoutTag = layout->mChannelLayoutTag;
+ }
+ }
+ afli.mChannelLayoutTag = layoutTag;
+
+ memcpy(ioPropertyData, &afli, sizeof(AudioFormatListItem));
+
+ ioDataSize = sizeof(AudioFormatListItem);
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetFormatList( UInt32 inDataSize,
+ const AudioFormatListItem *inPropertyData)
+{
+ return kAudioFileOperationNotSupportedError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::UpdateDataFormat(const AudioStreamBasicDescription* inStreamFormat)
+{
+ return SetDataFormat(inStreamFormat);
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Boolean AudioFileObject::IsDataFormatValid(AudioStreamBasicDescription const* inDesc)
+{
+ if (inDesc->mSampleRate < 0.)
+ return false;
+
+ if (inDesc->mSampleRate > 3e6)
+ return false;
+
+ if (inDesc->mChannelsPerFrame < 1 || inDesc->mChannelsPerFrame > 0x000FFFFF)
+ return false;
+
+ if (inDesc->mFormatID == kAudioFormatLinearPCM)
+ {
+ if (inDesc->mBitsPerChannel < 1 || inDesc->mBitsPerChannel > 64)
+ return false;
+
+ if (inDesc->mFramesPerPacket != 1)
+ return false;
+
+ if (inDesc->mBytesPerPacket == 0)
+ return false;
+
+ if (inDesc->mBytesPerFrame != inDesc->mBytesPerPacket)
+ return false;
+
+ // [3605260] we assume here that a packet is an integer number of frames.
+ UInt32 minimumBytesPerPacket = (inDesc->mBitsPerChannel * inDesc->mChannelsPerFrame + 7) / 8;
+ if (inDesc->mBytesPerPacket < minimumBytesPerPacket)
+ return false;
+ }
+ return true;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void AudioFileObject::SetDataSource(DataSource* inDataSource)
+{
+ if (mDataSource != inDataSource) {
+ delete mDataSource;
+ mDataSource = inDataSource;
+ }
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void AudioFileObject::SetURL (CFURLRef inURL)
+{
+ if (mFileRef == inURL) return;
+ if (inURL) CFRetain (inURL);
+ if (mFileRef) CFRelease(mFileRef);
+ mFileRef = inURL;
+}
+
+OSStatus AudioFileObject::OpenFile(SInt8 inPermissions, int inFD)
+{
+ OSStatus err = noErr;
+
+ SetDataSource(new Cached_DataSource(new UnixFile_DataSource(inFD, inPermissions, true)));
+
+ mFileD = inFD;
+ SetPermissions (inPermissions);
+
+ return err;
+}
+
+OSStatus AudioFileObject::CreateDataFile (CFURLRef inFileRef, int &outFileD)
+{
+ UInt8 fPath[FILENAME_MAX];
+ if (!CFURLGetFileSystemRepresentation (inFileRef, true, fPath, FILENAME_MAX))
+ return kAudio_FileNotFoundError;
+
+ struct stat stbuf;
+ if (stat ((const char*)fPath, &stbuf) == 0)
+ return kAudioFilePermissionsError;
+
+#if TARGET_OS_WIN32
+ int filePerms = S_IREAD | S_IWRITE;
+ int flags = O_CREAT | O_EXCL | O_RDWR | O_BINARY;
+#else
+ mode_t filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+ int flags = O_CREAT | O_EXCL | O_RDWR;
+#endif
+ outFileD = open((const char*)fPath, flags, filePerms);
+ if (outFileD < 0)
+ return AudioFileTranslateErrno(errno);
+
+ return noErr;
+}
+
+OSStatus AudioFileObject::AddDurationToInfoDictionary(CACFDictionary *infoDict, Float64 &inDuration)
+{
+#if !TARGET_OS_WIN32
+ CFLocaleRef currentLocale = CFLocaleGetSystem();
+ CFNumberFormatterRef numberFormatter = NULL;
+ numberFormatter = CFNumberFormatterCreate(kCFAllocatorDefault, currentLocale, kCFNumberFormatterDecimalStyle);
+ CFStringRef cfStr = CFNumberFormatterCreateStringWithValue( kCFAllocatorDefault, numberFormatter, kCFNumberFloat64Type, &inDuration);
+ if (cfStr)
+ {
+ if (CFStringGetLength(cfStr) != 0)
+ infoDict->AddString(CFSTR(kAFInfoDictionary_ApproximateDurationInSeconds), cfStr);
+ CFRelease(cfStr);
+ }
+ CFRelease(numberFormatter);
+#endif
+ return noErr;
+}
+
+OSStatus AudioFileObject::SizeChanged()
+{
+ OSStatus err = noErr;
+ if (mPermissions & kAudioFileWritePermission)
+ {
+ if (DeferSizeUpdates())
+ SetNeedsSizeUpdate(true);
+ else
+ err = UpdateSize();
+ }
+ return err;
+}
+
+OSStatus AudioFileObject::UpdateSizeIfNeeded()
+{
+ if (GetNeedsSizeUpdate())
+ {
+ OSStatus err = UpdateSize();
+ if (err) return err;
+ SetNeedsSizeUpdate(false);
+ }
+ return noErr;
+}
+
+OSStatus AudioFileObject::CountUserData( UInt32 /*inUserDataID*/,
+ UInt32* /*outNumberItems*/)
+{
+ return kAudioFileOperationNotSupportedError;
+}
+
+OSStatus AudioFileObject::GetUserDataSize( UInt32 /*inUserDataID*/,
+ UInt32 /*inIndex*/,
+ UInt32* /*outDataSize*/)
+{
+ return kAudioFileOperationNotSupportedError;
+}
+
+OSStatus AudioFileObject::GetUserData( UInt32 /*inUserDataID*/,
+ UInt32 /*inIndex*/,
+ UInt32* /*ioDataSize*/,
+ void* /*ioUserData*/)
+{
+ return kAudioFileOperationNotSupportedError;
+}
+
+OSStatus AudioFileObject::SetUserData( UInt32 /*inUserDataID*/,
+ UInt32 /*inIndex*/,
+ UInt32 /*inDataSize*/,
+ const void* /*inUserData*/)
+{
+ return kAudioFileOperationNotSupportedError;
+}
+
+OSStatus AudioFileObject::RemoveUserData( UInt32 /*inUserDataID*/,
+ UInt32 /*inIndex*/)
+{
+ return kAudioFileOperationNotSupportedError;
+}
+
+OSStatus AudioFileObject::MoveData(SInt64 fromPos, SInt64 toPos, SInt64 size)
+{
+ if (fromPos == toPos)
+ return noErr;
+
+ OSStatus err = noErr;
+ CAAutoFree<char> audioData(kCopySoundDataBufferSize, true);
+
+ SInt64 bytesRemaining = size;
+ if (fromPos < toPos) {
+ while (bytesRemaining > 0)
+ {
+ // read from old file
+ UInt32 byteCount;
+ SInt64 count = (bytesRemaining < kCopySoundDataBufferSize) ? bytesRemaining : kCopySoundDataBufferSize;
+ err = GetDataSource()->ReadBytes(SEEK_SET, fromPos+(bytesRemaining-count), (UInt32)count, audioData(), &byteCount);
+ FailIf (err != noErr, Bail, "MoveData ReadBytes failed");
+
+ err = GetDataSource()->WriteBytes(SEEK_SET, toPos+(bytesRemaining-count), (UInt32)count, audioData(), &byteCount);
+ FailIf (err != noErr, Bail, "WriteBytes failed");
+
+ bytesRemaining -= count;
+ }
+ } else {
+ while (bytesRemaining > 0)
+ {
+ // read from old file
+ UInt32 byteCount;
+ SInt64 count = (bytesRemaining < kCopySoundDataBufferSize) ? bytesRemaining : kCopySoundDataBufferSize;
+ err = GetDataSource()->ReadBytes(SEEK_SET, fromPos+(size - bytesRemaining), (UInt32)count, audioData(), &byteCount);
+ FailIf (err != noErr, Bail, "MoveData ReadBytes failed");
+
+ err = GetDataSource()->WriteBytes(SEEK_SET, toPos+(size - bytesRemaining), (UInt32)count, audioData(), &byteCount);
+ FailIf (err != noErr, Bail, "WriteBytes failed");
+
+ bytesRemaining -= count;
+ }
+ }
+
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.h b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.h
new file mode 100644
index 0000000000..6d7c868976
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.h
@@ -0,0 +1,667 @@
+/*
+ File: AudioFileObject.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef _AudioFileObject_H_
+#define _AudioFileObject_H_
+
+#include <TargetConditionals.h>
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <AudioToolbox/AudioFile.h>
+ #include <AudioToolbox/AudioFormat.h>
+#else
+ #include "CoreAudioTypes.h"
+ #include "AudioFile.h"
+ #include "AudioFormat.h"
+#endif
+
+#include "CompressedPacketTable.h"
+#include "CACFDictionary.h"
+#include "DataSource.h"
+#include <vector>
+#include <fcntl.h>
+
+#if TARGET_OS_WIN32
+#include <io.h>
+#endif
+
+/*
+ These are structs defined in 10.5. They are included here for compatibility with sources
+*/
+#if COREAUDIOTYPES_VERSION < 1050
+
+struct AudioFormatListItem
+{
+ AudioStreamBasicDescription mASBD;
+ AudioChannelLayoutTag mChannelLayoutTag;
+};
+typedef struct AudioFormatListItem AudioFormatListItem;
+
+struct AudioFormatInfo
+{
+ AudioStreamBasicDescription mASBD;
+ const void* mMagicCookie;
+ UInt32 mMagicCookieSize;
+};
+typedef struct AudioFormatInfo AudioFormatInfo;
+
+enum {
+
+ kAudioFormatProperty_FormatList = 'flst',
+ // Returns a list of AudioFormatListItem structs describing the audio formats contained within the compressed bit stream
+ // as described by the magic cookie.
+ // The specifier is an AudioFormatInfo struct. At a minimum formatID member of the ASBD struct must filled in. Other fields
+ // may be filled in.
+
+ kAudioFormatProperty_OutputFormatList = 'ofls',
+ // Returns a list of AudioFormatListItem structs describing the audio formats which may be obtained by decoding the format
+ // described by the specifier.
+ // The specifier is an AudioFormatInfo struct. At a minimum formatID member of the ASBD struct must filled in. Other fields
+ // may be filled in. If there is no magic cookie, then the number of channels and sample rate should be filled in.
+
+};
+
+enum {
+ kAudioFilePropertyPacketSizeUpperBound = 'pkub',
+ kAudioFilePropertyFormatList = 'flst',
+ kAudioFilePropertyEstimatedDuration = 'edur',
+ kAudioFilePropertyBitRate = 'brat'
+};
+
+enum {
+ kAudioFileCreateURLSelect = 0x0019,
+ kAudioFileOpenURLSelect = 0x001A,
+ kAudioFileFileDataIsThisFormatSelect = 0x001B
+};
+#endif
+
+enum {
+ kTEMPAudioFilePropertySoundCheckDictionary = 'scdc',
+ kTEMPAudioFilePropertyLoudnessInfo = 'loud',
+ kTEMPAudioFilePropertyGenerateLoudnessInfo = 'glou'
+};
+
+const UInt32 kCopySoundDataBufferSize = 1024 * 1024;
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+// some files encode these as upper case
+enum {
+ kUpperCase_IMACompression = 'IMA4', /*IMA 4:1*/
+ kUpperCase_ULawCompression = 'ULAW', /*µLaw 2:1*/
+ kUpperCase_ALawCompression = 'ALAW', /*aLaw 2:1*/
+
+ kUpperCase_Float32 = 'FL32',
+ kUpperCase_Float64 = 'FL64'
+};
+
+enum
+{
+ // in what header is this defined? what is it?
+ kGSM = 'agsm',
+ kUpperCase_GSM = 'GSM '
+};
+
+#define kPackedBESInt (kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsPacked)
+#define kPackedLESInt (kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked)
+#define kPackedBEFloat (kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsPacked)
+#define kPackedLEFloat (kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsPacked)
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+inline int TransformPerm_FS_O (SInt8 inPerm)
+{
+ switch (inPerm) {
+ case kAudioFileReadPermission: return O_RDONLY;
+ case kAudioFileWritePermission: return O_WRONLY;
+ case kAudioFileReadWritePermission: return O_RDWR;
+ }
+ return O_RDONLY;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#pragma mark "File Error Handling"
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+#include <errno.h>
+#include <CoreAudio/CoreAudioTypes.h>
+
+inline OSErr AudioFileTranslateErrno(int err)
+{
+ switch (err) {
+#if !TARGET_OS_WIN32
+ case ENFILE:
+#endif
+ case EMFILE:
+ return -42 /* kAudio_TooManyFilesOpenError */;
+#if !TARGET_OS_WIN32
+ case EPERM:
+ case EROFS:
+#endif
+ case EACCES:
+ case EEXIST:
+ return -54 /* kAudio_FilePermissionError */;
+#if !TARGET_OS_WIN32
+ case EMLINK:
+ return (OSErr)'!pth' /* kAudio_BadFilePathError */;
+ case ENOTDIR:
+ case ELOOP:
+#endif
+ case ENOENT:
+ default:
+ return (OSErr)kAudioFileUnspecifiedError;
+ }
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class AudioFileObject
+{
+protected:
+
+private:
+ SInt64 mNumBytes; // total bytes of audio data in the audio file
+ SInt64 mNumPackets; // total frames of audio data in the audio file
+ AudioStreamBasicDescription mDataFormat; // format of the audio data
+ SInt64 mDataOffset; // position if the file where audio data begins
+ UInt32 mIsOptimized; // 1 if there is nothing in the file following the audio data, 0 if there is
+ UInt32 mFileType; // file type of the audio file (i.e. AIFF, WAVE, etc.)
+ CFURLRef mFileRef; // URL of the file passed to AudioFileOpen or AudioFileCreate
+ int mFileD; // Ref num of the file after opening within Audio File
+ SInt8 mPermissions; // file permissions indicated by the caller, passed by AudioFileOpen or set with SetProperty function
+ Boolean mIsInitialized; // has the AudioFileObject for this file been intialized?
+ DataSource *mDataSource;
+ UInt32 mMaximumPacketSize;
+ CompressedPacketTable *mPacketTable;
+ UInt32 mDeferSizeUpdates;
+ Boolean mNeedsSizeUpdate;
+ Boolean mFirstSetFormat;
+ Boolean mAlignDataWithFillerChunks;
+
+public:
+
+ AudioFileObject (UInt32 inFileType)
+ : mNumBytes(0),
+ mNumPackets(0),
+ mDataOffset(0),
+ mIsOptimized(1),
+ mFileType(inFileType),
+ mFileRef(NULL),
+ mFileD(-1),
+ mPermissions(0),
+ mIsInitialized (false),
+ mDataSource(0),
+ mMaximumPacketSize(0),
+ mPacketTable(NULL),
+ mDeferSizeUpdates(1),
+ mNeedsSizeUpdate(false),
+ mFirstSetFormat(true),
+ mAlignDataWithFillerChunks(true)
+ {
+ memset(&mDataFormat, 0, sizeof(mDataFormat));
+ }
+
+ virtual ~AudioFileObject();
+
+
+/* Public API Function Implementation */
+ // The DoSomething() versions of these functions are wrappers that perform a standard prologue.
+ // The Something() methods are those which should be overridden in the subclasses.
+
+ OSStatus DoCreate( CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags);
+
+ virtual OSStatus Create( CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat);
+
+ OSStatus DoOpen( CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFD);
+
+ virtual OSStatus Open( CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFD);
+
+ OSStatus DoOpenWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc);
+
+
+ OSStatus DoInitialize( CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags);
+
+ virtual OSStatus Initialize( CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags);
+
+ OSStatus DoInitializeWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc,
+ UInt32 inFileType,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags);
+
+ virtual OSStatus OpenFromDataSource(void);
+
+ virtual OSStatus InitializeDataSource(const AudioStreamBasicDescription *inFormat, UInt32 inFlags);
+
+ OSStatus DoClose();
+
+ virtual OSStatus Close();
+
+ OSStatus DoOptimize();
+
+ virtual OSStatus Optimize();
+
+ virtual OSStatus ReadBytes( Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ void *outBuffer);
+
+ virtual OSStatus WriteBytes( Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ const void *inBuffer);
+
+ virtual OSStatus ReadPackets( Boolean inUseCache,
+ UInt32 *outNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer);
+
+ virtual OSStatus ReadPacketData(
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer);
+
+ virtual OSStatus ReadPacketDataVBR(
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer);
+
+ virtual OSStatus HowManyPacketsCanBeReadIntoBuffer(UInt32* ioNumBytes, SInt64 inStartingPacket, UInt32 *ioNumPackets);
+
+ virtual OSStatus ReadPacketDataVBR_InTable(
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer);
+
+ virtual OSStatus WritePackets( Boolean inUseCache,
+ UInt32 inNumBytes,
+ const AudioStreamPacketDescription *inPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ const void *inBuffer);
+/* Property Support */
+
+ virtual OSStatus GetPropertyInfo (
+ AudioFilePropertyID inPropertyID,
+ UInt32 *outDataSize,
+ UInt32 *isWritable);
+
+ virtual OSStatus GetProperty ( AudioFilePropertyID inPropertyID,
+ UInt32 *ioDataSize,
+ void *ioPropertyData);
+
+ virtual OSStatus SetProperty ( AudioFilePropertyID inPropertyID,
+ UInt32 inDataSize,
+ const void *inPropertyData);
+
+ UInt32 GetFileType() const { return mFileType; }
+ void SetFileType(UInt32 inFileType) { mFileType = inFileType; }
+
+ // this will set the format in memory only.
+ virtual OSStatus SetDataFormat(const AudioStreamBasicDescription* inStreamFormat);
+
+ // this will update the format info on disk and in memory.
+ virtual OSStatus UpdateDataFormat(const AudioStreamBasicDescription* inStreamFormat);
+
+ const UInt32 GetBytesPerPacket() const { return mDataFormat.mBytesPerPacket; }
+
+ const AudioStreamBasicDescription &GetDataFormat() const { return mDataFormat; }
+
+ virtual OSStatus GetFormatListInfo( UInt32 &outDataSize,
+ UInt32 &outWritable);
+
+ virtual OSStatus GetFormatList( UInt32 &ioDataSize,
+ AudioFormatListItem *ioPropertyData);
+
+ virtual OSStatus SetFormatList( UInt32 inDataSize,
+ const AudioFormatListItem *inPropertyData);
+
+ virtual OSStatus UpdateSize() { return noErr; }
+ UInt32 DeferSizeUpdates() { return mDeferSizeUpdates; }
+ void SetDeferSizeUpdates(UInt32 inFlag) { mDeferSizeUpdates = inFlag; }
+ OSStatus UpdateSizeIfNeeded();
+ OSStatus SizeChanged();
+
+ Boolean IsOptimized() const { return mIsOptimized != 0; }
+ void SetIsOptimized(Boolean inIsOptimized) { mIsOptimized = inIsOptimized ? 1 : 0; }
+
+ Boolean AlignDataWithFillerChunks() const { return mAlignDataWithFillerChunks; }
+
+ virtual SInt64 GetNumBytes() { return mNumBytes; }
+ virtual void SetNumBytes(SInt64 inNumBytes) { mNumBytes = inNumBytes; }
+
+ // this will update the header size info on disk
+ OSStatus UpdateNumBytes(SInt64 inNumBytes);
+
+ virtual SInt64 GetNumPackets(){ return mNumPackets; }
+ virtual void SetNumPackets(SInt64 inNumPackets) { mNumPackets = inNumPackets; }
+
+ // this will update the header size info on disk
+ OSStatus UpdateNumPackets(SInt64 inNumPackets);
+
+ virtual OSStatus PacketToFrame(SInt64 inPacket, SInt64& outFirstFrameInPacket);
+ virtual OSStatus FrameToPacket(SInt64 inFrame, SInt64& outPacket, UInt32& outFrameOffsetInPacket);
+
+ virtual OSStatus PacketToByte(AudioBytePacketTranslation* abpt);
+
+ virtual OSStatus ByteToPacket(AudioBytePacketTranslation* abpt);
+
+ virtual OSStatus GetBitRate( UInt32 *outBitRate);
+
+ virtual OSStatus GetMagicCookieDataSize( UInt32 *outDataSize,
+ UInt32 *isWritable);
+
+ virtual OSStatus GetMagicCookieData( UInt32 *ioDataSize,
+ void *ioPropertyData);
+
+ virtual OSStatus SetMagicCookieData( UInt32 inDataSize,
+ const void *inPropertyData);
+
+ virtual OSStatus GetMarkerListSize( UInt32 *outDataSize,
+ UInt32 *isWritable);
+
+ virtual OSStatus GetMarkerList( UInt32 *ioDataSize,
+ AudioFileMarkerList *ioMarkerList);
+
+ virtual OSStatus SetMarkerList( UInt32 inDataSize,
+ const AudioFileMarkerList *inMarkerList);
+
+
+ virtual OSStatus GetRegionListSize( UInt32 *outDataSize,
+ UInt32 *isWritable);
+
+ virtual OSStatus GetRegionList( UInt32 *ioDataSize,
+ AudioFileRegionList *ioRegionList);
+
+ virtual OSStatus SetRegionList( UInt32 inDataSize,
+ const AudioFileRegionList *inRegionList);
+
+ virtual OSStatus GetChannelLayoutSize( UInt32 *outDataSize,
+ UInt32 *isWritable);
+
+ virtual OSStatus GetChannelLayout( UInt32 *ioDataSize,
+ AudioChannelLayout *ioChannelLayout);
+
+ virtual OSStatus SetChannelLayout( UInt32 inDataSize,
+ const AudioChannelLayout *inChannelLayout);
+
+
+ virtual OSStatus GetInfoDictionarySize( UInt32 *outDataSize,
+ UInt32 *isWritable);
+
+ virtual OSStatus GetInfoDictionary( CACFDictionary *infoDict);
+
+ virtual OSStatus SetInfoDictionary( CACFDictionary *infoDict);
+
+ virtual OSStatus GetSoundCheckDictionarySize( UInt32 *outDataSize,
+ UInt32 *isWritable) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus GetSoundCheckDictionary( CACFDictionary *infoDict) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus SetSoundCheckDictionary( CACFDictionary *infoDict) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus GetLoudnessInfo( CACFDictionary *infoDict) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus GetSoundCheckDictionaryFromLoudnessInfo(CACFDictionary* outInfoDict) { return kAudioFileUnsupportedPropertyError; }
+ virtual OSStatus GetLoudnessInfoFromSoundCheckDictionary(CACFDictionary* outInfoDict) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus SetLoudnessInfo( CACFDictionary *infoDict) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus GetLoudnessInfoSize( UInt32 *outDataSize,
+ UInt32 *isWritable) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus GenerateLoudnessInfo( CACFDictionary *infoDict) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus GetEstimatedDuration( Float64* duration);
+
+ virtual OSStatus CountUserData( UInt32 inUserDataID,
+ UInt32 *outNumberItems);
+
+ virtual OSStatus GetUserDataSize( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *outDataSize);
+
+ virtual OSStatus GetUserData( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *ioDataSize,
+ void *ioUserData);
+
+ virtual OSStatus SetUserData( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 inDataSize,
+ const void *inUserData);
+
+ virtual OSStatus RemoveUserData( UInt32 inUserDataID,
+ UInt32 inIndex);
+
+ virtual OSStatus GetLyrics(CFStringRef *outLyrics) { return kAudioFileUnsupportedPropertyError; }
+
+
+ Boolean CanRead() const { return mPermissions & kAudioFileReadPermission; }
+ Boolean CanWrite() const { return mPermissions & kAudioFileWritePermission; }
+
+ void SetPermissions(SInt8 inPermissions) { mPermissions = inPermissions; }
+
+/* Other Helper Methods: (some may not be necessary depending on how things are refactored) */
+
+ OSStatus OpenFile(SInt8 inPermissions, int inFD);
+
+ OSStatus CreateDataFile (CFURLRef inFileRef, int &outFileD);
+
+ OSStatus AddDurationToInfoDictionary(CACFDictionary *infoDict, Float64 &inDuration);
+
+ virtual Boolean IsDataFormatSupported(const AudioStreamBasicDescription *inFormat) = 0;
+ virtual Boolean IsDataFormatValid(const AudioStreamBasicDescription *inFormat);
+
+ virtual OSStatus IsValidFilePosition(SInt64 /*position*/) { return noErr; }
+
+ OSStatus MoveData(SInt64 fromPos, SInt64 toPos, SInt64 size);
+
+/* Accessors: */
+ Boolean IsInitialized() const { return mIsInitialized; }
+ void SetInitialized(Boolean inFlag) { mIsInitialized = inFlag; }
+
+ DataSource* GetDataSource() const { return mDataSource; }
+ void SetDataSource(DataSource *inDataSource);
+
+ void SetURL (CFURLRef inURL);
+
+ virtual UInt32 GetMaximumPacketSize() { return mMaximumPacketSize; }
+ virtual UInt32 FindMaximumPacketSize() { return mMaximumPacketSize; }
+ virtual void SetMaximumPacketSize(const UInt32 inPacketSize) { mMaximumPacketSize = inPacketSize; }
+
+ virtual UInt32 GetPacketSizeUpperBound() { return GetMaximumPacketSize (); }
+
+ SInt64 GetDataOffset() const { return mDataOffset; }
+ void SetDataOffset(SInt64 inOffset) { mDataOffset = inOffset; }
+
+ // I like this idiom better than DoesPacketTableExist+NewPacketTable:
+ CompressedPacketTable* GetPacketTable(Boolean inCreateIt = false)
+ {
+ if (!mPacketTable && inCreateIt)
+ mPacketTable = new CompressedPacketTable(mDataFormat.mFramesPerPacket);
+ return mPacketTable;
+ }
+ void ClearPacketTable()
+ {
+ DeletePacketTable();
+ GetPacketTable(true);
+ }
+
+ virtual OSStatus ScanForPackets(SInt64 inToPacketCount, DataSource* inDataSrc = NULL, bool fullyParsedIfEndOfDataReached = true)
+ {
+ // In formats that read packets lazily, this will be overridden to scan for packets up to the index.
+ if (inToPacketCount > GetNumPackets())
+ return kAudioFileEndOfFileError;
+
+ return noErr;
+ }
+
+ void AppendPacket(const AudioStreamPacketDescription &inPacket)
+ {
+ CompressedPacketTable* packetTable = GetPacketTable(true);
+ UInt32 numFramesInPacket = mDataFormat.mFramesPerPacket ? mDataFormat.mFramesPerPacket : inPacket.mVariableFramesInPacket;
+
+ AudioStreamPacketDescriptionExtended pext;
+ memset(&pext, 0, sizeof(pext));
+ pext.mStartOffset = inPacket.mStartOffset;
+ pext.mDataByteSize = inPacket.mDataByteSize;
+ pext.mVariableFramesInPacket = inPacket.mVariableFramesInPacket;
+ pext.mFrameOffset = numFramesInPacket + (packetTable->size() ? packetTable->back().mFrameOffset : 0);
+
+ packetTable->push_back(pext);
+ if (inPacket.mDataByteSize > mMaximumPacketSize)
+ mMaximumPacketSize = inPacket.mDataByteSize;
+ }
+ void DeletePacketTable() { delete mPacketTable; mPacketTable = NULL;}
+ SInt64 GetPacketTableSize() { return mPacketTable ? mPacketTable->size() : 0; }
+ OSStatus GetPacketDescriptions(UInt32 inStartingPacket, UInt32 *ioDataSize, AudioStreamPacketDescription *outPacketDescriptions)
+ {
+ if (outPacketDescriptions == NULL) return kAudioFileUnspecifiedError;
+ if (mPacketTable)
+ {
+ // only get as many packet descriptions as can fit in outPacketDescriptions
+ UInt32 count = *ioDataSize / sizeof(AudioStreamPacketDescription);
+ if (count + inStartingPacket > GetPacketTableSize())
+ count = (UInt32)(GetPacketTableSize() - inStartingPacket);
+
+ *ioDataSize = 0;
+ for (UInt32 i = inStartingPacket; i < (count + inStartingPacket); i++)
+ {
+ AudioStreamPacketDescription curPacket = (*mPacketTable)[i];
+ outPacketDescriptions[i].mStartOffset = curPacket.mStartOffset - GetDataOffset();
+ outPacketDescriptions[i].mVariableFramesInPacket = curPacket.mVariableFramesInPacket;
+ outPacketDescriptions[i].mDataByteSize = curPacket.mDataByteSize;
+ *ioDataSize += sizeof(AudioStreamPacketDescription);
+ }
+ }
+ else
+ *ioDataSize = 0;
+
+ return noErr;
+ }
+
+#if DEBUG
+ void DumpPacketTable()
+ {
+ if (mPacketTable) {
+ SInt64 size = mPacketTable->size();
+ printf("PacketTable size %d\n", (int)size);
+ for (SInt64 i = 0; i < size; i++) {
+ AudioStreamPacketDescription curPacket = (*mPacketTable)[i];
+ printf("dpkt %5qd %8qd %5d %5d\n", i, curPacket.mStartOffset, (int)curPacket.mDataByteSize, (int)curPacket.mVariableFramesInPacket);
+ }
+ }
+ }
+#endif
+
+ Boolean GetNeedsSizeUpdate() const { return mNeedsSizeUpdate; }
+ void SetNeedsSizeUpdate(Boolean inNeedsSizeUpdate) { mNeedsSizeUpdate = inNeedsSizeUpdate; }
+
+ CFURLRef GetURL () const { return mFileRef; }
+
+ virtual OSStatus GetSourceBitDepth(SInt32& outValue) { outValue = 0; return kAudioFileUnsupportedPropertyError; }
+ virtual OSStatus SetSourceBitDepth(SInt32 inValue) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus GetAlbumArtwork(CFDataRef& outValue) { outValue = NULL; return kAudioFileUnsupportedPropertyError; }
+ virtual OSStatus SetAlbumArtwork(CFDataRef inValue){ return kAudioFileUnsupportedPropertyError; }
+
+private:
+
+ void SetAlignDataWithFillerChunks(Boolean inFlag) { mAlignDataWithFillerChunks = inFlag; }
+
+ OSStatus ValidateFormatAndData();
+
+/* debug */
+// virtual void PrintFile (FILE* inFile, const char *indent) = 0;
+};
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+inline Boolean cfstrcmpi(CFStringRef a, CFStringRef b)
+{
+ // case insensitive CFString compare
+ return CFStringCompare(a, b, kCFCompareCaseInsensitive) == kCFCompareEqualTo;
+}
+
+CFBundleRef GetAudioToolboxBundle();
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp
new file mode 100644
index 0000000000..ba07580bba
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp
@@ -0,0 +1,216 @@
+/*
+ File: CompressedPacketTable.cpp
+ Abstract: CompressedPacketTable.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CompressedPacketTable.h"
+#include "CAAutoDisposer.h"
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+const UInt32 CompressedPacketTable::kShift = 5;
+const UInt32 CompressedPacketTable::kMask = 31;
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+CompressedPacketTable::~CompressedPacketTable()
+{
+ size_t size = mBases.size();
+ for (size_t i = 0; i < size; ++i) {
+ free(mBases[i].mDescs);
+ }
+}
+
+void CompressedPacketTable::push_back(const AudioStreamPacketDescriptionExtended& inDesc)
+{
+ SInt64 baseIndex = mSize >> kShift;
+ UInt32 packetIndex = (UInt32)(mSize & kMask);
+
+ if (packetIndex == 0) {
+ // first packet in a new sequence. create a new PacketBase.
+ PacketBase newBase;
+ newBase.mBaseOffset = 0;
+ newBase.mDescs = CA_malloc((kMask+1) * sizeof(AudioStreamPacketDescriptionExtended));
+ newBase.mDescType = kExtendedPacketDescription;
+ mBases.push_back(newBase);
+ }
+
+ PacketBase& base = mBases[(size_t)baseIndex];
+ AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs;
+ descs[packetIndex] = inDesc;
+
+ if (packetIndex == kMask) {
+ // last packet in a sequence. compress the sequence.
+ Compress(base);
+ }
+
+ mSize++;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+#define ACCESS_TYPE(TYPE) \
+ case k##TYPE##ContiguousPacketDescription : { \
+ TYPE##ContiguousPacketDescription* descs = (TYPE##ContiguousPacketDescription*)base.mDescs; \
+ packetOffset = packetIndex ? descs[packetIndex-1].mNextOffset : 0; \
+ packetSize = (UInt32)(descs[packetIndex].mNextOffset - packetOffset); \
+ } break; \
+ case k##TYPE##DiscontiguousPacketDescription : { \
+ TYPE##DiscontiguousPacketDescription* descs = (TYPE##DiscontiguousPacketDescription*)base.mDescs; \
+ packetOffset = packetIndex ? descs[packetIndex-1].mNextOffset : 0; \
+ packetSize = descs[packetIndex].mDataByteSize; \
+ } break;
+
+const AudioStreamPacketDescriptionExtended CompressedPacketTable::operator[](SInt64 inPacketIndex) const
+{
+ SInt64 baseIndex = inPacketIndex >> kShift;
+ UInt32 packetIndex = (UInt32)(inPacketIndex & kMask);
+
+ if ((size_t)baseIndex >= mBases.size())
+ throw -1;
+
+ const PacketBase& base = mBases[(size_t)baseIndex];
+
+ SInt64 packetOffset = 0;
+ UInt32 packetSize = 0;
+
+ switch (base.mDescType)
+ {
+ ACCESS_TYPE(Tiny)
+ ACCESS_TYPE(Small)
+ ACCESS_TYPE(Big)
+ case kExtendedPacketDescription :
+ return ((AudioStreamPacketDescriptionExtended*)base.mDescs)[packetIndex];
+ }
+
+ AudioStreamPacketDescriptionExtended outDesc;
+ outDesc.mStartOffset = base.mBaseOffset + packetOffset;
+ outDesc.mDataByteSize = packetSize;
+ outDesc.mVariableFramesInPacket = 0;
+ outDesc.mFrameOffset = mFramesPerPacket * inPacketIndex;
+
+ //printf("get %d %10qd %10qd %2d %10qd %6d %10qd\n", base.mDescType, inPacketIndex, baseIndex, packetIndex, outDesc.mStartOffset, outDesc.mDataByteSize, outDesc.mFrameOffset);
+
+ return outDesc;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+bool CompressedPacketTable::isContiguous(PacketBase& base)
+{
+ AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs;
+ SInt64 expectedOffset = descs[0].mStartOffset + descs[0].mDataByteSize;
+ for (UInt32 i = 1; i <= kMask; ++i) {
+ if (expectedOffset != descs[i].mStartOffset) return false;
+ expectedOffset += descs[i].mDataByteSize;
+ }
+ return true;
+}
+
+bool CompressedPacketTable::hasVariableFrames(PacketBase& base)
+{
+ AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs;
+ for (UInt32 i = 0; i <= kMask; ++i) {
+ if (descs[i].mVariableFramesInPacket) return true;
+ }
+ return false;
+}
+
+UInt32 CompressedPacketTable::largestPacket(PacketBase& base)
+{
+ UInt32 maxPacketSize = 0;
+ AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs;
+ for (UInt32 i = 0; i <= kMask; ++i) {
+ UInt32 packetSize = descs[i].mDataByteSize;
+ if (packetSize > maxPacketSize) maxPacketSize = packetSize;
+ }
+ return maxPacketSize;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+#define COMPRESS_TYPE(TYPE, BITS) \
+ if (contiguous) { \
+ TYPE##ContiguousPacketDescription* newDescs = (TYPE##ContiguousPacketDescription*)CA_malloc((kMask+1) * sizeof(TYPE##ContiguousPacketDescription)); \
+ base.mDescs = newDescs; \
+ base.mDescType = k##TYPE##ContiguousPacketDescription; \
+ for (UInt32 i = 0; i <= kMask; ++i) { \
+ newDescs[i].mNextOffset = (BITS)(descs[i].mStartOffset + descs[i].mDataByteSize - baseOffset); \
+ } \
+ free(descs); \
+ } else { \
+ TYPE##DiscontiguousPacketDescription* newDescs = (TYPE##DiscontiguousPacketDescription*)CA_malloc((kMask+1) * sizeof(TYPE##DiscontiguousPacketDescription)); \
+ base.mDescs = newDescs; \
+ base.mDescType = k##TYPE##DiscontiguousPacketDescription; \
+ for (UInt32 i = 0; i <= kMask; ++i) { \
+ newDescs[i].mNextOffset = i == kMask ? 0 : (BITS)(descs[i+1].mStartOffset - baseOffset); \
+ newDescs[i].mDataByteSize = descs[i].mDataByteSize; \
+ } \
+ free(descs); \
+ } \
+ return;
+
+void CompressedPacketTable::Compress(PacketBase& base)
+{
+ if (hasVariableFrames(base))
+ return;
+
+ bool contiguous = isContiguous(base);
+
+ AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs;
+ SInt64 delta = descs[kMask].mStartOffset + descs[kMask].mDataByteSize - descs[0].mStartOffset;
+
+ SInt64 baseOffset = descs[0].mStartOffset;
+ base.mBaseOffset = baseOffset;
+
+ if (delta <= 65535LL) {
+ COMPRESS_TYPE(Tiny, UInt16)
+ } else if (delta <= 4294967295LL && largestPacket(base) <= 65535) {
+ COMPRESS_TYPE(Small, UInt32)
+ } else {
+ COMPRESS_TYPE(Big, SInt64)
+ }
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.h b/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.h
new file mode 100644
index 0000000000..47e28ca499
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.h
@@ -0,0 +1,186 @@
+/*
+ File: CompressedPacketTable.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include <iterator>
+#include <vector>
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include "CoreAudioTypes.h"
+#endif
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+struct AudioStreamPacketDescriptionExtended : AudioStreamPacketDescription
+{
+ SInt64 mFrameOffset; // this is the sum of the mVariableFramesInPacket up to this point so we can binary search.
+};
+typedef struct AudioStreamPacketDescriptionExtended AudioStreamPacketDescriptionExtended;
+
+inline bool operator < (const AudioStreamPacketDescriptionExtended& a, const AudioStreamPacketDescriptionExtended& b)
+{
+ return a.mFrameOffset < b.mFrameOffset;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class CompressedPacketTable
+{
+public:
+ CompressedPacketTable(UInt32 inFramesPerPacket) : mSize(0), mFramesPerPacket(inFramesPerPacket) {}
+ ~CompressedPacketTable();
+
+ SInt64 size() const { return mSize; }
+ void push_back(const AudioStreamPacketDescriptionExtended& inDesc);
+
+ const AudioStreamPacketDescriptionExtended operator[](SInt64 inPacketIndex) const;
+ const AudioStreamPacketDescriptionExtended front() const { return (*this)[0]; }
+ const AudioStreamPacketDescriptionExtended back() const { return (*this)[mSize-1]; }
+
+ //SInt64 PacketForByte(SInt64 inByteOffset) const;
+ SInt64 ByteForPacket(SInt64 inPacketIndex) const { return (*this)[inPacketIndex].mStartOffset; }
+
+ class iterator {
+ public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef iterator pointer;
+ typedef SInt64 difference_type;
+ typedef AudioStreamPacketDescriptionExtended value_type;
+ typedef value_type& reference;
+
+ iterator() : mTable(NULL), mIndex(0) {}
+ iterator(const CompressedPacketTable* table, SInt64 index) : mTable(table), mIndex(index) {}
+ iterator(const iterator& that) : mTable(that.mTable), mIndex(that.mIndex) {}
+
+ iterator& operator=(const iterator& that) { mTable = that.mTable; mIndex = that.mIndex; return *this; }
+
+ const AudioStreamPacketDescriptionExtended operator*() const { return (*mTable)[mIndex]; }
+ const AudioStreamPacketDescriptionExtended* const operator->() { mValue = (*mTable)[mIndex]; return &mValue; }
+ iterator& operator++() { ++mIndex; return *this; }
+ iterator& operator--() { --mIndex; return *this; }
+
+ SInt64 operator-(const iterator& that) { return mIndex - that.mIndex; }
+ const iterator operator-(SInt64 index) { return iterator(mTable, mIndex - index); }
+ const iterator operator+(SInt64 index) { return iterator(mTable, mIndex + index); }
+ bool operator==(const iterator& that) { return mIndex == that.mIndex; }
+ bool operator!=(const iterator& that) { return mIndex != that.mIndex; }
+ bool operator>(const iterator& that) { return mIndex > that.mIndex; }
+ bool operator<(const iterator& that) { return mIndex < that.mIndex; }
+ private:
+ const CompressedPacketTable* mTable;
+ SInt64 mIndex;
+ AudioStreamPacketDescriptionExtended mValue; // in order to support operator-> .
+ };
+
+ iterator begin() const { return iterator(this, 0); }
+ iterator end() const { return iterator(this, mSize); }
+
+private:
+ struct TinyContiguousPacketDescription
+ {
+ UInt16 mNextOffset;
+ };
+
+ struct TinyDiscontiguousPacketDescription : TinyContiguousPacketDescription
+ {
+ UInt16 mDataByteSize;
+ };
+
+ // There could be a 24 bit packet description. But ALAC is who usually needs SmallContiguousPacketDescription and
+ // it already uses 8x fewer packet descriptions than AAC due to the mFramesPerPacket being 8x greater.
+ // So there isn't as great a need for saving space. 4 bytes per packet is OK for ALAC.
+
+ struct SmallContiguousPacketDescription
+ {
+ UInt32 mNextOffset;
+ };
+
+ struct SmallDiscontiguousPacketDescription : SmallContiguousPacketDescription
+ {
+ UInt16 mDataByteSize;
+ };
+
+ struct BigContiguousPacketDescription
+ {
+ UInt64 mNextOffset;
+ };
+
+ struct BigDiscontiguousPacketDescription : BigContiguousPacketDescription
+ {
+ UInt32 mDataByteSize;
+ };
+
+ struct PacketBase
+ {
+ SInt64 mBaseOffset;
+ UInt8 mDescType;
+ void* mDescs;
+ };
+
+ enum {
+ kTinyContiguousPacketDescription,
+ kTinyDiscontiguousPacketDescription,
+ kSmallContiguousPacketDescription,
+ kSmallDiscontiguousPacketDescription,
+ kBigContiguousPacketDescription,
+ kBigDiscontiguousPacketDescription,
+ kExtendedPacketDescription
+ };
+ static const UInt32 kShift;
+ static const UInt32 kMask;
+
+ bool isContiguous(PacketBase& base);
+ bool hasVariableFrames(PacketBase& base);
+ UInt32 largestPacket(PacketBase& base);
+
+ void Compress(PacketBase& base);
+
+private:
+ std::vector<PacketBase> mBases;
+ UInt64 mSize;
+ UInt32 mFramesPerPacket;
+};
+
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.cpp
new file mode 100644
index 0000000000..c8a93d2756
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.cpp
@@ -0,0 +1,689 @@
+/*
+ File: DataSource.cpp
+ Abstract: DataSource.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "DataSource.h"
+#if TARGET_OS_WIN32
+ #include <io.h>
+#else
+ #include <unistd.h>
+ #include <fcntl.h>
+#endif
+#include <sys/stat.h>
+#include <algorithm>
+
+#define VERBOSE 0
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+const UInt16 kPositionModeMask = 3;
+
+DataSource::DataSource(Boolean inCloseOnDelete)
+ : mCloseOnDelete(inCloseOnDelete)
+{
+}
+
+DataSource::~DataSource()
+{
+}
+
+SInt64 DataSource::CalcOffset( UInt16 positionMode,
+ SInt64 positionOffset,
+ SInt64 currentOffset,
+ SInt64 size)
+{
+ SInt64 newOffset = 0;
+ switch (positionMode & kPositionModeMask) {
+ //case fsAtMark : newOffset = currentOffset; break;
+ case SEEK_SET : newOffset = positionOffset; break;
+ case SEEK_END : newOffset = size + positionOffset; break;
+ case SEEK_CUR : newOffset = positionOffset + currentOffset; break;
+ }
+ return newOffset;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#if 0
+
+MacFile_DataSource::MacFile_DataSource( FSIORefNum inForkRefNum, SInt8 inPermissions, Boolean inCloseOnDelete)
+ : DataSource(inCloseOnDelete), mFileNum(inForkRefNum), mPermissions(inPermissions)
+{
+}
+
+MacFile_DataSource::~MacFile_DataSource()
+{
+ if (mCloseOnDelete) FSCloseFork(mFileNum);
+}
+
+
+OSStatus MacFile_DataSource::GetSize(SInt64& outSize)
+{
+ outSize = -1; // in case of error
+ OSStatus err = FSGetForkSize(mFileNum, &outSize);
+ return err;
+}
+
+OSStatus MacFile_DataSource::GetPos(SInt64& outPos) const
+{
+ return FSGetForkPosition(mFileNum, &outPos);
+}
+
+OSStatus MacFile_DataSource::SetSize(SInt64 inSize)
+{
+ return FSSetForkSize(mFileNum, SEEK_SET, inSize);
+}
+
+
+OSStatus MacFile_DataSource::ReadBytes(
+ UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount)
+{
+ if (actualCount) *actualCount = 0;
+ if (!buffer) return kAudio_ParamError;
+ ByteCount bc_actualCount = 0;
+ OSStatus err = FSReadFork(mFileNum, positionMode, positionOffset, requestCount, buffer, &bc_actualCount);
+ if (actualCount) *actualCount = (UInt32)bc_actualCount;
+ return err;
+}
+
+OSStatus MacFile_DataSource::WriteBytes(
+ UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount)
+{
+ if (!buffer) return kAudio_ParamError;
+ ByteCount bc_actualCount = 0;
+ OSStatus err = FSWriteFork(mFileNum, positionMode, positionOffset, requestCount, buffer, &bc_actualCount);
+ if (actualCount) *actualCount = (UInt32)bc_actualCount;
+ return err;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#define kAudioFileNoCacheMask 0x20
+
+UnixFile_DataSource::UnixFile_DataSource( int inFD, SInt8 inPermissions, Boolean inCloseOnDelete)
+ : DataSource(inCloseOnDelete), mFileD(inFD), mPermissions(inPermissions), mNoCache(0), mCachedSize(-1), mFilePointer(0)
+{
+}
+
+UnixFile_DataSource::~UnixFile_DataSource()
+{
+ if (mCloseOnDelete) close(mFileD);
+}
+
+OSStatus UnixFile_DataSource::GetSize(SInt64& outSize)
+{
+#if 0 // 6764274 using the cached file size causes a regression for apps that play a file while writing to it.
+ if (mCachedSize >= 0) {
+ outSize = mCachedSize;
+ return noErr;
+ }
+#endif
+ outSize = -1; // in case of error
+ struct stat stbuf;
+ if (fstat (mFileD, &stbuf) == -1) return kAudio_FileNotFoundError;
+ outSize = mCachedSize = stbuf.st_size;
+ return noErr;
+}
+
+OSStatus UnixFile_DataSource::SetSize(SInt64 inSize)
+{
+ mCachedSize = -1;
+#if TARGET_OS_WIN32
+ if (chsize (mFileD, inSize)) return kAudioFilePermissionsError;
+#else
+ if (ftruncate (mFileD, inSize) == -1) return kAudioFilePermissionsError;
+#endif
+ mCachedSize = inSize;
+ return noErr;
+}
+
+
+OSStatus UnixFile_DataSource::GetPos(SInt64& outPos) const
+{
+ outPos = mFilePointer;
+ return noErr;
+}
+
+SInt64 UnixFile_DataSource::UFCurrentOffset (UInt16 positionMode,
+ SInt64 positionOffset)
+{
+ SInt64 offset = -1;
+ switch (positionMode & kPositionModeMask)
+ {
+ /*case fsAtMark :
+ {
+ SInt64 pos;
+ OSStatus result = GetPos (pos);
+ if (result) return result;
+ offset = pos;
+ break;
+ }*/
+ case SEEK_SET :
+ {
+ offset = positionOffset;
+ break;
+ }
+ case SEEK_END :
+ {
+ SInt64 size;
+ OSStatus result = GetSize (size);
+ if (result) return result;
+ offset = size + positionOffset;
+ break;
+ }
+ case SEEK_CUR :
+ {
+ SInt64 pos;
+ OSStatus result = GetPos (pos);
+ if (result) return result;
+ offset = positionOffset + pos;
+ break;
+ }
+ }
+ return offset;
+}
+
+OSStatus UnixFile_DataSource::ReadBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount)
+{
+ if (actualCount) *actualCount = 0;
+ if (!buffer) return kAudio_ParamError;
+
+ // can't use current offset as we need to go to the disk too much
+ SInt64 offset = UFCurrentOffset (positionMode, positionOffset);
+ if (offset < 0) return kAudioFilePositionError;
+
+#if 0 // 6571050 fstat-ing the file every read causes a performance regression
+ // 5931571 check that read may exceed eof and curtail it.
+ do {
+ SInt64 size;
+ OSStatus serr = GetSize(size);
+ if (serr) break;
+ SInt64 remain = size - offset;
+ if (remain < 0) requestCount = 0;
+ else if (requestCount > remain) requestCount = remain;
+ } while (false);
+#endif
+
+ if (requestCount <= 0) {
+ if (actualCount) *actualCount = 0;
+ return noErr;
+ }
+
+#if !TARGET_OS_WIN32
+ UInt32 noCache = positionMode & kAudioFileNoCacheMask ? 1 : 0;
+ if (noCache != mNoCache) {
+ mNoCache = noCache;
+ fcntl(mFileD, F_NOCACHE, mNoCache);
+ }
+#endif
+
+ size_t readBytes = requestCount;
+#if TARGET_OS_WIN32
+ lseek(mFileD, offset, SEEK_SET);
+ int numBytes = read (mFileD, buffer, readBytes);
+#else
+ ssize_t numBytes = pread (mFileD, buffer, readBytes, offset);
+#endif
+ if (numBytes == -1) return kAudioFilePositionError;
+ mFilePointer = offset + numBytes;
+
+ if (actualCount) *actualCount = (UInt32)numBytes;
+ return noErr;
+}
+
+OSStatus UnixFile_DataSource::WriteBytes(UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount)
+{
+ if (!buffer) return kAudio_ParamError;
+
+ // can't use current offset as we need to go to the disk too much
+ SInt64 offset = UFCurrentOffset (positionMode, positionOffset);
+ if (offset < 0) return kAudioFilePositionError;
+
+ mCachedSize = -1;
+
+ size_t writeBytes = requestCount;
+
+#if !TARGET_OS_WIN32
+ UInt32 noCache = positionMode & kAudioFileNoCacheMask ? 1 : 0;
+ if (noCache != mNoCache) {
+ mNoCache = noCache;
+ fcntl(mFileD, F_NOCACHE, mNoCache);
+ }
+#endif
+
+#if TARGET_OS_WIN32
+ lseek(mFileD, offset, SEEK_SET);
+ int numBytes = write (mFileD, buffer, writeBytes);
+#else
+ ssize_t numBytes = pwrite (mFileD, buffer, writeBytes, offset);
+#endif
+ if (numBytes == -1) return kAudioFilePositionError;
+ mFilePointer = offset + numBytes;
+
+ if (actualCount) *actualCount = (UInt32)numBytes;
+ return noErr;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#define NO_CACHE 0
+
+OSStatus Cached_DataSource::ReadFromHeaderCache(
+ SInt64 offset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount)
+{
+ if (actualCount) *actualCount = 0;
+ OSStatus err = noErr;
+ ByteCount theActualCount = 0;
+
+#if VERBOSE
+ printf("read from header %lld %lu %lld %lu\n", offset, requestCount, 0LL, mHeaderCacheSize);
+#endif
+
+ if (!mHeaderCache())
+ {
+ mHeaderCache.allocBytes(mHeaderCacheSize, true);
+ err = mDataSource->ReadBytes(SEEK_SET, 0, mHeaderCacheSize, mHeaderCache(), &mHeaderCacheSize);
+ if (err == kAudioFileEndOfFileError) err = noErr;
+ if (err) return err;
+ }
+
+ ByteCount firstPart = std::min((ByteCount)requestCount, (ByteCount)(mHeaderCacheSize - offset));
+ ByteCount secondPart = requestCount - firstPart;
+
+ memcpy(buffer, mHeaderCache + (ByteCount)offset, firstPart);
+ theActualCount = firstPart;
+
+ if (secondPart) {
+ UInt32 secondPartActualCount = 0;
+ err = mDataSource->ReadBytes(SEEK_SET, mHeaderCacheSize, static_cast<UInt32>(secondPart), (char*)buffer + firstPart, &secondPartActualCount);
+ theActualCount += secondPartActualCount;
+ }
+
+ if (actualCount) *actualCount = (UInt32)theActualCount;
+ mOffset = offset + theActualCount;
+
+ return err;
+}
+
+OSStatus Cached_DataSource::ReadBytes(
+ UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount)
+{
+ if (actualCount) *actualCount = 0;
+ OSStatus err = noErr;
+ SInt64 size;
+ UInt32 theActualCount = 0;
+
+ if (!buffer) return kAudio_ParamError;
+
+ if ((positionMode & kPositionModeMask) != SEEK_END) size = 0; // not used in this case
+ else
+ {
+ err = GetSize(size);
+ if (err) return err;
+ }
+
+ SInt64 offset = CalcOffset(positionMode, positionOffset, mOffset, size);
+ if (offset < 0) return kAudioFilePositionError;
+
+ if (offset < mHeaderCacheSize) {
+ return ReadFromHeaderCache(offset, requestCount, buffer, actualCount);
+ }
+
+#if NO_CACHE
+ err = mDataSource->ReadBytes(positionMode, positionOffset, requestCount, buffer, &theActualCount);
+ mOffset = offset + theActualCount;
+#else
+
+ SInt64 cacheEnd = mBodyCacheOffset + mBodyCacheCurSize;
+ if (mBodyCache() && requestCount < mBodyCacheSize && offset >= mBodyCacheOffset && offset < cacheEnd)
+ {
+ if (offset + requestCount <= cacheEnd)
+ {
+ // request is entirely within cache
+#if VERBOSE
+ printf("request is entirely within cache %lld %lu %lld %lu\n", offset, requestCount, mBodyCacheOffset, mBodyCacheCurSize);
+#endif
+ memcpy(buffer, mBodyCache + (size_t)(offset - mBodyCacheOffset), requestCount);
+ theActualCount = requestCount;
+ }
+ else
+ {
+ // part of request is within cache. copy, read next cache block, copy.
+#if VERBOSE
+ printf("part of request is within cache %lld %lu %lld %lu\n", offset, requestCount, mBodyCacheOffset, mBodyCacheCurSize);
+#endif
+
+ // copy first part.
+ ByteCount firstPart = (ByteCount)(cacheEnd - offset);
+ ByteCount secondPart = requestCount - firstPart;
+#if VERBOSE
+ printf("memcpy offset %lld mBodyCacheOffset %lld offset - mBodyCacheOffset %lld firstPart %lu requestCount %lu\n",
+ offset, mBodyCacheOffset, offset - mBodyCacheOffset, firstPart, requestCount);
+#endif
+ memcpy(buffer, mBodyCache + (size_t)(offset - mBodyCacheOffset), firstPart);
+
+ theActualCount = static_cast<UInt32>(firstPart);
+
+ // read new block
+ SInt64 nextOffset = mBodyCacheOffset + mBodyCacheCurSize;
+ err = mDataSource->ReadBytes(SEEK_SET, nextOffset, mBodyCacheSize, mBodyCache(), &mBodyCacheCurSize);
+
+ if (err == kAudioFileEndOfFileError) err = noErr;
+ if (err) goto leave;
+
+ mBodyCacheOffset = nextOffset;
+
+ // copy second part
+ secondPart = std::min(secondPart, (ByteCount)mBodyCacheCurSize);
+ if (secondPart) memcpy((char*)buffer + firstPart, mBodyCache(), secondPart);
+ theActualCount = static_cast<UInt32>(firstPart + secondPart);
+ }
+ }
+ else
+ {
+ if (requestCount > mBodyCacheSize)
+ {
+#if VERBOSE
+ printf("large request %lld %lu %lld %lu\n", offset, requestCount, mBodyCacheOffset, mBodyCacheCurSize);
+#endif
+ // the request is larger than we normally cache, just do a read and don't cache.
+ err = mDataSource->ReadBytes(positionMode, positionOffset, requestCount, buffer, &theActualCount);
+ mOffset = offset + theActualCount;
+ }
+ else
+ {
+ // request is outside cache. read new block.
+#if VERBOSE
+ printf("request is outside cache %lld %lu %lld %lu\n", offset, requestCount, mBodyCacheOffset, mBodyCacheCurSize);
+#endif
+ if (!mBodyCache())
+ {
+ mBodyCache.allocBytes(mBodyCacheSize, true);
+#if VERBOSE
+ printf("alloc mBodyCache %08X\n", mBodyCache());
+#endif
+ }
+ mBodyCacheOffset = offset;
+ err = mDataSource->ReadBytes(SEEK_SET, mBodyCacheOffset, mBodyCacheSize, mBodyCache(), &mBodyCacheCurSize);
+#if VERBOSE
+ printf("read %08X %d mBodyCacheOffset %lld %lu %lu\n", err, err, mBodyCacheOffset, mBodyCacheSize, mBodyCacheCurSize);
+#endif
+ if (err == kAudioFileEndOfFileError) err = noErr;
+ if (err) return err;
+
+ theActualCount = std::min(requestCount, mBodyCacheCurSize);
+ memcpy(buffer, mBodyCache(), theActualCount);
+ }
+
+ }
+
+leave:
+#endif
+ if (actualCount) *actualCount = (UInt32)theActualCount;
+#if VERBOSE
+ printf("<<read err %d actualCount %lu\n", err, *actualCount);
+#endif
+ return err;
+}
+
+OSStatus Cached_DataSource::WriteBytes(
+ UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount)
+{
+ OSStatus err = noErr;
+ SInt64 size;
+
+ if (!buffer) return kAudio_ParamError;
+
+ if ((positionMode & kPositionModeMask) != SEEK_END) size = 0; // not used in this case
+ else
+ {
+ err = GetSize(size);
+ if (err) return err;
+ }
+
+ SInt64 offset = CalcOffset(positionMode, positionOffset, mOffset, size);
+ if (offset < 0) return kAudioFilePositionError;
+
+ if (mHeaderCache() && offset < mHeaderCacheSize)
+ {
+ // header cache write through
+ ByteCount firstPart = std::min((ByteCount)requestCount, (ByteCount)(mHeaderCacheSize - offset));
+#if VERBOSE
+ printf("header cache write through %lu %lu\n", mHeaderCacheSize, firstPart);
+#endif
+ memcpy(mHeaderCache + (size_t)offset, buffer, firstPart);
+ }
+
+#if VERBOSE
+ printf("write %lld %lu %lld %d %lld\n", offset, requestCount, mOffset, positionMode, positionOffset);
+#endif
+
+ SInt64 cacheEnd = mBodyCacheOffset + mBodyCacheCurSize;
+ if (mBodyCache() && offset >= mBodyCacheOffset && offset < cacheEnd)
+ {
+ // body cache write through
+ ByteCount firstPart = std::min((SInt64)requestCount, cacheEnd - offset);
+#if VERBOSE
+ printf("body cache write through %lld %lu %lld %lu\n", mBodyCacheOffset, mBodyCacheCurSize, offset, firstPart);
+#endif
+ memcpy(mBodyCache + (offset - mBodyCacheOffset), buffer, firstPart);
+ }
+
+ UInt32 theActualCount;
+ err = mDataSource->WriteBytes(positionMode, positionOffset, requestCount, buffer, &theActualCount);
+
+ mOffset = offset + theActualCount;
+ if (actualCount) *actualCount = (UInt32)theActualCount;
+
+ return err;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+Seekable_DataSource::Seekable_DataSource( void * inClientData,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc)
+ : DataSource(false), mClientData(inClientData), mReadFunc(inReadFunc), mWriteFunc(inWriteFunc),
+ mSizeFunc(inGetSizeFunc), mSetSizeFunc(inSetSizeFunc)
+{
+}
+
+Seekable_DataSource::~Seekable_DataSource()
+{
+}
+
+
+OSStatus Seekable_DataSource::GetSize(SInt64& outSize)
+{
+ if (!mSizeFunc) {
+ outSize = LLONG_MAX;
+ } else {
+ outSize = (*mSizeFunc)(mClientData);
+ }
+ return noErr;
+}
+
+OSStatus Seekable_DataSource::SetSize(SInt64 inSize)
+{
+ if (!mSetSizeFunc) return kAudioFileOperationNotSupportedError;
+ return (*mSetSizeFunc)(mClientData, inSize);
+}
+
+OSStatus Seekable_DataSource::ReadBytes(
+ UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount)
+{
+ OSStatus err;
+
+ if (actualCount) *actualCount = 0;
+ if (!mReadFunc) return kAudioFileOperationNotSupportedError;
+ if (!buffer) return kAudio_ParamError;
+
+ positionMode &= kPositionModeMask;
+
+ SInt64 size;
+ err = GetSize(size);
+ if (err) return err;
+
+ SInt64 offset = CalcOffset(positionMode, positionOffset, mOffset, size);
+
+ // request is outside bounds of file
+ if (offset < 0)
+ return kAudioFilePositionError;
+ if (offset >= size)
+ return kAudioFileEndOfFileError;
+
+ // reduce request if it exceeds the amount available
+ requestCount = static_cast<UInt32>(std::min((SInt64)requestCount, size - offset));
+
+ UInt32 theActualCount = 0;
+ err = (*mReadFunc)(mClientData, offset, requestCount, buffer, &theActualCount);
+ if (actualCount) *actualCount = theActualCount;
+ mOffset = offset + theActualCount;
+ return err;
+}
+
+
+OSStatus Seekable_DataSource::WriteBytes(
+ UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount)
+{
+ OSStatus err;
+
+ if (!mWriteFunc) return kAudioFileOperationNotSupportedError;
+ if (!buffer) return kAudio_ParamError;
+
+ SInt64 size;
+ positionMode &= kPositionModeMask;
+ if (positionMode != SEEK_END) size = 0; // not used in this case
+ else
+ {
+ err = GetSize(size);
+ if (err) return err;
+ }
+
+ SInt64 offset = CalcOffset(positionMode, positionOffset, mOffset, size);
+ if (offset < 0) return kAudioFilePositionError;
+
+ UInt32 theActualCount;
+ err = (*mWriteFunc)(mClientData, offset, requestCount, buffer, &theActualCount);
+ if (err) return err;
+ if (actualCount) *actualCount = theActualCount;
+ mOffset = offset + theActualCount;
+ return noErr;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+OSStatus Buffer_DataSource::ReadBytes(
+ UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount)
+{
+ if (actualCount) *actualCount = 0;
+ SInt64 offsetWithinBuffer = CalcOffset(positionMode, positionOffset, mOffset, mDataByteSize + mStartOffset) - mStartOffset;
+ if (offsetWithinBuffer < 0 || offsetWithinBuffer >= mDataByteSize) return kAudioFilePositionError;
+
+ SInt64 bytesAfterOffset = mDataByteSize - offsetWithinBuffer;
+ SInt64 theActualCount = std::min(bytesAfterOffset, (SInt64)requestCount);
+
+ if (theActualCount <= 0) {
+ if (actualCount) *actualCount = 0;
+ return kAudio_ParamError;
+ }
+
+ memcpy(buffer, mData + offsetWithinBuffer, theActualCount);
+
+ if (actualCount) *actualCount = static_cast<UInt32>(theActualCount);
+ mOffset = offsetWithinBuffer + theActualCount;
+
+ return noErr;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.h b/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.h
new file mode 100644
index 0000000000..6c79c94df9
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.h
@@ -0,0 +1,372 @@
+/*
+ File: DataSource.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __DataSource_h__
+#define __DataSource_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioToolbox/AudioFile.h>
+#else
+ #include <ConditionalMacros.h>
+ #include "AudioFile.h"
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdexcept>
+#include "CAAutoDisposer.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+class DataSource
+{
+public:
+
+ DataSource(Boolean inCloseOnDelete);
+ virtual ~DataSource();
+
+ virtual OSStatus GetSize32(UInt32& outSize)
+ {
+ SInt64 size64;
+ OSStatus err = GetSize(size64);
+ if (err) return err;
+ if (size64 > 0x00000000FFFFffffLL) return kAudioFileDoesNotAllow64BitDataSizeError;
+ outSize = (UInt32)size64;
+ return noErr;
+ }
+
+ virtual OSStatus GetSize(SInt64& outSize) =0;
+
+ virtual OSStatus SetSize(SInt64 inSize)=0;
+
+ virtual OSStatus GetPos(SInt64& outPos) const=0;
+
+ /* non seekable data sources should use fsAtMark for the positionMode (or SEEK_CUR with offset zero,
+ or SEEK_SET with offset equal to the current position in the stream, in other words no seeking from the
+ current position is allowed.)
+ */
+
+ virtual OSStatus ReadBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount)=0;
+
+ virtual OSStatus WriteBytes(UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount)=0;
+
+ virtual void SetCloseOnDelete(Boolean inFlag) { mCloseOnDelete = inFlag; }
+
+ virtual Boolean CanSeek() const=0;
+ virtual Boolean CanGetSize() const=0;
+ virtual Boolean CanSetSize() const=0;
+ virtual Boolean CanRead() const=0;
+ virtual Boolean CanWrite() const=0;
+
+protected:
+ Boolean mCloseOnDelete;
+
+ /* utility method */
+ SInt64 CalcOffset( UInt16 positionMode,
+ SInt64 positionOffset,
+ SInt64 currentOffset,
+ SInt64 size);
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+ Initialize with a Macintosh file fork ref num as obtained from FSOpenFork.
+*/
+
+#if 0
+
+class MacFile_DataSource : public DataSource
+{
+ FSIORefNum mFileNum;
+ SInt8 mPermissions;
+
+public:
+
+ MacFile_DataSource( FSIORefNum inForkRefNum, SInt8 inPermissions, Boolean inCloseOnDelete);
+ virtual ~MacFile_DataSource();
+
+ virtual OSStatus GetSize(SInt64& outSize);
+ virtual OSStatus GetPos(SInt64& outPos) const;
+
+ virtual OSStatus SetSize(SInt64 inSize);
+
+ virtual OSStatus ReadBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount);
+
+ virtual OSStatus WriteBytes(UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount);
+
+ virtual Boolean CanSeek() const { return true; }
+ virtual Boolean CanGetSize() const { return true; }
+ virtual Boolean CanSetSize() const { return true; }
+
+ virtual Boolean CanRead() const { return mPermissions & kAudioFileReadPermission; }
+ virtual Boolean CanWrite() const { return mPermissions & kAudioFileWritePermission; }
+};
+#endif
+
+
+class UnixFile_DataSource : public DataSource
+{
+ int mFileD;
+ SInt8 mPermissions;
+ UInt32 mNoCache;
+ SInt64 mCachedSize;
+ SInt64 mFilePointer;
+
+public:
+
+ UnixFile_DataSource( int inFD, SInt8 inPermissions, Boolean inCloseOnDelete);
+ virtual ~UnixFile_DataSource();
+
+ virtual OSStatus GetSize(SInt64& outSize);
+ virtual OSStatus GetPos(SInt64& outPos) const;
+
+ virtual OSStatus SetSize(SInt64 inSize);
+
+ virtual OSStatus ReadBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount);
+
+ virtual OSStatus WriteBytes(UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount);
+
+ virtual Boolean CanSeek() const { return true; }
+ virtual Boolean CanGetSize() const { return true; }
+ virtual Boolean CanSetSize() const { return true; }
+
+ virtual Boolean CanRead() const { return mPermissions & kAudioFileReadPermission; }
+ virtual Boolean CanWrite() const { return mPermissions & kAudioFileWritePermission; }
+
+private:
+
+ SInt64 UFCurrentOffset (UInt16 positionMode,
+ SInt64 positionOffset);
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+ A wrapper that caches the wrapped source's header.
+*/
+class Cached_DataSource : public DataSource
+{
+ DataSource* mDataSource;
+ CAAutoFree<UInt8> mHeaderCache;
+ UInt32 mHeaderCacheSize;
+ CAAutoFree<UInt8> mBodyCache;
+ UInt32 mBodyCacheSize;
+ UInt32 mBodyCacheCurSize;
+ SInt64 mBodyCacheOffset;
+ SInt64 mOffset;
+ Boolean mOwnDataSource;
+
+public:
+
+ Cached_DataSource(DataSource* inDataSource, UInt32 inHeaderCacheSize = 4096, UInt32 inBodyCacheSize = 32768, Boolean inOwnDataSource = true)
+ : DataSource(false),
+ mDataSource(inDataSource), mHeaderCacheSize(inHeaderCacheSize),
+ mBodyCacheSize(inBodyCacheSize), mBodyCacheCurSize(0), mBodyCacheOffset(-1),
+ mOffset(0),
+ mOwnDataSource(inOwnDataSource)
+ {
+ }
+
+ virtual ~Cached_DataSource()
+ {
+ if (mOwnDataSource) delete mDataSource;
+ }
+
+
+ virtual OSStatus GetSize(SInt64& outSize) { return mDataSource->GetSize(outSize); }
+ virtual OSStatus GetPos(SInt64& outPos) const { return mDataSource->GetPos(outPos); }
+
+ virtual OSStatus SetSize(SInt64 inSize) { return mDataSource->SetSize(inSize); }
+
+ virtual OSStatus ReadBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount);
+
+ virtual OSStatus WriteBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount);
+
+ OSStatus ReadFromHeaderCache( SInt64 offset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount);
+
+ virtual Boolean CanSeek() const { return mDataSource->CanSeek(); }
+ virtual Boolean CanGetSize() const { return mDataSource->CanGetSize(); }
+ virtual Boolean CanSetSize() const { return mDataSource->CanSetSize(); }
+
+ virtual Boolean CanRead() const { return mDataSource->CanRead(); }
+ virtual Boolean CanWrite() const { return mDataSource->CanWrite(); }
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+/* This class calls user supplied routines on demand. */
+
+class Seekable_DataSource : public DataSource
+{
+ void * mClientData;
+ SInt64 mOffset;
+
+ AudioFile_ReadProc mReadFunc;
+ AudioFile_WriteProc mWriteFunc;
+ AudioFile_GetSizeProc mSizeFunc;
+ AudioFile_SetSizeProc mSetSizeFunc;
+
+public:
+ Seekable_DataSource( void * inClientData,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc
+ );
+
+ virtual ~Seekable_DataSource();
+
+ virtual OSStatus GetSize(SInt64& outSize);
+ virtual OSStatus GetPos(SInt64& outPos) const { outPos = mOffset; return noErr; };
+
+ virtual OSStatus SetSize(SInt64 inSize);
+
+ virtual OSStatus ReadBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount);
+
+ virtual OSStatus WriteBytes(UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount);
+
+ virtual Boolean CanSeek() const { return true; }
+ virtual Boolean CanGetSize() const { return mSizeFunc != 0; }
+ virtual Boolean CanSetSize() const { return mSetSizeFunc != 0; }
+ virtual Boolean CanRead() const { return mReadFunc != 0; }
+ virtual Boolean CanWrite() const { return mWriteFunc != 0; }
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+class Buffer_DataSource : public DataSource
+{
+ UInt32 mDataByteSize;
+ const char * mData;
+
+ SInt64 mStartOffset;
+ SInt64 mOffset;
+public:
+ Buffer_DataSource( UInt32 inDataByteSize,
+ const void * inData,
+ SInt64 inStartOffset = 0
+ ) : DataSource(false), mDataByteSize(inDataByteSize), mData((const char*)inData), mStartOffset(inStartOffset), mOffset(mStartOffset) {}
+
+ virtual ~Buffer_DataSource() {}
+
+ virtual OSStatus GetSize(SInt64& outSize) { outSize = mDataByteSize + mStartOffset; return noErr; }
+ virtual OSStatus GetPos(SInt64& outPos) const { outPos = mOffset; return noErr; };
+
+ virtual OSStatus SetSize(SInt64 inSize) { throw std::runtime_error("not writable"); }
+
+ virtual OSStatus ReadBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount);
+
+ virtual OSStatus WriteBytes(UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount) { throw std::runtime_error("not writable"); }
+
+ virtual Boolean CanSeek() const { return true; }
+ virtual Boolean CanGetSize() const { return true; }
+ virtual Boolean CanSetSize() const { return false; }
+ virtual Boolean CanRead() const { return true; }
+ virtual Boolean CanWrite() const { return false; }
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.cpp
new file mode 100644
index 0000000000..612bc4d308
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.cpp
@@ -0,0 +1,2393 @@
+/*
+ File: AUBase.cpp
+ Abstract: AUBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUBase.h"
+#include "AUDispatch.h"
+#include "AUInputElement.h"
+#include "AUOutputElement.h"
+#include <algorithm>
+#include <syslog.h>
+#include "CAAudioChannelLayout.h"
+#include "CAHostTimeBase.h"
+#include "CAVectorUnit.h"
+#include "CAXException.h"
+
+
+
+#if TARGET_OS_MAC && (TARGET_CPU_X86 || TARGET_CPU_X86_64)
+ // our compiler does ALL floating point with SSE
+ inline int GETCSR () { int _result; asm volatile ("stmxcsr %0" : "=m" (*&_result) ); return _result; }
+ inline void SETCSR (int a) { int _temp = a; asm volatile( "ldmxcsr %0" : : "m" (*&_temp ) ); }
+
+ #define DISABLE_DENORMALS int _savemxcsr = GETCSR(); SETCSR(_savemxcsr | 0x8040);
+ #define RESTORE_DENORMALS SETCSR(_savemxcsr);
+#else
+ #define DISABLE_DENORMALS
+ #define RESTORE_DENORMALS
+#endif
+
+static bool sAUBaseCFStringsInitialized = false;
+// this is used for the presets
+static CFStringRef kUntitledString = NULL;
+//these are the current keys for the class info document
+static CFStringRef kVersionString = NULL;
+static CFStringRef kTypeString = NULL;
+static CFStringRef kSubtypeString = NULL;
+static CFStringRef kManufacturerString = NULL;
+static CFStringRef kDataString = NULL;
+static CFStringRef kNameString = NULL;
+static CFStringRef kRenderQualityString = NULL;
+static CFStringRef kCPULoadString = NULL;
+static CFStringRef kElementNameString = NULL;
+static CFStringRef kPartString = NULL;
+
+SInt32 AUBase::sVectorUnitType = kVecUninitialized;
+
+//_____________________________________________________________________________
+//
+AUBase::AUBase( AudioComponentInstance inInstance,
+ UInt32 numInputElements,
+ UInt32 numOutputElements,
+ UInt32 numGroupElements) :
+ ComponentBase(inInstance),
+ mElementsCreated(false),
+ mInitialized(false),
+ mHasBegunInitializing(false),
+ mInitNumInputEls(numInputElements), mInitNumOutputEls(numOutputElements),
+#if !CA_BASIC_AU_FEATURES
+ mInitNumGroupEls(numGroupElements),
+#endif
+ mRenderCallbacksTouched(false),
+ mRenderThreadID (NULL),
+ mWantsRenderThreadID (false),
+ mLastRenderError(0),
+ mUsesFixedBlockSize(false),
+ mBuffersAllocated(false),
+ mLogString (NULL),
+ mNickName (NULL),
+ mAUMutex(NULL)
+ #if !CA_NO_AU_UI_FEATURES
+ ,
+ mContextName(NULL)
+ #endif
+{
+ ResetRenderTime ();
+
+ if(!sAUBaseCFStringsInitialized)
+ {
+ kUntitledString = CFSTR("Untitled");
+ kVersionString = CFSTR(kAUPresetVersionKey);
+ kTypeString = CFSTR(kAUPresetTypeKey);
+ kSubtypeString = CFSTR(kAUPresetSubtypeKey);
+ kManufacturerString = CFSTR(kAUPresetManufacturerKey);
+ kDataString = CFSTR(kAUPresetDataKey);
+ kNameString = CFSTR(kAUPresetNameKey);
+ kRenderQualityString = CFSTR(kAUPresetRenderQualityKey);
+ kCPULoadString = CFSTR(kAUPresetCPULoadKey);
+ kElementNameString = CFSTR(kAUPresetElementNameKey);
+ kPartString = CFSTR(kAUPresetPartKey);
+ sAUBaseCFStringsInitialized = true;
+ }
+
+ if (sVectorUnitType == kVecUninitialized) {
+ sVectorUnitType = CAVectorUnit::GetVectorUnitType() ;
+ }
+
+ mAudioUnitAPIVersion = 2;
+
+ SetMaxFramesPerSlice(kAUDefaultMaxFramesPerSlice);
+
+ GlobalScope().Initialize(this, kAudioUnitScope_Global, 1);
+
+#if !CA_NO_AU_UI_FEATURES
+ memset (&mHostCallbackInfo, 0, sizeof (mHostCallbackInfo));
+#endif
+
+
+ mCurrentPreset.presetNumber = -1;
+ mCurrentPreset.presetName = kUntitledString;
+ CFRetain (mCurrentPreset.presetName);
+}
+
+//_____________________________________________________________________________
+//
+AUBase::~AUBase()
+{
+ if (mCurrentPreset.presetName) CFRelease (mCurrentPreset.presetName);
+#if !CA_NO_AU_UI_FEATURES
+ if (mContextName) CFRelease (mContextName);
+#endif
+ if (mLogString) delete [] mLogString;
+ if (mNickName) CFRelease(mNickName);
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::CreateElements()
+{
+ if (!mElementsCreated) {
+ Inputs().Initialize(this, kAudioUnitScope_Input, mInitNumInputEls);
+ Outputs().Initialize(this, kAudioUnitScope_Output, mInitNumOutputEls);
+#if !CA_BASIC_AU_FEATURES
+ Groups().Initialize(this, kAudioUnitScope_Group, mInitNumGroupEls);
+#endif
+ CreateExtendedElements();
+
+ mElementsCreated = true;
+ }
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::SetMaxFramesPerSlice(UInt32 nFrames)
+{
+ mMaxFramesPerSlice = nFrames;
+ if (mBuffersAllocated)
+ ReallocateBuffers();
+ PropertyChanged(kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0);
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::CanSetMaxFrames() const
+{
+ return IsInitialized() ? kAudioUnitErr_Initialized : OSStatus(noErr);
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::ReallocateBuffers()
+{
+ CreateElements();
+
+ UInt32 nOutputs = Outputs().GetNumberOfElements();
+ for (UInt32 i = 0; i < nOutputs; ++i) {
+ AUOutputElement *output = GetOutput(i);
+ output->AllocateBuffer(); // does no work if already allocated
+ }
+ UInt32 nInputs = Inputs().GetNumberOfElements();
+ for (UInt32 i = 0; i < nInputs; ++i) {
+ AUInputElement *input = GetInput(i);
+ input->AllocateBuffer(); // does no work if already allocated
+ }
+ mBuffersAllocated = true;
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::DeallocateIOBuffers()
+{
+ if (!mBuffersAllocated)
+ return;
+
+ UInt32 nOutputs = Outputs().GetNumberOfElements();
+ for (UInt32 i = 0; i < nOutputs; ++i) {
+ AUOutputElement *output = GetOutput(i);
+ output->DeallocateBuffer();
+ }
+ UInt32 nInputs = Inputs().GetNumberOfElements();
+ for (UInt32 i = 0; i < nInputs; ++i) {
+ AUInputElement *input = GetInput(i);
+ input->DeallocateBuffer();
+ }
+ mBuffersAllocated = false;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DoInitialize()
+{
+ OSStatus result = noErr;
+
+ if (!mInitialized) {
+ result = Initialize();
+ if (result == noErr) {
+ if (CanScheduleParameters())
+ mParamList.reserve(24);
+ mHasBegunInitializing = true;
+ ReallocateBuffers(); // calls CreateElements()
+ mInitialized = true; // signal that it's okay to render
+ CAMemoryBarrier();
+ }
+ }
+
+ return result;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::Initialize()
+{
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::PreDestructor()
+{
+ // this is called from the ComponentBase dispatcher, which doesn't know anything about our (optional) lock
+ CAMutex::Locker lock(mAUMutex);
+ DoCleanup();
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::DoCleanup()
+{
+ if (mInitialized)
+ Cleanup();
+
+ DeallocateIOBuffers();
+ ResetRenderTime ();
+
+ mInitialized = false;
+ mHasBegunInitializing = false;
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::Cleanup()
+{
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ ResetRenderTime ();
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DispatchGetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus result = noErr;
+ bool validateElement = true;
+
+ switch (inID) {
+ case kAudioUnitProperty_MakeConnection:
+ ca_require(inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(AudioUnitConnection);
+ outWritable = true;
+ break;
+
+
+ case kAudioUnitProperty_SetRenderCallback:
+ ca_require(AudioUnitAPIVersion() > 1, InvalidProperty);
+ ca_require(inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(AURenderCallbackStruct);
+ outWritable = true;
+ break;
+
+ case kAudioUnitProperty_StreamFormat:
+ outDataSize = sizeof(CAStreamBasicDescription);
+ outWritable = IsStreamFormatWritable(inScope, inElement);
+ break;
+
+ case kAudioUnitProperty_SampleRate:
+ outDataSize = sizeof(Float64);
+ outWritable = IsStreamFormatWritable(inScope, inElement);
+ break;
+
+ case kAudioUnitProperty_ClassInfo:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(CFPropertyListRef);
+ outWritable = true;
+ break;
+
+ case kAudioUnitProperty_FactoryPresets:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ result = GetPresets(NULL);
+ if (!result) {
+ outDataSize = sizeof(CFArrayRef);
+ outWritable = false;
+ }
+ break;
+
+ case kAudioUnitProperty_PresentPreset:
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+#ifndef __LP64__
+ case kAudioUnitProperty_CurrentPreset:
+#endif
+#endif
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(AUPreset);
+ outWritable = true;
+ break;
+
+ case kAudioUnitProperty_ElementName:
+ outDataSize = sizeof (CFStringRef);
+ outWritable = true;
+ break;
+
+ case kAudioUnitProperty_ParameterList:
+ {
+ UInt32 nparams = 0;
+ result = GetParameterList(inScope, NULL, nparams);
+
+ outDataSize = sizeof(AudioUnitParameterID) * nparams;
+ outWritable = false;
+ validateElement = false;
+ }
+ break;
+
+ case kAudioUnitProperty_ParameterInfo:
+ outDataSize = sizeof(AudioUnitParameterInfo);
+ outWritable = false;
+ validateElement = false;
+ break;
+
+ case kAudioUnitProperty_ParameterHistoryInfo:
+ outDataSize = sizeof(AudioUnitParameterHistoryInfo);
+ outWritable = false;
+ validateElement = false;
+ break;
+
+ case kAudioUnitProperty_ElementCount:
+ outDataSize = sizeof(UInt32);
+ outWritable = BusCountWritable(inScope);
+ validateElement = false;
+ break;
+
+ case kAudioUnitProperty_Latency:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(Float64);
+ outWritable = false;
+ break;
+
+ case kAudioUnitProperty_TailTime:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ if (SupportsTail()) {
+ outDataSize = sizeof(Float64);
+ outWritable = false;
+ } else
+ goto InvalidProperty;
+ break;
+
+ case kAudioUnitProperty_MaximumFramesPerSlice:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(UInt32);
+ outWritable = true;
+ break;
+
+ case kAudioUnitProperty_LastRenderError:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(OSStatus);
+ outWritable = false;
+ break;
+
+ case kAudioUnitProperty_SupportedNumChannels:
+ {
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ UInt32 num = SupportedNumChannels (NULL);
+ if (num) {
+ outDataSize = sizeof (AUChannelInfo) * num;
+ result = noErr;
+ } else
+ goto InvalidProperty;
+ outWritable = false;
+ break;
+ }
+
+ case kAudioUnitProperty_SupportedChannelLayoutTags:
+ {
+ UInt32 numLayouts = GetChannelLayoutTags(inScope, inElement, NULL);
+ if (numLayouts) {
+ outDataSize = numLayouts * sizeof(AudioChannelLayoutTag);
+ result = noErr;
+ } else
+ goto InvalidProperty;
+ outWritable = false;
+ validateElement = false; //already done it
+ break;
+ }
+
+ case kAudioUnitProperty_AudioChannelLayout:
+ {
+ outWritable = false;
+ outDataSize = GetAudioChannelLayout(inScope, inElement, NULL, outWritable);
+ if (outDataSize) {
+ result = noErr;
+ } else {
+ if (GetChannelLayoutTags(inScope, inElement, NULL) == 0)
+ goto InvalidProperty;
+ else
+ result = kAudioUnitErr_InvalidPropertyValue;
+ }
+ validateElement = false; //already done it
+ break;
+ }
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE
+ case kAudioUnitProperty_ShouldAllocateBuffer:
+ ca_require((inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Output), InvalidScope);
+ outWritable = true;
+ outDataSize = sizeof(UInt32);
+ break;
+#endif
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ case kAudioUnitProperty_FastDispatch:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ if (!IsCMgrObject()) goto InvalidProperty;
+ outDataSize = sizeof(void *);
+ outWritable = false;
+ validateElement = false;
+ break;
+
+ case kAudioUnitProperty_GetUIComponentList:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = GetNumCustomUIComponents();
+ if (outDataSize == 0)
+ goto InvalidProperty;
+ outDataSize *= sizeof (AudioComponentDescription);
+
+ outWritable = false;
+ break;
+#endif
+
+ case kAudioUnitProperty_ParameterValueStrings:
+ result = GetParameterValueStrings(inScope, inElement, NULL);
+ if (result == noErr) {
+ outDataSize = sizeof(CFArrayRef);
+ outWritable = false;
+ validateElement = false;
+ }
+ break;
+
+#if !CA_NO_AU_HOST_CALLBACKS
+ case kAudioUnitProperty_HostCallbacks:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(mHostCallbackInfo);
+ outWritable = true;
+ break;
+#endif
+#if !CA_NO_AU_UI_FEATURES
+ case kAudioUnitProperty_ContextName:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(CFStringRef);
+ outWritable = true;
+ break;
+
+ case kAudioUnitProperty_IconLocation:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outWritable = false;
+ if (!HasIcon())
+ goto InvalidProperty;
+ outDataSize = sizeof(CFURLRef);
+ break;
+
+ case kAudioUnitProperty_ParameterClumpName:
+ outDataSize = sizeof(AudioUnitParameterNameInfo );
+ outWritable = false;
+ break;
+
+#endif // !CA_NO_AU_UI_FEATURES
+
+ case 'lrst' : // kAudioUnitProperty_LastRenderedSampleTime
+ outDataSize = sizeof(Float64);
+ outWritable = false;
+ break;
+
+ case kAudioUnitProperty_NickName:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(CFStringRef);
+ outWritable = true;
+ break;
+
+ default:
+ result = GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);
+ validateElement = false;
+ break;
+ }
+
+ if (result == noErr && validateElement) {
+ ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+ }
+
+ return result;
+InvalidProperty:
+ return kAudioUnitErr_InvalidProperty;
+InvalidScope:
+ return kAudioUnitErr_InvalidScope;
+InvalidElement:
+ return kAudioUnitErr_InvalidElement;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DispatchGetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ // NOTE: We're currently only called from AUBase::ComponentEntryDispatch, which
+ // calls DispatchGetPropertyInfo first, which performs validation of the scope/element,
+ // and ensures that the outData buffer is non-null and large enough.
+ OSStatus result = noErr;
+
+ switch (inID) {
+ case kAudioUnitProperty_StreamFormat:
+ *(CAStreamBasicDescription *)outData = GetStreamFormat(inScope, inElement);
+ break;
+
+ case kAudioUnitProperty_SampleRate:
+ *(Float64 *)outData = GetStreamFormat(inScope, inElement).mSampleRate;
+ break;
+
+ case kAudioUnitProperty_ParameterList:
+ {
+ UInt32 nparams = 0;
+ result = GetParameterList(inScope, (AudioUnitParameterID *)outData, nparams);
+ }
+ break;
+
+ case kAudioUnitProperty_ParameterInfo:
+ result = GetParameterInfo(inScope, inElement, *(AudioUnitParameterInfo *)outData);
+ break;
+
+ case kAudioUnitProperty_ParameterHistoryInfo:
+ {
+ AudioUnitParameterHistoryInfo* info = (AudioUnitParameterHistoryInfo*)outData;
+ result = GetParameterHistoryInfo(inScope, inElement, info->updatesPerSecond, info->historyDurationInSeconds);
+ }
+ break;
+
+ case kAudioUnitProperty_ClassInfo:
+ {
+ *(CFPropertyListRef *)outData = NULL;
+ result = SaveState((CFPropertyListRef *)outData);
+ }
+ break;
+
+ case kAudioUnitProperty_FactoryPresets:
+ {
+ *(CFArrayRef *)outData = NULL;
+ result = GetPresets ((CFArrayRef *)outData);
+ }
+ break;
+
+ case kAudioUnitProperty_PresentPreset:
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+#ifndef __LP64__
+ case kAudioUnitProperty_CurrentPreset:
+#endif
+#endif
+ {
+ *(AUPreset *)outData = mCurrentPreset;
+
+ // retain current string (as client owns a reference to it and will release it)
+ if (inID == kAudioUnitProperty_PresentPreset && mCurrentPreset.presetName)
+ CFRetain (mCurrentPreset.presetName);
+
+ result = noErr;
+ }
+ break;
+
+ case kAudioUnitProperty_ElementName:
+ {
+ AUElement * element = GetElement(inScope, inElement);
+ if (element->HasName()) {
+ *(CFStringRef *)outData = element->GetName();
+ CFRetain (element->GetName());
+ result = noErr;
+ } else
+ result = kAudioUnitErr_InvalidPropertyValue;
+ }
+ break;
+
+ case kAudioUnitProperty_ElementCount:
+ *(UInt32 *)outData = GetScope(inScope).GetNumberOfElements();
+ break;
+
+ case kAudioUnitProperty_Latency:
+ *(Float64 *)outData = GetLatency();
+ break;
+
+ case kAudioUnitProperty_TailTime:
+ if (SupportsTail())
+ *(Float64 *)outData = GetTailTime();
+ else
+ result = kAudioUnitErr_InvalidProperty;
+ break;
+
+ case kAudioUnitProperty_MaximumFramesPerSlice:
+ *(UInt32 *)outData = mMaxFramesPerSlice;
+ break;
+
+ case kAudioUnitProperty_LastRenderError:
+ *(OSStatus *)outData = mLastRenderError;
+ mLastRenderError = 0;
+ break;
+
+ case kAudioUnitProperty_SupportedNumChannels:
+ {
+ const AUChannelInfo* infoPtr = NULL;
+ UInt32 num = SupportedNumChannels (&infoPtr);
+ if(num != 0 && infoPtr != NULL)
+ memcpy (outData, infoPtr, num * sizeof (AUChannelInfo));
+ }
+ break;
+
+ case kAudioUnitProperty_SupportedChannelLayoutTags:
+ {
+ AudioChannelLayoutTag* ptr = outData ? static_cast<AudioChannelLayoutTag*>(outData) : NULL;
+ UInt32 numLayouts = GetChannelLayoutTags (inScope, inElement, ptr);
+ if (numLayouts == 0)
+ result = kAudioUnitErr_InvalidProperty;
+ }
+ break;
+
+ case kAudioUnitProperty_AudioChannelLayout:
+ {
+ AudioChannelLayout* ptr = outData ? static_cast<AudioChannelLayout*>(outData) : NULL;
+ Boolean writable;
+ UInt32 dataSize = GetAudioChannelLayout(inScope, inElement, ptr, writable);
+ if (!dataSize) {
+ result = kAudioUnitErr_InvalidProperty;
+ }
+ break;
+ }
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE
+ case kAudioUnitProperty_ShouldAllocateBuffer:
+ {
+ AUIOElement * element = GetIOElement(inScope, inElement);
+ *(UInt32*)outData = element->WillAllocateBuffer();
+ break;
+ }
+#endif
+
+ case kAudioUnitProperty_ParameterValueStrings:
+ result = GetParameterValueStrings(inScope, inElement, (CFArrayRef *)outData);
+ break;
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ case kAudioUnitProperty_FastDispatch:
+ if (!IsCMgrObject()) result = kAudioUnitErr_InvalidProperty;
+ else {
+ switch (inElement) {
+ case kAudioUnitGetParameterSelect:
+ *(AudioUnitGetParameterProc *)outData = (AudioUnitGetParameterProc)CMgr_AudioUnitBaseGetParameter;
+ break;
+ case kAudioUnitSetParameterSelect:
+ *(AudioUnitSetParameterProc *)outData = (AudioUnitSetParameterProc)CMgr_AudioUnitBaseSetParameter;
+ break;
+ case kAudioUnitRenderSelect:
+ if (AudioUnitAPIVersion() > 1)
+ *(AudioUnitRenderProc *)outData = (AudioUnitRenderProc)CMgr_AudioUnitBaseRender;
+ else result = kAudioUnitErr_InvalidElement;
+ break;
+ default:
+ result = GetProperty(inID, inScope, inElement, outData);
+ break;
+ }
+ }
+ break;
+
+ case kAudioUnitProperty_GetUIComponentList:
+ GetUIComponentDescs ((ComponentDescription*)outData);
+ break;
+#endif
+
+#if !CA_NO_AU_HOST_CALLBACKS
+ case kAudioUnitProperty_HostCallbacks:
+ memcpy(outData, &mHostCallbackInfo, sizeof(mHostCallbackInfo));
+ break;
+#endif
+#if !CA_NO_AU_UI_FEATURES
+ case kAudioUnitProperty_IconLocation:
+ {
+ CFURLRef iconLocation = CopyIconLocation();
+ if (iconLocation) {
+ *(CFURLRef*)outData = iconLocation;
+ } else
+ result = kAudioUnitErr_InvalidProperty;
+ }
+ break;
+
+ case kAudioUnitProperty_ContextName:
+ *(CFStringRef *)outData = mContextName;
+ if (mContextName) {
+ CFRetain(mContextName);
+ // retain CFString (if exists) since client will be responsible for its release
+ result = noErr;
+ } else {
+ result = kAudioUnitErr_InvalidPropertyValue;
+ }
+ break;
+
+ case kAudioUnitProperty_ParameterClumpName:
+ {
+ AudioUnitParameterNameInfo * ioClumpInfo = (AudioUnitParameterNameInfo*) outData;
+ if (ioClumpInfo->inID == kAudioUnitClumpID_System) // this ID value is reserved
+ result = kAudioUnitErr_InvalidPropertyValue;
+ else
+ {
+ result = CopyClumpName(inScope, ioClumpInfo->inID, ioClumpInfo->inDesiredLength, &ioClumpInfo->outName);
+
+ // this is provided for compatbility with existing implementations that don't know
+ // about this new mechanism
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = GetProperty (inID, inScope, inElement, outData);
+ }
+ }
+ break;
+
+#endif // !CA_NO_AU_UI_FEATURES
+
+ case 'lrst' : // kAudioUnitProperty_LastRenderedSampleTime
+ *(Float64*)outData = mCurrentRenderTime.mSampleTime;
+ break;
+
+ case kAudioUnitProperty_NickName:
+ // Ownership follows Core Foundation's 'Copy Rule'
+ if (mNickName) CFRetain(mNickName);
+ *(CFStringRef*)outData = mNickName;
+ break;
+
+ default:
+ result = GetProperty(inID, inScope, inElement, outData);
+ break;
+ }
+ return result;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DispatchSetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ OSStatus result = noErr;
+
+ switch (inID) {
+ case kAudioUnitProperty_MakeConnection:
+ ca_require(inDataSize >= sizeof(AudioUnitConnection), InvalidPropertyValue);
+ {
+ AudioUnitConnection &connection = *(AudioUnitConnection *)inData;
+ result = SetConnection(connection);
+ }
+ break;
+
+
+ case kAudioUnitProperty_SetRenderCallback:
+ {
+ ca_require(inDataSize >= sizeof(AURenderCallbackStruct), InvalidPropertyValue);
+ ca_require(AudioUnitAPIVersion() > 1, InvalidProperty);
+ AURenderCallbackStruct &callback = *(AURenderCallbackStruct*)inData;
+ result = SetInputCallback(kAudioUnitProperty_SetRenderCallback, inElement, callback.inputProc, callback.inputProcRefCon);
+ }
+ break;
+
+ case kAudioUnitProperty_ElementCount:
+ ca_require(inDataSize == sizeof(UInt32), InvalidPropertyValue);
+ ca_require(BusCountWritable(inScope), NotWritable);
+ result = SetBusCount(inScope, *(UInt32*)inData);
+ if (result == noErr) {
+ PropertyChanged(inID, inScope, inElement);
+ }
+ break;
+
+ case kAudioUnitProperty_MaximumFramesPerSlice:
+ ca_require(inDataSize == sizeof(UInt32), InvalidPropertyValue);
+ result = CanSetMaxFrames();
+ if (result) return result;
+ SetMaxFramesPerSlice(*(UInt32 *)inData);
+ break;
+
+ case kAudioUnitProperty_StreamFormat:
+ {
+ if (inDataSize < 36) goto InvalidPropertyValue;
+ ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+
+ CAStreamBasicDescription newDesc;
+ // now we're going to be ultra conservative! because of discrepancies between
+ // sizes of this struct based on aligment padding inconsistencies
+ memset (&newDesc, 0, sizeof(newDesc));
+ memcpy (&newDesc, inData, 36);
+
+ ca_require(ValidFormat(inScope, inElement, newDesc), InvalidFormat);
+
+ const CAStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement);
+
+ if ( !curDesc.IsEqual(newDesc, false) ) {
+ ca_require(IsStreamFormatWritable(inScope, inElement), NotWritable);
+ result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc);
+ }
+ }
+ break;
+
+ case kAudioUnitProperty_SampleRate:
+ {
+ ca_require(inDataSize == sizeof(Float64), InvalidPropertyValue);
+ ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+
+ const CAStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement);
+ CAStreamBasicDescription newDesc = curDesc;
+ newDesc.mSampleRate = *(Float64 *)inData;
+
+ ca_require(ValidFormat(inScope, inElement, newDesc), InvalidFormat);
+
+ if ( !curDesc.IsEqual(newDesc, false) ) {
+ ca_require(IsStreamFormatWritable(inScope, inElement), NotWritable);
+ result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc);
+ }
+ }
+ break;
+
+ case kAudioUnitProperty_AudioChannelLayout:
+ {
+ const AudioChannelLayout *layout = static_cast<const AudioChannelLayout *>(inData);
+ size_t headerSize = sizeof(AudioChannelLayout) - sizeof(AudioChannelDescription);
+
+ ca_require(inDataSize >= headerSize + layout->mNumberChannelDescriptions * sizeof(AudioChannelDescription), InvalidPropertyValue);
+ result = SetAudioChannelLayout(inScope, inElement, layout);
+ if (result == noErr)
+ PropertyChanged(inID, inScope, inElement);
+ break;
+ }
+
+ case kAudioUnitProperty_ClassInfo:
+ ca_require(inDataSize == sizeof(CFPropertyListRef *), InvalidPropertyValue);
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ result = RestoreState(*(CFPropertyListRef *)inData);
+ break;
+
+ case kAudioUnitProperty_PresentPreset:
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+#ifndef __LP64__
+ case kAudioUnitProperty_CurrentPreset:
+#endif
+#endif
+ {
+ ca_require(inDataSize == sizeof(AUPreset), InvalidPropertyValue);
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ AUPreset & newPreset = *(AUPreset *)inData;
+
+ if (newPreset.presetNumber >= 0)
+ {
+ result = NewFactoryPresetSet(newPreset);
+ // NewFactoryPresetSet SHOULD call SetAFactoryPreset if the preset is valid
+ // from its own list of preset number->name
+ if (!result)
+ PropertyChanged(inID, inScope, inElement);
+ }
+ else if (newPreset.presetName)
+ {
+ result = NewCustomPresetSet(newPreset);
+ if (!result)
+ PropertyChanged(inID, inScope, inElement);
+ }
+ else
+ result = kAudioUnitErr_InvalidPropertyValue;
+ }
+ break;
+
+ case kAudioUnitProperty_ElementName:
+ {
+ ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+ ca_require(inDataSize == sizeof(CFStringRef), InvalidPropertyValue);
+ AUElement * element = GetScope(inScope).GetElement (inElement);
+ element->SetName (*(CFStringRef *)inData);
+ PropertyChanged(inID, inScope, inElement);
+ }
+ break;
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE
+ case kAudioUnitProperty_ShouldAllocateBuffer:
+ {
+ ca_require((inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Output), InvalidScope);
+ ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+ ca_require(inDataSize == sizeof(UInt32), InvalidPropertyValue);
+ ca_require(!IsInitialized(), Initialized);
+
+ AUIOElement * element = GetIOElement(inScope, inElement);
+ element->SetWillAllocateBuffer(*(UInt32 *)inData != 0);
+ }
+ break;
+#endif
+
+#if !CA_NO_AU_HOST_CALLBACKS
+ case kAudioUnitProperty_HostCallbacks:
+ {
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ UInt32 availSize = std::min(inDataSize, (UInt32)sizeof(HostCallbackInfo));
+ bool hasChanged = !memcmp (&mHostCallbackInfo, inData, availSize);
+ memset (&mHostCallbackInfo, 0, sizeof (mHostCallbackInfo));
+ memcpy (&mHostCallbackInfo, inData, availSize);
+ if (hasChanged)
+ PropertyChanged(inID, inScope, inElement);
+ break;
+ }
+#endif
+#if !CA_NO_AU_UI_FEATURES
+ case kAudioUnitProperty_SetExternalBuffer:
+ ca_require(inDataSize >= sizeof(AudioUnitExternalBuffer), InvalidPropertyValue);
+ ca_require(IsInitialized(), Uninitialized);
+ {
+ AudioUnitExternalBuffer &buf = *(AudioUnitExternalBuffer*)inData;
+ if (intptr_t(buf.buffer) & 0x0F) result = kAudio_ParamError;
+ else if (inScope == kAudioUnitScope_Input) {
+ AUInputElement *input = GetInput(inElement);
+ input->UseExternalBuffer(buf);
+ } else {
+ AUOutputElement *output = GetOutput(inElement);
+ output->UseExternalBuffer(buf);
+ }
+ }
+ break;
+
+ case kAudioUnitProperty_ContextName:
+ {
+ ca_require(inDataSize == sizeof(CFStringRef), InvalidPropertyValue);
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ CFStringRef inStr = *(CFStringRef *)inData;
+ if (mContextName) CFRelease(mContextName);
+ if (inStr) CFRetain(inStr);
+ mContextName = inStr;
+ PropertyChanged(inID, inScope, inElement);
+ }
+ break;
+
+#endif // !CA_NO_AU_UI_FEATURES
+
+ case kAudioUnitProperty_NickName:
+ {
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inDataSize == sizeof(CFStringRef), InvalidPropertyValue);
+ CFStringRef inStr = *(CFStringRef *)inData;
+ if (mNickName) CFRelease(mNickName);
+ if (inStr) CFRetain(inStr);
+ mNickName = inStr;
+ PropertyChanged(inID, inScope, inElement);
+ break;
+ }
+
+ default:
+ result = SetProperty(inID, inScope, inElement, inData, inDataSize);
+ if (result == noErr)
+ PropertyChanged(inID, inScope, inElement);
+
+ break;
+ }
+ return result;
+NotWritable:
+ return kAudioUnitErr_PropertyNotWritable;
+InvalidFormat:
+ return kAudioUnitErr_FormatNotSupported;
+#if !CA_NO_AU_UI_FEATURES
+Uninitialized:
+ return kAudioUnitErr_Uninitialized;
+#endif
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || CA_USE_AUDIO_PLUGIN_ONLY
+Initialized:
+ return kAudioUnitErr_Initialized;
+#endif
+InvalidScope:
+ return kAudioUnitErr_InvalidScope;
+InvalidProperty:
+ return kAudioUnitErr_InvalidProperty;
+InvalidPropertyValue:
+ return kAudioUnitErr_InvalidPropertyValue;
+InvalidElement:
+ return kAudioUnitErr_InvalidElement;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DispatchRemovePropertyValue (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ OSStatus result = noErr;
+ switch (inID)
+ {
+ case kAudioUnitProperty_AudioChannelLayout:
+ {
+ result = RemoveAudioChannelLayout(inScope, inElement);
+ if (result == noErr)
+ PropertyChanged(inID, inScope, inElement);
+ break;
+ }
+
+#if !CA_NO_AU_HOST_CALLBACKS
+ case kAudioUnitProperty_HostCallbacks:
+ {
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ bool hasValue = false;
+ void* ptr = &mHostCallbackInfo;
+ for (unsigned int i = 0; i < sizeof (HostCallbackInfo); ++i) {
+ if (static_cast<char*>(ptr)[i]) {
+ hasValue = true;
+ break;
+ }
+ }
+ if (hasValue) {
+ memset (&mHostCallbackInfo, 0, sizeof (HostCallbackInfo));
+ PropertyChanged(inID, inScope, inElement);
+ }
+ break;
+ }
+#endif
+#if !CA_NO_AU_UI_FEATURES
+ case kAudioUnitProperty_ContextName:
+ if (mContextName) CFRelease(mContextName);
+ mContextName = NULL;
+ result = noErr;
+ break;
+
+#endif // !CA_NO_AU_UI_FEATURES
+
+ case kAudioUnitProperty_NickName:
+ {
+ if(inScope == kAudioUnitScope_Global) {
+ if (mNickName) CFRelease(mNickName);
+ mNickName = NULL;
+ PropertyChanged(inID, inScope, inElement);
+ } else {
+ result = kAudioUnitErr_InvalidScope;
+ }
+ break;
+ }
+
+ default:
+ result = RemovePropertyValue (inID, inScope, inElement);
+ break;
+ }
+
+ return result;
+#if !CA_NO_AU_UI_FEATURES || !CA_NO_AU_HOST_CALLBACKS
+InvalidScope:
+ return kAudioUnitErr_InvalidScope;
+#endif
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::GetPropertyInfo( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::RemovePropertyValue ( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ return kAudioUnitErr_InvalidPropertyValue;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::AddPropertyListener( AudioUnitPropertyID inID,
+ AudioUnitPropertyListenerProc inProc,
+ void * inProcRefCon)
+{
+ PropertyListener pl;
+
+ pl.propertyID = inID;
+ pl.listenerProc = inProc;
+ pl.listenerRefCon = inProcRefCon;
+
+ if (mPropertyListeners.empty())
+ mPropertyListeners.reserve(32);
+ mPropertyListeners.push_back(pl);
+
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::RemovePropertyListener( AudioUnitPropertyID inID,
+ AudioUnitPropertyListenerProc inProc,
+ void * inProcRefCon,
+ bool refConSpecified)
+{
+ // iterate in reverse so that it's safe to erase in the middle of the vector
+ for (int i = (int)mPropertyListeners.size(); --i >=0; ) {
+ PropertyListeners::iterator it = mPropertyListeners.begin() + i;
+ if ((*it).propertyID == inID && (*it).listenerProc == inProc && (!refConSpecified || (*it).listenerRefCon == inProcRefCon))
+ mPropertyListeners.erase(it);
+ }
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::PropertyChanged( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ for (PropertyListeners::iterator it = mPropertyListeners.begin(); it != mPropertyListeners.end(); ++it)
+ if ((*it).propertyID == inID)
+ ((*it).listenerProc)((*it).listenerRefCon, mComponentInstance, inID, inScope, inElement);
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::SetRenderNotification( AURenderCallback inProc,
+ void * inRefCon)
+{
+ if (inProc == NULL)
+ return kAudio_ParamError;
+
+ mRenderCallbacksTouched = true;
+ mRenderCallbacks.deferred_add(RenderCallback(inProc, inRefCon));
+ // this will do nothing if it's already in the list
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::RemoveRenderNotification( AURenderCallback inProc,
+ void * inRefCon)
+{
+ mRenderCallbacks.deferred_remove(RenderCallback(inProc, inRefCon));
+ return noErr; // error?
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::GetParameter( AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioUnitParameterValue & outValue)
+{
+ AUElement *elem = SafeGetElement(inScope, inElement);
+ outValue = elem->GetParameter(inID);
+ return noErr;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::SetParameter( AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioUnitParameterValue inValue,
+ UInt32 inBufferOffsetInFrames)
+{
+ AUElement *elem = SafeGetElement(inScope, inElement);
+ elem->SetParameter(inID, inValue);
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::ScheduleParameter ( const AudioUnitParameterEvent *inParameterEvent,
+ UInt32 inNumEvents)
+{
+ bool canScheduleParameters = CanScheduleParameters();
+
+ for (UInt32 i = 0; i < inNumEvents; ++i)
+ {
+ if (inParameterEvent[i].eventType == kParameterEvent_Immediate)
+ {
+ SetParameter (inParameterEvent[i].parameter,
+ inParameterEvent[i].scope,
+ inParameterEvent[i].element,
+ inParameterEvent[i].eventValues.immediate.value,
+ inParameterEvent[i].eventValues.immediate.bufferOffset);
+ }
+ if (canScheduleParameters) {
+ mParamList.push_back (inParameterEvent[i]);
+ }
+ }
+
+ return noErr;
+}
+
+// ____________________________________________________________________________
+//
+static bool SortParameterEventList(const AudioUnitParameterEvent &ev1, const AudioUnitParameterEvent &ev2 )
+{
+ int offset1 = ev1.eventType == kParameterEvent_Immediate ? ev1.eventValues.immediate.bufferOffset : ev1.eventValues.ramp.startBufferOffset;
+ int offset2 = ev2.eventType == kParameterEvent_Immediate ? ev2.eventValues.immediate.bufferOffset : ev2.eventValues.ramp.startBufferOffset;
+
+ if(offset1 < offset2) return true;
+ return false;
+}
+
+
+// ____________________________________________________________________________
+//
+OSStatus AUBase::ProcessForScheduledParams( ParameterEventList &inParamList,
+ UInt32 inFramesToProcess,
+ void *inUserData )
+{
+ OSStatus result = noErr;
+
+ int totalFramesToProcess = inFramesToProcess;
+
+ int framesRemaining = totalFramesToProcess;
+
+ unsigned int currentStartFrame = 0; // start of the whole buffer
+
+
+
+ // sort the ParameterEventList by startBufferOffset
+ std::sort(inParamList.begin(), inParamList.end(), SortParameterEventList);
+
+ ParameterEventList::iterator iter = inParamList.begin();
+
+
+ while(framesRemaining > 0 )
+ {
+ // first of all, go through the ramped automation events and find out where the next
+ // division of our whole buffer will be
+
+ int currentEndFrame = totalFramesToProcess; // start out assuming we'll process all the way to
+ // the end of the buffer
+
+ iter = inParamList.begin();
+
+ // find the next break point
+ while(iter != inParamList.end() )
+ {
+ AudioUnitParameterEvent &event = *iter;
+
+ int offset = event.eventType == kParameterEvent_Immediate ? event.eventValues.immediate.bufferOffset : event.eventValues.ramp.startBufferOffset;
+
+ if(offset > (int)currentStartFrame && offset < currentEndFrame )
+ {
+ currentEndFrame = offset;
+ break;
+ }
+
+ // consider ramp end to be a possible choice (there may be gaps in the supplied ramp events)
+ if(event.eventType == kParameterEvent_Ramped )
+ {
+ offset = event.eventValues.ramp.startBufferOffset + event.eventValues.ramp.durationInFrames;
+
+ if(offset > (int)currentStartFrame && offset < currentEndFrame )
+ {
+ currentEndFrame = offset;
+ }
+ }
+
+ iter++;
+ }
+
+ int framesThisTime = currentEndFrame - currentStartFrame;
+
+ // next, setup the parameter maps to be current for the ramp parameters active during
+ // this time segment...
+
+ for(ParameterEventList::iterator iter2 = inParamList.begin(); iter2 != inParamList.end(); iter2++ )
+ {
+ AudioUnitParameterEvent &event = *iter2;
+
+ bool eventFallsInSlice;
+
+
+ if(event.eventType == kParameterEvent_Ramped)
+ eventFallsInSlice = event.eventValues.ramp.startBufferOffset < currentEndFrame
+ && event.eventValues.ramp.startBufferOffset + event.eventValues.ramp.durationInFrames > currentStartFrame;
+ else /* kParameterEvent_Immediate */
+ // actually, for the same parameter, there may be future immediate events which override this one,
+ // but it's OK since the event list is sorted in time order, we're guaranteed to end up with the current one
+ eventFallsInSlice = event.eventValues.immediate.bufferOffset <= currentStartFrame;
+
+ if(eventFallsInSlice)
+ {
+ AUElement *element = GetElement(event.scope, event.element );
+
+ if(element) element->SetScheduledEvent( event.parameter,
+ event,
+ currentStartFrame,
+ currentEndFrame - currentStartFrame );
+ }
+ }
+
+
+
+ // Finally, actually do the processing for this slice.....
+
+ result = ProcessScheduledSlice( inUserData,
+ currentStartFrame,
+ framesThisTime,
+ inFramesToProcess );
+
+ if(result != noErr) break;
+
+ framesRemaining -= framesThisTime;
+ currentStartFrame = currentEndFrame; // now start from where we left off last time
+ }
+
+ return result;
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::SetWantsRenderThreadID (bool inFlag)
+{
+ if (inFlag == mWantsRenderThreadID)
+ return;
+
+ mWantsRenderThreadID = inFlag;
+ if (!mWantsRenderThreadID)
+ mRenderThreadID = NULL;
+}
+
+//_____________________________________________________________________________
+//
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DoRender( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inFramesToProcess,
+ AudioBufferList & ioData)
+{
+ OSStatus theError;
+ RenderCallbackList::iterator rcit;
+
+ AUTRACE(kCATrace_AUBaseRenderStart, mComponentInstance, (uintptr_t)this, inBusNumber, inFramesToProcess, (uintptr_t)ioData.mBuffers[0].mData);
+ DISABLE_DENORMALS
+
+ try {
+ ca_require(IsInitialized(), Uninitialized);
+ ca_require(mAudioUnitAPIVersion >= 2, ParamErr);
+ if (inFramesToProcess > mMaxFramesPerSlice) {
+ static time_t lastTimeMessagePrinted = 0;
+ time_t now = time(NULL);
+ if (now != lastTimeMessagePrinted) {
+ lastTimeMessagePrinted = now;
+ syslog(LOG_ERR, "kAudioUnitErr_TooManyFramesToProcess : inFramesToProcess=%u, mMaxFramesPerSlice=%u", (unsigned)inFramesToProcess, (unsigned)mMaxFramesPerSlice);
+ DebugMessageN4("%s:%d inFramesToProcess=%u, mMaxFramesPerSlice=%u; TooManyFrames", __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)mMaxFramesPerSlice);
+ }
+ goto TooManyFrames;
+ }
+ ca_require (!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), ParamErr);
+
+ AUOutputElement *output = GetOutput(inBusNumber); // will throw if non-existant
+ if (output->GetStreamFormat().NumberChannelStreams() != ioData.mNumberBuffers) {
+ DebugMessageN4("%s:%d ioData.mNumberBuffers=%u, output->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError",
+ __FILE__, __LINE__, (unsigned)ioData.mNumberBuffers, (unsigned)output->GetStreamFormat().NumberChannelStreams());
+ goto ParamErr;
+ }
+
+ unsigned expectedBufferByteSize = inFramesToProcess * output->GetStreamFormat().mBytesPerFrame;
+ for (unsigned ibuf = 0; ibuf < ioData.mNumberBuffers; ++ibuf) {
+ AudioBuffer &buf = ioData.mBuffers[ibuf];
+ if (buf.mData != NULL) {
+ // only care about the size if the buffer is non-null
+ if (buf.mDataByteSize < expectedBufferByteSize) {
+ // if the buffer is too small, we cannot render safely. kAudio_ParamError.
+ DebugMessageN7("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; ioData.mBuffers[%u].mDataByteSize=%u; kAudio_ParamError",
+ __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)output->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, ibuf, (unsigned)buf.mDataByteSize);
+ goto ParamErr;
+ }
+ // Some clients incorrectly pass bigger buffers than expectedBufferByteSize.
+ // We will generally set the buffer size at the end of rendering, before we return.
+ // However we should ensure that no one, DURING rendering, READS a
+ // potentially incorrect size. This can lead to doing too much work, or
+ // reading past the end of an input buffer into unmapped memory.
+ buf.mDataByteSize = expectedBufferByteSize;
+ }
+ }
+
+ if (WantsRenderThreadID())
+ {
+ #if TARGET_OS_MAC
+ mRenderThreadID = pthread_self();
+ #elif TARGET_OS_WIN32
+ mRenderThreadID = GetCurrentThreadId();
+ #endif
+ }
+
+ AudioUnitRenderActionFlags flags;
+ if (mRenderCallbacksTouched) {
+ mRenderCallbacks.update();
+ flags = ioActionFlags | kAudioUnitRenderAction_PreRender;
+ for (rcit = mRenderCallbacks.begin(); rcit != mRenderCallbacks.end(); ++rcit) {
+ RenderCallback &rc = *rcit;
+ AUTRACE(kCATrace_AUBaseRenderCallbackStart, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 1, 0);
+ (*(AURenderCallback)rc.mRenderNotify)(rc.mRenderNotifyRefCon,
+ &flags,
+ &inTimeStamp, inBusNumber, inFramesToProcess, &ioData);
+ AUTRACE(kCATrace_AUBaseRenderCallbackEnd, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 1, 0);
+ }
+ }
+
+ theError = DoRenderBus(ioActionFlags, inTimeStamp, inBusNumber, output, inFramesToProcess, ioData);
+
+ if (mRenderCallbacksTouched) {
+ flags = ioActionFlags | kAudioUnitRenderAction_PostRender;
+
+ if (SetRenderError (theError)) {
+ flags |= kAudioUnitRenderAction_PostRenderError;
+ }
+
+ for (rcit = mRenderCallbacks.begin(); rcit != mRenderCallbacks.end(); ++rcit) {
+ RenderCallback &rc = *rcit;
+ AUTRACE(kCATrace_AUBaseRenderCallbackStart, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 2, 0);
+ (*(AURenderCallback)rc.mRenderNotify)(rc.mRenderNotifyRefCon,
+ &flags,
+ &inTimeStamp, inBusNumber, inFramesToProcess, &ioData);
+ AUTRACE(kCATrace_AUBaseRenderCallbackEnd, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 2, 0);
+ }
+ }
+
+ // The vector's being emptied
+ // because these events should only apply to this Render cycle, so anything
+ // left over is from a preceding cycle and should be dumped. New scheduled
+ // parameters must be scheduled from the next pre-render callback.
+ if (!mParamList.empty())
+ mParamList.clear();
+
+ }
+ catch (OSStatus err) {
+ theError = err;
+ goto errexit;
+ }
+ catch (...) {
+ theError = -1;
+ goto errexit;
+ }
+done:
+ RESTORE_DENORMALS
+ AUTRACE(kCATrace_AUBaseRenderEnd, mComponentInstance, (intptr_t)this, theError, ioActionFlags, CATrace::ablData(ioData));
+
+ return theError;
+
+Uninitialized: theError = kAudioUnitErr_Uninitialized; goto errexit;
+ParamErr: theError = kAudio_ParamError; goto errexit;
+TooManyFrames: theError = kAudioUnitErr_TooManyFramesToProcess; goto errexit;
+errexit:
+ DebugMessageN2 (" from %s, render err: %d", GetLoggingString(), (int)theError);
+ SetRenderError(theError);
+ goto done;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DoProcess ( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inFramesToProcess,
+ AudioBufferList & ioData)
+{
+ OSStatus theError;
+ AUTRACE(kCATrace_AUBaseRenderStart, mComponentInstance, (intptr_t)this, -1, inFramesToProcess, 0);
+ DISABLE_DENORMALS
+
+ try {
+
+ if (!(ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)) {
+ ca_require(IsInitialized(), Uninitialized);
+ ca_require(inFramesToProcess <= mMaxFramesPerSlice, TooManyFrames);
+ ca_require(!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), ParamErr);
+
+ AUInputElement *input = GetInput(0); // will throw if non-existant
+ if (input->GetStreamFormat().NumberChannelStreams() != ioData.mNumberBuffers) {
+ DebugMessageN4("%s:%d ioData.mNumberBuffers=%u, input->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError",
+ __FILE__, __LINE__, (unsigned)ioData.mNumberBuffers, (unsigned)input->GetStreamFormat().NumberChannelStreams());
+ goto ParamErr;
+ }
+
+ unsigned expectedBufferByteSize = inFramesToProcess * input->GetStreamFormat().mBytesPerFrame;
+ for (unsigned ibuf = 0; ibuf < ioData.mNumberBuffers; ++ibuf) {
+ AudioBuffer &buf = ioData.mBuffers[ibuf];
+ if (buf.mData != NULL) {
+ // only care about the size if the buffer is non-null
+ if (buf.mDataByteSize < expectedBufferByteSize) {
+ // if the buffer is too small, we cannot render safely. kAudio_ParamError.
+ DebugMessageN7("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; ioData.mBuffers[%u].mDataByteSize=%u; kAudio_ParamError",
+ __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)input->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, ibuf, (unsigned)buf.mDataByteSize);
+ goto ParamErr;
+ }
+ // Some clients incorrectly pass bigger buffers than expectedBufferByteSize.
+ // We will generally set the buffer size at the end of rendering, before we return.
+ // However we should ensure that no one, DURING rendering, READS a
+ // potentially incorrect size. This can lead to doing too much work, or
+ // reading past the end of an input buffer into unmapped memory.
+ buf.mDataByteSize = expectedBufferByteSize;
+ }
+ }
+ }
+
+ if (WantsRenderThreadID())
+ {
+ #if TARGET_OS_MAC
+ mRenderThreadID = pthread_self();
+ #elif TARGET_OS_WIN32
+ mRenderThreadID = GetCurrentThreadId();
+ #endif
+ }
+
+ if (NeedsToRender (inTimeStamp)) {
+ theError = ProcessBufferLists (ioActionFlags, ioData, ioData, inFramesToProcess);
+ } else
+ theError = noErr;
+
+ }
+ catch (OSStatus err) {
+ theError = err;
+ goto errexit;
+ }
+ catch (...) {
+ theError = -1;
+ goto errexit;
+ }
+done:
+ RESTORE_DENORMALS
+ AUTRACE(kCATrace_AUBaseRenderEnd, mComponentInstance, (intptr_t)this, theError, ioActionFlags, CATrace::ablData(ioData));
+
+ return theError;
+
+Uninitialized: theError = kAudioUnitErr_Uninitialized; goto errexit;
+ParamErr: theError = kAudio_ParamError; goto errexit;
+TooManyFrames: theError = kAudioUnitErr_TooManyFramesToProcess; goto errexit;
+errexit:
+ DebugMessageN2 (" from %s, process err: %d", GetLoggingString(), (int)theError);
+ SetRenderError(theError);
+ goto done;
+}
+
+OSStatus AUBase::DoProcessMultiple ( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inFramesToProcess,
+ UInt32 inNumberInputBufferLists,
+ const AudioBufferList ** inInputBufferLists,
+ UInt32 inNumberOutputBufferLists,
+ AudioBufferList ** ioOutputBufferLists)
+{
+ OSStatus theError;
+ DISABLE_DENORMALS
+
+ try {
+
+ if (!(ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)) {
+ ca_require(IsInitialized(), Uninitialized);
+ ca_require(inFramesToProcess <= mMaxFramesPerSlice, TooManyFrames);
+ ca_require (!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), ParamErr);
+
+ for (unsigned ibl = 0; ibl < inNumberInputBufferLists; ++ibl) {
+ if (inInputBufferLists[ibl] != NULL) {
+ AUInputElement *input = GetInput(ibl); // will throw if non-existant
+ unsigned expectedBufferByteSize = inFramesToProcess * input->GetStreamFormat().mBytesPerFrame;
+
+ if (input->GetStreamFormat().NumberChannelStreams() != inInputBufferLists[ibl]->mNumberBuffers) {
+ DebugMessageN5("%s:%d inInputBufferLists[%u]->mNumberBuffers=%u, input->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError",
+ __FILE__, __LINE__, ibl, (unsigned)inInputBufferLists[ibl]->mNumberBuffers, (unsigned)input->GetStreamFormat().NumberChannelStreams());
+ goto ParamErr;
+ }
+
+ for (unsigned ibuf = 0; ibuf < inInputBufferLists[ibl]->mNumberBuffers; ++ibuf) {
+ const AudioBuffer &buf = inInputBufferLists[ibl]->mBuffers[ibuf];
+ if (buf.mData != NULL) {
+ if (buf.mDataByteSize < expectedBufferByteSize) {
+ // the buffer is too small
+ DebugMessageN8("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; inInputBufferLists[%u].mBuffers[%u].mDataByteSize=%u; kAudio_ParamError",
+ __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)input->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, ibl, ibuf, (unsigned)buf.mDataByteSize);
+ goto ParamErr;
+ }
+ } else {
+ // the buffer must exist
+ goto ParamErr;
+ }
+ }
+ } else {
+ // skip NULL input audio buffer list
+ }
+ }
+
+ for (unsigned obl = 0; obl < inNumberOutputBufferLists; ++obl) {
+ if (ioOutputBufferLists[obl] != NULL) {
+ AUOutputElement *output = GetOutput(obl); // will throw if non-existant
+ unsigned expectedBufferByteSize = inFramesToProcess * output->GetStreamFormat().mBytesPerFrame;
+
+ if (output->GetStreamFormat().NumberChannelStreams() != ioOutputBufferLists[obl]->mNumberBuffers) {
+ DebugMessageN5("%s:%d ioOutputBufferLists[%u]->mNumberBuffers=%u, output->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError",
+ __FILE__, __LINE__, obl, (unsigned)ioOutputBufferLists[obl]->mNumberBuffers, (unsigned)output->GetStreamFormat().NumberChannelStreams());
+ goto ParamErr;
+ }
+
+ for (unsigned obuf = 0; obuf < ioOutputBufferLists[obl]->mNumberBuffers; ++obuf) {
+ AudioBuffer &buf = ioOutputBufferLists[obl]->mBuffers[obuf];
+ if (buf.mData != NULL) {
+ // only care about the size if the buffer is non-null
+ if (buf.mDataByteSize < expectedBufferByteSize) {
+ // if the buffer is too small, we cannot render safely. kAudio_ParamError.
+ DebugMessageN8("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; ioOutputBufferLists[%u]->mBuffers[%u].mDataByteSize=%u; kAudio_ParamError",
+ __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)output->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, obl, obuf, (unsigned)buf.mDataByteSize);
+ goto ParamErr;
+ }
+ // Some clients incorrectly pass bigger buffers than expectedBufferByteSize.
+ // We will generally set the buffer size at the end of rendering, before we return.
+ // However we should ensure that no one, DURING rendering, READS a
+ // potentially incorrect size. This can lead to doing too much work, or
+ // reading past the end of an input buffer into unmapped memory.
+ buf.mDataByteSize = expectedBufferByteSize;
+ }
+ }
+ } else {
+ // skip NULL output audio buffer list
+ }
+ }
+ }
+
+ if (WantsRenderThreadID())
+ {
+#if TARGET_OS_MAC
+ mRenderThreadID = pthread_self();
+#elif TARGET_OS_WIN32
+ mRenderThreadID = GetCurrentThreadId();
+#endif
+ }
+
+ if (NeedsToRender (inTimeStamp)) {
+ theError = ProcessMultipleBufferLists (ioActionFlags, inFramesToProcess, inNumberInputBufferLists, inInputBufferLists, inNumberOutputBufferLists, ioOutputBufferLists);
+ } else
+ theError = noErr;
+ }
+ catch (OSStatus err) {
+ theError = err;
+ goto errexit;
+ }
+ catch (...) {
+ theError = -1;
+ goto errexit;
+ }
+done:
+ RESTORE_DENORMALS
+
+ return theError;
+
+Uninitialized: theError = kAudioUnitErr_Uninitialized; goto errexit;
+ParamErr: theError = kAudio_ParamError; goto errexit;
+TooManyFrames: theError = kAudioUnitErr_TooManyFramesToProcess; goto errexit;
+errexit:
+ DebugMessageN2 (" from %s, processmultiple err: %d", GetLoggingString(), (int)theError);
+ SetRenderError(theError);
+ goto done;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::SetInputCallback( UInt32 inPropertyID,
+ AudioUnitElement inElement,
+ AURenderCallback inProc,
+ void * inRefCon)
+{
+ AUInputElement *input = GetInput(inElement); // may throw
+
+ input->SetInputCallback(inProc, inRefCon);
+ PropertyChanged(inPropertyID, kAudioUnitScope_Input, inElement);
+
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::SetConnection( const AudioUnitConnection & inConnection)
+{
+
+ OSStatus err;
+ AUInputElement *input = GetInput(inConnection.destInputNumber); // may throw
+
+ if (inConnection.sourceAudioUnit) {
+ // connecting, not disconnecting
+ CAStreamBasicDescription sourceDesc;
+ UInt32 size = sizeof(CAStreamBasicDescription);
+ ca_require_noerr(err = AudioUnitGetProperty(
+ inConnection.sourceAudioUnit,
+ kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Output,
+ inConnection.sourceOutputNumber,
+ &sourceDesc,
+ &size), errexit);
+ ca_require_noerr(err = DispatchSetProperty (kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Input, inConnection.destInputNumber,
+ &sourceDesc, sizeof(CAStreamBasicDescription)), errexit);
+ }
+ input->SetConnection(inConnection);
+
+ PropertyChanged(kAudioUnitProperty_MakeConnection, kAudioUnitScope_Input, inConnection.destInputNumber);
+ return noErr;
+
+errexit:
+ return err;
+}
+
+//_____________________________________________________________________________
+//
+UInt32 AUBase::SupportedNumChannels ( const AUChannelInfo** outInfo)
+{
+ return 0;
+}
+
+//_____________________________________________________________________________
+//
+bool AUBase::ValidFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inNewFormat)
+{
+ return FormatIsCanonical(inNewFormat);
+}
+
+//_____________________________________________________________________________
+//
+bool AUBase::IsStreamFormatWritable( AudioUnitScope scope,
+ AudioUnitElement element)
+{
+ switch (scope) {
+ case kAudioUnitScope_Input:
+ {
+ AUInputElement *input = GetInput(element);
+ if (input->HasConnection()) return false; // can't write format when input comes from connection
+ }
+ // ... fall ...
+ case kAudioUnitScope_Output:
+ return StreamFormatWritable(scope, element);
+
+//#warning "aliasing of global scope format should be pushed to subclasses"
+ case kAudioUnitScope_Global:
+ return StreamFormatWritable(kAudioUnitScope_Output, 0);
+ }
+ return false;
+}
+
+//_____________________________________________________________________________
+//
+const CAStreamBasicDescription &
+ AUBase::GetStreamFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+//#warning "aliasing of global scope format should be pushed to subclasses"
+ AUIOElement *element;
+
+ switch (inScope) {
+ case kAudioUnitScope_Input:
+ element = Inputs().GetIOElement(inElement);
+ break;
+ case kAudioUnitScope_Output:
+ element = Outputs().GetIOElement(inElement);
+ break;
+ case kAudioUnitScope_Global: // global stream description is an alias for that of output 0
+ element = Outputs().GetIOElement(0);
+ break;
+ default:
+ COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+ }
+ return element->GetStreamFormat();
+}
+
+OSStatus AUBase::SetBusCount( AudioUnitScope inScope,
+ UInt32 inCount)
+{
+ if (IsInitialized())
+ return kAudioUnitErr_Initialized;
+
+ GetScope(inScope).SetNumberOfElements(inCount);
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::ChangeStreamFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inPrevFormat,
+ const CAStreamBasicDescription & inNewFormat)
+{
+//#warning "aliasing of global scope format should be pushed to subclasses"
+ AUIOElement *element;
+
+ switch (inScope) {
+ case kAudioUnitScope_Input:
+ element = Inputs().GetIOElement(inElement);
+ break;
+ case kAudioUnitScope_Output:
+ element = Outputs().GetIOElement(inElement);
+ break;
+ case kAudioUnitScope_Global:
+ element = Outputs().GetIOElement(0);
+ break;
+ default:
+ COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+ }
+ element->SetStreamFormat(inNewFormat);
+ PropertyChanged(kAudioUnitProperty_StreamFormat, inScope, inElement);
+ return noErr;
+}
+
+UInt32 AUBase::GetChannelLayoutTags( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag * outLayoutTags)
+{
+ return GetIOElement(inScope, inElement)->GetChannelLayoutTags(outLayoutTags);
+}
+
+UInt32 AUBase::GetAudioChannelLayout( AudioUnitScope scope,
+ AudioUnitElement element,
+ AudioChannelLayout * outLayoutPtr,
+ Boolean & outWritable)
+{
+ AUIOElement * el = GetIOElement(scope, element);
+ return el->GetAudioChannelLayout(outLayoutPtr, outWritable);
+}
+
+OSStatus AUBase::RemoveAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ OSStatus result = noErr;
+ AUIOElement * el = GetIOElement(inScope, inElement);
+ Boolean writable;
+ if (el->GetAudioChannelLayout(NULL, writable)) {
+ result = el->RemoveAudioChannelLayout();
+ }
+ return result;
+}
+
+OSStatus AUBase::SetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const AudioChannelLayout * inLayout)
+{
+ AUIOElement* ioEl = GetIOElement (inScope, inElement);
+
+ // the num channels of the layout HAS TO MATCH the current channels of the Element's stream format
+ UInt32 currentChannels = ioEl->GetStreamFormat().NumberChannels();
+ UInt32 numChannelsInLayout = CAAudioChannelLayout::NumberChannels(*inLayout);
+ if (currentChannels != numChannelsInLayout)
+ return kAudioUnitErr_InvalidPropertyValue;
+
+ UInt32 numLayouts = GetChannelLayoutTags (inScope, inElement, NULL);
+ if (numLayouts == 0)
+ return kAudioUnitErr_InvalidProperty;
+ AudioChannelLayoutTag *tags = (AudioChannelLayoutTag *)CA_malloc (numLayouts * sizeof (AudioChannelLayoutTag));
+ GetChannelLayoutTags (inScope, inElement, tags);
+ bool foundTag = false;
+ for (unsigned int i = 0; i < numLayouts; ++i) {
+ if (tags[i] == inLayout->mChannelLayoutTag || tags[i] == kAudioChannelLayoutTag_UseChannelDescriptions) {
+ foundTag = true;
+ break;
+ }
+ }
+ free(tags);
+
+ if (foundTag == false)
+ return kAudioUnitErr_InvalidPropertyValue;
+
+ return ioEl->SetAudioChannelLayout(*inLayout);
+}
+
+static void AddNumToDictionary (CFMutableDictionaryRef dict, CFStringRef key, SInt32 value)
+{
+ CFNumberRef num = CFNumberCreate (NULL, kCFNumberSInt32Type, &value);
+ CFDictionarySetValue (dict, key, num);
+ CFRelease (num);
+}
+
+#define kCurrentSavedStateVersion 0
+
+OSStatus AUBase::SaveState( CFPropertyListRef * outData)
+{
+ AudioComponentDescription desc = GetComponentDescription();
+
+ CFMutableDictionaryRef dict = CFDictionaryCreateMutable (NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+// first step -> save the version to the data ref
+ SInt32 value = kCurrentSavedStateVersion;
+ AddNumToDictionary (dict, kVersionString, value);
+
+// second step -> save the component type, subtype, manu to the data ref
+ value = desc.componentType;
+ AddNumToDictionary (dict, kTypeString, value);
+
+ value = desc.componentSubType;
+ AddNumToDictionary (dict, kSubtypeString, value);
+
+ value = desc.componentManufacturer;
+ AddNumToDictionary (dict, kManufacturerString, value);
+
+// fourth step -> save the state of all parameters on all scopes and elements
+ CFMutableDataRef data = CFDataCreateMutable(NULL, 0);
+ for (AudioUnitScope iscope = 0; iscope < 3; ++iscope) {
+ AUScope &scope = GetScope(iscope);
+ scope.SaveState (data);
+ }
+
+ SaveExtendedScopes(data);
+
+// save all this in the data section of the dictionary
+ CFDictionarySetValue(dict, kDataString, data);
+ CFRelease (data);
+
+//OK - now we're going to do some properties
+//save the preset name...
+ CFDictionarySetValue (dict, kNameString, mCurrentPreset.presetName);
+
+// Does the unit support the RenderQuality property - if so, save it...
+ value = 0;
+ OSStatus result = DispatchGetProperty (kAudioUnitProperty_RenderQuality,
+ kAudioUnitScope_Global,
+ 0,
+ &value);
+
+ if (result == noErr) {
+ AddNumToDictionary (dict, kRenderQualityString, value);
+ }
+
+// Does the unit support the CPULoad Quality property - if so, save it...
+ Float32 cpuLoad;
+ result = DispatchGetProperty (6/*kAudioUnitProperty_CPULoad*/,
+ kAudioUnitScope_Global,
+ 0,
+ &cpuLoad);
+
+ if (result == noErr) {
+ CFNumberRef num = CFNumberCreate (NULL, kCFNumberFloatType, &cpuLoad);
+ CFDictionarySetValue (dict, kCPULoadString, num);
+ CFRelease (num);
+ }
+
+// Do we have any element names for any of our scopes?
+ // first check to see if we have any names...
+ bool foundName = false;
+ for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
+ foundName = GetScope (i).HasElementWithName();
+ if (foundName)
+ break;
+ }
+ // OK - we found a name away we go...
+ if (foundName) {
+ CFMutableDictionaryRef nameDict = CFDictionaryCreateMutable (NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
+ GetScope (i).AddElementNamesToDict (nameDict);
+ }
+
+ CFDictionarySetValue (dict, kElementNameString, nameDict);
+ CFRelease (nameDict);
+ }
+
+// we're done!!!
+ *outData = dict;
+
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::RestoreState( CFPropertyListRef plist)
+{
+ if (CFGetTypeID(plist) != CFDictionaryGetTypeID()) return kAudioUnitErr_InvalidPropertyValue;
+
+ AudioComponentDescription desc = GetComponentDescription();
+
+ CFDictionaryRef dict = static_cast<CFDictionaryRef>(plist);
+
+// zeroeth step - make sure the Part key is NOT present, as this method is used
+// to restore the GLOBAL state of the dictionary
+ if (CFDictionaryContainsKey (dict, kPartString))
+ return kAudioUnitErr_InvalidPropertyValue;
+
+// first step -> check the saved version in the data ref
+// at this point we're only dealing with version==0
+ CFNumberRef cfnum = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue (dict, kVersionString));
+ if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue;
+ SInt32 value;
+ CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+ if (value != kCurrentSavedStateVersion) return kAudioUnitErr_InvalidPropertyValue;
+
+// second step -> check that this data belongs to this kind of audio unit
+// by checking the component subtype and manuID
+// We're not checking the type, since there may be different versions (effect, format-converter, offline)
+// of essentially the same AU
+ cfnum = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue (dict, kSubtypeString));
+ if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue;
+ CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+ if (UInt32(value) != desc.componentSubType) return kAudioUnitErr_InvalidPropertyValue;
+
+ cfnum = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue (dict, kManufacturerString));
+ if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue;
+ CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+ if (UInt32(value) != desc.componentManufacturer) return kAudioUnitErr_InvalidPropertyValue;
+
+// fourth step -> restore the state of all of the parameters for each scope and element
+ CFDataRef data = reinterpret_cast<CFDataRef>(CFDictionaryGetValue (dict, kDataString));
+ if (data != NULL)
+ {
+ const UInt8 *p, *pend;
+
+ p = CFDataGetBytePtr(data);
+ pend = p + CFDataGetLength(data);
+
+ // we have a zero length data, which may just mean there were no parameters to save!
+ // if (p >= pend) return noErr;
+
+ while (p < pend) {
+ UInt32 scopeIdx = CFSwapInt32BigToHost(*(UInt32 *)p);
+ p += sizeof(UInt32);
+
+ AUScope &scope = GetScope(scopeIdx);
+ p = scope.RestoreState(p);
+ }
+ }
+
+//OK - now we're going to do some properties
+//restore the preset name...
+ CFStringRef name = reinterpret_cast<CFStringRef>(CFDictionaryGetValue (dict, kNameString));
+ if (mCurrentPreset.presetName) CFRelease (mCurrentPreset.presetName);
+ if (name)
+ {
+ mCurrentPreset.presetName = name;
+ mCurrentPreset.presetNumber = -1;
+ }
+ else { // no name entry make the default one
+ mCurrentPreset.presetName = kUntitledString;
+ mCurrentPreset.presetNumber = -1;
+ }
+
+ CFRetain (mCurrentPreset.presetName);
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+#ifndef __LP64__
+ PropertyChanged(kAudioUnitProperty_CurrentPreset, kAudioUnitScope_Global, 0);
+#endif
+#endif
+ PropertyChanged(kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global, 0);
+
+// Does the dict contain render quality information?
+ if (CFDictionaryGetValueIfPresent (dict, kRenderQualityString, reinterpret_cast<const void**>(&cfnum)))
+ {
+ CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+ DispatchSetProperty (kAudioUnitProperty_RenderQuality,
+ kAudioUnitScope_Global,
+ 0,
+ &value,
+ sizeof(value));
+ }
+
+// Does the unit support the CPULoad Quality property - if so, save it...
+ if (CFDictionaryGetValueIfPresent (dict, kCPULoadString, reinterpret_cast<const void**>(&cfnum)))
+ {
+ Float32 floatValue;
+ CFNumberGetValue (cfnum, kCFNumberFloatType, &floatValue);
+ DispatchSetProperty (6/*kAudioUnitProperty_CPULoad*/,
+ kAudioUnitScope_Global,
+ 0,
+ &floatValue,
+ sizeof(floatValue));
+ }
+
+// Do we have any element names for any of our scopes?
+ CFDictionaryRef nameDict;
+ if (CFDictionaryGetValueIfPresent (dict, kElementNameString, reinterpret_cast<const void**>(&nameDict)))
+ {
+ char string[64];
+ for (int i = 0; i < kNumScopes; ++i)
+ {
+ snprintf (string, sizeof(string), "%d", i);
+ CFStringRef key = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
+ CFDictionaryRef elementDict;
+ if (CFDictionaryGetValueIfPresent (nameDict, key, reinterpret_cast<const void**>(&elementDict)))
+ {
+ bool didAddElements = GetScope (i).RestoreElementNames (elementDict);
+ if (didAddElements)
+ PropertyChanged (kAudioUnitProperty_ElementCount, i, 0);
+ }
+ CFRelease (key);
+ }
+ }
+
+ return noErr;
+}
+
+OSStatus AUBase::GetPresets ( CFArrayRef * outData) const
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+OSStatus AUBase::NewFactoryPresetSet (const AUPreset & inNewFactoryPreset)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+OSStatus AUBase::NewCustomPresetSet (const AUPreset & inNewCustomPreset)
+{
+ CFRelease (mCurrentPreset.presetName);
+ mCurrentPreset = inNewCustomPreset;
+ CFRetain (mCurrentPreset.presetName);
+ return noErr;
+}
+
+ // set the default preset for the unit -> the number of the preset MUST be >= 0
+ // and the name should be valid, or the preset WON'T take
+bool AUBase::SetAFactoryPresetAsCurrent (const AUPreset & inPreset)
+{
+ if (inPreset.presetNumber < 0 || inPreset.presetName == NULL) return false;
+ CFRelease (mCurrentPreset.presetName);
+ mCurrentPreset = inPreset;
+ CFRetain (mCurrentPreset.presetName);
+ return true;
+}
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+int AUBase::GetNumCustomUIComponents ()
+{
+ return 0;
+}
+
+void AUBase::GetUIComponentDescs (ComponentDescription* inDescArray) {}
+#endif
+
+bool AUBase::HasIcon ()
+{
+#if !CA_NO_AU_UI_FEATURES
+ CFURLRef url = CopyIconLocation();
+ if (url) {
+ CFRelease (url);
+ return true;
+ }
+#endif
+ return false;
+}
+
+CFURLRef AUBase::CopyIconLocation ()
+{
+ return NULL;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::GetParameterList( AudioUnitScope inScope,
+ AudioUnitParameterID * outParameterList,
+ UInt32 & outNumParameters)
+{
+ AUScope &scope = GetScope(inScope);
+ AUElement *elementWithMostParameters = NULL;
+ UInt32 maxNumParams = 0;
+
+ int nElems = scope.GetNumberOfElements();
+ for (int ielem = 0; ielem < nElems; ++ielem) {
+ AUElement *element = scope.GetElement(ielem);
+ UInt32 nParams = element->GetNumberOfParameters();
+ if (nParams > maxNumParams) {
+ maxNumParams = nParams;
+ elementWithMostParameters = element;
+ }
+ }
+
+ if (outParameterList != NULL && elementWithMostParameters != NULL)
+ elementWithMostParameters->GetParameterList(outParameterList);
+
+ outNumParameters = maxNumParams;
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::GetParameterInfo( AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ AudioUnitParameterInfo &outParameterInfo )
+{
+ return kAudioUnitErr_InvalidParameter;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::GetParameterValueStrings(AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ CFArrayRef * outStrings)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::GetParameterHistoryInfo( AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ Float32 & outUpdatesPerSecond,
+ Float32 & outHistoryDurationInSeconds)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::CopyClumpName( AudioUnitScope inScope,
+ UInt32 inClumpID,
+ UInt32 inDesiredNameLength,
+ CFStringRef * outClumpName)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::SetNumberOfElements( AudioUnitScope inScope,
+ UInt32 numElements)
+{
+ if (inScope == kAudioUnitScope_Global && numElements != 1)
+ COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+
+ GetScope(inScope).SetNumberOfElements(numElements);
+}
+
+//_____________________________________________________________________________
+//
+AUElement * AUBase::CreateElement( AudioUnitScope scope,
+ AudioUnitElement element)
+{
+ switch (scope) {
+ case kAudioUnitScope_Global:
+ return new AUElement(this);
+ case kAudioUnitScope_Input:
+ return new AUInputElement(this);
+ case kAudioUnitScope_Output:
+ return new AUOutputElement(this);
+#if !CA_BASIC_AU_FEATURES
+ case kAudioUnitScope_Group:
+ return new AUElement(this);
+ case kAudioUnitScope_Part:
+ return new AUElement(this);
+#endif
+ }
+ COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+
+ return NULL; // get rid of compiler warning
+}
+
+//_____________________________________________________________________________
+//
+bool AUBase::FormatIsCanonical( const CAStreamBasicDescription &f)
+{
+ return (f.mFormatID == kAudioFormatLinearPCM
+ && f.mFramesPerPacket == 1
+ && f.mBytesPerPacket == f.mBytesPerFrame
+// && f.mChannelsPerFrame >= 0 -- this is always true since it's unsigned
+ // so far, it's a valid PCM format
+#if CA_PREFER_FIXED_POINT
+ && (f.mFormatFlags & kLinearPCMFormatFlagIsFloat) == 0
+ && (((f.mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift) == kAudioUnitSampleFractionBits)
+#else
+ && (f.mFormatFlags & kLinearPCMFormatFlagIsFloat) != 0
+#endif
+ && ((f.mChannelsPerFrame == 1) || ((f.mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0) == (mAudioUnitAPIVersion == 1))
+#if TARGET_RT_BIG_ENDIAN
+ && (f.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) != 0
+#else
+ && (f.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) == 0
+#endif
+ && f.mBitsPerChannel == 8 * sizeof(AudioUnitSampleType)
+ && f.mBytesPerFrame == f.NumberInterleavedChannels() * sizeof(AudioUnitSampleType)
+ );
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::MakeCanonicalFormat( CAStreamBasicDescription & f,
+ int nChannels)
+{
+ f.SetAUCanonical(nChannels, mAudioUnitAPIVersion < 2); // interleaved for v1, non for v2
+ f.mSampleRate = 0.0;
+}
+
+const Float64 AUBase::kNoLastRenderedSampleTime = -1.;
+
+#include "AUBaseHelper.h"
+
+char* AUBase::GetLoggingString () const
+{
+ if (mLogString) return mLogString;
+
+ AudioComponentDescription desc = GetComponentDescription();
+
+ const size_t logStringSize = 256;
+ const_cast<AUBase*>(this)->mLogString = new char[logStringSize];
+ char str[24];
+ char str1[24];
+ char str2[24];
+ snprintf (const_cast<AUBase*>(this)->mLogString, logStringSize, "AU (%p): %s %s %s",
+ GetComponentInstance(),
+ CAStringForOSType(desc.componentType, str, sizeof(str)),
+ CAStringForOSType(desc.componentSubType, str1, sizeof(str1)),
+ CAStringForOSType(desc.componentManufacturer, str2, sizeof(str2)));
+
+ return mLogString;
+}
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.h
new file mode 100644
index 0000000000..0c78221cc8
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.h
@@ -0,0 +1,1048 @@
+/*
+ File: AUBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUBase_h__
+#define __AUBase_h__
+
+#include <TargetConditionals.h>
+
+#if TARGET_OS_MAC
+ #include <pthread.h>
+#elif TARGET_OS_WIN32
+ #include <windows.h>
+#else
+ #error Unsupported Operating System
+#endif
+
+#include <vector>
+
+#include "AUScopeElement.h"
+#include "AUInputElement.h"
+#include "AUOutputElement.h"
+#include "AUBuffer.h"
+#include "CAMath.h"
+#include "CAThreadSafeList.h"
+#include "CAVectorUnit.h"
+#include "CAMutex.h"
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnit.h>
+ #if !CA_BASIC_AU_FEATURES
+ #include <AudioUnit/MusicDevice.h>
+ #endif
+#else
+ #include "AudioUnit.h"
+ #if !CA_BASIC_AU_FEATURES
+ #include "MusicDevice.h"
+ #endif
+#endif
+
+#ifndef AUTRACE
+ #define AUTRACE(code, obj, a, b, c, d)
+#endif
+
+#include "AUPlugInDispatch.h"
+
+
+
+// ________________________________________________________________________
+// These are to be moved to the public AudioUnit headers
+
+#define kAUDefaultSampleRate 44100.0
+#if !TARGET_OS_WIN32
+#define kAUDefaultMaxFramesPerSlice 1156
+//this allows enough default frames for a 512 dest 44K and SRC from 96K
+// add a padding of 4 frames for any altivec rounding
+#else
+#define kAUDefaultMaxFramesPerSlice 2048
+#endif
+
+// ________________________________________________________________________
+
+/*! @class AUBase */
+class AUBase : public ComponentBase {
+public:
+
+ /*! @ctor AUBase */
+ AUBase( AudioComponentInstance inInstance,
+ UInt32 numInputElements,
+ UInt32 numOutputElements,
+ UInt32 numGroupElements = 0);
+ /*! @dtor AUBase */
+ virtual ~AUBase();
+
+ /*! @method PostConstructor */
+ virtual void PostConstructor() { CreateElements(); }
+
+ /*! @method PreDestructor */
+ virtual void PreDestructor();
+
+ /*! @method CreateElements */
+ void CreateElements();
+ // Called immediately after construction, when virtual methods work.
+ // Or, a subclass may call this in order to have access to elements
+ // in its constructor.
+
+ /*! @method CreateExtendedElements */
+ virtual void CreateExtendedElements() {}
+
+#pragma mark -
+#pragma mark AU dispatch
+ // ________________________________________________________________________
+ // Virtual methods (mostly) directly corresponding to the entry points. Many of these
+ // have useful implementations here and will not need overriding.
+
+ /*! @method DoInitialize */
+ OSStatus DoInitialize();
+ // this implements the entry point and makes sure that initialization
+ // is only attempted exactly once...
+
+ /*! @method Initialize */
+ virtual OSStatus Initialize();
+ // ... so that overrides to this method can assume that they will only
+ // be called exactly once.
+
+ /*! @method IsInitialized */
+ bool IsInitialized() const { return mInitialized; }
+ /*! @method HasBegunInitializing */
+ bool HasBegunInitializing() const { return mHasBegunInitializing; }
+
+ /*! @method DoCleanup */
+ void DoCleanup();
+ // same pattern as with Initialize
+
+ /*! @method Cleanup */
+ virtual void Cleanup();
+
+ /*! @method Reset */
+ virtual OSStatus Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ // Note about GetPropertyInfo, GetProperty, SetProperty:
+ // Certain properties are trapped out in these dispatch functions and handled with different virtual
+ // methods. (To discourage hacks and keep vtable size down, these are non-virtual)
+
+ /*! @method DispatchGetPropertyInfo */
+ OSStatus DispatchGetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ /*! @method DispatchGetProperty */
+ OSStatus DispatchGetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+
+ /*! @method DispatchSetProperty */
+ OSStatus DispatchSetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+
+ OSStatus DispatchRemovePropertyValue( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ /*! @method GetPropertyInfo */
+ virtual OSStatus GetPropertyInfo( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ /*! @method GetProperty */
+ virtual OSStatus GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+
+ /*! @method SetProperty */
+ virtual OSStatus SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+
+ /*! @method ClearPropertyUsage */
+ virtual OSStatus RemovePropertyValue ( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ /*! @method AddPropertyListener */
+ virtual OSStatus AddPropertyListener( AudioUnitPropertyID inID,
+ AudioUnitPropertyListenerProc inProc,
+ void * inProcRefCon);
+
+ /*! @method RemovePropertyListener */
+ virtual OSStatus RemovePropertyListener( AudioUnitPropertyID inID,
+ AudioUnitPropertyListenerProc inProc,
+ void * inProcRefCon,
+ bool refConSpecified);
+
+ /*! @method SetRenderNotification */
+ virtual OSStatus SetRenderNotification( AURenderCallback inProc,
+ void * inRefCon);
+
+ /*! @method RemoveRenderNotification */
+ virtual OSStatus RemoveRenderNotification(
+ AURenderCallback inProc,
+ void * inRefCon);
+
+ /*! @method GetParameter */
+ virtual OSStatus GetParameter( AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioUnitParameterValue & outValue);
+
+ /*! @method SetParameter */
+ virtual OSStatus SetParameter( AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioUnitParameterValue inValue,
+ UInt32 inBufferOffsetInFrames);
+
+ /*! @method CanScheduleParams */
+ virtual bool CanScheduleParameters() const = 0;
+
+ /*! @method ScheduleParameter */
+ virtual OSStatus ScheduleParameter ( const AudioUnitParameterEvent *inParameterEvent,
+ UInt32 inNumEvents);
+
+
+ /*! @method DoRender */
+ OSStatus DoRender( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList & ioData);
+
+
+ /*! @method Process */
+ OSStatus DoProcess ( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inFramesToProcess,
+ AudioBufferList & ioData);
+
+ /*! @method ProcessMultiple */
+ OSStatus DoProcessMultiple ( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inFramesToProcess,
+ UInt32 inNumberInputBufferLists,
+ const AudioBufferList ** inInputBufferLists,
+ UInt32 inNumberOutputBufferLists,
+ AudioBufferList ** ioOutputBufferLists);
+
+ /*! @method ProcessBufferLists */
+ virtual OSStatus ProcessBufferLists( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioBufferList & inBuffer,
+ AudioBufferList & outBuffer,
+ UInt32 inFramesToProcess )
+ {
+ return kAudio_UnimplementedError;
+ }
+
+ /*! @method ProcessMultipleBufferLists */
+ virtual OSStatus ProcessMultipleBufferLists( AudioUnitRenderActionFlags & ioActionFlags,
+ UInt32 inFramesToProcess,
+ UInt32 inNumberInputBufferLists,
+ const AudioBufferList ** inInputBufferLists,
+ UInt32 inNumberOutputBufferLists,
+ AudioBufferList ** ioOutputBufferLists)
+ {
+ return kAudio_UnimplementedError;
+ }
+
+ /*! @method ComplexRender */
+ virtual OSStatus ComplexRender( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inOutputBusNumber,
+ UInt32 inNumberOfPackets,
+ UInt32 * outNumberOfPackets,
+ AudioStreamPacketDescription * outPacketDescriptions,
+ AudioBufferList & ioData,
+ void * outMetadata,
+ UInt32 * outMetadataByteSize)
+ {
+ return kAudio_UnimplementedError;
+ }
+
+ // Override this method if your AU processes multiple output busses completely independently --
+ // you'll want to just call Render without the NeedsToRender check.
+ // Otherwise, override Render().
+ //
+ // N.B. Implementations of this method can assume that the output's buffer list has already been
+ // prepared and access it with GetOutput(inBusNumber)->GetBufferList() instead of
+ // GetOutput(inBusNumber)->PrepareBuffer(nFrames) -- if PrepareBuffer is called, a
+ // copy may occur after rendering.
+ /*! @method RenderBus */
+ virtual OSStatus RenderBus( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames)
+ {
+ if (NeedsToRender(inTimeStamp))
+ return Render(ioActionFlags, inTimeStamp, inNumberFrames);
+ return noErr; // was presumably already rendered via another bus
+ }
+
+ // N.B. For a unit with only one output bus, it can assume in its implementation of this
+ // method that the output's buffer list has already been prepared and access it with
+ // GetOutput(0)->GetBufferList() instead of GetOutput(0)->PrepareBuffer(nFrames)
+ // -- if PrepareBuffer is called, a copy may occur after rendering.
+ /*! @method Render */
+ virtual OSStatus Render( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames)
+ {
+ return noErr;
+ }
+
+
+#pragma mark -
+#pragma mark Property Dispatch
+
+ static const Float64 kNoLastRenderedSampleTime;
+
+ // ________________________________________________________________________
+ // These are generated from DispatchGetProperty/DispatchGetPropertyInfo/DispatchSetProperty
+
+ /*! @method BusCountWritable */
+ virtual bool BusCountWritable( AudioUnitScope inScope)
+ {
+ return false;
+ }
+ virtual OSStatus SetBusCount( AudioUnitScope inScope,
+ UInt32 inCount);
+
+ /*! @method SetConnection */
+ virtual OSStatus SetConnection( const AudioUnitConnection & inConnection);
+
+ /*! @method SetInputCallback */
+ virtual OSStatus SetInputCallback( UInt32 inPropertyID,
+ AudioUnitElement inElement,
+ AURenderCallback inProc,
+ void * inRefCon);
+
+ /*! @method GetParameterList */
+ virtual OSStatus GetParameterList( AudioUnitScope inScope,
+ AudioUnitParameterID * outParameterList,
+ UInt32 & outNumParameters);
+ // outParameterList may be a null pointer
+
+ /*! @method GetParameterInfo */
+ virtual OSStatus GetParameterInfo( AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ AudioUnitParameterInfo & outParameterInfo);
+
+ virtual OSStatus GetParameterHistoryInfo(AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ Float32 & outUpdatesPerSecond,
+ Float32 & outHistoryDurationInSeconds);
+
+ /*! @method SaveState */
+ virtual OSStatus SaveState( CFPropertyListRef * outData);
+
+ /*! @method SaveExtendedScopes */
+ virtual void SaveExtendedScopes( CFMutableDataRef outData) {};
+
+ /*! @method RestoreState */
+ virtual OSStatus RestoreState( CFPropertyListRef inData);
+
+ /*! @method GetParameterValueStrings */
+ virtual OSStatus GetParameterValueStrings(AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ CFArrayRef * outStrings);
+
+ /*! @method CopyClumpName */
+ virtual OSStatus CopyClumpName( AudioUnitScope inScope,
+ UInt32 inClumpID,
+ UInt32 inDesiredNameLength,
+ CFStringRef * outClumpName);
+
+ /*! @method GetPresets */
+ virtual OSStatus GetPresets ( CFArrayRef * outData) const;
+
+ // set the default preset for the unit -> the number of the preset MUST be >= 0
+ // and the name should be valid, or the preset WON'T take
+ /*! @method SetAFactoryPresetAsCurrent */
+ bool SetAFactoryPresetAsCurrent (const AUPreset & inPreset);
+
+ // Called when someone sets a new, valid preset
+ // If this is a valid preset, then the subclass sets its state to that preset
+ // and returns noErr.
+ // If not a valid preset, return an error, and the pre-existing preset is restored
+ /*! @method NewFactoryPresetSet */
+ virtual OSStatus NewFactoryPresetSet (const AUPreset & inNewFactoryPreset);
+
+ /*! @method NewCustomPresetSet */
+ virtual OSStatus NewCustomPresetSet (const AUPreset & inNewCustomPreset);
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ /*! @method GetNumCustomUIComponents */
+ virtual int GetNumCustomUIComponents ();
+
+ /*! @method GetUIComponentDescs */
+ virtual void GetUIComponentDescs (ComponentDescription* inDescArray);
+#endif
+
+ /*! @method CopyIconLocation */
+ virtual CFURLRef CopyIconLocation ();
+
+ // default is no latency, and unimplemented tail time
+ /*! @method GetLatency */
+ virtual Float64 GetLatency() {return 0.0;}
+ /*! @method GetTailTime */
+ virtual Float64 GetTailTime() {return 0;}
+ /*! @method SupportsRampAndTail */
+ virtual bool SupportsTail () { return false; }
+
+ /*! @method IsStreamFormatWritable */
+ bool IsStreamFormatWritable( AudioUnitScope scope,
+ AudioUnitElement element);
+
+ /*! @method StreamFormatWritable */
+ virtual bool StreamFormatWritable( AudioUnitScope scope,
+ AudioUnitElement element) = 0;
+ // scope will always be input or output
+
+ // pass in a pointer to get the struct, and num channel infos
+ // you can pass in NULL to just get the number
+ // a return value of 0 (the default in AUBase) means the property is not supported...
+ /*! @method SupportedNumChannels */
+ virtual UInt32 SupportedNumChannels ( const AUChannelInfo** outInfo);
+
+ /*! @method ValidFormat */
+ virtual bool ValidFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inNewFormat);
+ // Will only be called after StreamFormatWritable
+ // has succeeded.
+ // Default implementation requires canonical format:
+ // native-endian 32-bit float, any sample rate,
+ // any number of channels; override when other
+ // formats are supported. A subclass's override can
+ // choose to always return true and trap invalid
+ // formats in ChangeStreamFormat.
+
+
+ /*! @method FormatIsCanonical */
+ bool FormatIsCanonical( const CAStreamBasicDescription &format);
+
+ /*! @method MakeCanonicalFormat */
+ void MakeCanonicalFormat( CAStreamBasicDescription & outDesc,
+ int numChannels = 2);
+
+ /*! @method GetStreamFormat */
+ virtual const CAStreamBasicDescription &
+ GetStreamFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ /*! @method ChangeStreamFormat */
+ virtual OSStatus ChangeStreamFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inPrevFormat,
+ const CAStreamBasicDescription & inNewFormat);
+ // Will only be called after StreamFormatWritable
+ // and ValidFormat have succeeded.
+
+ // ________________________________________________________________________
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch( ComponentParameters * params,
+ AUBase * This);
+#endif
+
+ // ________________________________________________________________________
+ // Methods useful for subclasses
+
+ /*! @method GetScope */
+ AUScope & GetScope( AudioUnitScope inScope)
+ {
+ if (inScope >= kNumScopes) {
+ AUScope * scope = GetScopeExtended(inScope);
+ if (!scope) COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+ return *scope;
+ }
+ return mScopes[inScope];
+ }
+
+ /*! @method GetScopeExtended */
+ virtual AUScope * GetScopeExtended (AudioUnitScope inScope) { return NULL; }
+
+ /*! @method GlobalScope */
+ AUScope & GlobalScope() { return mScopes[kAudioUnitScope_Global]; }
+ /*! @method Inputs */
+ AUScope & Inputs() { return mScopes[kAudioUnitScope_Input]; }
+ /*! @method Outputs */
+ AUScope & Outputs() { return mScopes[kAudioUnitScope_Output]; }
+#if !CA_BASIC_AU_FEATURES
+ /*! @method Groups */
+ AUScope & Groups() { return mScopes[kAudioUnitScope_Group]; }
+#endif
+ /*! @method Globals */
+ AUElement * Globals() { return mScopes[kAudioUnitScope_Global].GetElement(0); }
+
+ /*! @method SetNumberOfElements */
+ void SetNumberOfElements( AudioUnitScope inScope,
+ UInt32 numElements);
+
+ /*! @method GetElement */
+ AUElement * GetElement( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+ {
+ return GetScope(inScope).GetElement(inElement);
+ }
+
+ /*! @method GetIOElement */
+ AUIOElement * GetIOElement( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+ {
+ return GetScope(inScope).GetIOElement(inElement);
+ }
+
+ /*! @method SafeGetElement */
+ AUElement * SafeGetElement( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+ {
+ return GetScope(inScope).SafeGetElement(inElement);
+ }
+
+ /*! @method GetInput */
+ AUInputElement * GetInput( AudioUnitElement inElement)
+ {
+ return static_cast<AUInputElement *>(Inputs().SafeGetElement(inElement));
+ }
+
+ /*! @method GetOutput */
+ AUOutputElement * GetOutput( AudioUnitElement inElement)
+ {
+ return static_cast<AUOutputElement *>(Outputs().SafeGetElement(inElement));
+ }
+
+#if !CA_BASIC_AU_FEATURES
+ /*! @method GetGroup */
+ AUElement * GetGroup( AudioUnitElement inElement)
+ {
+ return Groups().SafeGetElement(inElement);
+ }
+#endif
+
+ /*! @method PullInput */
+ OSStatus PullInput( UInt32 inBusNumber,
+ AudioUnitRenderActionFlags &ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames)
+ {
+ AUInputElement *input = GetInput(inBusNumber); // throws if error
+ return input->PullInput(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
+ }
+
+ /*! @method GetMaxFramesPerSlice */
+ UInt32 GetMaxFramesPerSlice() const { return mMaxFramesPerSlice; }
+ /*! @method UsesFixedBlockSize */
+ bool UsesFixedBlockSize() const { return mUsesFixedBlockSize; }
+ /*! @method SetUsesFixedBlockSize */
+ void SetUsesFixedBlockSize(bool inUsesFixedBlockSize) { mUsesFixedBlockSize = inUsesFixedBlockSize; }
+
+ /*! @method GetVectorUnitType */
+ static SInt32 GetVectorUnitType() { return sVectorUnitType; }
+ /*! @method HasVectorUnit */
+ static bool HasVectorUnit() { return sVectorUnitType > 0; }
+ /*! @method HasAltivec */
+ static bool HasAltivec() { return sVectorUnitType == kVecAltivec; }
+ /*! @method HasSSE2 */
+ static bool HasSSE2() { return sVectorUnitType >= kVecSSE2; }
+ /*! @method HasSSE3 */
+ static bool HasSSE3() { return sVectorUnitType >= kVecSSE3; }
+
+ /*! @method AudioUnitAPIVersion */
+ UInt8 AudioUnitAPIVersion() const { return mAudioUnitAPIVersion; }
+
+ /*! @method IsRenderThread */
+ bool InRenderThread () const
+ {
+#if TARGET_OS_MAC
+ return (mRenderThreadID ? pthread_equal (mRenderThreadID, pthread_self()) : false);
+#elif TARGET_OS_WIN32
+ return (mRenderThreadID ? mRenderThreadID == GetCurrentThreadId() : false);
+#endif
+ }
+
+ /*! @method HasInput */
+ bool HasInput( AudioUnitElement inElement) {
+ AUInputElement *in = static_cast<AUInputElement *>(Inputs().GetElement(inElement));
+ return in != NULL && in->IsActive();
+ }
+ // says whether an input is connected or has a callback
+
+ /*! @method PropertyChanged */
+ virtual void PropertyChanged( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+#if !CA_NO_AU_UI_FEATURES
+ // These calls can be used to call a Host's Callbacks. The method returns -1 if the host
+ // hasn't supplied the callback. Any other result is returned by the host.
+ // As in the API contract, for a parameter's value, you specify a pointer
+ // to that data type. Specify NULL for a parameter that you are not interested
+ // as this can save work in the host.
+
+ /*! @method CallHostBeatAndTempo */
+ OSStatus CallHostBeatAndTempo (Float64 *outCurrentBeat,
+ Float64 *outCurrentTempo)
+ {
+ return (mHostCallbackInfo.beatAndTempoProc
+ ? (*mHostCallbackInfo.beatAndTempoProc) (mHostCallbackInfo.hostUserData,
+ outCurrentBeat,
+ outCurrentTempo)
+ : -1);
+ }
+
+ /*! @method CallHostMusicalTimeLocation */
+ OSStatus CallHostMusicalTimeLocation (UInt32 *outDeltaSampleOffsetToNextBeat,
+ Float32 *outTimeSig_Numerator,
+ UInt32 *outTimeSig_Denominator,
+ Float64 *outCurrentMeasureDownBeat)
+ {
+ return (mHostCallbackInfo.musicalTimeLocationProc
+ ? (*mHostCallbackInfo.musicalTimeLocationProc) (mHostCallbackInfo.hostUserData,
+ outDeltaSampleOffsetToNextBeat,
+ outTimeSig_Numerator,
+ outTimeSig_Denominator,
+ outCurrentMeasureDownBeat)
+ : -1);
+ }
+
+ /*! @method CallHostTransportState */
+ OSStatus CallHostTransportState (Boolean *outIsPlaying,
+ Boolean *outTransportStateChanged,
+ Float64 *outCurrentSampleInTimeLine,
+ Boolean *outIsCycling,
+ Float64 *outCycleStartBeat,
+ Float64 *outCycleEndBeat)
+ {
+ return (mHostCallbackInfo.transportStateProc
+ ? (*mHostCallbackInfo.transportStateProc) (mHostCallbackInfo.hostUserData,
+ outIsPlaying,
+ outTransportStateChanged,
+ outCurrentSampleInTimeLine,
+ outIsCycling,
+ outCycleStartBeat,
+ outCycleEndBeat)
+ : -1);
+ }
+#endif
+
+ char* GetLoggingString () const;
+
+ CAMutex* GetMutex() { return mAUMutex; }
+
+ // ________________________________________________________________________
+ /*! @method CreateElement */
+ virtual AUElement * CreateElement( AudioUnitScope scope,
+ AudioUnitElement element);
+
+#pragma mark -
+#pragma mark AU Output Base Dispatch
+ // ________________________________________________________________________
+ // ________________________________________________________________________
+ // ________________________________________________________________________
+ // output unit methods
+ /*! @method Start */
+ virtual OSStatus Start() { return kAudio_UnimplementedError; }
+ /*! @method Stop */
+ virtual OSStatus Stop() { return kAudio_UnimplementedError; }
+
+#if !CA_BASIC_AU_FEATURES
+#pragma mark -
+#pragma mark AU Music Base Dispatch
+
+#if !TARGET_OS_IPHONE
+// these methods are deprecated, so we don't include them except for compatability
+ /*! @method PrepareInstrument */
+ virtual OSStatus PrepareInstrument(MusicDeviceInstrumentID inInstrument) { return kAudio_UnimplementedError; }
+
+ /*! @method PrepareInstrument */
+ virtual OSStatus ReleaseInstrument(MusicDeviceInstrumentID inInstrument) { return kAudio_UnimplementedError; }
+#endif
+
+ // ________________________________________________________________________
+ // ________________________________________________________________________
+ // ________________________________________________________________________
+ // music device/music effect methods -- incomplete
+ /*! @method MIDIEvent */
+ virtual OSStatus MIDIEvent( UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame) { return kAudio_UnimplementedError; }
+
+ /*! @method SysEx */
+ virtual OSStatus SysEx( const UInt8 * inData,
+ UInt32 inLength) { return kAudio_UnimplementedError;}
+
+ /*! @method StartNote */
+ virtual OSStatus StartNote( MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams) { return kAudio_UnimplementedError; }
+
+ /*! @method StopNote */
+ virtual OSStatus StopNote( MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame) { return kAudio_UnimplementedError; }
+#endif
+
+ // ________________________________________________________________________
+ // ________________________________________________________________________
+ // ________________________________________________________________________
+
+protected:
+#pragma mark -
+#pragma mark Implementation methods
+
+ /*! @method ReallocateBuffers */
+ virtual void ReallocateBuffers();
+ // needs to be called when mMaxFramesPerSlice changes
+ virtual void DeallocateIOBuffers();
+
+ /*! @method FillInParameterName */
+ static void FillInParameterName (AudioUnitParameterInfo& ioInfo, CFStringRef inName, bool inShouldRelease)
+ {
+ ioInfo.cfNameString = inName;
+ ioInfo.flags |= kAudioUnitParameterFlag_HasCFNameString;
+ if (inShouldRelease)
+ ioInfo.flags |= kAudioUnitParameterFlag_CFNameRelease;
+ CFStringGetCString (inName, ioInfo.name, offsetof (AudioUnitParameterInfo, clumpID), kCFStringEncodingUTF8);
+ }
+
+ static void HasClump (AudioUnitParameterInfo& ioInfo, UInt32 inClumpID)
+ {
+ ioInfo.clumpID = inClumpID;
+ ioInfo.flags |= kAudioUnitParameterFlag_HasClump;
+ }
+
+ /*! @method SetMaxFramesPerSlice */
+ virtual void SetMaxFramesPerSlice(UInt32 nFrames);
+
+ /*! @method CanSetMaxFrames */
+ virtual OSStatus CanSetMaxFrames() const;
+
+ /*! @method WantsRenderThreadID */
+ bool WantsRenderThreadID () const { return mWantsRenderThreadID; }
+
+ /*! @method SetWantsRenderThreadID */
+ void SetWantsRenderThreadID (bool inFlag);
+
+ /*! @method SetRenderError */
+ OSStatus SetRenderError (OSStatus inErr)
+ {
+ if (inErr && mLastRenderError == 0) {
+ mLastRenderError = inErr;
+ PropertyChanged(kAudioUnitProperty_LastRenderError, kAudioUnitScope_Global, 0);
+ }
+ return inErr;
+ }
+
+private:
+ /*! @method DoRenderBus */
+ // shared between Render and RenderSlice, inlined to minimize function call overhead
+ OSStatus DoRenderBus( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inBusNumber,
+ AUOutputElement * theOutput,
+ UInt32 inNumberFrames,
+ AudioBufferList & ioData)
+ {
+ if (ioData.mBuffers[0].mData == NULL || (theOutput->WillAllocateBuffer() && Outputs().GetNumberOfElements() > 1))
+ // will render into cache buffer
+ theOutput->PrepareBuffer(inNumberFrames);
+ else
+ // will render into caller's buffer
+ theOutput->SetBufferList(ioData);
+ OSStatus result = RenderBus(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
+ if (result == noErr) {
+ if (ioData.mBuffers[0].mData == NULL) {
+ theOutput->CopyBufferListTo(ioData);
+ AUTRACE(kCATrace_AUBaseDoRenderBus, mComponentInstance, inNumberFrames, (intptr_t)theOutput->GetBufferList().mBuffers[0].mData, 0, *(UInt32 *)ioData.mBuffers[0].mData);
+ } else {
+ theOutput->CopyBufferContentsTo(ioData);
+ AUTRACE(kCATrace_AUBaseDoRenderBus, mComponentInstance, inNumberFrames, (intptr_t)theOutput->GetBufferList().mBuffers[0].mData, (intptr_t)ioData.mBuffers[0].mData, *(UInt32 *)ioData.mBuffers[0].mData);
+ theOutput->InvalidateBufferList();
+ }
+ }
+ return result;
+ }
+
+ /*! @method HasIcon */
+ bool HasIcon ();
+
+ /*! @method ResetRenderTime */
+ void ResetRenderTime ()
+ {
+ memset (&mCurrentRenderTime, 0, sizeof(mCurrentRenderTime));
+ mCurrentRenderTime.mSampleTime = kNoLastRenderedSampleTime;
+ }
+
+protected:
+ /*! @method GetAudioChannelLayout */
+ virtual UInt32 GetChannelLayoutTags( AudioUnitScope scope,
+ AudioUnitElement element,
+ AudioChannelLayoutTag * outLayoutTags);
+
+ /*! @method GetAudioChannelLayout */
+ virtual UInt32 GetAudioChannelLayout( AudioUnitScope scope,
+ AudioUnitElement element,
+ AudioChannelLayout * outLayoutPtr,
+ Boolean & outWritable);
+
+ /*! @method SetAudioChannelLayout */
+ virtual OSStatus SetAudioChannelLayout( AudioUnitScope scope,
+ AudioUnitElement element,
+ const AudioChannelLayout * inLayout);
+
+ /*! @method RemoveAudioChannelLayout */
+ virtual OSStatus RemoveAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element);
+
+ /*! @method NeedsToRender */
+ bool NeedsToRender( const AudioTimeStamp & inTimeStamp)
+ {
+ bool needsToRender = fnotequal(inTimeStamp.mSampleTime, mCurrentRenderTime.mSampleTime);
+ if (needsToRender) // only copy this if we need to render
+ mCurrentRenderTime = inTimeStamp;
+ return needsToRender;
+ }
+
+ // Scheduled parameter implementation:
+
+ typedef std::vector<AudioUnitParameterEvent> ParameterEventList;
+
+ // Usually, you won't override this method. You only need to call this if your DSP code
+ // is prepared to handle scheduled immediate and ramped parameter changes.
+ // Before calling this method, it is assumed you have already called PullInput() on the input busses
+ // for which the DSP code depends. ProcessForScheduledParams() will call (potentially repeatedly)
+ // virtual method ProcessScheduledSlice() to perform the actual DSP for a given sub-division of
+ // the buffer. The job of ProcessForScheduledParams() is to sub-divide the buffer into smaller
+ // pieces according to the scheduled times found in the ParameterEventList (usually coming
+ // directly from a previous call to ScheduleParameter() ), setting the appropriate immediate or
+ // ramped parameter values for the corresponding scopes and elements, then calling ProcessScheduledSlice()
+ // to do the actual DSP for each of these divisions.
+ virtual OSStatus ProcessForScheduledParams( ParameterEventList &inParamList,
+ UInt32 inFramesToProcess,
+ void *inUserData );
+
+ // This method is called (potentially repeatedly) by ProcessForScheduledParams()
+ // in order to perform the actual DSP required for this portion of the entire buffer
+ // being processed. The entire buffer can be divided up into smaller "slices"
+ // according to the timestamps on the scheduled parameters...
+ //
+ // sub-classes wishing to handle scheduled parameter changes should override this method
+ // in order to do the appropriate DSP. AUEffectBase already overrides this for standard
+ // effect AudioUnits.
+ virtual OSStatus ProcessScheduledSlice( void *inUserData,
+ UInt32 inStartFrameInBuffer,
+ UInt32 inSliceFramesToProcess,
+ UInt32 inTotalBufferFrames ) {return noErr;}; // default impl does nothing...
+
+
+ /*! @method CurrentRenderTime */
+ const AudioTimeStamp & CurrentRenderTime () const { return mCurrentRenderTime; }
+
+ // ________________________________________________________________________
+ // Private data members to discourage hacking in subclasses
+private:
+ struct RenderCallback {
+ RenderCallback(AURenderCallback proc, void *ref) :
+ mRenderNotify(proc),
+ mRenderNotifyRefCon(ref)
+ { }
+
+ AURenderCallback mRenderNotify;
+ void * mRenderNotifyRefCon;
+
+ bool operator == (const RenderCallback &other) {
+ return this->mRenderNotify == other.mRenderNotify &&
+ this->mRenderNotifyRefCon == other.mRenderNotifyRefCon;
+ }
+ };
+ typedef TThreadSafeList<RenderCallback> RenderCallbackList;
+
+#if !CA_BASIC_AU_FEATURES
+ enum { kNumScopes = 4 };
+#else
+ enum { kNumScopes = 3 };
+#endif
+
+ /*! @var mElementsCreated */
+ bool mElementsCreated;
+protected:
+ /*! @var mInitialized */
+ bool mInitialized;
+ /*! @var mHasBegunInitializing */
+ bool mHasBegunInitializing;
+private:
+ /*! @var mAudioUnitAPIVersion */
+ UInt8 mAudioUnitAPIVersion;
+
+ /*! @var mInitNumInputEls */
+ const UInt32 mInitNumInputEls;
+ /*! @var mInitNumOutputEls */
+ const UInt32 mInitNumOutputEls;
+#if !CA_BASIC_AU_FEATURES
+ /*! @var mInitNumGroupEls */
+ const UInt32 mInitNumGroupEls;
+#endif
+ /*! @var mScopes */
+ AUScope mScopes[kNumScopes];
+
+ /*! @var mRenderCallbacks */
+ RenderCallbackList mRenderCallbacks;
+ bool mRenderCallbacksTouched;
+
+ /*! @var mRenderThreadID */
+#if TARGET_OS_MAC
+ pthread_t mRenderThreadID;
+#elif TARGET_OS_WIN32
+ UInt32 mRenderThreadID;
+#endif
+
+ /*! @var mWantsRenderThreadID */
+ bool mWantsRenderThreadID;
+
+ /*! @var mCurrentRenderTime */
+ AudioTimeStamp mCurrentRenderTime;
+
+ /*! @var mMaxFramesPerSlice */
+ UInt32 mMaxFramesPerSlice;
+
+ /*! @var mLastRenderError */
+ OSStatus mLastRenderError;
+ /*! @var mCurrentPreset */
+ AUPreset mCurrentPreset;
+
+protected:
+ /*! @var mUsesFixedBlockSize */
+ bool mUsesFixedBlockSize;
+
+ struct PropertyListener {
+ AudioUnitPropertyID propertyID;
+ AudioUnitPropertyListenerProc listenerProc;
+ void * listenerRefCon;
+ };
+ typedef std::vector<PropertyListener> PropertyListeners;
+
+ /*! @var mParamList */
+ ParameterEventList mParamList;
+ /*! @var mPropertyListeners */
+ PropertyListeners mPropertyListeners;
+
+ /*! @var mBuffersAllocated */
+ bool mBuffersAllocated;
+
+ /*! @var mLogString */
+ // if this is NOT null, it will contain identifying info about this AU.
+ char* mLogString;
+
+ /*! @var mNickName */
+ CFStringRef mNickName;
+
+ /*! @var mAUMutex */
+ CAMutex * mAUMutex;
+
+private:
+ /*! @var sVectorUnitType */
+ static SInt32 sVectorUnitType;
+
+#if !CA_NO_AU_HOST_CALLBACKS
+protected:
+ /*! @var mHostCallbackInfo */
+ HostCallbackInfo mHostCallbackInfo;
+
+#endif
+#if !CA_NO_AU_UI_FEATURES
+protected:
+ /*! @var mContextInfo */
+ CFStringRef mContextName;
+#endif
+};
+
+inline OSStatus AUInputElement::PullInputWithBufferList(
+ AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ AudioUnitElement inElement,
+ UInt32 nFrames,
+ AudioBufferList * inBufferList)
+{
+ OSStatus theResult;
+
+ if (HasConnection()) {
+ // only support connections for V2 audio units
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ if (mConnRenderProc != NULL)
+ theResult = reinterpret_cast<AudioUnitRenderProc>(mConnRenderProc)(
+ mConnInstanceStorage, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
+ else
+#endif
+ theResult = AudioUnitRender(
+ mConnection.sourceAudioUnit, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
+ } else {
+ // kFromCallback:
+ theResult = (mInputProc)(
+ mInputProcRefCon, &ioActionFlags, &inTimeStamp, inElement, nFrames, inBufferList);
+ }
+
+ if (mInputType == kNoInput) // defense: the guy upstream could have disconnected
+ // it's a horrible thing to do, but may happen!
+ return kAudioUnitErr_NoConnection;
+
+
+ return theResult;
+}
+
+#endif // __AUBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.cpp
new file mode 100644
index 0000000000..1f0f01c7d5
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.cpp
@@ -0,0 +1,438 @@
+/*
+ File: AUDispatch.cpp
+ Abstract: AUDispatch.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUBase.h"
+#include "CAXException.h"
+#include "AUDispatch.h"
+
+
+
+#if TARGET_OS_MAC
+ #if __LP64__
+ // comp instance, parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index + 1];
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
+ #endif
+#elif TARGET_OS_WIN32
+ // (no comp instance), parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index];
+#endif
+
+
+OSStatus AUBase::ComponentEntryDispatch(ComponentParameters *params, AUBase *This)
+{
+ if (This == NULL) return kAudio_ParamError;
+
+ OSStatus result = noErr;
+
+ switch (params->what) {
+ case kComponentCanDoSelect:
+ switch (GetSelectorForCanDo(params)) {
+ // any selectors
+ case kAudioUnitInitializeSelect:
+ case kAudioUnitUninitializeSelect:
+ case kAudioUnitGetPropertyInfoSelect:
+ case kAudioUnitGetPropertySelect:
+ case kAudioUnitSetPropertySelect:
+ case kAudioUnitAddPropertyListenerSelect:
+#if (!__LP64__)
+ case kAudioUnitRemovePropertyListenerSelect:
+#endif
+ case kAudioUnitGetParameterSelect:
+ case kAudioUnitSetParameterSelect:
+ case kAudioUnitResetSelect:
+ result = 1;
+ break;
+ // v1 selectors
+
+ // v2 selectors
+ case kAudioUnitRemovePropertyListenerWithUserDataSelect:
+ case kAudioUnitAddRenderNotifySelect:
+ case kAudioUnitRemoveRenderNotifySelect:
+ case kAudioUnitScheduleParametersSelect:
+ case kAudioUnitRenderSelect:
+ result = (This->AudioUnitAPIVersion() > 1);
+ break;
+
+ default:
+ return ComponentBase::ComponentEntryDispatch(params, This);
+ }
+ break;
+
+ case kAudioUnitInitializeSelect:
+ {
+ CAMutex::Locker lock2(This->GetMutex());
+ result = This->DoInitialize();
+ }
+ break;
+
+ case kAudioUnitUninitializeSelect:
+ {
+ CAMutex::Locker lock2(This->GetMutex());
+ This->DoCleanup();
+ result = noErr;
+ }
+ break;
+
+ case kAudioUnitGetPropertyInfoSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitPropertyID, pinID, 0, 5);
+ PARAM(AudioUnitScope, pinScope, 1, 5);
+ PARAM(AudioUnitElement, pinElement, 2, 5);
+ PARAM(UInt32 *, poutDataSize, 3, 5);
+ PARAM(Boolean *, poutWritable, 4, 5);
+
+ // pass our own copies so that we assume responsibility for testing
+ // the caller's pointers against null and our C++ classes can
+ // always assume they're non-null
+ UInt32 dataSize;
+ Boolean writable;
+
+ result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement, dataSize, writable);
+ if (poutDataSize != NULL)
+ *poutDataSize = dataSize;
+ if (poutWritable != NULL)
+ *poutWritable = writable;
+ }
+ break;
+
+ case kAudioUnitGetPropertySelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitPropertyID, pinID, 0, 5);
+ PARAM(AudioUnitScope, pinScope, 1, 5);
+ PARAM(AudioUnitElement, pinElement, 2, 5);
+ PARAM(void *, poutData, 3, 5);
+ PARAM(UInt32 *, pioDataSize, 4, 5);
+
+ UInt32 actualPropertySize, clientBufferSize;
+ Boolean writable;
+ char *tempBuffer;
+ void *destBuffer;
+
+ if (pioDataSize == NULL) {
+ ca_debug_string("AudioUnitGetProperty: null size pointer");
+ result = kAudio_ParamError;
+ goto finishGetProperty;
+ }
+ if (poutData == NULL) {
+ UInt32 dataSize;
+
+ result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement, dataSize, writable);
+ *pioDataSize = dataSize;
+ goto finishGetProperty;
+ }
+
+ clientBufferSize = *pioDataSize;
+ if (clientBufferSize == 0)
+ {
+ ca_debug_string("AudioUnitGetProperty: *ioDataSize == 0 on entry");
+ // $$$ or should we allow this as a shortcut for finding the size?
+ result = kAudio_ParamError;
+ goto finishGetProperty;
+ }
+
+ result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement,
+ actualPropertySize, writable);
+ if (result)
+ goto finishGetProperty;
+
+ if (clientBufferSize < actualPropertySize)
+ {
+ tempBuffer = new char[actualPropertySize];
+ destBuffer = tempBuffer;
+ } else {
+ tempBuffer = NULL;
+ destBuffer = poutData;
+ }
+
+ result = This->DispatchGetProperty(pinID, pinScope, pinElement, destBuffer);
+
+ if (result == noErr) {
+ if (clientBufferSize < actualPropertySize && tempBuffer != NULL)
+ {
+ memcpy(poutData, tempBuffer, clientBufferSize);
+ delete[] tempBuffer;
+ // pioDataSize remains correct, the number of bytes we wrote
+ } else
+ *pioDataSize = actualPropertySize;
+ } else
+ *pioDataSize = 0;
+
+ finishGetProperty:
+ ;
+
+ }
+ break;
+
+ case kAudioUnitSetPropertySelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitPropertyID, pinID, 0, 5);
+ PARAM(AudioUnitScope, pinScope, 1, 5);
+ PARAM(AudioUnitElement, pinElement, 2, 5);
+ PARAM(const void *, pinData, 3, 5);
+ PARAM(UInt32, pinDataSize, 4, 5);
+
+ if (pinData && pinDataSize)
+ result = This->DispatchSetProperty(pinID, pinScope, pinElement, pinData, pinDataSize);
+ else {
+ if (pinData == NULL && pinDataSize == 0) {
+ result = This->DispatchRemovePropertyValue (pinID, pinScope, pinElement);
+ } else {
+ if (pinData == NULL) {
+ ca_debug_string("AudioUnitSetProperty: inData == NULL");
+ result = kAudio_ParamError;
+ goto finishSetProperty;
+ }
+
+ if (pinDataSize == 0) {
+ ca_debug_string("AudioUnitSetProperty: inDataSize == 0");
+ result = kAudio_ParamError;
+ goto finishSetProperty;
+ }
+ }
+ }
+ finishSetProperty:
+ ;
+
+ }
+ break;
+
+ case kAudioUnitAddPropertyListenerSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitPropertyID, pinID, 0, 3);
+ PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 3);
+ PARAM(void *, pinProcRefCon, 2, 3);
+ result = This->AddPropertyListener(pinID, pinProc, pinProcRefCon);
+ }
+ break;
+
+#if (!__LP64__)
+ case kAudioUnitRemovePropertyListenerSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitPropertyID, pinID, 0, 2);
+ PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 2);
+ result = This->RemovePropertyListener(pinID, pinProc, NULL, false);
+ }
+ break;
+#endif
+
+ case kAudioUnitRemovePropertyListenerWithUserDataSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitPropertyID, pinID, 0, 3);
+ PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 3);
+ PARAM(void *, pinProcRefCon, 2, 3);
+ result = This->RemovePropertyListener(pinID, pinProc, pinProcRefCon, true);
+ }
+ break;
+
+ case kAudioUnitAddRenderNotifySelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AURenderCallback, pinProc, 0, 2);
+ PARAM(void *, pinProcRefCon, 1, 2);
+ result = This->SetRenderNotification (pinProc, pinProcRefCon);
+ }
+ break;
+
+ case kAudioUnitRemoveRenderNotifySelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AURenderCallback, pinProc, 0, 2);
+ PARAM(void *, pinProcRefCon, 1, 2);
+ result = This->RemoveRenderNotification (pinProc, pinProcRefCon);
+ }
+ break;
+
+ case kAudioUnitGetParameterSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitParameterID, pinID, 0, 4);
+ PARAM(AudioUnitScope, pinScope, 1, 4);
+ PARAM(AudioUnitElement, pinElement, 2, 4);
+ PARAM(AudioUnitParameterValue *, poutValue, 3, 4);
+ result = (poutValue == NULL ? kAudio_ParamError : This->GetParameter(pinID, pinScope, pinElement, *poutValue));
+ }
+ break;
+
+ case kAudioUnitSetParameterSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex()); // is this realtime or no???
+ PARAM(AudioUnitParameterID, pinID, 0, 5);
+ PARAM(AudioUnitScope, pinScope, 1, 5);
+ PARAM(AudioUnitElement, pinElement, 2, 5);
+ PARAM(AudioUnitParameterValue, pinValue, 3, 5);
+ PARAM(UInt32, pinBufferOffsetInFrames, 4, 5);
+ result = This->SetParameter(pinID, pinScope, pinElement, pinValue, pinBufferOffsetInFrames);
+ }
+ break;
+
+ case kAudioUnitScheduleParametersSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex()); // is this realtime or no???
+ if (This->AudioUnitAPIVersion() > 1)
+ {
+ PARAM(AudioUnitParameterEvent *, pinParameterEvent, 0, 2);
+ PARAM(UInt32, pinNumParamEvents, 1, 2);
+ result = This->ScheduleParameter (pinParameterEvent, pinNumParamEvents);
+ } else
+ result = badComponentSelector;
+ }
+ break;
+
+
+ case kAudioUnitRenderSelect:
+ {
+ // realtime; no lock
+ {
+ PARAM(AudioUnitRenderActionFlags *, pinActionFlags, 0, 5);
+ PARAM(const AudioTimeStamp *, pinTimeStamp, 1, 5);
+ PARAM(UInt32, pinOutputBusNumber, 2, 5);
+ PARAM(UInt32, pinNumberFrames, 3, 5);
+ PARAM(AudioBufferList *, pioData, 4, 5);
+ AudioUnitRenderActionFlags tempFlags;
+
+ if (pinTimeStamp == NULL || pioData == NULL)
+ result = kAudio_ParamError;
+ else {
+ if (pinActionFlags == NULL) {
+ tempFlags = 0;
+ pinActionFlags = &tempFlags;
+ }
+ result = This->DoRender(*pinActionFlags, *pinTimeStamp, pinOutputBusNumber, pinNumberFrames, *pioData);
+ }
+ }
+ }
+ break;
+
+ case kAudioUnitResetSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitScope, pinScope, 0, 2);
+ PARAM(AudioUnitElement, pinElement, 1, 2);
+ This->ResetRenderTime();
+ result = This->Reset(pinScope, pinElement);
+ }
+ break;
+
+ default:
+ result = ComponentBase::ComponentEntryDispatch(params, This);
+ break;
+ }
+
+ return result;
+}
+
+// Fast dispatch entry points -- these need to replicate all error-checking logic from above
+
+OSStatus CMgr_AudioUnitBaseGetParameter( AUBase * This,
+ AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ float *outValue)
+{
+ OSStatus result = AUBase::noErr;
+
+ try {
+ if (This == NULL || outValue == NULL) return kAudio_ParamError;
+ result = This->GetParameter(inID, inScope, inElement, *outValue);
+ }
+ COMPONENT_CATCH
+
+ return result;
+}
+
+OSStatus CMgr_AudioUnitBaseSetParameter( AUBase * This,
+ AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ float inValue,
+ UInt32 inBufferOffset)
+{
+ OSStatus result = AUBase::noErr;
+
+ try {
+ if (This == NULL) return kAudio_ParamError;
+ result = This->SetParameter(inID, inScope, inElement, inValue, inBufferOffset);
+ }
+ COMPONENT_CATCH
+
+ return result;
+}
+
+OSStatus CMgr_AudioUnitBaseRender( AUBase * This,
+ AudioUnitRenderActionFlags *ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList * ioData)
+{
+ if (inTimeStamp == NULL || ioData == NULL) return kAudio_ParamError;
+
+ OSStatus result = AUBase::noErr;
+ AudioUnitRenderActionFlags tempFlags;
+
+ try {
+ if (ioActionFlags == NULL) {
+ tempFlags = 0;
+ ioActionFlags = &tempFlags;
+ }
+ result = This->DoRender(*ioActionFlags, *inTimeStamp, inBusNumber, inNumberFrames, *ioData);
+ }
+ COMPONENT_CATCH
+
+ return result;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.h
new file mode 100644
index 0000000000..5acd96250a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.h
@@ -0,0 +1,82 @@
+/*
+ File: AUDispatch.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUDispatch_h__
+#define __AUDispatch_h__
+
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnit.h>
+#else
+ #include "AudioUnit.h"
+#endif
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+/*! @function AudioUnitBaseGetParameter */
+OSStatus CMgr_AudioUnitBaseGetParameter( AUBase * This,
+ AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ float * outValue);
+
+/*! @function AudioUnitBaseSetParameter */
+OSStatus CMgr_AudioUnitBaseSetParameter( AUBase * This,
+ AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ float inValue,
+ UInt32 inBufferOffset);
+
+/*! @function AudioUnitBaseRender */
+OSStatus CMgr_AudioUnitBaseRender( AUBase * This,
+ AudioUnitRenderActionFlags *ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList * ioData);
+#endif
+
+#endif // __AUDispatch_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.cpp
new file mode 100644
index 0000000000..2e148e8ba7
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.cpp
@@ -0,0 +1,151 @@
+/*
+ File: AUInputElement.cpp
+ Abstract: AUInputElement.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUBase.h"
+
+inline bool HasGoodBufferPointers(const AudioBufferList &abl, UInt32 nBytes)
+{
+ const AudioBuffer *buf = abl.mBuffers;
+ for (UInt32 i = abl.mNumberBuffers; i--;++buf) {
+ if (buf->mData == NULL || buf->mDataByteSize < nBytes)
+ return false;
+ }
+ return true;
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUInputElement::AUInputElement
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+AUInputElement::AUInputElement(AUBase *audioUnit) :
+ AUIOElement(audioUnit),
+ mInputType(kNoInput)
+{
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUInputElement::SetConnection
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void AUInputElement::SetConnection(const AudioUnitConnection &conn)
+{
+ if (conn.sourceAudioUnit == 0) {
+ Disconnect();
+ return;
+ }
+
+ mInputType = kFromConnection;
+ mConnection = conn;
+ AllocateBuffer();
+
+ mConnInstanceStorage = NULL;
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ mConnRenderProc = NULL;
+ UInt32 size = sizeof(AudioUnitRenderProc);
+ OSStatus result = AudioUnitGetProperty( conn.sourceAudioUnit,
+ kAudioUnitProperty_FastDispatch,
+ kAudioUnitScope_Global,
+ kAudioUnitRenderSelect,
+ &mConnRenderProc,
+ &size);
+ if (result == noErr)
+ mConnInstanceStorage = CMgr_GetComponentInstanceStorage (conn.sourceAudioUnit);
+ else
+ mConnRenderProc = NULL;
+#endif
+}
+
+void AUInputElement::Disconnect()
+{
+ mInputType = kNoInput;
+ mIOBuffer.Deallocate();
+}
+
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUInputElement::SetInputCallback
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void AUInputElement::SetInputCallback(AURenderCallback proc, void *refCon)
+{
+ if (proc == NULL)
+ Disconnect();
+ else {
+ mInputType = kFromCallback;
+ mInputProc = proc;
+ mInputProcRefCon = refCon;
+ AllocateBuffer();
+ }
+}
+
+OSStatus AUInputElement::SetStreamFormat(const CAStreamBasicDescription &fmt)
+{
+ OSStatus err = AUIOElement::SetStreamFormat(fmt);
+ if (err == AUBase::noErr)
+ AllocateBuffer();
+ return err;
+}
+
+OSStatus AUInputElement::PullInput( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ AudioUnitElement inElement,
+ UInt32 nFrames)
+{
+ if (!IsActive())
+ return kAudioUnitErr_NoConnection;
+
+ AudioBufferList *pullBuffer;
+
+ if (HasConnection() || !WillAllocateBuffer())
+ pullBuffer = &mIOBuffer.PrepareNullBuffer(mStreamFormat, nFrames);
+ else
+ pullBuffer = &mIOBuffer.PrepareBuffer(mStreamFormat, nFrames);
+
+ return PullInputWithBufferList (ioActionFlags, inTimeStamp, inElement, nFrames, pullBuffer);
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.h
new file mode 100644
index 0000000000..891e4c60b7
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.h
@@ -0,0 +1,119 @@
+/*
+ File: AUInputElement.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUInput_h__
+#define __AUInput_h__
+
+#include "AUScopeElement.h"
+#include "AUBuffer.h"
+
+/*! @class AUInputElement */
+class AUInputElement : public AUIOElement {
+public:
+
+ /*! @ctor AUInputElement */
+ AUInputElement(AUBase *audioUnit);
+ /*! @dtor ~AUInputElement */
+ virtual ~AUInputElement() { }
+
+ // AUElement override
+ /*! @method SetStreamFormat */
+ virtual OSStatus SetStreamFormat(const CAStreamBasicDescription &desc);
+ /*! @method NeedsBufferSpace */
+ virtual bool NeedsBufferSpace() const { return IsCallback(); }
+
+ /*! @method SetConnection */
+ void SetConnection(const AudioUnitConnection &conn);
+ /*! @method SetInputCallback */
+ void SetInputCallback(AURenderCallback proc, void *refCon);
+
+ /*! @method IsActive */
+ bool IsActive() const { return mInputType != kNoInput; }
+ /*! @method IsCallback */
+ bool IsCallback() const { return mInputType == kFromCallback; }
+ /*! @method HasConnection */
+ bool HasConnection() const { return mInputType == kFromConnection; }
+
+ /*! @method PullInput */
+ OSStatus PullInput( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ AudioUnitElement inElement,
+ UInt32 inNumberFrames);
+
+ /*! @method PullInputWithBufferList */
+ OSStatus PullInputWithBufferList( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ AudioUnitElement inElement,
+ UInt32 nFrames,
+ AudioBufferList * inBufferList);
+protected:
+ /*! @method Disconnect */
+ void Disconnect();
+
+ enum EInputType { kNoInput, kFromConnection, kFromCallback };
+
+ /*! @var mInputType */
+ EInputType mInputType;
+
+ // if from callback:
+ /*! @var mInputProc */
+ AURenderCallback mInputProc;
+ /*! @var mInputProcRefCon */
+ void * mInputProcRefCon;
+
+ // if from connection:
+ /*! @var mConnection */
+ AudioUnitConnection mConnection;
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ /*! @var mConnRenderProc */
+ AudioUnitRenderProc mConnRenderProc;
+#endif
+ /*! @var mConnInstanceStorage */
+ void * mConnInstanceStorage; // for the input component
+};
+
+
+#endif // __AUInput_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp
new file mode 100644
index 0000000000..5eb34a1c20
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp
@@ -0,0 +1,62 @@
+/*
+ File: AUOutputElement.cpp
+ Abstract: AUOutputElement.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUOutputElement.h"
+#include "AUBase.h"
+
+AUOutputElement::AUOutputElement(AUBase *audioUnit) :
+ AUIOElement(audioUnit)
+{
+ AllocateBuffer();
+}
+
+OSStatus AUOutputElement::SetStreamFormat(const CAStreamBasicDescription &desc)
+{
+ OSStatus result = AUIOElement::SetStreamFormat(desc); // inherited
+ if (result == AUBase::noErr)
+ AllocateBuffer();
+ return result;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.h
new file mode 100644
index 0000000000..3e6a938fff
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.h
@@ -0,0 +1,66 @@
+/*
+ File: AUOutputElement.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUOutput_h__
+#define __AUOutput_h__
+
+#include "AUScopeElement.h"
+#include "AUBuffer.h"
+
+ /*! @class AUOutputElement */
+class AUOutputElement : public AUIOElement {
+public:
+ /*! @ctor AUOutputElement */
+ AUOutputElement(AUBase *audioUnit);
+
+ // AUElement override
+ /*! @method SetStreamFormat */
+ virtual OSStatus SetStreamFormat(const CAStreamBasicDescription &desc);
+ /*! @method NeedsBufferSpace */
+ virtual bool NeedsBufferSpace() const { return true; }
+};
+
+#endif // __AUOutput_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.cpp
new file mode 100644
index 0000000000..3bab198369
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.cpp
@@ -0,0 +1,669 @@
+/*
+ File: AUPlugInDispatch.cpp
+ Abstract: AUPlugInDispatch.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUPlugInDispatch.h"
+#include "CAXException.h"
+#include "ComponentBase.h"
+#include "AUBase.h"
+
+#define ACPI ((AudioComponentPlugInInstance *)self)
+#define AUI ((AUBase *)&ACPI->mInstanceStorage)
+
+#define AUI_LOCK CAMutex::Locker auLock(AUI->GetMutex());
+
+// ------------------------------------------------------------------------------------------------
+static OSStatus AUMethodInitialize(void *self)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->DoInitialize();
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodUninitialize(void *self)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ AUI->DoCleanup();
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodGetPropertyInfo(void *self, AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32 *outDataSize, Boolean *outWritable)
+{
+ OSStatus result = noErr;
+ try {
+ UInt32 dataSize = 0; // 13517289 GetPropetyInfo was returning an uninitialized value when there is an error. This is a problem for auval.
+ Boolean writable = false;
+
+ AUI_LOCK
+ result = AUI->DispatchGetPropertyInfo(prop, scope, elem, dataSize, writable);
+ if (outDataSize != NULL)
+ *outDataSize = dataSize;
+ if (outWritable != NULL)
+ *outWritable = writable;
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodGetProperty(void *self, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void *outData, UInt32 *ioDataSize)
+{
+ OSStatus result = noErr;
+ try {
+ UInt32 actualPropertySize, clientBufferSize;
+ Boolean writable;
+ char *tempBuffer;
+ void *destBuffer;
+
+ AUI_LOCK
+ if (ioDataSize == NULL) {
+ ca_debug_string("AudioUnitGetProperty: null size pointer");
+ result = kAudio_ParamError;
+ goto finishGetProperty;
+ }
+ if (outData == NULL) {
+ UInt32 dataSize;
+
+ result = AUI->DispatchGetPropertyInfo(inID, inScope, inElement, dataSize, writable);
+ *ioDataSize = dataSize;
+ goto finishGetProperty;
+ }
+
+ clientBufferSize = *ioDataSize;
+ if (clientBufferSize == 0)
+ {
+ ca_debug_string("AudioUnitGetProperty: *ioDataSize == 0 on entry");
+ // $$$ or should we allow this as a shortcut for finding the size?
+ result = kAudio_ParamError;
+ goto finishGetProperty;
+ }
+
+ result = AUI->DispatchGetPropertyInfo(inID, inScope, inElement, actualPropertySize, writable);
+ if (result != noErr)
+ goto finishGetProperty;
+
+ if (clientBufferSize < actualPropertySize)
+ {
+ tempBuffer = new char[actualPropertySize];
+ destBuffer = tempBuffer;
+ } else {
+ tempBuffer = NULL;
+ destBuffer = outData;
+ }
+
+ result = AUI->DispatchGetProperty(inID, inScope, inElement, destBuffer);
+
+ if (result == noErr) {
+ if (clientBufferSize < actualPropertySize && tempBuffer != NULL)
+ {
+ memcpy(outData, tempBuffer, clientBufferSize);
+ delete[] tempBuffer;
+ // ioDataSize remains correct, the number of bytes we wrote
+ } else
+ *ioDataSize = actualPropertySize;
+ } else
+ *ioDataSize = 0;
+ }
+ COMPONENT_CATCH
+finishGetProperty:
+ return result;
+}
+
+static OSStatus AUMethodSetProperty(void *self, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, const void *inData, UInt32 inDataSize)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ if (inData && inDataSize)
+ result = AUI->DispatchSetProperty(inID, inScope, inElement, inData, inDataSize);
+ else {
+ if (inData == NULL && inDataSize == 0) {
+ result = AUI->DispatchRemovePropertyValue(inID, inScope, inElement);
+ } else {
+ if (inData == NULL) {
+ ca_debug_string("AudioUnitSetProperty: inData == NULL");
+ result = kAudio_ParamError;
+ goto finishSetProperty;
+ }
+
+ if (inDataSize == 0) {
+ ca_debug_string("AudioUnitSetProperty: inDataSize == 0");
+ result = kAudio_ParamError;
+ goto finishSetProperty;
+ }
+ }
+ }
+ }
+ COMPONENT_CATCH
+finishSetProperty:
+ return result;
+}
+
+static OSStatus AUMethodAddPropertyListener(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void *userData)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->AddPropertyListener(prop, proc, userData);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodRemovePropertyListener(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->RemovePropertyListener(prop, proc, NULL, false);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodRemovePropertyListenerWithUserData(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void *userData)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->RemovePropertyListener(prop, proc, userData, true);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodAddRenderNotify(void *self, AURenderCallback proc, void *userData)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->SetRenderNotification(proc, userData);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodRemoveRenderNotify(void *self, AURenderCallback proc, void *userData)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->RemoveRenderNotification(proc, userData);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodGetParameter(void *self, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue *value)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = (value == NULL ? kAudio_ParamError : AUI->GetParameter(param, scope, elem, *value));
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodSetParameter(void *self, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a (potentially) realtime method; no lock
+ result = AUI->SetParameter(param, scope, elem, value, bufferOffset);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodScheduleParameters(void *self, const AudioUnitParameterEvent *events, UInt32 numEvents)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a (potentially) realtime method; no lock
+ result = AUI->ScheduleParameter(events, numEvents);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodRender(void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
+{
+ OSStatus result = noErr;
+
+#if !TARGET_OS_IPHONE
+ try {
+#endif
+ // this is a processing method; no lock
+ AudioUnitRenderActionFlags tempFlags;
+
+ if (inTimeStamp == NULL || ioData == NULL)
+ result = kAudio_ParamError;
+ else {
+ if (ioActionFlags == NULL) {
+ tempFlags = 0;
+ ioActionFlags = &tempFlags;
+ }
+ result = AUI->DoRender(*ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberFrames, *ioData);
+ }
+
+#if !TARGET_OS_IPHONE
+ }
+ COMPONENT_CATCH
+#endif
+
+ return result;
+}
+
+static OSStatus AUMethodComplexRender(void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberOfPackets, UInt32 *outNumberOfPackets, AudioStreamPacketDescription *outPacketDescriptions, AudioBufferList *ioData, void *outMetadata, UInt32 *outMetadataByteSize)
+{
+ OSStatus result = noErr;
+
+#if !TARGET_OS_IPHONE
+ try {
+#endif
+ // this is a processing method; no lock
+ AudioUnitRenderActionFlags tempFlags;
+
+ if (inTimeStamp == NULL || ioData == NULL)
+ result = kAudio_ParamError;
+ else {
+ if (ioActionFlags == NULL) {
+ tempFlags = 0;
+ ioActionFlags = &tempFlags;
+ }
+ result = AUI->ComplexRender(*ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberOfPackets, outNumberOfPackets, outPacketDescriptions, *ioData, outMetadata, outMetadataByteSize);
+ }
+
+#if !TARGET_OS_IPHONE
+ }
+ COMPONENT_CATCH
+#endif
+
+ return result;
+}
+
+static OSStatus AUMethodReset(void *self, AudioUnitScope scope, AudioUnitElement elem)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->Reset(scope, elem);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodProcess (void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, AudioBufferList *ioData)
+{
+ OSStatus result = noErr;
+
+#if !TARGET_OS_IPHONE
+ try {
+#endif
+ // this is a processing method; no lock
+ bool doParamCheck = true;
+
+ AudioUnitRenderActionFlags tempFlags;
+
+ if (ioActionFlags == NULL) {
+ tempFlags = 0;
+ ioActionFlags = &tempFlags;
+ } else {
+ if (*ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)
+ doParamCheck = false;
+ }
+
+ if (doParamCheck && (inTimeStamp == NULL || ioData == NULL))
+ result = kAudio_ParamError;
+ else {
+ result = AUI->DoProcess(*ioActionFlags, *inTimeStamp, inNumberFrames, *ioData);
+ }
+
+#if !TARGET_OS_IPHONE
+ }
+ COMPONENT_CATCH
+#endif
+
+ return result;
+}
+
+static OSStatus AUMethodProcessMultiple (void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, UInt32 inNumberInputBufferLists, const AudioBufferList **inInputBufferLists, UInt32 inNumberOutputBufferLists, AudioBufferList **ioOutputBufferLists)
+{
+ OSStatus result = noErr;
+
+#if !TARGET_OS_IPHONE
+ try {
+#endif
+ // this is a processing method; no lock
+ bool doParamCheck = true;
+
+ AudioUnitRenderActionFlags tempFlags;
+
+ if (ioActionFlags == NULL) {
+ tempFlags = 0;
+ ioActionFlags = &tempFlags;
+ } else {
+ if (*ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)
+ doParamCheck = false;
+ }
+
+ if (doParamCheck && (inTimeStamp == NULL || inInputBufferLists == NULL || ioOutputBufferLists == NULL))
+ result = kAudio_ParamError;
+ else {
+ result = AUI->DoProcessMultiple(*ioActionFlags, *inTimeStamp, inNumberFrames, inNumberInputBufferLists, inInputBufferLists, inNumberOutputBufferLists, ioOutputBufferLists);
+ }
+
+#if !TARGET_OS_IPHONE
+ }
+ COMPONENT_CATCH
+#endif
+
+ return result;
+}
+// ------------------------------------------------------------------------------------------------
+
+static OSStatus AUMethodStart(void *self)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->Start();
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodStop(void *self)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->Stop();
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+#if !CA_BASIC_AU_FEATURES
+// I don't know what I'm doing here; conflicts with the multiple inheritence in MusicDeviceBase.
+static OSStatus AUMethodMIDIEvent(void *self, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a potential render-time method; no lock
+ result = AUI->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodSysEx(void *self, const UInt8 *inData, UInt32 inLength)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a potential render-time method; no lock
+ result = AUI->SysEx(inData, inLength);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodStartNote(void *self, MusicDeviceInstrumentID inInstrument, MusicDeviceGroupID inGroupID, NoteInstanceID *outNoteInstanceID, UInt32 inOffsetSampleFrame, const MusicDeviceNoteParams *inParams)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a potential render-time method; no lock
+ if (inParams == NULL || outNoteInstanceID == NULL)
+ result = kAudio_ParamError;
+ else
+ result = AUI->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodStopNote(void *self, MusicDeviceGroupID inGroupID, NoteInstanceID inNoteInstanceID, UInt32 inOffsetSampleFrame)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a potential render-time method; no lock
+ result = AUI->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+#if !TARGET_OS_IPHONE
+static OSStatus AUMethodPrepareInstrument (void *self, MusicDeviceInstrumentID inInstrument)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a potential render-time method; no lock
+ result = AUI->PrepareInstrument(inInstrument);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodReleaseInstrument (void *self, MusicDeviceInstrumentID inInstrument)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a potential render-time method; no lock
+ result = AUI->ReleaseInstrument(inInstrument);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+#endif // TARGET_OS_IPHONE
+#endif // CA_BASIC_AU_FEATURES
+
+
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#pragma mark -
+#pragma mark Lookup Methods
+
+AudioComponentMethod AUBaseLookup::Lookup (SInt16 selector)
+{
+ switch (selector) {
+ case kAudioUnitInitializeSelect: return (AudioComponentMethod)AUMethodInitialize;
+ case kAudioUnitUninitializeSelect: return (AudioComponentMethod)AUMethodUninitialize;
+ case kAudioUnitGetPropertyInfoSelect: return (AudioComponentMethod)AUMethodGetPropertyInfo;
+ case kAudioUnitGetPropertySelect: return (AudioComponentMethod)AUMethodGetProperty;
+ case kAudioUnitSetPropertySelect: return (AudioComponentMethod)AUMethodSetProperty;
+ case kAudioUnitAddPropertyListenerSelect:return (AudioComponentMethod)AUMethodAddPropertyListener;
+ case kAudioUnitRemovePropertyListenerSelect:
+ return (AudioComponentMethod)AUMethodRemovePropertyListener;
+ case kAudioUnitRemovePropertyListenerWithUserDataSelect:
+ return (AudioComponentMethod)AUMethodRemovePropertyListenerWithUserData;
+ case kAudioUnitAddRenderNotifySelect: return (AudioComponentMethod)AUMethodAddRenderNotify;
+ case kAudioUnitRemoveRenderNotifySelect:return (AudioComponentMethod)AUMethodRemoveRenderNotify;
+ case kAudioUnitGetParameterSelect: return (AudioComponentMethod)AUMethodGetParameter;
+ case kAudioUnitSetParameterSelect: return (AudioComponentMethod)AUMethodSetParameter;
+ case kAudioUnitScheduleParametersSelect:return (AudioComponentMethod)AUMethodScheduleParameters;
+ case kAudioUnitRenderSelect: return (AudioComponentMethod)AUMethodRender;
+ case kAudioUnitResetSelect: return (AudioComponentMethod)AUMethodReset;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+AudioComponentMethod AUOutputLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+ if (method) return method;
+
+ switch (selector) {
+ case kAudioOutputUnitStartSelect: return (AudioComponentMethod)AUMethodStart;
+ case kAudioOutputUnitStopSelect: return (AudioComponentMethod)AUMethodStop;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+AudioComponentMethod AUComplexOutputLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+ if (method) return method;
+
+ method = AUOutputLookup::Lookup(selector);
+ if (method) return method;
+
+ if (selector == kAudioUnitComplexRenderSelect)
+ return (AudioComponentMethod)AUMethodComplexRender;
+ return NULL;
+}
+
+AudioComponentMethod AUBaseProcessLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+ if (method) return method;
+
+ if (selector == kAudioUnitProcessSelect)
+ return (AudioComponentMethod)AUMethodProcess;
+
+ return NULL;
+}
+
+AudioComponentMethod AUBaseProcessMultipleLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+ if (method) return method;
+
+ if (selector == kAudioUnitProcessMultipleSelect)
+ return (AudioComponentMethod)AUMethodProcessMultiple;
+
+ return NULL;
+}
+
+AudioComponentMethod AUBaseProcessAndMultipleLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+ if (method) return method;
+
+ method = AUBaseProcessMultipleLookup::Lookup(selector);
+ if (method) return method;
+
+ method = AUBaseProcessLookup::Lookup(selector);
+ if (method) return method;
+
+ return NULL;
+}
+
+#if !CA_BASIC_AU_FEATURES
+inline AudioComponentMethod MIDI_Lookup (SInt16 selector)
+{
+ switch (selector) {
+ case kMusicDeviceMIDIEventSelect: return (AudioComponentMethod)AUMethodMIDIEvent;
+ case kMusicDeviceSysExSelect: return (AudioComponentMethod)AUMethodSysEx;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+AudioComponentMethod AUMIDILookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+ if (method) return method;
+
+ return MIDI_Lookup(selector);
+}
+
+AudioComponentMethod AUMIDIProcessLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseProcessLookup::Lookup(selector);
+ if (method) return method;
+
+ return MIDI_Lookup(selector);
+}
+
+AudioComponentMethod AUMusicLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+ if (method) return method;
+
+ switch (selector) {
+ case kMusicDeviceStartNoteSelect: return (AudioComponentMethod)AUMethodStartNote;
+ case kMusicDeviceStopNoteSelect: return (AudioComponentMethod)AUMethodStopNote;
+#if !TARGET_OS_IPHONE
+ case kMusicDevicePrepareInstrumentSelect: return (AudioComponentMethod)AUMethodPrepareInstrument;
+ case kMusicDeviceReleaseInstrumentSelect: return (AudioComponentMethod)AUMethodReleaseInstrument;
+#endif
+ default:
+ break;
+ }
+ return MIDI_Lookup (selector);
+}
+
+AudioComponentMethod AUAuxBaseLookup::Lookup (SInt16 selector)
+{
+ switch (selector) {
+ case kAudioUnitGetPropertyInfoSelect: return (AudioComponentMethod)AUMethodGetPropertyInfo;
+ case kAudioUnitGetPropertySelect: return (AudioComponentMethod)AUMethodGetProperty;
+ case kAudioUnitSetPropertySelect: return (AudioComponentMethod)AUMethodSetProperty;
+
+ case kAudioUnitGetParameterSelect: return (AudioComponentMethod)AUMethodGetParameter;
+ case kAudioUnitSetParameterSelect: return (AudioComponentMethod)AUMethodSetParameter;
+
+ default:
+ break;
+ }
+ return NULL;
+}
+#endif
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.h
new file mode 100644
index 0000000000..6ebea75fd6
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.h
@@ -0,0 +1,144 @@
+/*
+ File: AUPlugInDispatch.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUPlugInBase_h__
+#define __AUPlugInBase_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioComponent.h>
+ #if !CA_BASIC_AU_FEATURES
+ #include <AudioUnit/MusicDevice.h>
+ #endif
+#else
+ #include "AudioComponent.h"
+ #include "MusicDevice.h"
+#endif
+
+#include "ComponentBase.h"
+
+struct AUBaseLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUBaseFactory : public APFactory<AUBaseLookup, Implementor>
+{
+};
+
+struct AUOutputLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUOutputBaseFactory : public APFactory<AUOutputLookup, Implementor>
+{
+};
+
+struct AUComplexOutputLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUOutputComplexBaseFactory : public APFactory<AUComplexOutputLookup, Implementor>
+{
+};
+
+struct AUBaseProcessLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUBaseProcessFactory : public APFactory<AUBaseProcessLookup, Implementor>
+{
+};
+
+struct AUBaseProcessMultipleLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUBaseProcessMultipleFactory : public APFactory<AUBaseProcessMultipleLookup, Implementor>
+{
+};
+
+struct AUBaseProcessAndMultipleLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUBaseProcessAndMultipleFactory : public APFactory<AUBaseProcessAndMultipleLookup, Implementor>
+{
+};
+
+#if !CA_BASIC_AU_FEATURES
+struct AUMIDILookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUMIDIEffectFactory : public APFactory<AUMIDILookup, Implementor>
+{
+};
+
+struct AUMIDIProcessLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUMIDIProcessFactory : public APFactory<AUMIDIProcessLookup, Implementor>
+{
+};
+
+struct AUMusicLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUMusicDeviceFactory : public APFactory<AUMusicLookup, Implementor>
+{
+};
+
+struct AUAuxBaseLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUAuxBaseFactory : public APFactory<AUAuxBaseLookup, Implementor>
+{
+};
+#endif // CA_BASIC_AU_FEATURES
+
+#endif // __AUPlugInBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUResources.r b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUResources.r
new file mode 100644
index 0000000000..55040fc396
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUResources.r
@@ -0,0 +1,140 @@
+/*
+ File: AUResources.r
+ Abstract: AUResources.r
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUResources.r
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* sample macro definitions -- all of these symbols must be defined
+#define RES_ID kHALOutputResID
+#define COMP_TYPE kAudioUnitComponentType
+#define COMP_SUBTYPE kAudioUnitOutputSubType
+#define COMP_MANUF kAudioUnitAudioHardwareOutputSubSubType
+#define VERSION 0x00010000
+#define NAME "AudioHALOutput"
+#define DESCRIPTION "Audio hardware output AudioUnit"
+#define ENTRY_POINT "AUHALEntry"
+*/
+#define UseExtendedThingResource 1
+
+#include <CoreServices/CoreServices.r>
+
+// this is a define used to indicate that a component has no static data that would mean
+// that no more than one instance could be open at a time - never been true for AUs
+#ifndef cmpThreadSafeOnMac
+#define cmpThreadSafeOnMac 0x10000000
+#endif
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+resource 'STR ' (RES_ID, purgeable) {
+ NAME
+};
+
+resource 'STR ' (RES_ID + 1, purgeable) {
+ DESCRIPTION
+};
+
+resource 'dlle' (RES_ID) {
+ ENTRY_POINT
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+resource 'thng' (RES_ID, NAME) {
+ COMP_TYPE,
+ COMP_SUBTYPE,
+ COMP_MANUF,
+ 0, 0, 0, 0, // no 68K
+ 'STR ', RES_ID,
+ 'STR ', RES_ID + 1,
+ 0, 0, /* icon */
+ VERSION,
+ componentHasMultiplePlatforms | componentDoAutoVersion,
+ 0,
+ {
+ #if defined(ppc_YES)
+ cmpThreadSafeOnMac,
+ 'dlle', RES_ID, platformPowerPCNativeEntryPoint
+ #define NeedLeadingComma 1
+ #endif
+ #if defined(ppc64_YES)
+ #if defined(NeedLeadingComma)
+ ,
+ #endif
+ cmpThreadSafeOnMac,
+ 'dlle', RES_ID, platformPowerPC64NativeEntryPoint
+ #define NeedLeadingComma 1
+ #endif
+ #if defined(i386_YES)
+ #if defined(NeedLeadingComma)
+ ,
+ #endif
+ cmpThreadSafeOnMac,
+ 'dlle', RES_ID, platformIA32NativeEntryPoint
+ #define NeedLeadingComma 1
+ #endif
+ #if defined(x86_64_YES)
+ #if defined(NeedLeadingComma)
+ ,
+ #endif
+ cmpThreadSafeOnMac,
+ 'dlle', RES_ID, 8
+ #define NeedLeadingComma 1
+ #endif
+ }
+};
+
+#undef RES_ID
+#undef COMP_TYPE
+#undef COMP_SUBTYPE
+#undef COMP_MANUF
+#undef VERSION
+#undef NAME
+#undef DESCRIPTION
+#undef ENTRY_POINT
+#undef NeedLeadingComma
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp
new file mode 100644
index 0000000000..24bd18e434
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp
@@ -0,0 +1,565 @@
+/*
+ File: AUScopeElement.cpp
+ Abstract: AUScopeElement.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUScopeElement.h"
+#include "AUBase.h"
+
+//_____________________________________________________________________________
+//
+// By default, parameterIDs may be arbitrarily spaced, and an STL map
+// will be used for access. Calling UseIndexedParameters() will
+// instead use an STL vector for faster indexed access.
+// This assumes the paramIDs are numbered 0.....inNumberOfParameters-1
+// Call this before defining/adding any parameters with SetParameter()
+//
+void AUElement::UseIndexedParameters(int inNumberOfParameters)
+{
+ mIndexedParameters.resize (inNumberOfParameters);
+ mUseIndexedParameters = true;
+}
+
+//_____________________________________________________________________________
+//
+// Helper method.
+// returns the ParameterMapEvent object associated with the paramID
+//
+inline ParameterMapEvent& AUElement::GetParamEvent(AudioUnitParameterID paramID)
+{
+ ParameterMapEvent *event;
+
+ if(mUseIndexedParameters)
+ {
+ if(paramID >= mIndexedParameters.size() )
+ COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
+
+ event = &mIndexedParameters[paramID];
+ }
+ else
+ {
+ ParameterMap::iterator i = mParameters.find(paramID);
+ if (i == mParameters.end())
+ COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
+
+ event = &(*i).second;
+ }
+
+ return *event;
+}
+
+//_____________________________________________________________________________
+//
+// Helper method.
+// returns whether the specified paramID is known to the element
+//
+bool AUElement::HasParameterID (AudioUnitParameterID paramID) const
+{
+ if(mUseIndexedParameters)
+ {
+ if(paramID >= mIndexedParameters.size() )
+ return false;
+
+ return true;
+ }
+
+ ParameterMap::const_iterator i = mParameters.find(paramID);
+ if (i == mParameters.end())
+ return false;
+
+ return true;
+}
+
+//_____________________________________________________________________________
+//
+// caller assumes that this is actually an immediate parameter
+//
+AudioUnitParameterValue AUElement::GetParameter(AudioUnitParameterID paramID)
+{
+ ParameterMapEvent &event = GetParamEvent(paramID);
+
+ return event.GetValue();
+}
+
+
+//_____________________________________________________________________________
+//
+void AUElement::GetRampSliceStartEnd( AudioUnitParameterID paramID,
+ AudioUnitParameterValue & outStartValue,
+ AudioUnitParameterValue & outEndValue,
+ AudioUnitParameterValue & outValuePerFrameDelta )
+
+{
+ ParameterMapEvent &event = GetParamEvent(paramID);
+
+ // works even if the value is constant (immediate parameter value)
+ event.GetRampSliceStartEnd(outStartValue, outEndValue, outValuePerFrameDelta );
+}
+
+//_____________________________________________________________________________
+//
+AudioUnitParameterValue AUElement::GetEndValue( AudioUnitParameterID paramID)
+
+{
+ ParameterMapEvent &event = GetParamEvent(paramID);
+
+ // works even if the value is constant (immediate parameter value)
+ return event.GetEndValue();
+}
+
+//_____________________________________________________________________________
+//
+void AUElement::SetParameter(AudioUnitParameterID paramID, AudioUnitParameterValue inValue, bool okWhenInitialized)
+{
+ if(mUseIndexedParameters)
+ {
+ ParameterMapEvent &event = GetParamEvent(paramID);
+ event.SetValue(inValue);
+ }
+ else
+ {
+ ParameterMap::iterator i = mParameters.find(paramID);
+
+ if (i == mParameters.end())
+ {
+ if (mAudioUnit->IsInitialized() && !okWhenInitialized) {
+ // The AU should not be creating new parameters once initialized.
+ // If a client tries to set an undefined parameter, we could throw as follows,
+ // but this might cause a regression. So it is better to just fail silently.
+ // COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
+#if DEBUG
+ fprintf(stderr, "WARNING: %s SetParameter for undefined param ID %d while initialized. Ignoring..\n",
+ mAudioUnit->GetLoggingString(), (int)paramID);
+#endif
+ } else {
+ // create new entry in map for the paramID (only happens first time)
+ ParameterMapEvent event(inValue);
+ mParameters[paramID] = event;
+ }
+ }
+ else
+ {
+ // paramID already exists in map so simply change its value
+ ParameterMapEvent &event = (*i).second;
+ event.SetValue(inValue);
+ }
+ }
+}
+
+//_____________________________________________________________________________
+//
+void AUElement::SetScheduledEvent( AudioUnitParameterID paramID,
+ const AudioUnitParameterEvent &inEvent,
+ UInt32 inSliceOffsetInBuffer,
+ UInt32 inSliceDurationFrames,
+ bool okWhenInitialized )
+{
+ if(mUseIndexedParameters)
+ {
+ ParameterMapEvent &event = GetParamEvent(paramID);
+ event.SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
+ }
+ else
+ {
+ ParameterMap::iterator i = mParameters.find(paramID);
+
+ if (i == mParameters.end())
+ {
+ if (mAudioUnit->IsInitialized() && !okWhenInitialized) {
+ // The AU should not be creating new parameters once initialized.
+ // If a client tries to set an undefined parameter, we could throw as follows,
+ // but this might cause a regression. So it is better to just fail silently.
+ // COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
+#if DEBUG
+ fprintf(stderr, "WARNING: %s SetScheduledEvent for undefined param ID %d while initialized. Ignoring..\n",
+ mAudioUnit->GetLoggingString(), (int)paramID);
+#endif
+ } else {
+ // create new entry in map for the paramID (only happens first time)
+ ParameterMapEvent event(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames);
+ mParameters[paramID] = event;
+ }
+ }
+ else
+ {
+ // paramID already exists in map so simply change its value
+ ParameterMapEvent &event = (*i).second;
+
+ event.SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
+ }
+ }
+}
+
+
+
+//_____________________________________________________________________________
+//
+void AUElement::GetParameterList(AudioUnitParameterID *outList)
+{
+ if(mUseIndexedParameters)
+ {
+ UInt32 nparams = static_cast<UInt32>(mIndexedParameters.size());
+ for (UInt32 i = 0; i < nparams; i++ )
+ *outList++ = (AudioUnitParameterID)i;
+ }
+ else
+ {
+ for (ParameterMap::iterator i = mParameters.begin(); i != mParameters.end(); ++i)
+ *outList++ = (*i).first;
+ }
+}
+
+//_____________________________________________________________________________
+//
+void AUElement::SaveState(CFMutableDataRef data)
+{
+ if(mUseIndexedParameters)
+ {
+ UInt32 nparams = static_cast<UInt32>(mIndexedParameters.size());
+ UInt32 theData = CFSwapInt32HostToBig(nparams);
+ CFDataAppendBytes(data, (UInt8 *)&theData, sizeof(nparams));
+
+ for (UInt32 i = 0; i < nparams; i++)
+ {
+ struct {
+ UInt32 paramID;
+ //CFSwappedFloat32 value; crashes gcc3 PFE
+ UInt32 value; // really a big-endian float
+ } entry;
+
+ entry.paramID = CFSwapInt32HostToBig(i);
+
+ AudioUnitParameterValue v = mIndexedParameters[i].GetValue();
+ entry.value = CFSwapInt32HostToBig(*(UInt32 *)&v );
+
+ CFDataAppendBytes(data, (UInt8 *)&entry, sizeof(entry));
+ }
+ }
+ else
+ {
+ UInt32 nparams = CFSwapInt32HostToBig(static_cast<uint32_t>(mParameters.size()));
+ CFDataAppendBytes(data, (UInt8 *)&nparams, sizeof(nparams));
+
+ for (ParameterMap::iterator i = mParameters.begin(); i != mParameters.end(); ++i) {
+ struct {
+ UInt32 paramID;
+ //CFSwappedFloat32 value; crashes gcc3 PFE
+ UInt32 value; // really a big-endian float
+ } entry;
+
+ entry.paramID = CFSwapInt32HostToBig((*i).first);
+
+ AudioUnitParameterValue v = (*i).second.GetValue();
+ entry.value = CFSwapInt32HostToBig(*(UInt32 *)&v );
+
+ CFDataAppendBytes(data, (UInt8 *)&entry, sizeof(entry));
+ }
+ }
+}
+
+//_____________________________________________________________________________
+//
+const UInt8 * AUElement::RestoreState(const UInt8 *state)
+{
+ union FloatInt32 { UInt32 i; AudioUnitParameterValue f; };
+ const UInt8 *p = state;
+ UInt32 nparams = CFSwapInt32BigToHost(*(UInt32 *)p);
+ p += sizeof(UInt32);
+
+ for (UInt32 i = 0; i < nparams; ++i) {
+ struct {
+ AudioUnitParameterID paramID;
+ AudioUnitParameterValue value;
+ } entry;
+
+ entry.paramID = CFSwapInt32BigToHost(*(UInt32 *)p);
+ p += sizeof(UInt32);
+ FloatInt32 temp;
+ temp.i = CFSwapInt32BigToHost(*(UInt32 *)p);
+ entry.value = temp.f;
+ p += sizeof(AudioUnitParameterValue);
+
+ SetParameter(entry.paramID, entry.value);
+ }
+ return p;
+}
+
+//_____________________________________________________________________________
+//
+void AUElement::SetName (CFStringRef inName)
+{
+ if (mElementName) CFRelease (mElementName);
+ mElementName = inName;
+ if (mElementName) CFRetain (mElementName);
+}
+
+
+//_____________________________________________________________________________
+//
+AUIOElement::AUIOElement(AUBase *audioUnit) :
+ AUElement(audioUnit),
+ mWillAllocate (true)
+{
+ mStreamFormat.SetAUCanonical(2, // stereo
+ audioUnit->AudioUnitAPIVersion() == 1);
+ // interleaved if API version 1, deinterleaved if version 2
+ mStreamFormat.mSampleRate = kAUDefaultSampleRate;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUIOElement::SetStreamFormat(const CAStreamBasicDescription &desc)
+{
+ mStreamFormat = desc;
+ return AUBase::noErr;
+}
+
+//_____________________________________________________________________________
+// inFramesToAllocate == 0 implies the AudioUnit's max-frames-per-slice will be used
+void AUIOElement::AllocateBuffer(UInt32 inFramesToAllocate)
+{
+ if (GetAudioUnit()->HasBegunInitializing())
+ {
+ UInt32 framesToAllocate = inFramesToAllocate > 0 ? inFramesToAllocate : GetAudioUnit()->GetMaxFramesPerSlice();
+
+// printf ("will allocate: %d\n", (int)((mWillAllocate && NeedsBufferSpace()) ? framesToAllocate : 0));
+
+ mIOBuffer.Allocate(mStreamFormat, (mWillAllocate && NeedsBufferSpace()) ? framesToAllocate : 0);
+ }
+}
+
+//_____________________________________________________________________________
+//
+void AUIOElement::DeallocateBuffer()
+{
+ mIOBuffer.Deallocate();
+}
+
+//_____________________________________________________________________________
+//
+// AudioChannelLayout support
+
+// outLayoutTagsPtr WILL be NULL if called to find out how many
+// layouts that Audio Unit will report
+// return 0 (ie. NO channel layouts) if the AU doesn't require channel layout knowledge
+UInt32 AUIOElement::GetChannelLayoutTags (AudioChannelLayoutTag *outLayoutTagsPtr)
+{
+ return 0;
+}
+
+// As the AudioChannelLayout can be a variable length structure
+// (though in most cases it won't be!!!)
+// The size of the ACL is always returned by the method
+// if outMapPtr is NOT-NULL, then AU should copy into this pointer (outMapPtr) the current ACL that it has in use.
+// the AU should also return whether the property is writable (that is the client can provide any arbitrary ACL that the audio unit will then honour)
+// or if the property is read only - which is the generally preferred mode.
+// If the AU doesn't require an AudioChannelLayout, then just return 0.
+UInt32 AUIOElement::GetAudioChannelLayout (AudioChannelLayout *outMapPtr,
+ Boolean &outWritable)
+{
+ return 0;
+}
+
+// the incoming channel map will be at least as big as a basic AudioChannelLayout
+// but its contents will determine its actual size
+// Subclass should overide if channel map is writable
+OSStatus AUIOElement::SetAudioChannelLayout (const AudioChannelLayout &inData)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+// Some units support optional usage of channel maps - typically converter units
+// that can do channel remapping between different maps. In that optional case
+// the user should be able to remove a channel map if that is possible.
+// Typically this is NOT the case (e.g., the 3DMixer even in the stereo case
+// needs to know if it is rendering to speakers or headphones)
+OSStatus AUIOElement::RemoveAudioChannelLayout ()
+{
+ return kAudioUnitErr_InvalidPropertyValue;
+}
+
+
+//_____________________________________________________________________________
+//
+AUScope::~AUScope()
+{
+ for (ElementVector::iterator it = mElements.begin(); it != mElements.end(); ++it)
+ delete *it;
+}
+
+//_____________________________________________________________________________
+//
+void AUScope::SetNumberOfElements(UInt32 numElements)
+{
+ if (mDelegate)
+ return mDelegate->SetNumberOfElements(numElements);
+
+ if (numElements > mElements.size()) {
+ mElements.reserve(numElements);
+ while (numElements > mElements.size()) {
+ AUElement *elem = mCreator->CreateElement(GetScope(), static_cast<UInt32>(mElements.size()));
+ mElements.push_back(elem);
+ }
+ } else
+ while (numElements < mElements.size()) {
+ AUElement *elem = mElements.back();
+ mElements.pop_back();
+ delete elem;
+ }
+}
+
+//_____________________________________________________________________________
+//
+bool AUScope::HasElementWithName () const
+{
+ for (UInt32 i = 0; i < GetNumberOfElements(); ++i) {
+ AUElement * el = const_cast<AUScope*>(this)->GetElement (i);
+ if (el && el->HasName()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+//_____________________________________________________________________________
+//
+
+void AUScope::AddElementNamesToDict (CFMutableDictionaryRef & inNameDict)
+{
+ if (HasElementWithName())
+ {
+ static char string[32];
+ CFMutableDictionaryRef elementDict = CFDictionaryCreateMutable (NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CFStringRef str;
+ for (UInt32 i = 0; i < GetNumberOfElements(); ++i) {
+ AUElement * el = GetElement (i);
+ if (el && el->HasName()) {
+ snprintf (string, sizeof(string), "%d", int(i));
+ str = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
+ CFDictionarySetValue (elementDict, str, el->GetName());
+ CFRelease (str);
+ }
+ }
+
+ snprintf (string, sizeof(string), "%d", int(mScope));
+ str = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
+ CFDictionarySetValue (inNameDict, str, elementDict);
+ CFRelease (str);
+ CFRelease (elementDict);
+ }
+}
+
+//_____________________________________________________________________________
+//
+bool AUScope::RestoreElementNames (CFDictionaryRef& inNameDict)
+{
+ static char string[32];
+
+ //first we have to see if we have enough elements
+ bool didAddElements = false;
+ unsigned int maxElNum = GetNumberOfElements();
+
+ int dictSize = static_cast<int>(CFDictionaryGetCount(inNameDict));
+ CFStringRef * keys = (CFStringRef*)CA_malloc (dictSize * sizeof (CFStringRef));
+ CFDictionaryGetKeysAndValues (inNameDict, reinterpret_cast<const void**>(keys), NULL);
+ for (int i = 0; i < dictSize; i++)
+ {
+ unsigned int intKey = 0;
+ CFStringGetCString (keys[i], string, 32, kCFStringEncodingASCII);
+ int result = sscanf (string, "%u", &intKey);
+ // check if sscanf succeeded and element index is less than max elements.
+ if (result && UInt32(intKey) < maxElNum)
+ {
+ CFStringRef elName = reinterpret_cast<CFStringRef>(CFDictionaryGetValue (inNameDict, keys[i]));
+ AUElement* element = GetElement (intKey);
+ if (element)
+ element->SetName (elName);
+ }
+ }
+ free (keys);
+
+ return didAddElements;
+}
+
+void AUScope::SaveState(CFMutableDataRef data)
+{
+ AudioUnitElement nElems = GetNumberOfElements();
+ for (AudioUnitElement ielem = 0; ielem < nElems; ++ielem) {
+ AUElement *element = GetElement(ielem);
+ UInt32 nparams = element->GetNumberOfParameters();
+ if (nparams > 0) {
+ struct {
+ UInt32 scope;
+ UInt32 element;
+ } hdr;
+
+ hdr.scope = CFSwapInt32HostToBig(GetScope());
+ hdr.element = CFSwapInt32HostToBig(ielem);
+ CFDataAppendBytes(data, (UInt8 *)&hdr, sizeof(hdr));
+
+ element->SaveState(data);
+ }
+ }
+}
+
+const UInt8 * AUScope::RestoreState(const UInt8 *state)
+{
+ const UInt8 *p = state;
+ UInt32 elementIdx = CFSwapInt32BigToHost(*(UInt32 *)p); p += sizeof(UInt32);
+ AUElement *element = GetElement(elementIdx);
+ if (!element) {
+ struct {
+ AudioUnitParameterID paramID;
+ AudioUnitParameterValue value;
+ } entry;
+ UInt32 nparams = CFSwapInt32BigToHost(*(UInt32 *)p);
+ p += sizeof(UInt32);
+
+ p += nparams * sizeof(entry);
+ } else
+ p = element->RestoreState(p);
+
+ return p;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.h
new file mode 100644
index 0000000000..47ebe2f338
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.h
@@ -0,0 +1,553 @@
+/*
+ File: AUScopeElement.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUScopeElement_h__
+#define __AUScopeElement_h__
+
+#include <map>
+#include <vector>
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnit.h>
+#else
+ #include <AudioUnit.h>
+#endif
+#include "ComponentBase.h"
+#include "AUBuffer.h"
+
+
+class AUBase;
+
+// ____________________________________________________________________________
+//
+// represents a parameter's value (either constant or ramped)
+/*! @class ParameterMapEvent */
+class ParameterMapEvent
+{
+public:
+/*! @ctor ParameterMapEvent */
+ ParameterMapEvent()
+ : mEventType(kParameterEvent_Immediate), mBufferOffset(0), mDurationInFrames(0), mValue1(0.0f), mValue2(0.0f), mSliceDurationFrames(0)
+ {}
+
+/*! @ctor ParameterMapEvent */
+ ParameterMapEvent(AudioUnitParameterValue inValue)
+ : mEventType(kParameterEvent_Immediate), mBufferOffset(0), mDurationInFrames(0), mValue1(inValue), mValue2(inValue), mSliceDurationFrames(0)
+ {}
+
+ // constructor for scheduled event
+/*! @ctor ParameterMapEvent */
+ ParameterMapEvent( const AudioUnitParameterEvent &inEvent,
+ UInt32 inSliceOffsetInBuffer,
+ UInt32 inSliceDurationFrames )
+ {
+ SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
+ };
+
+/*! @method SetScheduledEvent */
+ void SetScheduledEvent( const AudioUnitParameterEvent &inEvent,
+ UInt32 inSliceOffsetInBuffer,
+ UInt32 inSliceDurationFrames )
+ {
+ mEventType = inEvent.eventType;
+ mSliceDurationFrames = inSliceDurationFrames;
+
+ if(mEventType == kParameterEvent_Immediate )
+ {
+ // constant immediate value for the whole slice
+ mValue1 = inEvent.eventValues.immediate.value;
+ mValue2 = mValue1;
+ mDurationInFrames = inSliceDurationFrames;
+ mBufferOffset = 0;
+ }
+ else
+ {
+ mDurationInFrames = inEvent.eventValues.ramp.durationInFrames;
+ mBufferOffset = inEvent.eventValues.ramp.startBufferOffset - inSliceOffsetInBuffer; // shift over for this slice
+ mValue1 = inEvent.eventValues.ramp.startValue;
+ mValue2 = inEvent.eventValues.ramp.endValue;
+ }
+ };
+
+
+
+/*! @method GetEventType */
+ AUParameterEventType GetEventType() const {return mEventType;};
+
+/*! @method GetValue */
+ AudioUnitParameterValue GetValue() const {return mValue1;}; // only valid if immediate event type
+/*! @method GetEndValue */
+ AudioUnitParameterValue GetEndValue() const {return mValue2;}; // only valid if immediate event type
+/*! @method SetValue */
+ void SetValue(AudioUnitParameterValue inValue)
+ {
+ mEventType = kParameterEvent_Immediate;
+ mValue1 = inValue;
+ mValue2 = inValue;
+ }
+
+ // interpolates the start and end values corresponding to the current processing slice
+ // most ramp parameter implementations will want to use this method
+ // the start value will correspond to the start of the slice
+ // the end value will correspond to the end of the slice
+/*! @method GetRampSliceStartEnd */
+ void GetRampSliceStartEnd( AudioUnitParameterValue & outStartValue,
+ AudioUnitParameterValue & outEndValue,
+ AudioUnitParameterValue & outValuePerFrameDelta )
+ {
+ if (mEventType == kParameterEvent_Ramped) {
+ outValuePerFrameDelta = (mValue2 - mValue1) / mDurationInFrames;
+
+ outStartValue = mValue1 + outValuePerFrameDelta * (-mBufferOffset); // corresponds to frame 0 of this slice
+ outEndValue = outStartValue + outValuePerFrameDelta * mSliceDurationFrames;
+ } else {
+ outValuePerFrameDelta = 0;
+ outStartValue = outEndValue = mValue1;
+ }
+ };
+
+ // Some ramp parameter implementations will want to interpret the ramp using their
+ // own interpolation method (perhaps non-linear)
+ // This method gives the raw ramp information, relative to this processing slice
+ // for the client to interpret as desired
+/*! @method GetRampInfo */
+ void GetRampInfo( SInt32 & outBufferOffset,
+ UInt32 & outDurationInFrames,
+ AudioUnitParameterValue & outStartValue,
+ AudioUnitParameterValue & outEndValue )
+ {
+ outBufferOffset = mBufferOffset;
+ outDurationInFrames = mDurationInFrames;
+ outStartValue = mValue1;
+ outEndValue = mValue2;
+ };
+
+#if DEBUG
+ void Print()
+ {
+ printf("ParameterEvent @ %p\n", this);
+ printf(" mEventType = %d\n", (int)mEventType);
+ printf(" mBufferOffset = %d\n", (int)mBufferOffset);
+ printf(" mDurationInFrames = %d\n", (int)mDurationInFrames);
+ printf(" mSliceDurationFrames = %d\n", (int)mSliceDurationFrames);
+ printf(" mValue1 = %.5f\n", mValue1);
+ printf(" mValue2 = %.5f\n", mValue2);
+ }
+#endif
+
+private:
+ AUParameterEventType mEventType;
+
+ SInt32 mBufferOffset; // ramp start offset relative to start of this slice (may be negative)
+ UInt32 mDurationInFrames; // total duration of ramp parameter
+ AudioUnitParameterValue mValue1; // value if immediate : startValue if ramp
+ AudioUnitParameterValue mValue2; // endValue (only used for ramp)
+
+ UInt32 mSliceDurationFrames; // duration of this processing slice
+};
+
+
+
+// ____________________________________________________________________________
+//
+class AUIOElement;
+
+/*! @class AUElement */
+class AUElement {
+public:
+/*! @ctor AUElement */
+ AUElement(AUBase *audioUnit) : mAudioUnit(audioUnit),
+ mUseIndexedParameters(false), mElementName(0) { }
+
+/*! @dtor ~AUElement */
+ virtual ~AUElement() { if (mElementName) CFRelease (mElementName); }
+
+/*! @method GetNumberOfParameters */
+ virtual UInt32 GetNumberOfParameters()
+ {
+ if(mUseIndexedParameters) return static_cast<UInt32>(mIndexedParameters.size()); else return static_cast<UInt32>(mParameters.size());
+ }
+/*! @method GetParameterList */
+ virtual void GetParameterList(AudioUnitParameterID *outList);
+/*! @method HasParameterID */
+ bool HasParameterID (AudioUnitParameterID paramID) const;
+
+/*! @method GetParameter */
+ AudioUnitParameterValue GetParameter(AudioUnitParameterID paramID);
+/*! @method SetParameter */
+ void SetParameter(AudioUnitParameterID paramID, AudioUnitParameterValue value, bool okWhenInitialized = false);
+ // Only set okWhenInitialized to true when you know the outside world cannot access this element. Otherwise the parameter map could get corrupted.
+
+ // interpolates the start and end values corresponding to the current processing slice
+ // most ramp parameter implementations will want to use this method
+/*! @method GetRampSliceStartEnd */
+ void GetRampSliceStartEnd( AudioUnitParameterID paramID,
+ AudioUnitParameterValue & outStartValue,
+ AudioUnitParameterValue & outEndValue,
+ AudioUnitParameterValue & outValuePerFrameDelta );
+
+/*! @method GetEndValue */
+ AudioUnitParameterValue GetEndValue( AudioUnitParameterID paramID);
+
+/*! @method SetRampParameter */
+ void SetScheduledEvent( AudioUnitParameterID paramID,
+ const AudioUnitParameterEvent &inEvent,
+ UInt32 inSliceOffsetInBuffer,
+ UInt32 inSliceDurationFrames,
+ bool okWhenInitialized = false );
+ // Only set okWhenInitialized to true when you know the outside world cannot access this element. Otherwise the parameter map could get corrupted.
+
+
+/*! @method GetAudioUnit */
+ AUBase * GetAudioUnit() const { return mAudioUnit; };
+
+/*! @method SaveState */
+ void SaveState(CFMutableDataRef data);
+/*! @method RestoreState */
+ const UInt8 * RestoreState(const UInt8 *state);
+/*! @method GetName */
+ CFStringRef GetName () const { return mElementName; }
+/*! @method SetName */
+ void SetName (CFStringRef inName);
+/*! @method HasName */
+ bool HasName () const { return mElementName != 0; }
+/*! @method UseIndexedParameters */
+ virtual void UseIndexedParameters(int inNumberOfParameters);
+
+/*! @method AsIOElement*/
+ virtual AUIOElement* AsIOElement () { return NULL; }
+
+protected:
+ inline ParameterMapEvent& GetParamEvent(AudioUnitParameterID paramID);
+
+private:
+ typedef std::map<AudioUnitParameterID, ParameterMapEvent, std::less<AudioUnitParameterID> > ParameterMap;
+
+/*! @var mAudioUnit */
+ AUBase * mAudioUnit;
+/*! @var mParameters */
+ ParameterMap mParameters;
+
+/*! @var mUseIndexedParameters */
+ bool mUseIndexedParameters;
+/*! @var mIndexedParameters */
+ std::vector<ParameterMapEvent> mIndexedParameters;
+
+/*! @var mElementName */
+ CFStringRef mElementName;
+};
+
+
+
+// ____________________________________________________________________________
+//
+/*! @class AUIOElement */
+class AUIOElement : public AUElement {
+public:
+/*! @ctor AUIOElement */
+ AUIOElement(AUBase *audioUnit);
+
+/*! @method GetStreamFormat */
+ const CAStreamBasicDescription &GetStreamFormat() const { return mStreamFormat; }
+
+/*! @method SetStreamFormat */
+ virtual OSStatus SetStreamFormat(const CAStreamBasicDescription &desc);
+
+/*! @method AllocateBuffer */
+ virtual void AllocateBuffer(UInt32 inFramesToAllocate = 0);
+/*! @method DeallocateBuffer */
+ void DeallocateBuffer();
+/*! @method NeedsBufferSpace */
+ virtual bool NeedsBufferSpace() const = 0;
+
+/*! @method SetWillAllocateBuffer */
+ void SetWillAllocateBuffer(bool inFlag) {
+ mWillAllocate = inFlag;
+ }
+/*! @method WillAllocateBuffer */
+ bool WillAllocateBuffer() const {
+ return mWillAllocate;
+ }
+
+/*! @method UseExternalBuffer */
+ void UseExternalBuffer(const AudioUnitExternalBuffer &buf) {
+ mIOBuffer.UseExternalBuffer(mStreamFormat, buf);
+ }
+/*! @method PrepareBuffer */
+ AudioBufferList & PrepareBuffer(UInt32 nFrames) {
+ if (mWillAllocate)
+ return mIOBuffer.PrepareBuffer(mStreamFormat, nFrames);
+ throw OSStatus(kAudioUnitErr_InvalidPropertyValue);
+ }
+/*! @method PrepareNullBuffer */
+ AudioBufferList & PrepareNullBuffer(UInt32 nFrames) {
+ return mIOBuffer.PrepareNullBuffer(mStreamFormat, nFrames);
+ }
+/*! @method SetBufferList */
+ AudioBufferList & SetBufferList(AudioBufferList &abl) { return mIOBuffer.SetBufferList(abl); }
+/*! @method SetBuffer */
+ void SetBuffer(UInt32 index, AudioBuffer &ab) { mIOBuffer.SetBuffer(index, ab); }
+/*! @method InvalidateBufferList */
+ void InvalidateBufferList() { mIOBuffer.InvalidateBufferList(); }
+
+/*! @method GetBufferList */
+ AudioBufferList & GetBufferList() const { return mIOBuffer.GetBufferList(); }
+
+/*! @method GetChannelData */
+ AudioUnitSampleType * GetChannelData(int ch) const {
+ if (mStreamFormat.IsInterleaved())
+ return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
+ else
+ return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
+ }
+ Float32 * GetFloat32ChannelData(int ch) const {
+ if (mStreamFormat.IsInterleaved())
+ return static_cast<Float32 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
+ else
+ return static_cast<Float32 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
+ }
+ SInt32 * GetSInt32ChannelData(int ch) const {
+ if (mStreamFormat.IsInterleaved())
+ return static_cast<SInt32 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
+ else
+ return static_cast<SInt32 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
+ }
+ SInt16 * GetInt16ChannelData(int ch) const {
+ if (mStreamFormat.IsInterleaved())
+ return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
+ else
+ return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
+ }
+
+/*! @method CopyBufferListTo */
+ void CopyBufferListTo(AudioBufferList &abl) const {
+ mIOBuffer.CopyBufferListTo(abl);
+ }
+/*! @method CopyBufferContentsTo */
+ void CopyBufferContentsTo(AudioBufferList &abl) const {
+ mIOBuffer.CopyBufferContentsTo(abl);
+ }
+
+/* UInt32 BytesToFrames(UInt32 nBytes) { return nBytes / mStreamFormat.mBytesPerFrame; }
+ UInt32 BytesToFrames(AudioBufferList &abl) {
+ return BytesToFrames(abl.mBuffers[0].mDataByteSize);
+ }
+ UInt32 FramesToBytes(UInt32 nFrames) { return nFrames * mStreamFormat.mBytesPerFrame; }*/
+
+/*! @method IsInterleaved */
+ bool IsInterleaved() const { return mStreamFormat.IsInterleaved(); }
+/*! @method NumberChannels */
+ UInt32 NumberChannels() const { return mStreamFormat.NumberChannels(); }
+/*! @method NumberInterleavedChannels */
+ UInt32 NumberInterleavedChannels() const { return mStreamFormat.NumberInterleavedChannels(); }
+
+/*! @method GetChannelMapTags */
+ virtual UInt32 GetChannelLayoutTags (AudioChannelLayoutTag *outLayoutTagsPtr);
+
+/*! @method GetAudioChannelLayout */
+ virtual UInt32 GetAudioChannelLayout (AudioChannelLayout *outMapPtr, Boolean &outWritable);
+
+/*! @method SetAudioChannelLayout */
+ virtual OSStatus SetAudioChannelLayout (const AudioChannelLayout &inData);
+
+/*! @method RemoveAudioChannelLayout */
+ virtual OSStatus RemoveAudioChannelLayout ();
+
+/*! @method AsIOElement*/
+ virtual AUIOElement* AsIOElement () { return this; }
+
+protected:
+/*! @var mStreamFormat */
+ CAStreamBasicDescription mStreamFormat;
+/*! @var mIOBuffer */
+ AUBufferList mIOBuffer; // for input: input proc buffer, only allocated when needed
+ // for output: output cache, usually allocated early on
+/*! @var mWillAllocate */
+ bool mWillAllocate;
+};
+
+// ____________________________________________________________________________
+//
+// AUScopeDelegates are a way to get virtual scopes.
+/*! @class AUScopeDelegate */
+class AUScopeDelegate {
+public:
+/*! @ctor AUScopeDelegate */
+ AUScopeDelegate() : mCreator(NULL), mScope(0) { }
+/*! @dtor ~AUScopeDelegate */
+ virtual ~AUScopeDelegate() {}
+
+/*! @method Initialize */
+ void Initialize( AUBase *creator,
+ AudioUnitScope scope,
+ UInt32 numElements)
+ {
+ mCreator = creator;
+ mScope = scope;
+ SetNumberOfElements(numElements);
+ }
+
+/*! @method SetNumberOfElements */
+ virtual void SetNumberOfElements(UInt32 numElements) = 0;
+
+/*! @method GetNumberOfElements */
+ virtual UInt32 GetNumberOfElements() = 0;
+
+/*! @method GetElement */
+ virtual AUElement * GetElement(UInt32 elementIndex) = 0;
+
+ AUBase * GetCreator() const { return mCreator; }
+ AudioUnitScope GetScope() const { return mScope; }
+
+
+private:
+/*! @var mCreator */
+ AUBase * mCreator;
+/*! @var mScope */
+ AudioUnitScope mScope;
+};
+
+
+
+// ____________________________________________________________________________
+//
+/*! @class AUScope */
+class AUScope {
+public:
+/*! @ctor AUScope */
+ AUScope() : mCreator(NULL), mScope(0), mDelegate(0) { }
+/*! @dtor ~AUScope */
+ ~AUScope();
+
+/*! @method Initialize */
+ void Initialize(AUBase *creator,
+ AudioUnitScope scope,
+ UInt32 numElements)
+ {
+ mCreator = creator;
+ mScope = scope;
+
+ if (mDelegate)
+ return mDelegate->Initialize(creator, scope, numElements);
+
+ SetNumberOfElements(numElements);
+ }
+
+/*! @method SetNumberOfElements */
+ void SetNumberOfElements(UInt32 numElements);
+
+/*! @method GetNumberOfElements */
+ UInt32 GetNumberOfElements() const
+ {
+ if (mDelegate)
+ return mDelegate->GetNumberOfElements();
+
+ return static_cast<UInt32>(mElements.size());
+ }
+
+/*! @method GetElement */
+ AUElement * GetElement(UInt32 elementIndex) const
+ {
+ if (mDelegate)
+ return mDelegate->GetElement(elementIndex);
+
+ ElementVector::const_iterator i = mElements.begin() + elementIndex;
+ // catch passing -1 in as the elementIndex - causes a wrap around
+ return (i >= mElements.end() || i < mElements.begin()) ? NULL : *i;
+ }
+
+/*! @method SafeGetElement */
+ AUElement * SafeGetElement(UInt32 elementIndex)
+ {
+ AUElement *element = GetElement(elementIndex);
+ if (element == NULL)
+ COMPONENT_THROW(kAudioUnitErr_InvalidElement);
+ return element;
+ }
+
+/*! @method GetIOElement */
+ AUIOElement * GetIOElement(UInt32 elementIndex) const
+ {
+ AUElement *element = GetElement(elementIndex);
+ AUIOElement *ioel = element ? element->AsIOElement () : NULL;
+ if (!ioel)
+ COMPONENT_THROW (kAudioUnitErr_InvalidElement);
+ return ioel;
+ }
+
+/*! @method HasElementWithName */
+ bool HasElementWithName () const;
+
+/*! @method AddElementNamesToDict */
+ void AddElementNamesToDict (CFMutableDictionaryRef & inNameDict);
+
+ bool RestoreElementNames (CFDictionaryRef& inNameDict);
+
+ AudioUnitScope GetScope() const { return mScope; }
+
+ void SetDelegate(AUScopeDelegate* inDelegate) { mDelegate = inDelegate; }
+
+/*! @method SaveState */
+ void SaveState(CFMutableDataRef data);
+
+/*! @method RestoreState */
+ const UInt8 * RestoreState(const UInt8 *state);
+
+private:
+ typedef std::vector<AUElement *> ElementVector;
+/*! @var mCreator */
+ AUBase * mCreator;
+/*! @var mScope */
+ AudioUnitScope mScope;
+/*! @var mElements */
+ ElementVector mElements;
+/*! @var mDelegate */
+ AUScopeDelegate * mDelegate;
+};
+
+
+
+#endif // __AUScopeElement_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.cpp
new file mode 100644
index 0000000000..fc987335dc
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.cpp
@@ -0,0 +1,370 @@
+/*
+ File: ComponentBase.cpp
+ Abstract: ComponentBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "ComponentBase.h"
+#include "CAXException.h"
+
+#if TARGET_OS_MAC
+pthread_mutex_t ComponentInitLocker::sComponentOpenMutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_once_t ComponentInitLocker::sOnce = PTHREAD_ONCE_INIT;
+
+void ComponentInitLocker::InitComponentInitLocker()
+{
+ // have to do this because OS X lacks PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&sComponentOpenMutex, &attr);
+ pthread_mutexattr_destroy(&attr);
+}
+
+#elif TARGET_OS_WIN32
+CAGuard ComponentInitLocker::sComponentOpenGuard("sComponentOpenGuard");
+#endif
+
+ComponentBase::EInstanceType ComponentBase::sNewInstanceType;
+
+static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc);
+#if !CA_USE_AUDIO_PLUGIN_ONLY && !TARGET_OS_WIN32
+ static OSStatus CMgr_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc);
+#endif
+
+ComponentBase::ComponentBase(AudioComponentInstance inInstance)
+ : mComponentInstance(inInstance),
+ mInstanceType(sNewInstanceType)
+{
+ GetComponentDescription();
+}
+
+ComponentBase::~ComponentBase()
+{
+}
+
+void ComponentBase::PostConstructor()
+{
+}
+
+void ComponentBase::PreDestructor()
+{
+}
+
+#define ACPI ((AudioComponentPlugInInstance *)self)
+#define ACImp ((ComponentBase *)&ACPI->mInstanceStorage)
+
+OSStatus ComponentBase::AP_Open(void *self, AudioUnit compInstance)
+{
+ OSStatus result = noErr;
+ try {
+ ComponentInitLocker lock;
+
+ ComponentBase::sNewInstanceType = ComponentBase::kAudioComponentInstance;
+ ComponentBase *cb = (ComponentBase *)(*ACPI->mConstruct)(&ACPI->mInstanceStorage, compInstance);
+ cb->PostConstructor(); // allows base class to do additional initialization
+ // once the derived class is fully constructed
+ result = noErr;
+ }
+ COMPONENT_CATCH
+ if (result)
+ delete ACPI;
+ return result;
+}
+
+OSStatus ComponentBase::AP_Close(void *self)
+{
+ OSStatus result = noErr;
+ try {
+ if (ACImp) {
+ ACImp->PreDestructor();
+ (*ACPI->mDestruct)(&ACPI->mInstanceStorage);
+ free(self);
+ }
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+OSStatus ComponentBase::Version()
+{
+ return 0x00000001;
+}
+
+OSStatus ComponentBase::ComponentEntryDispatch(ComponentParameters *p, ComponentBase *This)
+{
+ if (This == NULL) return kAudio_ParamError;
+
+ OSStatus result = noErr;
+
+ switch (p->what) {
+ case kComponentCloseSelect:
+ This->PreDestructor();
+ delete This;
+ break;
+
+ case kComponentVersionSelect:
+ result = This->Version();
+ break;
+
+ case kComponentCanDoSelect:
+ switch (GetSelectorForCanDo(p)) {
+ case kComponentOpenSelect:
+ case kComponentCloseSelect:
+ case kComponentVersionSelect:
+ case kComponentCanDoSelect:
+ return 1;
+ default:
+ return 0;
+ }
+
+ default:
+ result = badComponentSelector;
+ break;
+ }
+ return result;
+}
+
+SInt16 ComponentBase::GetSelectorForCanDo(ComponentParameters *params)
+{
+ if (params->what != kComponentCanDoSelect) return 0;
+
+ #if TARGET_CPU_X86
+ SInt16 sel = params->params[0];
+ #elif TARGET_CPU_X86_64
+ SInt16 sel = params->params[1];
+ #elif TARGET_CPU_PPC
+ SInt16 sel = (params->params[0] >> 16);
+ #else
+ SInt16 sel = params->params[0];
+ #endif
+
+ return sel;
+/*
+ printf ("flags:%d, paramSize: %d, what: %d\n\t", params->flags, params->paramSize, params->what);
+ for (int i = 0; i < params->paramSize; ++i) {
+ printf ("[%d]:%d(0x%x), ", i, params->params[i], params->params[i]);
+ }
+ printf("\n\tsel:%d\n", sel);
+*/
+}
+
+#endif
+
+#if CA_DO_NOT_USE_AUDIO_COMPONENT
+static OSStatus ComponentBase_GetComponentDescription (const AudioComponentInstance & inInstance, AudioComponentDescription &outDesc);
+#endif
+
+AudioComponentDescription ComponentBase::GetComponentDescription() const
+{
+ AudioComponentDescription desc;
+ OSStatus result = 1;
+
+ if (IsPluginObject()) {
+ ca_require_noerr(result = CB_GetComponentDescription (mComponentInstance, &desc), home);
+ }
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ else {
+ ca_require_noerr(result = CMgr_GetComponentDescription (mComponentInstance, &desc), home);
+ }
+#endif
+
+home:
+ if (result)
+ memset (&desc, 0, sizeof(AudioComponentDescription));
+
+ return desc;
+}
+
+#if CA_USE_AUDIO_PLUGIN_ONLY
+// everything we need is there and we should be linking against it
+static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
+{
+ AudioComponent comp = AudioComponentInstanceGetComponent(inInstance);
+ if (comp)
+ return AudioComponentGetDescription(comp, outDesc);
+
+ return kAudio_ParamError;
+}
+
+#elif !TARGET_OS_WIN32
+// these are the direct dependencies on ComponentMgr calls that an AU
+// that is a component mgr is dependent on
+
+// these are dynamically loaded so that these calls will work on Leopard
+#include <dlfcn.h>
+
+static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
+{
+ typedef AudioComponent (*AudioComponentInstanceGetComponentProc) (AudioComponentInstance);
+ static AudioComponentInstanceGetComponentProc aciGCProc = NULL;
+
+ typedef OSStatus (*AudioComponentGetDescriptionProc)(AudioComponent, AudioComponentDescription *);
+ static AudioComponentGetDescriptionProc acGDProc = NULL;
+
+ static int doneInit = 0;
+ if (doneInit == 0) {
+ doneInit = 1;
+ void* theImage = dlopen("/System/Library/Frameworks/AudioUnit.framework/AudioUnit", RTLD_LAZY);
+ if (theImage != NULL)
+ {
+ aciGCProc = (AudioComponentInstanceGetComponentProc)dlsym (theImage, "AudioComponentInstanceGetComponent");
+ if (aciGCProc) {
+ acGDProc = (AudioComponentGetDescriptionProc)dlsym (theImage, "AudioComponentGetDescription");
+ }
+ }
+ }
+
+ OSStatus result = kAudio_UnimplementedError;
+ if (acGDProc && aciGCProc) {
+ AudioComponent comp = (*aciGCProc)(inInstance);
+ if (comp)
+ result = (*acGDProc)(comp, outDesc);
+ }
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ else {
+ result = CMgr_GetComponentDescription (inInstance, outDesc);
+ }
+#endif
+
+ return result;
+}
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+// these are the direct dependencies on ComponentMgr calls that an AU
+// that is a component mgr is dependent on
+
+// these are dynamically loaded
+
+#include <CoreServices/CoreServices.h>
+#include <AudioUnit/AudioUnit.h>
+#include "CAXException.h"
+#include "ComponentBase.h"
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Component Manager
+// Used for fast dispatch with audio units
+typedef Handle (*GetComponentInstanceStorageProc)(ComponentInstance aComponentInstance);
+static GetComponentInstanceStorageProc sGetComponentInstanceStorageProc = NULL;
+
+typedef OSErr (*GetComponentInfoProc)(Component, ComponentDescription *, void*, void*, void*);
+static GetComponentInfoProc sGetComponentInfoProc = NULL;
+
+typedef void (*SetComponentInstanceStorageProc)(ComponentInstance, Handle);
+static SetComponentInstanceStorageProc sSetComponentInstanceStorageProc = NULL;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+static void CSInitOnce(void* /*unused*/)
+{
+ void *theImage = dlopen("/System/Library/Frameworks/CoreServices.framework/CoreServices", RTLD_LAZY);
+ if (!theImage) return;
+
+ sGetComponentInstanceStorageProc = (GetComponentInstanceStorageProc) dlsym(theImage, "GetComponentInstanceStorage");
+ sGetComponentInfoProc = (GetComponentInfoProc)dlsym (theImage, "GetComponentInfo");
+ sSetComponentInstanceStorageProc = (SetComponentInstanceStorageProc) dlsym(theImage, "SetComponentInstanceStorage");
+}
+
+#if TARGET_OS_MAC
+
+#include <dispatch/dispatch.h>
+
+static dispatch_once_t sCSInitOnce = 0;
+
+static void CSInit ()
+{
+ dispatch_once_f(&sCSInitOnce, NULL, CSInitOnce);
+}
+
+#else
+
+static void CSInit ()
+{
+ static int sDoCSLoad = 1;
+ if (sDoCSLoad) {
+ sDoCSLoad = 0;
+ CSInitOnce(NULL);
+ }
+}
+
+#endif
+
+OSStatus CMgr_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
+{
+ CSInit();
+ if (sGetComponentInfoProc)
+ return (*sGetComponentInfoProc)((Component)inInstance, (ComponentDescription*)outDesc, NULL, NULL, NULL);
+ return kAudio_UnimplementedError;
+}
+
+Handle CMgr_GetComponentInstanceStorage(ComponentInstance aComponentInstance)
+{
+ CSInit();
+ if (sGetComponentInstanceStorageProc)
+ return (*sGetComponentInstanceStorageProc)(aComponentInstance);
+ return NULL;
+}
+
+void CMgr_SetComponentInstanceStorage(ComponentInstance aComponentInstance, Handle theStorage)
+{
+ CSInit();
+ if (sSetComponentInstanceStorageProc)
+ (*sSetComponentInstanceStorageProc)(aComponentInstance, theStorage);
+}
+#endif // !CA_USE_AUDIO_PLUGIN_ONLY
+
+#else
+//#include "ComponentManagerDependenciesWin.h"
+// everything we need is there and we should be linking against it
+static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
+{
+ AudioComponent comp = AudioComponentInstanceGetComponent(inInstance);
+ if (comp)
+ return AudioComponentGetDescription(comp, outDesc);
+
+ return kAudio_ParamError;
+}
+
+#endif
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.h
new file mode 100644
index 0000000000..67417aa9d1
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.h
@@ -0,0 +1,353 @@
+/*
+ File: ComponentBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __ComponentBase_h__
+#define __ComponentBase_h__
+
+#include <new>
+#include "CADebugMacros.h"
+#include "CAXException.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <AudioUnit/AudioUnit.h>
+
+ #if !CA_USE_AUDIO_PLUGIN_ONLY
+ #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/Components.h>
+
+ #if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)
+ #define AudioComponentInstance ComponentInstance
+ #define AudioComponentDescription ComponentDescription
+ #define AudioComponent Component
+ #endif
+ Handle CMgr_GetComponentInstanceStorage(ComponentInstance aComponentInstance);
+ void CMgr_SetComponentInstanceStorage(ComponentInstance aComponentInstance, Handle theStorage);
+ #endif
+
+ #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+ typedef Float32 AudioUnitParameterValue;
+ #endif
+ #if COREAUDIOTYPES_VERSION < 1051
+ typedef Float32 AudioUnitSampleType;
+ #endif
+
+ #if !TARGET_OS_WIN32
+ #include <pthread.h>
+ #endif
+
+ #if TARGET_OS_WIN32
+ #include "CAGuard.h"
+ #endif
+#else
+ #include "CoreAudioTypes.h"
+ #if !CA_USE_AUDIO_PLUGIN_ONLY
+ #include "ComponentManagerDependenciesWin.h"
+ #endif
+ #include "AudioUnit.h"
+ #include "CAGuard.h"
+#endif
+
+#ifndef COMPONENT_THROW
+ #if VERBOSE_COMPONENT_THROW
+ #define COMPONENT_THROW(throw_err) \
+ do { DebugMessage(#throw_err); throw static_cast<OSStatus>(throw_err); } while (0)
+ #else
+ #define COMPONENT_THROW(throw_err) \
+ throw static_cast<OSStatus>(throw_err)
+ #endif
+#endif
+
+#define COMPONENT_CATCH \
+ catch (const CAXException &ex) { result = ex.mError; } \
+ catch (std::bad_alloc &) { result = kAudio_MemFullError; } \
+ catch (OSStatus catch_err) { result = catch_err; } \
+ catch (OSErr catch_err) { result = catch_err; } \
+ catch (...) { result = -1; }
+
+/*! @class ComponentBase */
+class ComponentBase {
+public:
+ // classic MacErrors
+ enum { noErr = 0};
+
+ /*! @ctor ComponentBase */
+ ComponentBase(AudioComponentInstance inInstance);
+
+ /*! @dtor ~ComponentBase */
+ virtual ~ComponentBase();
+
+ /*! @method PostConstructor */
+ virtual void PostConstructor();
+
+ /*! @method PreDestructor */
+ virtual void PreDestructor();
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ /*! @method Version */
+ virtual OSStatus Version();
+
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch(ComponentParameters *p, ComponentBase *This);
+
+ /*! GetSelectorForCanDo */
+ static SInt16 GetSelectorForCanDo(ComponentParameters *params);
+#endif
+
+ /*! @method GetComponentInstance */
+ AudioComponentInstance GetComponentInstance() const { return mComponentInstance; }
+
+ /*! @method GetComponentDescription */
+ AudioComponentDescription GetComponentDescription() const;
+
+ // This global variable is so that new instances know how they were instantiated: via the Component Manager,
+ // or as AudioComponents. It's ugly, but preferable to altering the constructor of every class in the hierarchy.
+ // It's safe because construction is protected by ComponentInitLocker.
+ enum EInstanceType { kComponentMgrInstance, kAudioComponentInstance };
+ static EInstanceType sNewInstanceType;
+
+ /*! @method IsPluginObject */
+ bool IsPluginObject () const { return mInstanceType == kAudioComponentInstance; }
+ /*! @method IsCMgrObject */
+ bool IsCMgrObject () const { return mInstanceType == kComponentMgrInstance; }
+
+ /*! @method AP_Open */
+ static OSStatus AP_Open(void *self, AudioUnit compInstance);
+
+ /*! @method AP_Close */
+ static OSStatus AP_Close(void *self);
+
+protected:
+ /*! @var mComponentInstance */
+ AudioComponentInstance mComponentInstance;
+ EInstanceType mInstanceType;
+};
+
+class ComponentInitLocker
+{
+#if TARGET_OS_MAC
+public:
+ ComponentInitLocker()
+ {
+ pthread_once(&sOnce, InitComponentInitLocker);
+ pthread_mutex_lock(&sComponentOpenMutex);
+ mPreviousNewInstanceType = ComponentBase::sNewInstanceType;
+ }
+ ~ComponentInitLocker()
+ {
+ ComponentBase::sNewInstanceType = mPreviousNewInstanceType;
+ pthread_mutex_unlock(&sComponentOpenMutex);
+ }
+
+ // There are situations (11844772) where we need to be able to release the lock early.
+ class Unlocker {
+ public:
+ Unlocker()
+ {
+ pthread_mutex_unlock(&sComponentOpenMutex);
+ }
+ ~Unlocker()
+ {
+ pthread_mutex_lock(&sComponentOpenMutex);
+ }
+ };
+
+private:
+ static pthread_mutex_t sComponentOpenMutex;
+ static pthread_once_t sOnce;
+ static void InitComponentInitLocker();
+
+#elif TARGET_OS_WIN32
+public:
+ bool sNeedsUnlocking;
+ ComponentInitLocker() { sNeedsUnlocking = sComponentOpenGuard.Lock(); }
+ ~ComponentInitLocker() { if(sNeedsUnlocking) { sComponentOpenGuard.Unlock(); } }
+private:
+ static CAGuard sComponentOpenGuard;
+#endif
+
+private:
+ ComponentBase::EInstanceType mPreviousNewInstanceType;
+};
+
+/*! @class AudioComponentPlugInInstance */
+struct AudioComponentPlugInInstance {
+ AudioComponentPlugInInterface mPlugInInterface;
+ void * (*mConstruct)(void *memory, AudioComponentInstance ci);
+ void (*mDestruct)(void *memory);
+ void * mPad[2]; // pad to a 16-byte boundary (in either 32 or 64 bit mode)
+ UInt32 mInstanceStorage; // the ACI implementation object is constructed into this memory
+ // this member is just a placeholder. it is aligned to a 16byte boundary
+};
+
+/*! @class APFactory */
+template <class APMethodLookup, class Implementor>
+class APFactory {
+public:
+ static void *Construct(void *memory, AudioComponentInstance compInstance)
+ {
+ return new(memory) Implementor(compInstance);
+ }
+
+ static void Destruct(void *memory)
+ {
+ ((Implementor *)memory)->~Implementor();
+ }
+
+ // This is the AudioComponentFactoryFunction. It returns an AudioComponentPlugInInstance.
+ // The actual implementation object is not created until Open().
+ static AudioComponentPlugInInterface *Factory(const AudioComponentDescription * /* inDesc */)
+ {
+ AudioComponentPlugInInstance *acpi =
+ (AudioComponentPlugInInstance *)malloc( offsetof(AudioComponentPlugInInstance, mInstanceStorage) + sizeof(Implementor) );
+ acpi->mPlugInInterface.Open = ComponentBase::AP_Open;
+ acpi->mPlugInInterface.Close = ComponentBase::AP_Close;
+ acpi->mPlugInInterface.Lookup = APMethodLookup::Lookup;
+ acpi->mPlugInInterface.reserved = NULL;
+ acpi->mConstruct = Construct;
+ acpi->mDestruct = Destruct;
+ acpi->mPad[0] = NULL;
+ acpi->mPad[1] = NULL;
+ return (AudioComponentPlugInInterface*)acpi;
+ }
+
+ // This is for runtime registration (not for plug-ins loaded from bundles).
+ static AudioComponent Register(UInt32 type, UInt32 subtype, UInt32 manuf, CFStringRef name, UInt32 vers, UInt32 flags=0)
+ {
+ AudioComponentDescription desc = { type, subtype, manuf, flags, 0 };
+ return AudioComponentRegister(&desc, name, vers, Factory);
+ }
+};
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+/*! @class ComponentEntryPoint
+ * @discussion This is only used for a component manager version
+*/
+template <class Class>
+class ComponentEntryPoint {
+public:
+ /*! @method Dispatch */
+ static OSStatus Dispatch(ComponentParameters *params, Class *obj)
+ {
+ OSStatus result = noErr;
+
+ try {
+ if (params->what == kComponentOpenSelect) {
+ // solve a host of initialization thread safety issues.
+ ComponentInitLocker lock;
+
+ ComponentBase::sNewInstanceType = ComponentBase::kComponentMgrInstance;
+ ComponentInstance ci = (ComponentInstance)(params->params[0]);
+ Class *This = new Class((AudioComponentInstance)ci);
+ This->PostConstructor(); // allows base class to do additional initialization
+ // once the derived class is fully constructed
+
+ CMgr_SetComponentInstanceStorage(ci, (Handle)This);
+ } else
+ result = Class::ComponentEntryDispatch(params, obj);
+ }
+ COMPONENT_CATCH
+
+ return result;
+ }
+
+ /*! @method Register */
+ static Component Register(OSType compType, OSType subType, OSType manufacturer)
+ {
+ ComponentDescription description = {compType, subType, manufacturer, 0, 0};
+ Component component = RegisterComponent(&description, (ComponentRoutineUPP) Dispatch, registerComponentGlobal, NULL, NULL, NULL);
+ if (component != NULL) {
+ SetDefaultComponent(component, defaultComponentAnyFlagsAnyManufacturerAnySubType);
+ }
+ return component;
+ }
+};
+
+// NOTE: Component Mgr is deprecated in ML.
+// this macro should not be used with new audio components
+// it is only for backwards compatibility with Lion and SL.
+// this macro registers both a plugin and a component mgr version.
+#define AUDIOCOMPONENT_ENTRY(FactoryType, Class) \
+ extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj); \
+ extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj) { \
+ return ComponentEntryPoint<Class>::Dispatch(params, obj); \
+ } \
+ extern "C" void * Class##Factory(const AudioComponentDescription *inDesc); \
+ extern "C" void * Class##Factory(const AudioComponentDescription *inDesc) { \
+ return FactoryType<Class>::Factory(inDesc); \
+ }
+ // the only component we still support are the carbon based view components
+ // you should be using this macro now to exclusively register those types
+#define VIEW_COMPONENT_ENTRY(Class) \
+ extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj); \
+ extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj) { \
+ return ComponentEntryPoint<Class>::Dispatch(params, obj); \
+ }
+
+ /*! @class ComponentRegistrar */
+template <class Class, OSType Type, OSType Subtype, OSType Manufacturer>
+class ComponentRegistrar {
+public:
+ /*! @ctor ComponentRegistrar */
+ ComponentRegistrar() { ComponentEntryPoint<Class>::Register(Type, Subtype, Manufacturer); }
+};
+
+#define COMPONENT_REGISTER(Class,Type,Subtype,Manufacturer) \
+ static ComponentRegistrar<Class, Type, Subtype, Manufacturer> gRegistrar##Class
+#else
+#define COMPONENT_ENTRY(Class)
+#define COMPONENT_REGISTER(Class)
+// this macro is used to generate the Entry Point for a given Audio Plugin
+// you should be using this macro now with audio components
+#define AUDIOCOMPONENT_ENTRY(FactoryType, Class) \
+ extern "C" void * Class##Factory(const AudioComponentDescription *inDesc); \
+ extern "C" void * Class##Factory(const AudioComponentDescription *inDesc) { \
+ return FactoryType<Class>::Factory(inDesc); \
+ }
+
+#endif // !CA_USE_AUDIO_PLUGIN_ONLY
+
+
+#endif // __ComponentBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp
new file mode 100644
index 0000000000..332475335d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp
@@ -0,0 +1,403 @@
+/*
+ File: AUCarbonViewBase.cpp
+ Abstract: AUCarbonViewBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUCarbonViewBase.h"
+#include "AUCarbonViewControl.h"
+#include <algorithm>
+
+AUCarbonViewBase::AUCarbonViewBase(AudioUnitCarbonView inInstance, Float32 inNotificationInterval /* in seconds */) :
+ ComponentBase(inInstance),
+ mEditAudioUnit(0),
+ mParameterListener(NULL),
+#if !__LP64__
+ mEventListener(NULL),
+#endif
+ mTimerRef (NULL),
+ mTimerUPP (NULL),
+ mCarbonWindow(NULL),
+ mCarbonPane(NULL),
+ mXOffset(0),
+ mYOffset(0)
+{
+ AUEventListenerCreate (ParameterListener, this,
+ CFRunLoopGetCurrent(), kCFRunLoopCommonModes,
+ inNotificationInterval, inNotificationInterval,
+ &mParameterListener);
+}
+
+AUCarbonViewBase::~AUCarbonViewBase()
+{
+#if !__LP64__
+ if (mCarbonPane)
+ DisposeControl(mCarbonPane);
+
+ for (ControlList::iterator it = mControlList.begin(); it != mControlList.end(); ++it) {
+ AUCarbonViewControl *ctl = *it;
+ delete ctl;
+ }
+ AUListenerDispose(mParameterListener);
+
+ if (mTimerRef)
+ ::RemoveEventLoopTimer (mTimerRef);
+
+ if (mTimerUPP)
+ DisposeEventLoopTimerUPP (mTimerUPP);
+#endif
+}
+
+void AUCarbonViewBase::AddControl(AUCarbonViewControl *control)
+{
+ ControlList::iterator it = find(mControlList.begin(), mControlList.end(), control);
+ if (it == mControlList.end())
+ mControlList.push_back(control);
+}
+
+void AUCarbonViewBase::RemoveControl(AUCarbonViewControl *control)
+{
+ ControlList::iterator it = find(mControlList.begin(), mControlList.end(), control);
+ if (it != mControlList.end()) {
+ AUCarbonViewControl *ctl = *it;
+ mControlList.erase(it);
+ delete ctl;
+ }
+}
+
+void AUCarbonViewBase::ClearControls ()
+{
+ for (ControlList::iterator it = mControlList.begin(); it != mControlList.end(); ++it) {
+ AUCarbonViewControl *ctl = *it;
+ delete ctl;
+ }
+ mControlList.clear();
+}
+
+void AUCarbonViewBase::ParameterListener(void * inCallbackRefCon,
+ void * inObject,
+ const AudioUnitEvent * inEvent,
+ UInt64 inEventHostTime,
+ Float32 inParameterValue)
+{
+ if (inEvent->mEventType == kAudioUnitEvent_ParameterValueChange) {
+ AUCarbonViewControl *ctl = (AUCarbonViewControl *)inObject;
+ ctl->ParameterToControl(inParameterValue);
+ }
+}
+
+
+OSStatus AUCarbonViewBase::CreateCarbonView(AudioUnit inAudioUnit, WindowRef inWindow, ControlRef inParentControl, const Float32Point &inLocation, const Float32Point &inSize, ControlRef &outParentControl)
+{
+#if !__LP64__
+ mEditAudioUnit = inAudioUnit;
+ mCarbonWindow = inWindow;
+
+ WindowAttributes attributes;
+ verify_noerr(GetWindowAttributes(mCarbonWindow, &attributes));
+ mCompositWindow = (attributes & kWindowCompositingAttribute) != 0;
+
+ Rect area;
+ area.left = short(inLocation.x); area.top = short(inLocation.y);
+ area.right = short(area.left + inSize.x); area.bottom = short(area.top + inSize.y);
+ OSStatus err = ::CreateUserPaneControl(inWindow, &area,
+ kControlSupportsEmbedding,
+ &mCarbonPane); // subclass can resize mCarbonPane to taste
+ verify_noerr(err);
+ if (err) return err;
+ outParentControl = mCarbonPane;
+
+ // register for mouse-down in our pane -- we want to clear focus
+ EventTypeSpec paneEvents[] = {
+ { kEventClassControl, kEventControlClick }
+ };
+ WantEventTypes(GetControlEventTarget(mCarbonPane), GetEventTypeCount(paneEvents), paneEvents);
+
+ if (IsCompositWindow()) {
+ verify_noerr(::HIViewAddSubview(inParentControl, mCarbonPane));
+ mXOffset = 0;
+ mYOffset = 0;
+ }
+ else {
+ verify_noerr(::EmbedControl(mCarbonPane, inParentControl));
+ mXOffset = inLocation.x;
+ mYOffset = inLocation.y;
+ }
+ mBottomRight.h = mBottomRight.v = 0;
+
+ SizeControl(mCarbonPane, 0, 0);
+ if (err = CreateUI(mXOffset, mYOffset))
+ return err;
+
+ // we should only resize the control if a subclass has embedded
+ // controls in this AND this is done with the EmbedControl call below
+ // if mBottomRight is STILL equal to zero, then that wasn't done
+ // so don't size the control
+ Rect paneBounds;
+ GetControlBounds(mCarbonPane, &paneBounds);
+ // only resize mCarbonPane if it has not already been resized during CreateUI
+ if ((paneBounds.top == paneBounds.bottom) && (paneBounds.left == paneBounds.right)) {
+ if (mBottomRight.h != 0 && mBottomRight.v != 0)
+ SizeControl(mCarbonPane, (short) (mBottomRight.h - mXOffset), (short) (mBottomRight.v - mYOffset));
+ }
+
+ if (IsCompositWindow()) {
+ // prepare for handling scroll-events
+ EventTypeSpec scrollEvents[] = {
+ { kEventClassScrollable, kEventScrollableGetInfo },
+ { kEventClassScrollable, kEventScrollableScrollTo }
+ };
+
+ WantEventTypes(GetControlEventTarget(mCarbonPane), GetEventTypeCount(scrollEvents), scrollEvents);
+
+ mCurrentScrollPoint.x = mCurrentScrollPoint.y = 0.0f;
+ }
+
+ return err;
+#else
+ return noErr;
+#endif
+}
+
+OSStatus AUCarbonViewBase::CreateUI(Float32 inXOffset, Float32 inYOffset)
+{
+ return noErr;
+}
+
+OSStatus AUCarbonViewBase::EmbedControl(ControlRef ctl)
+{
+#if !__LP64__
+ Rect r;
+ ::GetControlBounds(ctl, &r);
+ if (r.right > mBottomRight.h) mBottomRight.h = r.right;
+ if (r.bottom > mBottomRight.v) mBottomRight.v = r.bottom;
+
+ if (IsCompositWindow())
+ return ::HIViewAddSubview(mCarbonPane, ctl);
+ else
+ return ::EmbedControl(ctl, mCarbonPane);
+#else
+ return noErr;
+#endif
+}
+
+void AUCarbonViewBase::AddCarbonControl(AUCarbonViewControl::ControlType type, const CAAUParameter &param, ControlRef control)
+{
+ verify_noerr(EmbedControl(control));
+
+ AUCarbonViewControl *auvc = new AUCarbonViewControl(this, mParameterListener, type, param, control);
+ auvc->Bind();
+ AddControl(auvc);
+}
+
+bool AUCarbonViewBase::HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event)
+{
+#if !__LP64__
+ UInt32 eclass = GetEventClass(event);
+ UInt32 ekind = GetEventKind(event);
+ ControlRef control;
+
+ switch (eclass) {
+ case kEventClassControl:
+ {
+ switch (ekind) {
+ case kEventControlClick:
+ GetEventParameter(event, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
+ if (control == mCarbonPane) {
+ ClearKeyboardFocus(mCarbonWindow);
+ return true;
+ }
+ }
+ }
+ break;
+
+ case kEventClassScrollable:
+ {
+ switch (ekind) {
+ case kEventScrollableGetInfo:
+ {
+ // [1/4]
+ /* <-- kEventParamImageSize (out, typeHISize)
+ * On exit, contains the size of the entire scrollable view.
+ */
+ HISize originalSize = { mBottomRight.h, mBottomRight.v };
+ verify_noerr(SetEventParameter(event, kEventParamImageSize, typeHISize, sizeof(HISize), &originalSize));
+
+ // [2/4]
+ /* <-- kEventParamViewSize (out, typeHISize)
+ * On exit, contains the amount of the scrollable view that is
+ * visible.
+ */
+ HIViewRef parentView = HIViewGetSuperview(mCarbonPane);
+ HIRect parentBounds;
+ verify_noerr(HIViewGetBounds(parentView, &parentBounds));
+ //HISize windowSize = { float(windowBounds.right - windowBounds.left),
+ // float(windowBounds.bottom - windowBounds.top) };
+ verify_noerr(SetEventParameter(event, kEventParamViewSize, typeHISize, sizeof(HISize), &(parentBounds.size)));
+
+ // [3/4]
+ /* <-- kEventParamLineSize (out, typeHISize)
+ * On exit, contains the amount that should be scrolled in
+ * response to a single click on a scrollbar arrow.
+ */
+ HISize scrollIncrementSize = { 16.0f, float(20) };
+ verify_noerr(SetEventParameter(event, kEventParamLineSize, typeHISize, sizeof(HISize), &scrollIncrementSize));
+
+ // [4/4]
+ /* <-- kEventParamOrigin (out, typeHIPoint)
+ * On exit, contains the scrollable viewÕs current origin (the
+ * view-relative coordinate that is drawn at the top left
+ * corner of its frame). These coordinates should always be
+ * greater than or equal to zero. They should be less than or
+ * equal to the viewÕs image size minus its view size.
+ */
+ verify_noerr(SetEventParameter(event, kEventParamOrigin, typeHIPoint, sizeof(HIPoint), &mCurrentScrollPoint));
+ }
+ return true;
+
+ case kEventScrollableScrollTo:
+ {
+ /*
+ * kEventClassScrollable / kEventScrollableScrollTo
+ *
+ * Summary:
+ * Requests that an HIScrollViewÕs scrollable view should scroll to
+ * a particular origin.
+ */
+
+ /* --> kEventParamOrigin (in, typeHIPoint)
+ * The new origin for the scrollable view. The origin
+ * coordinates will vary from (0,0) to scrollable viewÕs image
+ * size minus its view size.
+ */
+ HIPoint pointToScrollTo;
+ verify_noerr(GetEventParameter(event, kEventParamOrigin, typeHIPoint, NULL, sizeof(HIPoint), NULL, &pointToScrollTo));
+
+ float xDelta = mCurrentScrollPoint.x - pointToScrollTo.x;
+ float yDelta = mCurrentScrollPoint.y - pointToScrollTo.y;
+ // move visible portion the appropriate amount
+ verify_noerr(HIViewScrollRect(mCarbonPane, NULL, xDelta, yDelta));
+ // set new content to be drawn
+ verify_noerr(HIViewSetBoundsOrigin(mCarbonPane, pointToScrollTo.x, pointToScrollTo.y));
+
+ mCurrentScrollPoint = pointToScrollTo;
+ }
+ return true;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+#endif
+ return false;
+}
+
+/*! @method TellListener */
+void AUCarbonViewBase::TellListener (const CAAUParameter &auvp, AudioUnitCarbonViewEventID event, void *evpar)
+{
+#if !__LP64__
+ if (mEventListener)
+ (*mEventListener)(mEventListenerUserData, mComponentInstance, &auvp, event, evpar);
+#endif
+
+ AudioUnitEvent auEvent;
+ auEvent.mArgument.mParameter = auvp;
+ if (event == kAudioUnitCarbonViewEvent_MouseDownInControl) {
+ auEvent.mEventType = kAudioUnitEvent_BeginParameterChangeGesture;
+ } else {
+ auEvent.mEventType = kAudioUnitEvent_EndParameterChangeGesture;
+ }
+ AUEventListenerNotify(mParameterListener, this, &auEvent);
+}
+
+
+void AUCarbonViewBase::Update (bool inUIThread)
+{
+ for (ControlList::iterator iter = mControlList.begin(); iter != mControlList.end(); ++iter)
+ {
+ (*iter)->Update(inUIThread);
+ }
+}
+
+pascal void AUCarbonViewBase::TheTimerProc (EventLoopTimerRef inTimer, void *inUserData)
+{
+ AUCarbonViewBase* This = reinterpret_cast<AUCarbonViewBase*>(inUserData);
+ This->RespondToEventTimer (inTimer);
+}
+
+void AUCarbonViewBase::RespondToEventTimer (EventLoopTimerRef inTimer)
+{}
+
+/*
+ THESE are reasonable values for these two times
+ 0.005 // delay
+ 0.050 // interval
+*/
+
+OSStatus AUCarbonViewBase::CreateEventLoopTimer (Float32 inDelay, Float32 inInterval)
+{
+ if (mTimerUPP)
+ return noErr;
+
+ mTimerUPP = NewEventLoopTimerUPP(TheTimerProc);
+
+ EventLoopRef mainEventLoop = GetMainEventLoop();
+
+ //doesn't seem to like too small a value
+ if (inDelay < 0.005)
+ inDelay = 0.005;
+
+ OSStatus timerResult = ::InstallEventLoopTimer(
+ mainEventLoop,
+ inDelay,
+ inInterval,
+ mTimerUPP,
+ this,
+ &mTimerRef);
+ return timerResult;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h
new file mode 100644
index 0000000000..910e53ffa6
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h
@@ -0,0 +1,188 @@
+/*
+ File: AUCarbonViewBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUCarbonViewBase_h__
+#define __AUCarbonViewBase_h__
+
+#include <vector>
+#include "AUCarbonViewControl.h"
+#include "ComponentBase.h"
+
+static const Float32 kDefaultNotificationInterval = 0.100;
+
+ /*! @class AUCarbonViewBase */
+class AUCarbonViewBase : public ComponentBase, public CarbonEventHandler
+{
+public:
+ /*! @ctor AUCarbonViewBase */
+ AUCarbonViewBase ( AudioUnitCarbonView inInstance,
+ Float32 inNotificationInterval = kDefaultNotificationInterval /* in seconds */);
+ /*! @dtor ~AUCarbonViewBase */
+ virtual ~AUCarbonViewBase();
+
+ // AUViewBase overrides
+ /*! @method CreateCarbonView */
+ virtual OSStatus CreateCarbonView (AudioUnit inAudioUnit, WindowRef inWindow, ControlRef inParentControl, const Float32Point &inLocation, const Float32Point &inSize, ControlRef &outParentControl);
+
+ // our own virtual methods
+ /*! @method CreateUI */
+ virtual OSStatus CreateUI (Float32 inXOffset, Float32 inYOffset);
+
+ /*! @method HandleEvent */
+ virtual bool HandleEvent (EventHandlerCallRef inHandlerRef, EventRef event);
+
+ /*! @method GetEditAudioUnit */
+ const AudioUnit GetEditAudioUnit () const { return mEditAudioUnit; }
+ //
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch (
+ ComponentParameters * params,
+ AUCarbonViewBase * This);
+
+ /*! @method AddCarbonControl */
+ void AddCarbonControl (
+ AUCarbonViewControl::ControlType type,
+ const CAAUParameter & param,
+ ControlRef control);
+
+ /*! @method GetCarbonWindow */
+ WindowRef GetCarbonWindow () { return mCarbonWindow; }
+ /*! @method GetCarbonPane */
+ ControlRef GetCarbonPane () { return mCarbonPane; }
+ /*! @method EmbedControl */
+ OSStatus EmbedControl (ControlRef ctl);
+
+ /*! @method TellListener */
+ void TellListener (const CAAUParameter &auvp, AudioUnitCarbonViewEventID event, void *evpar);
+
+ // pass in true if wanting an update to the view and you're calling this from a thread
+ // that is safe to do UI in.
+ // If you don't know, pass in false!
+ /*! @method Update */
+ void Update (bool inUIThread);
+
+ /*! @method GetXOffset */
+ Float32 GetXOffset () { return mXOffset; }
+ /*! @method GetYOffset */
+ Float32 GetYOffset () { return mYOffset; }
+
+ /*! @method ClearControls */
+ void ClearControls ();
+
+ /*! @method IsCompositWindow */
+ bool IsCompositWindow () const { return mCompositWindow; }
+
+protected:
+#if !__LP64__
+ /*! @method SetEventListener */
+ void SetEventListener (AudioUnitCarbonViewEventListener listener, void *userData)
+ {
+ mEventListener = listener;
+ mEventListenerUserData = userData;
+ }
+#endif
+
+ /*! @method AddControl */
+ void AddControl (AUCarbonViewControl *control);
+ /*! @method RemoveControl */
+ void RemoveControl (AUCarbonViewControl *control);
+
+ OSStatus CreateEventLoopTimer (Float32 inDelay, Float32 inInterval);
+
+ /*! @method ParameterListener */
+ static void ParameterListener (void * inCallbackRefCon,
+ void * inObject,
+ const AudioUnitEvent * inEvent,
+ UInt64 inEventHostTime,
+ Float32 inParameterValue);
+
+ static pascal void TheTimerProc ( EventLoopTimerRef inTimer,
+ void * inUserData);
+
+ virtual void RespondToEventTimer (EventLoopTimerRef inTimer);
+
+ /*! @var mEditAudioUnit */
+ AudioUnit mEditAudioUnit; // the AU we're controlling
+ /*! @var mParameterListener */
+ AUEventListenerRef mParameterListener;
+
+#if !__LP64__
+ /*! @var mEventListener */
+ AudioUnitCarbonViewEventListener
+ mEventListener;
+#endif
+
+ /*! @var mEventListenerUserData */
+ void * mEventListenerUserData;
+
+private:
+ typedef std::vector<AUCarbonViewControl *> ControlList;
+ /*! @var mControlList */
+ ControlList mControlList;
+
+ EventLoopTimerRef mTimerRef;
+
+ EventLoopTimerUPP mTimerUPP;
+
+protected:
+ /*! @var mCarbonWindow */
+ WindowRef mCarbonWindow;
+ /*! @var mCarbonPane */
+ ControlRef mCarbonPane; // user pane, contains all other controls
+ /*! @var mBottomRight */
+ Point mBottomRight; // largest width and height of child controls
+ /*! @var mXOffset */
+ Float32 mXOffset;
+ /*! @var mYOffset */
+ Float32 mYOffset;
+ /*! @var mCompositWindow */
+ bool mCompositWindow;
+ /*! @var mCurrentScrollPoint */
+ HIPoint mCurrentScrollPoint; // needed for scrolling
+};
+
+
+#endif // __AUCarbonViewBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp
new file mode 100644
index 0000000000..981347b0f1
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp
@@ -0,0 +1,710 @@
+/*
+ File: AUCarbonViewControl.cpp
+ Abstract: AUCarbonViewControl.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUCarbonViewControl.h"
+#include "AUCarbonViewBase.h"
+#include "AUViewLocalizedStringKeys.h"
+
+AUCarbonViewControl::AUCarbonViewControl(AUCarbonViewBase *ownerView, AUParameterListenerRef listener, ControlType type, const CAAUParameter &param, ControlRef control) :
+ mOwnerView(ownerView),
+ mListener(listener),
+ mType(type),
+ mParam(param),
+ mControl(control),
+ mInControlInitialization(0)
+{
+#if !__LP64__
+ SetControlReference(control, SRefCon(this));
+#endif
+}
+
+AUCarbonViewControl::~AUCarbonViewControl()
+{
+ AUListenerRemoveParameter(mListener, this, &mParam);
+}
+
+AUCarbonViewControl* AUCarbonViewControl::mLastControl = NULL;
+
+void AUCarbonViewControl::Bind()
+{
+#if !__LP64__
+ mInControlInitialization = 1; // true
+ AUListenerAddParameter(mListener, this, &mParam);
+ // will cause an almost-immediate callback
+
+ EventTypeSpec events[] = {
+ { kEventClassControl, kEventControlValueFieldChanged } // N.B. OS X only
+ };
+
+ WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
+
+ if (mType == kTypeContinuous || mType == kTypeText || mType == kTypeDiscrete) {
+ EventTypeSpec events[] = {
+ { kEventClassControl, kEventControlHit },
+ { kEventClassControl, kEventControlClick },
+ { kEventClassControl, kEventControlTrack }
+ };
+ WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
+ }
+
+ if (mType == kTypeText) {
+ EventTypeSpec events[] = {
+ { kEventClassControl, kEventControlSetFocusPart }
+ };
+ WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
+ ControlKeyFilterUPP proc = mParam.ValuesHaveStrings() ? StdKeyFilterCallback : NumericKeyFilterCallback;
+ // this will fail for a static text field
+ SetControlData(mControl, 0, kControlEditTextKeyFilterTag, sizeof(proc), &proc);
+ }
+
+ Update(true);
+ mInControlInitialization = 0; // false
+#endif
+}
+
+void AUCarbonViewControl::ParameterToControl(Float32 paramValue)
+{
+#if !__LP64__
+ ++mInControlInitialization;
+ switch (mType) {
+ case kTypeContinuous:
+ SetValueFract(AUParameterValueToLinear(paramValue, &mParam));
+ break;
+ case kTypeDiscrete:
+ {
+ long value = long(paramValue);
+
+ // special case [1] -- menu parameters
+ if (mParam.HasNamedParams()) {
+ // if we're dealing with menus they behave differently!
+ // becaue setting min and max doesn't work correctly for the control value
+ // first menu item always reports a control value of 1
+ ControlKind ctrlKind;
+ if (GetControlKind(mControl, &ctrlKind) == noErr) {
+ if ((ctrlKind.kind == kControlKindPopupArrow)
+ || (ctrlKind.kind == kControlKindPopupButton))
+ {
+ value = value - long(mParam.ParamInfo().minValue) + 1;
+ }
+ }
+ }
+
+ // special case [2] -- Write-only boolean parameters
+ AudioUnitParameterInfo AUPI = mParam.ParamInfo();
+
+ bool isWriteOnlyBoolParameter = ( (AUPI.unit == kAudioUnitParameterUnit_Boolean) &&
+ (AUPI.flags & kAudioUnitParameterFlag_IsWritable) &&
+ !(AUPI.flags & kAudioUnitParameterFlag_IsReadable) );
+ if (!isWriteOnlyBoolParameter) {
+ SetValue (value);
+ }
+ }
+ break;
+ case kTypeText:
+ {
+ CFStringRef cfstr = mParam.GetStringFromValueCopy(&paramValue);
+
+ if ( !(mParam.ParamInfo().flags & kAudioUnitParameterFlag_IsWritable) //READ ONLY PARAMS
+ && (mParam.ParamInfo().flags & kAudioUnitParameterFlag_IsReadable))
+ {
+ if (mParam.GetParamTag()) {
+ CFMutableStringRef str = CFStringCreateMutableCopy(NULL, 256, cfstr);
+ CFRelease (cfstr);
+ CFStringAppend (str, CFSTR(" "));
+ CFStringAppend (str, mParam.GetParamTag());
+ cfstr = str;
+ }
+ }
+ SetTextValue(cfstr);
+ CFRelease (cfstr);
+ }
+ break;
+ }
+ --mInControlInitialization;
+#endif
+}
+
+void AUCarbonViewControl::ControlToParameter()
+{
+#if !__LP64__
+ if (mInControlInitialization)
+ return;
+
+ switch (mType) {
+ case kTypeContinuous:
+ {
+ double controlValue = GetValueFract();
+ Float32 paramValue = AUParameterValueFromLinear(controlValue, &mParam);
+ mParam.SetValue(mListener, this, paramValue);
+ }
+ break;
+ case kTypeDiscrete:
+ {
+ long value = GetValue();
+
+ // special case [1] -- Menus
+ if (mParam.HasNamedParams()) {
+ // if we're dealing with menus they behave differently!
+ // becaue setting min and max doesn't work correctly for the control value
+ // first menu item always reports a control value of 1
+ ControlKind ctrlKind;
+ if (GetControlKind(mControl, &ctrlKind) == noErr) {
+ if ((ctrlKind.kind == kControlKindPopupArrow)
+ || (ctrlKind.kind == kControlKindPopupButton))
+ {
+ value = value + long(mParam.ParamInfo().minValue) - 1;
+ }
+ }
+ }
+
+ // special case [2] -- Write-only boolean parameters
+ AudioUnitParameterInfo AUPI = mParam.ParamInfo();
+
+ bool isWriteOnlyBoolParameter = ( (AUPI.unit == kAudioUnitParameterUnit_Boolean) &&
+ (AUPI.flags & kAudioUnitParameterFlag_IsWritable) &&
+ !(AUPI.flags & kAudioUnitParameterFlag_IsReadable) );
+ if (isWriteOnlyBoolParameter) {
+ value = 1;
+ }
+
+ mParam.SetValue (mListener, this, value);
+ }
+ break;
+ case kTypeText:
+ {
+ Float32 val = mParam.GetValueFromString (GetTextValue());
+ mParam.SetValue(mListener, this, (mParam.IsIndexedParam() ? (int)val : val));
+ if (mParam.ValuesHaveStrings())
+ ParameterToControl(val); //make sure we display the correct text (from the AU)
+ }
+ break;
+ }
+#endif
+}
+
+void AUCarbonViewControl::SetValueFract(double value)
+{
+#if !__LP64__
+ SInt32 minimum = GetControl32BitMinimum(mControl);
+ SInt32 maximum = GetControl32BitMaximum(mControl);
+ SInt32 cval = SInt32(value * (maximum - minimum) + minimum + 0.5);
+ SetControl32BitValue(mControl, cval);
+// printf("set: value=%lf, min=%ld, max=%ld, ctl value=%ld\n", value, minimum, maximum, cval);
+#endif
+}
+
+double AUCarbonViewControl::GetValueFract()
+{
+#if !__LP64__
+ SInt32 minimum = GetControl32BitMinimum(mControl);
+ SInt32 maximum = GetControl32BitMaximum(mControl);
+ SInt32 cval = GetControl32BitValue(mControl);
+ double result = double(cval - minimum) / double(maximum - minimum);
+// printf("get: min=%ld, max=%ld, value=%ld, result=%f\n", minimum, maximum, cval, result);
+ return result;
+#else
+ return 0;
+#endif
+}
+
+void AUCarbonViewControl::SetTextValue(CFStringRef cfstr)
+{
+#if !__LP64__
+ verify_noerr(SetControlData(mControl, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), &cfstr));
+#endif
+}
+
+CFStringRef AUCarbonViewControl::GetTextValue()
+{
+#if !__LP64__
+ CFStringRef cfstr;
+ verify_noerr(GetControlData(mControl, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), &cfstr, NULL));
+ return cfstr;
+#else
+ return CFSTR("");
+#endif
+}
+
+void AUCarbonViewControl::SetValue(long value)
+{
+#if !__LP64__
+ SetControl32BitValue(mControl, value);
+#endif
+}
+
+long AUCarbonViewControl::GetValue()
+{
+#if !__LP64__
+ return GetControl32BitValue(mControl);
+#else
+ return 0;
+#endif
+}
+
+/* Notes on event handling
+
+ Button (Click and release on button)
+ kEventControlClick received
+ kEventControlTrack received
+ kEventControlValueFieldChanged received
+ kEventControlHit received
+
+ Button (Click and release outside of button bounds)
+ kEventControlClick received
+ kEventControlTrack received
+
+ Slider (Click, drag, and release)
+ kEventControlClick received
+ kEventControlTrack received
+ kEventControlValueFieldChanged received
+ kEventControlValueFieldChanged received
+ kEventControlHit received
+
+ Slider (Click, release without changing value)
+ kEventControlClick received
+ kEventControlTrack received
+*/
+bool AUCarbonViewControl::HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event)
+{
+ UInt32 eclass = GetEventClass(event);
+ UInt32 ekind = GetEventKind(event);
+ ControlRef control;
+ bool handled = true;
+
+ switch (eclass) {
+ case kEventClassControl:
+ {
+ AudioUnitParameterInfo AUPI = mParam.ParamInfo();
+
+ bool isWriteOnlyBoolParameter = ( (AUPI.unit == kAudioUnitParameterUnit_Boolean) &&
+ (AUPI.flags & kAudioUnitParameterFlag_IsWritable) &&
+ !(AUPI.flags & kAudioUnitParameterFlag_IsReadable) );
+
+ switch (ekind) {
+ case kEventControlSetFocusPart: // tab
+ handled = !handled; // fall through to next case
+ mLastControl = this;
+ case kEventControlValueFieldChanged:
+ GetEventParameter(event, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
+ verify(control == mControl);
+ ControlToParameter();
+ return handled;
+ case kEventControlClick:
+ if (isWriteOnlyBoolParameter) {
+ GetEventParameter(event, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
+ verify(control == mControl);
+ ControlToParameter();
+ } else if (mLastControl != this) {
+ if (mLastControl != NULL) {
+ mLastControl->Update(false);
+ }
+ mLastControl = this;
+ }
+ mOwnerView->TellListener(mParam, kAudioUnitCarbonViewEvent_MouseDownInControl, NULL);
+ break; // don't return true, continue normal processing
+ case kEventControlHit:
+ if (mLastControl != this) {
+ if (mLastControl != NULL)
+ mLastControl->Update(false);
+ mLastControl = this;
+ }
+ mOwnerView->TellListener(mParam, kAudioUnitCarbonViewEvent_MouseUpInControl, NULL);
+ break; // don't return true, continue normal processing
+ case kEventControlTrack:
+ if (mLastControl != this) {
+ if (mLastControl != NULL)
+ mLastControl->Update(false);
+ mLastControl = this;
+ }
+
+ CallNextEventHandler(inHandlerRef, event);
+ ControlToParameter(); // new code
+ mOwnerView->TellListener(mParam, kAudioUnitCarbonViewEvent_MouseUpInControl, NULL);
+ // old code:
+ // break; // don't return true, continue normal processing
+
+ return handled; // don't return true, continue normal processing
+ }
+ }
+ }
+ return !handled;
+}
+
+pascal void AUCarbonViewControl::SliderTrackProc(ControlRef theControl, ControlPartCode partCode)
+{
+ // this doesn't need to actually do anything
+// AUCarbonViewControl *This = (AUCarbonViewControl *)GetControlReference(theControl);
+}
+
+pascal ControlKeyFilterResult AUCarbonViewControl::StdKeyFilterCallback(ControlRef theControl,
+ SInt16 *keyCode, SInt16 *charCode,
+ EventModifiers *modifiers)
+{
+#if !__LP64__
+ SInt16 c = *charCode;
+ if (c >= ' ' || c == '\b' || c == 0x7F || (c >= 0x1c && c <= 0x1f) || c == '\t')
+ return kControlKeyFilterPassKey;
+ if (c == '\r' || c == 3) { // return or Enter
+ AUCarbonViewControl *This = (AUCarbonViewControl *)GetControlReference(theControl);
+ ControlEditTextSelectionRec sel = { 0, 32767 };
+ SetControlData(This->mControl, 0, kControlEditTextSelectionTag, sizeof(sel), &sel);
+ This->ControlToParameter();
+ }
+#endif
+ return kControlKeyFilterBlockKey;
+}
+
+pascal ControlKeyFilterResult AUCarbonViewControl::NumericKeyFilterCallback(ControlRef theControl,
+ SInt16 *keyCode, SInt16 *charCode,
+ EventModifiers *modifiers)
+{
+#if !__LP64__
+ SInt16 c = *charCode;
+ if (isdigit(c) || c == '+' || c == '-' || c == '.' || c == '\b' || c == 0x7F || (c >= 0x1c && c <= 0x1f)
+ || c == '\t')
+ return kControlKeyFilterPassKey;
+ if (c == '\r' || c == 3) { // return or Enter
+ AUCarbonViewControl *This = (AUCarbonViewControl *)GetControlReference(theControl);
+ ControlEditTextSelectionRec sel = { 0, 32767 };
+ SetControlData(This->mControl, 0, kControlEditTextSelectionTag, sizeof(sel), &sel);
+ This->ControlToParameter();
+ }
+#endif
+ return kControlKeyFilterBlockKey;
+}
+
+Boolean AUCarbonViewControl::SizeControlToFit(ControlRef inControl, SInt16 *outWidth, SInt16 *outHeight)
+{
+#if !__LP64__
+ if (inControl == 0) return false;
+
+ Boolean bValue = false;
+ // this only works on text controls -- returns an error for other controls, but doesn't do anything,
+ // so the error is irrelevant
+ SetControlData(inControl, kControlEntireControl, 'stim' /* kControlStaticTextIsMultilineTag */, sizeof(Boolean), &bValue);
+
+ SInt16 baseLineOffset;
+ Rect bestRect;
+ OSErr err = GetBestControlRect(inControl, &bestRect, &baseLineOffset);
+ if (err != noErr) return false;
+
+ int width = (bestRect.right - bestRect.left) + 1;
+ int height = (bestRect.bottom - bestRect.top) + 1;
+
+ Rect boundsRect;
+ GetControlBounds (inControl, &boundsRect);
+
+ Rect newRect;
+ newRect.top = boundsRect.top;
+ newRect.bottom = newRect.top + height;
+ newRect.left = boundsRect.left;
+ newRect.right = newRect.left + width;
+
+ SetControlBounds (inControl, &newRect);
+
+ if (outWidth)
+ *outWidth = width;
+
+ if (outHeight)
+ *outHeight = height;
+#endif
+ return true;
+}
+
+#pragma mark ___AUPropertyControl
+bool AUPropertyControl::HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event)
+{
+ UInt32 eclass = GetEventClass(event);
+ UInt32 ekind = GetEventKind(event);
+ switch (eclass) {
+ case kEventClassControl:
+ switch (ekind) {
+ case kEventControlValueFieldChanged:
+ HandleControlChange();
+ return true; // handled
+ }
+ }
+
+ return false;
+}
+
+void AUPropertyControl::RegisterEvents ()
+{
+#if !__LP64__
+ EventTypeSpec events[] = {
+ { kEventClassControl, kEventControlValueFieldChanged } // N.B. OS X only
+ };
+
+ WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
+#endif
+}
+
+void AUPropertyControl::EmbedControl (ControlRef theControl)
+{
+ mView->EmbedControl (theControl);
+}
+
+WindowRef AUPropertyControl::GetCarbonWindow()
+{
+ return mView->GetCarbonWindow();
+}
+
+#pragma mark ___AUVPreset
+#if !__LP64__
+static CFStringRef kStringFactoryPreset = kAUViewLocalizedStringKey_FactoryPreset;
+static bool sAUVPresetLocalized = false;
+#endif
+
+AUVPresets::AUVPresets (AUCarbonViewBase* inParentView,
+ CFArrayRef& inPresets,
+ Point inLocation,
+ int nameWidth,
+ int controlWidth,
+ ControlFontStyleRec & inFontStyle)
+ : AUPropertyControl (inParentView),
+ mPresets (inPresets),
+ mView (inParentView)
+{
+#if !__LP64__
+ Rect r;
+
+ // ok we now have an array of factory presets
+ // get their strings and display them
+
+ r.top = inLocation.v; r.bottom = r.top;
+ r.left = inLocation.h; r.right = r.left;
+
+ // localize as necessary
+ if (!sAUVPresetLocalized) {
+ CFBundleRef mainBundle = CFBundleGetBundleWithIdentifier(kLocalizedStringBundle_AUView);
+ if (mainBundle) {
+ kStringFactoryPreset = CFCopyLocalizedStringFromTableInBundle(
+ kAUViewLocalizedStringKey_FactoryPreset, kLocalizedStringTable_AUView,
+ mainBundle, CFSTR("FactoryPreset title string"));
+ sAUVPresetLocalized = true;
+ }
+ }
+
+ // create localized title string
+ CFMutableStringRef factoryPresetsTitle = CFStringCreateMutable(NULL, 0);
+ CFStringAppend(factoryPresetsTitle, kStringFactoryPreset);
+ CFStringAppend(factoryPresetsTitle, kAUViewUnlocalizedString_TitleSeparator);
+
+ ControlRef theControl;
+ verify_noerr(CreateStaticTextControl(mView->GetCarbonWindow(), &r, factoryPresetsTitle, &inFontStyle, &theControl));
+ SInt16 width = 0;
+ AUCarbonViewControl::SizeControlToFit(theControl, &width, &mHeight);
+ CFRelease(factoryPresetsTitle);
+ EmbedControl(theControl);
+
+ r.top -= 2;
+ r.left += width + 10;
+ r.right = r.left;
+ r.bottom = r.top;
+
+ verify_noerr(CreatePopupButtonControl ( mView->GetCarbonWindow(), &r, NULL,
+ -12345, // DON'T GET MENU FROM RESOURCE mMenuID,!!!
+ FALSE, // variableWidth,
+ 0, // titleWidth,
+ 0, // titleJustification,
+ 0, // titleStyle,
+ &mControl));
+
+ MenuRef menuRef;
+ verify_noerr(CreateNewMenu(1, 0, &menuRef));
+
+ int numPresets = CFArrayGetCount(mPresets);
+
+ for (int i = 0; i < numPresets; ++i)
+ {
+ AUPreset* preset = (AUPreset*) CFArrayGetValueAtIndex (mPresets, i);
+ verify_noerr(AppendMenuItemTextWithCFString (menuRef, preset->presetName, 0, 0, 0));
+ }
+
+ verify_noerr(SetControlData(mControl, 0, kControlPopupButtonMenuRefTag, sizeof(menuRef), &menuRef));
+ verify_noerr (SetControlFontStyle (mControl, &inFontStyle));
+
+ SetControl32BitMaximum (mControl, numPresets);
+
+ // size popup
+ SInt16 height = 0;
+
+ AUCarbonViewControl::SizeControlToFit(mControl, &width, &height);
+
+ if (height > mHeight) mHeight = height;
+ if (mHeight < 0) mHeight = 0;
+
+ // find which menu item is the Default preset
+ UInt32 propertySize = sizeof(AUPreset);
+ AUPreset defaultPreset;
+ OSStatus result = AudioUnitGetProperty (mView->GetEditAudioUnit(),
+ kAudioUnitProperty_PresentPreset,
+ kAudioUnitScope_Global,
+ 0,
+ &defaultPreset,
+ &propertySize);
+
+ mPropertyID = kAudioUnitProperty_PresentPreset;
+#endif
+#ifndef __LP64__
+ if (result != noErr) { // if the PresentPreset property is not implemented, fall back to the CurrentPreset property
+ OSStatus result = AudioUnitGetProperty (mView->GetEditAudioUnit(),
+ kAudioUnitProperty_CurrentPreset,
+ kAudioUnitScope_Global,
+ 0,
+ &defaultPreset,
+ &propertySize);
+ mPropertyID = kAudioUnitProperty_CurrentPreset;
+ if (result == noErr)
+ CFRetain (defaultPreset.presetName);
+ }
+#endif
+#if !__LP64__
+ EmbedControl (mControl);
+
+ HandlePropertyChange(defaultPreset);
+
+ RegisterEvents();
+#endif
+}
+
+void AUVPresets::AddInterest (AUEventListenerRef inListener,
+ void * inObject)
+{
+ AudioUnitEvent e;
+ e.mEventType = kAudioUnitEvent_PropertyChange;
+ e.mArgument.mProperty.mAudioUnit = mView->GetEditAudioUnit();
+ e.mArgument.mProperty.mPropertyID = mPropertyID;
+ e.mArgument.mProperty.mScope = kAudioUnitScope_Global;
+ e.mArgument.mProperty.mElement = 0;
+
+ AUEventListenerAddEventType(inListener, inObject, &e);
+}
+
+void AUVPresets::RemoveInterest (AUEventListenerRef inListener,
+ void * inObject)
+{
+ AudioUnitEvent e;
+ e.mEventType = kAudioUnitEvent_PropertyChange;
+ e.mArgument.mProperty.mAudioUnit = mView->GetEditAudioUnit();
+ e.mArgument.mProperty.mPropertyID = mPropertyID;
+ e.mArgument.mProperty.mScope = kAudioUnitScope_Global;
+ e.mArgument.mProperty.mElement = 0;
+
+ AUEventListenerRemoveEventType(inListener, inObject, &e);
+}
+
+void AUVPresets::HandleControlChange ()
+{
+#if !__LP64__
+ SInt32 i = GetControl32BitValue(mControl);
+ if (i > 0)
+ {
+ AUPreset* preset = (AUPreset*) CFArrayGetValueAtIndex (mPresets, i-1);
+
+ verify_noerr(AudioUnitSetProperty (mView->GetEditAudioUnit(),
+ mPropertyID, // either currentPreset or PresentPreset depending on which is supported
+ kAudioUnitScope_Global,
+ 0,
+ preset,
+ sizeof(AUPreset)));
+
+ // when we change a preset we can't expect the AU to update its state
+ // as it isn't meant to know that its being viewed!
+ // so we broadcast a notification to all listeners that all parameters on this AU have changed
+ AudioUnitParameter changedUnit;
+ changedUnit.mAudioUnit = mView->GetEditAudioUnit();
+ changedUnit.mParameterID = kAUParameterListener_AnyParameter;
+ verify_noerr (AUParameterListenerNotify (NULL, NULL, &changedUnit) );
+ }
+#endif
+}
+
+void AUVPresets::HandlePropertyChange(AUPreset &preset)
+{
+#if !__LP64__
+ // check to see if the preset is in our menu
+ int numPresets = CFArrayGetCount(mPresets);
+ if (preset.presetNumber < 0) {
+ SetControl32BitValue (mControl, 0); //controls are one-based
+ } else {
+ for (SInt32 i = 0; i < numPresets; ++i) {
+ AUPreset* currPreset = (AUPreset*) CFArrayGetValueAtIndex (mPresets, i);
+ if (preset.presetNumber == currPreset->presetNumber) {
+ SetControl32BitValue (mControl, ++i); //controls are one-based
+ break;
+ }
+ }
+ }
+
+ if (preset.presetName)
+ CFRelease (preset.presetName);
+#endif
+}
+
+bool AUVPresets::HandlePropertyChange (const AudioUnitProperty &inProp)
+{
+ if (inProp.mPropertyID == mPropertyID)
+ {
+ UInt32 theSize = sizeof(AUPreset);
+ AUPreset currentPreset;
+
+ OSStatus result = AudioUnitGetProperty(inProp.mAudioUnit,
+ inProp.mPropertyID,
+ inProp.mScope,
+ inProp.mElement, &currentPreset, &theSize);
+
+ if (result == noErr) {
+#ifndef __LP64__
+ if (inProp.mPropertyID == kAudioUnitProperty_CurrentPreset && currentPreset.presetName)
+ CFRetain (currentPreset.presetName);
+#endif
+ HandlePropertyChange(currentPreset);
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h
new file mode 100644
index 0000000000..3d5f975614
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h
@@ -0,0 +1,230 @@
+/*
+ File: AUCarbonViewControl.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUCarbonViewControl_h__
+#define __AUCarbonViewControl_h__
+
+#include <Carbon/Carbon.h>
+#include <AudioUnit/AudioUnitCarbonView.h>
+#include <AudioToolbox/AudioUnitUtilities.h>
+#include "CarbonEventHandler.h"
+#include "CAAUParameter.h"
+
+class AUCarbonViewBase;
+
+// ____________________________________________________________________________
+// AUCarbonViewControl
+// Wrapper for a control that is wired to an AudioUnit parameter.
+ /*! @class AUCarbonViewControl */
+class AUCarbonViewControl : public CarbonEventHandler {
+ // note that the controls are never disposed; that's managed by the AUCarbonViewBase's
+ // parent pane which contains all of them ... if we later need to be able to delete
+ // individual controls on the fly, extra work needed
+public:
+ enum ControlType {
+ kTypeContinuous, // e.g. slider
+ kTypeDiscrete, // e.g. pop-up menu
+ kTypeText
+ };
+
+ AUCarbonViewControl(AUCarbonViewBase *ownerView, AUParameterListenerRef listener, ControlType type, const CAAUParameter &param, ControlRef control);
+ ~AUCarbonViewControl();
+
+ /*! @method Bind */
+ virtual void Bind(); // second-stage construction
+
+ /*! @method ControlToParameter */
+ virtual void ControlToParameter();
+ /*! @method ParameterToControl */
+ virtual void ParameterToControl(Float32 newValue);
+
+ /*! @method SetValueFract */
+ virtual void SetValueFract(double value);
+ /*! @method GetValueFract */
+ virtual double GetValueFract();
+ /*! @method SetTextValue */
+ virtual void SetTextValue(CFStringRef str);
+ /*! @method GetTextValue */
+ virtual CFStringRef GetTextValue();
+ /*! @method SetValue */
+ virtual void SetValue(long value);
+ /*! @method GetValue */
+ virtual long GetValue();
+
+ /*! @method GetOwnerView */
+ AUCarbonViewBase * GetOwnerView() {return mOwnerView;}
+
+ /*! @method Update */
+ void Update (bool inUIThread)
+ {
+ if (inUIThread)
+ ParameterToControl (mParam.GetValue());
+ else
+ AUParameterListenerNotify (mListener, this, &mParam);
+ }
+
+
+ // CarbonEventHandler overrides
+ /*! @method HandleEvent */
+ virtual bool HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event);
+
+ /*! @method ControlRef */
+ operator ControlRef() { return mControl; }
+
+ /*! @method SizeControlToFit */
+ static Boolean SizeControlToFit(ControlRef inControl, SInt16 *outWidth = NULL, SInt16 *outHeight = NULL);
+
+ /*! @method SliderTrackProc */
+ static pascal void SliderTrackProc(ControlRef theControl, ControlPartCode partCode);
+ /*! @method NumericKeyFilterCallback */
+ static pascal ControlKeyFilterResult NumericKeyFilterCallback(ControlRef theControl, SInt16 *keyCode, SInt16 *charCode,
+ EventModifiers *modifiers);
+protected:
+ /*! @method ParamInfo */
+ const AudioUnitParameterInfo &ParamInfo() { return mParam.ParamInfo(); }
+
+ /*! @var mOwnerView */
+ AUCarbonViewBase * mOwnerView;
+ /*! @var mListener */
+ AUParameterListenerRef mListener;
+ /*! @var mType */
+ ControlType mType;
+ /*! @var mParam */
+ CAAUParameter mParam;
+
+ /*! @var mControl */
+ ControlRef mControl;
+
+ /*! @method StdKeyFilterCallback */
+ static pascal ControlKeyFilterResult StdKeyFilterCallback(ControlRef theControl, SInt16 *keyCode, SInt16 *charCode,
+ EventModifiers *modifiers);
+ SInt16 mInControlInitialization;
+
+ static AUCarbonViewControl* mLastControl;
+};
+
+ /*! @class AUPropertyControl */
+class AUPropertyControl : public CarbonEventHandler {
+public:
+ /*! @ctor AUPropertyControl */
+ AUPropertyControl (AUCarbonViewBase * inBase) : mControl(0), mView (inBase), mHeight(0) {}
+
+ /*! @method HandleEvent */
+ virtual bool HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event);
+
+ /*! @method HandlePropertyChange */
+ virtual bool HandlePropertyChange (const AudioUnitProperty &inProp) = 0;
+
+ /*! @method AddInterest */
+ virtual void AddInterest (AUEventListenerRef inListener,
+ void * inObject) = 0;
+
+ /*! @method RemoveInterest */
+ virtual void RemoveInterest (AUEventListenerRef inListener,
+ void * inObject) = 0;
+
+ /*! @method GetHeight */
+ int GetHeight() { return mHeight;}
+
+protected:
+ /*! @method HandleControlChange */
+ virtual void HandleControlChange () = 0;
+
+ /*! @method RegisterEvents */
+ void RegisterEvents ();
+
+ /*! @method EmbedControl */
+ void EmbedControl (ControlRef theControl);
+
+ /*! @method GetCarbonWindow */
+ WindowRef GetCarbonWindow();
+
+ /*! @var mControl */
+ ControlRef mControl;
+ /*! @var mView */
+ AUCarbonViewBase* mView;
+ /*! @var mHeight */
+ SInt16 mHeight;
+};
+
+ /*! @class AUVPresets */
+class AUVPresets : public AUPropertyControl {
+public:
+ /*! @ctor HandleControlChange */
+ AUVPresets (AUCarbonViewBase * inBase,
+ CFArrayRef& inPresets,
+ Point inLocation,
+ int nameWidth,
+ int controlWidth,
+ ControlFontStyleRec & inFontStyle);
+
+ virtual ~AUVPresets () { CFRelease (mPresets); }
+
+ /*! @method HandlePropertyChange */
+ virtual bool HandlePropertyChange (const AudioUnitProperty &inProp);
+
+ /*! @method AddInterest */
+ virtual void AddInterest (AUEventListenerRef inListener,
+ void * inObject);
+
+ /*! @method RemoveInterest */
+ virtual void RemoveInterest (AUEventListenerRef inListener,
+ void * inObject);
+
+protected:
+ /*! @method HandleControlChange */
+ virtual void HandleControlChange ();
+
+ /*! @var mPresets */
+ CFArrayRef mPresets;
+ /*! @var mView */
+ AUCarbonViewBase* mView;
+ AudioUnitPropertyID mPropertyID;
+
+ void HandlePropertyChange(AUPreset &preset);
+};
+
+#endif // __AUCarbonViewControl_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp
new file mode 100644
index 0000000000..15a04e827e
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp
@@ -0,0 +1,125 @@
+/*
+ File: AUCarbonViewDispatch.cpp
+ Abstract: AUCarbonViewDispatch.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUCarbonViewBase.h"
+
+// ____________________________________________________________________________
+// component dispatch
+
+#if PRAGMA_STRUCT_ALIGN
+ #pragma options align=mac68k
+#elif PRAGMA_STRUCT_PACKPUSH
+ #pragma pack(push, 2)
+#elif PRAGMA_STRUCT_PACK
+ #pragma pack(2)
+#endif
+ struct AudioUnitCarbonViewCreateGluePB {
+ unsigned char componentFlags;
+ unsigned char componentParamSize;
+ short componentWhat;
+ ControlRef* outControl;
+ const Float32Point* inSize;
+ const Float32Point* inLocation;
+ ControlRef inParentControl;
+ WindowRef inWindow;
+ AudioUnit inAudioUnit;
+ AudioUnitCarbonView inView;
+ };
+#if !__LP64__
+ struct AudioUnitCarbonViewSetEventListenerGluePB {
+ unsigned char componentFlags;
+ unsigned char componentParamSize;
+ short componentWhat;
+ void* inUserData;
+ AudioUnitCarbonViewEventListener inCallback;
+ AudioUnitCarbonView inView;
+ };
+#endif
+#if PRAGMA_STRUCT_ALIGN
+ #pragma options align=reset
+#elif PRAGMA_STRUCT_PACKPUSH
+ #pragma pack(pop)
+#elif PRAGMA_STRUCT_PACK
+ #pragma pack()
+#endif
+
+#define CheckNull(x) if ((x) == NULL) return paramErr;
+
+OSStatus AUCarbonViewBase::ComponentEntryDispatch(ComponentParameters *p, AUCarbonViewBase *This)
+{
+ if (This == NULL) return paramErr;
+
+ OSStatus result = noErr;
+
+ switch (p->what) {
+ case kAudioUnitCarbonViewCreateSelect:
+ {
+ AudioUnitCarbonViewCreateGluePB *pb = (AudioUnitCarbonViewCreateGluePB *)p;
+ CheckNull(pb->inAudioUnit);
+ CheckNull(pb->inWindow);
+ CheckNull(pb->inParentControl);
+ CheckNull(pb->inSize);
+ CheckNull(pb->inLocation);
+ CheckNull(pb->outControl);
+ result = This->CreateCarbonView(pb->inAudioUnit, pb->inWindow, pb->inParentControl,
+ *pb->inLocation, *pb->inSize, *pb->outControl);
+ }
+ break;
+#if !__LP64__
+ case kAudioUnitCarbonViewSetEventListenerSelect:
+ {
+ AudioUnitCarbonViewSetEventListenerGluePB *pb = (AudioUnitCarbonViewSetEventListenerGluePB *)p;
+ This->SetEventListener(pb->inCallback, pb->inUserData);
+ }
+ break;
+#endif
+
+ default:
+ result = ComponentBase::ComponentEntryDispatch(p, This);
+ break;
+ }
+ return result;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp
new file mode 100644
index 0000000000..8976b401c0
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp
@@ -0,0 +1,359 @@
+/*
+ File: AUControlGroup.cpp
+ Abstract: AUControlGroup.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include <Carbon/Carbon.h>
+#include "AUCarbonViewBase.h"
+#include "AUCarbonViewControl.h"
+#include "AUControlGroup.h"
+#include "AUViewLocalizedStringKeys.h"
+
+#define kSliderThinDimension 10
+#define kLabelAndSliderSpacing 4
+
+#if !__LP64__
+static CFStringRef kStringManufacturer = kAUViewLocalizedStringKey_Manufacturer;
+static bool sLocalized = false;
+#endif
+
+void AUControlGroup::CreateLabelledSlider(
+ AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ Point labelSize,
+ const ControlFontStyleRec & inFontStyle)
+{
+#if !__LP64__
+ ControlFontStyleRec fontStyle = inFontStyle;
+ Rect minValRect, maxValRect, sliderRect;
+ ControlRef newControl;
+ int width = area.right - area.left, height = area.bottom - area.top;
+ CFStringRef cfstr;
+ int sliderValueMax, sliderValueMin, sliderValueDefault;
+ AUCarbonViewControl::ControlType sliderType;
+
+ bool horizontal = (width > height);
+
+ if (horizontal) {
+ maxValRect.top = minValRect.top = area.top + (height - labelSize.v) / 2;
+ minValRect.left = area.left;
+ maxValRect.left = area.right - labelSize.h;
+
+ minValRect.bottom = minValRect.top + labelSize.v;
+ minValRect.right = minValRect.left + labelSize.h;
+ maxValRect.bottom = maxValRect.top + labelSize.v;
+ maxValRect.right = maxValRect.left + labelSize.h;
+
+ sliderRect.left = minValRect.right + kLabelAndSliderSpacing;
+ sliderRect.right = maxValRect.left - kLabelAndSliderSpacing;
+ sliderRect.top = area.top + (height - kSliderThinDimension) / 2;
+ sliderRect.bottom = sliderRect.top + kSliderThinDimension + 4;
+
+ if (auvp.IsIndexedParam ()) {
+ sliderValueMin = sliderValueDefault = int(auvp.ParamInfo().minValue);
+ sliderValueMax = int(auvp.ParamInfo().maxValue);
+ sliderType = AUCarbonViewControl::kTypeDiscrete;
+ } else {
+ sliderValueMin = sliderValueDefault = 0;
+ sliderValueMax = sliderRect.right - sliderRect.left;
+ sliderType = AUCarbonViewControl::kTypeContinuous;
+ }
+ } else {
+ maxValRect.left = minValRect.left = area.left + (width - labelSize.h) / 2;
+ maxValRect.top = area.top;
+ minValRect.top = area.bottom - labelSize.v;
+
+ minValRect.bottom = minValRect.top + labelSize.v;
+ minValRect.right = minValRect.left + labelSize.h;
+ maxValRect.bottom = maxValRect.top + labelSize.v;
+ maxValRect.right = maxValRect.left + labelSize.h;
+
+ sliderRect.left = area.left + (width - kSliderThinDimension) / 2;
+ sliderRect.right = sliderRect.left + kSliderThinDimension + 4;
+ sliderRect.top = maxValRect.bottom + kLabelAndSliderSpacing;
+ sliderRect.bottom = minValRect.top - kLabelAndSliderSpacing;
+
+ if (auvp.IsIndexedParam ()) {
+ sliderValueMin = sliderValueDefault = int(auvp.ParamInfo().minValue);
+ sliderValueMax = int(auvp.ParamInfo().maxValue);
+ sliderType = AUCarbonViewControl::kTypeDiscrete;
+ } else {
+ sliderValueMin = sliderValueDefault = 0;
+ sliderValueMax = sliderRect.bottom - sliderRect.top;
+ sliderType = AUCarbonViewControl::kTypeContinuous;
+ }
+ }
+
+ // minimum value label
+ if (labelSize.v > 0 && labelSize.h > 0) {
+ // check to see if the minimum value has a label
+ cfstr = auvp.GetStringFromValueCopy(&auvp.ParamInfo().minValue);
+ fontStyle.just = horizontal ? teFlushRight : teCenter;
+ verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &minValRect, cfstr, &fontStyle, &newControl));
+ CFRelease(cfstr);
+ verify_noerr(auView->EmbedControl(newControl));
+
+ // maximum value label
+ cfstr = auvp.GetStringFromValueCopy(&auvp.ParamInfo().maxValue);
+ fontStyle.just = horizontal ? teFlushLeft : teCenter;
+ verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &maxValRect, cfstr, &fontStyle, &newControl));
+ CFRelease(cfstr);
+ verify_noerr(auView->EmbedControl(newControl));
+ }
+
+ // slider
+ verify_noerr(CreateSliderControl(auView->GetCarbonWindow(), &sliderRect, sliderValueDefault, sliderValueMin, sliderValueMax, kControlSliderDoesNotPoint, 0, true, AUCarbonViewControl::SliderTrackProc, &newControl));
+
+
+ ControlSize small = kControlSizeSmall;
+ SetControlData(newControl, kControlEntireControl, kControlSizeTag, sizeof(ControlSize), &small);
+ auView->AddCarbonControl(sliderType, auvp, newControl);
+#endif
+}
+
+void AUControlGroup::CreateLabelledSliderAndEditText(
+ AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ Point labelSize,
+ Point editTextSize,
+ const ControlFontStyleRec & inFontStyle)
+{
+#if !__LP64__
+ ControlFontStyleRec fontStyle = inFontStyle;
+ Rect sliderArea, textArea;
+ ControlRef newControl;
+ int width = area.right - area.left, height = area.bottom - area.top;
+
+ bool horizontal = (width > height);
+
+ sliderArea = area;
+ textArea = area;
+ if (horizontal) {
+ textArea.left = area.right - editTextSize.h;
+ // provide a large text box if param is generic and its values have strings...
+ if (auvp.ValuesHaveStrings() && (auvp.ParamInfo().unit == kAudioUnitParameterUnit_Generic))
+ {
+ textArea.right += 30;
+ }
+ sliderArea.right = textArea.left - kLabelAndSliderSpacing;
+ textArea.top = area.top + (height - editTextSize.v) / 2;
+ textArea.bottom = textArea.top + editTextSize.v;
+ } else {
+ textArea.top = area.bottom - editTextSize.v;
+ sliderArea.bottom = textArea.top - kLabelAndSliderSpacing;
+ textArea.left = area.left + (width - editTextSize.h) / 2;
+ textArea.right = textArea.left + editTextSize.h;
+ }
+ CreateLabelledSlider(auView, auvp, sliderArea, labelSize, fontStyle);
+
+ verify_noerr(CreateEditUnicodeTextControl(auView->GetCarbonWindow(), &textArea, CFSTR(""), false,
+ &fontStyle, &newControl));
+ auView->AddCarbonControl(AUCarbonViewControl::kTypeText, auvp, newControl);
+#endif
+}
+
+void AUControlGroup::CreatePopupMenu (AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ const ControlFontStyleRec & inFontStyle,
+ const bool inSizeToFit)
+{
+#if !__LP64__
+ ControlRef thePopUp;
+
+ verify_noerr(CreatePopupButtonControl (auView->GetCarbonWindow(), &area, NULL,
+ -12345, // DON'T GET MENU FROM RESOURCE mMenuID
+ FALSE, // variableWidth,
+ 0, // titleWidth,
+ 0, // titleJustification,
+ 0, // titleStyle,
+ &thePopUp));
+
+ ControlSize small = kControlSizeSmall;
+ SetControlData(thePopUp, kControlEntireControl, kControlSizeTag, sizeof(ControlSize), &small);
+
+ MenuRef menuRef;
+ verify_noerr(CreateNewMenu( 1, 0, &menuRef));
+
+ for (int i = 0; i < auvp.GetNumIndexedParams(); ++i) {
+ verify_noerr(AppendMenuItemTextWithCFString (menuRef, auvp.GetParamName(i), kMenuItemAttrIgnoreMeta, 0, 0));
+ }
+
+ verify_noerr(SetControlData(thePopUp, 0, kControlPopupButtonMenuRefTag, sizeof(menuRef), &menuRef));
+ SetControl32BitMaximum(thePopUp, auvp.GetNumIndexedParams());
+
+ verify_noerr (SetControlFontStyle (thePopUp, &inFontStyle));
+
+ if (inSizeToFit) {
+ AUCarbonViewControl::SizeControlToFit(thePopUp);
+ }
+
+ auView->AddCarbonControl(AUCarbonViewControl::kTypeDiscrete, auvp, thePopUp);
+#endif
+}
+
+void AUControlGroup::AddAUInfo ( AUCarbonViewBase * auView,
+ const Point & inLocation,
+ const SInt16 inRightOffset,
+ const SInt16 inTotalWidth)
+{
+#if !__LP64__
+ // get component info
+ ComponentDescription desc;
+ Handle h1 = NewHandleClear(4);
+ OSStatus err = GetComponentInfo ((Component)auView->GetEditAudioUnit(), &desc, h1, 0, 0);
+
+ if (err == noErr) {
+ // Get the manufacturer's name... look for the ':' character convention
+ HLock(h1);
+ char* ptr1 = *h1;
+ int len = *ptr1++;
+ char* displayStr = 0;
+
+ for (int i = 0; i < len; ++i) {
+ if (ptr1[i] == ':') { // found the name
+ ptr1[i++] = 0;
+ displayStr = ptr1;
+ break;
+ }
+ }
+
+ // localize as necessary:
+ if (!sLocalized) {
+ CFBundleRef mainBundle = CFBundleGetBundleWithIdentifier(kLocalizedStringBundle_AUView);
+ if (mainBundle) {
+ kStringManufacturer = CFCopyLocalizedStringFromTableInBundle(
+ kAUViewLocalizedStringKey_Manufacturer, kLocalizedStringTable_AUView,
+ mainBundle, CFSTR("Manufacturer title string"));
+ sLocalized = true;
+ }
+ }
+
+ // display strings
+ ControlRef newControl;
+ Rect r;
+ r.top = SInt16(inLocation.v); r.bottom = SInt16(inLocation.v) + 16;
+ ControlFontStyleRec fontStyle;
+ fontStyle.flags = kControlUseFontMask | kControlUseJustMask;
+ fontStyle.font = kControlFontSmallBoldSystemFont;
+
+ // display manufacturer string
+ if (displayStr) {
+ CFMutableStringRef mfrstring = CFStringCreateMutable(NULL, 0);
+ CFStringAppend(mfrstring, kStringManufacturer); // "Manufacturer"
+ CFStringAppend(mfrstring, kAUViewUnlocalizedString_TitleSeparator);
+ // "Manufacturer: "
+ CFStringRef mfrname = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingUTF8);
+ if (mfrname) {
+ CFStringAppend(mfrstring, mfrname); // "Manufacturer: MFRName"
+ CFRelease (mfrname);
+ }
+
+ r.left = inLocation.h + inRightOffset;
+ r.right = inLocation.h + inTotalWidth - 28;
+ fontStyle.just = teFlushRight;
+
+ verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &r, mfrstring, &fontStyle, &newControl));
+ verify_noerr(auView->EmbedControl(newControl));
+ CFRelease (mfrstring);
+
+ //move displayStr ptr past the manu, to the name
+ // we move the characters down an index, because the handle doesn't have any room
+ // at the end for the \0
+ int i = strlen(displayStr), j = 0;
+ while (displayStr[++i] == ' ' && i < len)
+ ;
+ while (i < len)
+ displayStr[j++] = displayStr[i++];
+ displayStr[j] = 0;
+ } else {
+ displayStr = ptr1;
+ int i = 0, j = 0;
+ do {
+ displayStr[j] = displayStr[i];
+ ++j; ++i;
+ } while (i < len);
+
+ displayStr[j] = 0;
+ }
+
+ // display AudioUnit string
+ r.left = inLocation.h; r.right = r.left + inRightOffset;
+ fontStyle.just = 0;
+
+ CFMutableStringRef cfstr = CFStringCreateMutable(NULL, 0);
+ CFStringAppend(cfstr, kAUViewLocalizedStringKey_AudioUnit); // "Audio Unit"
+ CFStringAppend(cfstr, kAUViewUnlocalizedString_TitleSeparator);
+ // "Audio Unit: "
+
+ CFStringRef auname = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingUTF8);
+ CFStringAppend(cfstr, auname); // "Audio Unit: AUName"
+ CFRelease (auname);
+
+ verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &r, cfstr, &fontStyle, &newControl));
+
+ // size text control correctly
+ Boolean bValue = false;
+ SetControlData(newControl, kControlEntireControl, 'stim' /* kControlStaticTextIsMultilineTag */, sizeof(Boolean), &bValue);
+ SInt16 baseLineOffset;
+ Rect bestRect;
+ err = GetBestControlRect(newControl, &bestRect, &baseLineOffset);
+ if (err == noErr)
+ {
+ int width = (bestRect.right - bestRect.left) + 1;
+ int height = (bestRect.bottom - bestRect.top) + 1;
+ SizeControl (newControl, width, height);
+ }
+
+ verify_noerr(auView->EmbedControl(newControl));
+ CFRelease (cfstr);
+ }
+
+ DisposeHandle (h1);
+#endif
+}
+
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h
new file mode 100644
index 0000000000..0e16100d2a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h
@@ -0,0 +1,90 @@
+/*
+ File: AUControlGroup.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUControlGroup_h__
+#define __AUControlGroup_h__
+
+#include <Carbon/Carbon.h>
+
+class AUCarbonViewBase;
+class CAAUParameter;
+
+// Utility class to create clusters of controls related to a single parameter
+ /*! @class AUControlGroup */
+class AUControlGroup {
+public:
+ /*! @method CreateLabelledSlider */
+ static void CreateLabelledSlider( AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ Point labelSize,
+ const ControlFontStyleRec & fontStyle);
+
+ /*! @method CreateLabelledSliderAndEditText */
+ static void CreateLabelledSliderAndEditText(
+ AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ Point labelSize,
+ Point editTextSize,
+ const ControlFontStyleRec & fontStyle);
+
+ /*! @method CreatePopupMenu */
+ static void CreatePopupMenu ( AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ const ControlFontStyleRec & inFontStyle,
+ const bool inSizeToFit = false);
+
+ /*! @method AddAUInfo */
+ static void AddAUInfo ( AUCarbonViewBase * auView,
+ const Point & inLocation,
+ const SInt16 inRightOffset,
+ const SInt16 inTotalWidth);
+};
+
+
+#endif // __AUControlGroup_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp
new file mode 100644
index 0000000000..fe9a731d1d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp
@@ -0,0 +1,90 @@
+/*
+ File: CarbonEventHandler.cpp
+ Abstract: CarbonEventHandler.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CarbonEventHandler.h"
+
+static pascal OSStatus TheEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData)
+{
+ CarbonEventHandler *handler = (CarbonEventHandler *)inUserData;
+ if (handler->HandleEvent(inHandlerRef, inEvent))
+ return noErr;
+ else return eventNotHandledErr;
+}
+
+CarbonEventHandler::CarbonEventHandler() :
+ mHandlers(NULL)
+{
+}
+
+CarbonEventHandler::~CarbonEventHandler()
+{
+ if (mHandlers != NULL) {
+ int count = static_cast<int>(CFDictionaryGetCount(mHandlers));
+ EventHandlerRef *theHandlers = (EventHandlerRef*) malloc(count * sizeof(EventHandlerRef));
+ CFDictionaryGetKeysAndValues(mHandlers, NULL, (const void **)theHandlers);
+
+ for (int i = 0; i < count; i++)
+ RemoveEventHandler(theHandlers[i]);
+ CFDictionaryRemoveAllValues(mHandlers);
+ CFRelease (mHandlers);
+ free(theHandlers);
+ }
+}
+
+void CarbonEventHandler::WantEventTypes(EventTargetRef target, UInt32 inNumTypes, const EventTypeSpec *inList)
+{
+ if (mHandlers == NULL)
+ mHandlers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
+
+ EventHandlerRef handler;
+
+ if (CFDictionaryGetValueIfPresent (mHandlers, target, (const void **)&handler)) // if there is already a handler for the target, add the type
+ verify_noerr(AddEventTypesToHandler(handler, inNumTypes, inList));
+ else {
+ verify_noerr(InstallEventHandler(target, TheEventHandler, inNumTypes, inList, this, &handler));
+ CFDictionaryAddValue(mHandlers, target, handler);
+ }
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h
new file mode 100644
index 0000000000..9225e1acd7
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h
@@ -0,0 +1,71 @@
+/*
+ File: CarbonEventHandler.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CarbonEventHandler_h__
+#define __CarbonEventHandler_h__
+
+#include <Carbon/Carbon.h>
+
+ /*! @class CarbonEventHandler */
+class CarbonEventHandler {
+public:
+ /*! @ctor CarbonEventHandler */
+ CarbonEventHandler();
+ /*! @dtor ~CarbonEventHandler */
+ virtual ~CarbonEventHandler();
+
+ /*! @method WantEventTypes */
+ virtual void WantEventTypes(EventTargetRef target, UInt32 inNumTypes, const EventTypeSpec *inList);
+
+ /*! @method HandleEvent */
+ virtual bool HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event) = 0;
+
+protected:
+ /*! @var mHandlers */
+ CFMutableDictionaryRef mHandlers;
+};
+
+#endif // __CarbonEventHandler_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp
new file mode 100644
index 0000000000..1ce8b308b4
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp
@@ -0,0 +1,843 @@
+/*
+ File: AUInstrumentBase.cpp
+ Abstract: AUInstrumentBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUInstrumentBase.h"
+#include "AUMIDIDefs.h"
+
+#if DEBUG
+ #define DEBUG_PRINT 0
+ #define DEBUG_PRINT_NOTE 0
+ #define DEBUG_PRINT_RENDER 0
+#endif
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const UInt32 kEventQueueSize = 1024;
+
+AUInstrumentBase::AUInstrumentBase(
+ AudioComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups,
+ UInt32 numParts)
+ : MusicDeviceBase(inInstance, numInputs, numOutputs, numGroups),
+ mAbsoluteSampleFrame(0),
+ mEventQueue(kEventQueueSize),
+ mNumNotes(0),
+ mNumActiveNotes(0),
+ mMaxActiveNotes(0),
+ mNotes(0),
+ mNoteSize(0),
+ mInitNumPartEls(numParts)
+{
+#if DEBUG_PRINT
+ printf("new AUInstrumentBase\n");
+#endif
+ mFreeNotes.mState = kNoteState_Free;
+ SetWantsRenderThreadID(true);
+}
+
+
+AUInstrumentBase::~AUInstrumentBase()
+{
+#if DEBUG_PRINT
+ printf("delete AUInstrumentBase\n");
+#endif
+}
+
+AUElement * AUInstrumentBase::CreateElement(AudioUnitScope inScope, AudioUnitElement element)
+{
+ switch (inScope)
+ {
+ case kAudioUnitScope_Group:
+ return new SynthGroupElement(this, element, new MidiControls);
+ case kAudioUnitScope_Part:
+ return new SynthPartElement (this, element);
+ }
+ return MusicDeviceBase::CreateElement(inScope, element);
+}
+
+void AUInstrumentBase::CreateExtendedElements()
+{
+ Parts().Initialize(this, kAudioUnitScope_Part, mInitNumPartEls);
+}
+
+AUScope * AUInstrumentBase::GetScopeExtended (AudioUnitScope inScope)
+{
+ if (inScope == kAudioUnitScope_Part)
+ return &mPartScope;
+ return NULL;
+}
+
+
+void AUInstrumentBase::SetNotes(UInt32 inNumNotes, UInt32 inMaxActiveNotes, SynthNote* inNotes, UInt32 inNoteDataSize)
+{
+#if DEBUG_PRINT_NOTE
+ printf("AUInstrumentBase::SetNotes %d %d %p %d\n", inNumNotes, inMaxActiveNotes, inNotes, inNoteDataSize);
+#endif
+ mNumNotes = inNumNotes;
+ mMaxActiveNotes = inMaxActiveNotes;
+ mNoteSize = inNoteDataSize;
+ mNotes = inNotes;
+
+ for (UInt32 i=0; i<mNumNotes; ++i)
+ {
+ SynthNote *note = GetNote(i);
+ note->Reset();
+ mFreeNotes.AddNote(note);
+ }
+}
+
+UInt32 AUInstrumentBase::CountActiveNotes()
+{
+ // debugging tool.
+ UInt32 sum = 0;
+ for (UInt32 i=0; i<mNumNotes; ++i)
+ {
+ SynthNote *note = GetNote(i);
+ if (note->GetState() <= kNoteState_Released)
+ sum++;
+ }
+ return sum;
+}
+
+void AUInstrumentBase::AddFreeNote(SynthNote* inNote)
+{
+ // Fast-released notes are already considered inactive and have already decr'd the active count
+ if (inNote->GetState() < kNoteState_FastReleased) {
+ DecNumActiveNotes();
+ }
+#if DEBUG_PRINT_NOTE
+ else {
+ printf("AUInstrumentBase::AddFreeNote: adding fast-released note %p\n", inNote);
+ }
+ printf("AUInstrumentBase::AddFreeNote (%p) mNumActiveNotes %lu\n", inNote, mNumActiveNotes);
+#endif
+ mFreeNotes.AddNote(inNote);
+}
+
+OSStatus AUInstrumentBase::Initialize()
+{
+/*
+TO DO:
+ Currently ValidFormat will check and validate that the num channels is not being
+ changed if the AU doesn't support the SupportedNumChannels property - which is correct
+
+ What needs to happen here is that IFF the AU does support this property, (ie, the AU
+ can be configured to have different num channels than its original configuration) then
+ the state of the AU at Initialization needs to be validated.
+
+ This is work still to be done - see AUEffectBase for the kind of logic that needs to be applied here
+*/
+
+ // override to call SetNotes
+
+ mNoteIDCounter = 128; // reset this every time we initialise
+ mAbsoluteSampleFrame = 0;
+ return noErr;
+}
+
+void AUInstrumentBase::Cleanup()
+{
+ mFreeNotes.Empty();
+}
+
+
+OSStatus AUInstrumentBase::Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::Reset\n");
+#endif
+ if (inScope == kAudioUnitScope_Global)
+ {
+ // kill all notes..
+ mFreeNotes.Empty();
+ for (UInt32 i=0; i<mNumNotes; ++i)
+ {
+ SynthNote *note = GetNote(i);
+ if (note->IsSounding())
+ note->Kill(0);
+ note->ListRemove();
+ mFreeNotes.AddNote(note);
+ }
+ mNumActiveNotes = 0;
+ mAbsoluteSampleFrame = 0;
+
+ // empty lists.
+ UInt32 numGroups = Groups().GetNumberOfElements();
+ for (UInt32 j = 0; j < numGroups; ++j)
+ {
+ SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
+ group->Reset();
+ }
+ }
+ return MusicDeviceBase::Reset(inScope, inElement);
+}
+
+void AUInstrumentBase::PerformEvents(const AudioTimeStamp& inTimeStamp)
+{
+#if DEBUG_PRINT_RENDER
+ printf("AUInstrumentBase::PerformEvents\n");
+#endif
+ SynthEvent *event;
+ SynthGroupElement *group;
+
+ while ((event = mEventQueue.ReadItem()) != NULL)
+ {
+#if DEBUG_PRINT_RENDER
+ printf("event %08X %d\n", event, event->GetEventType());
+#endif
+ switch(event->GetEventType())
+ {
+ case SynthEvent::kEventType_NoteOn :
+ RealTimeStartNote(GetElForGroupID (event->GetGroupID()), event->GetNoteID(),
+ event->GetOffsetSampleFrame(), *event->GetParams());
+ break;
+ case SynthEvent::kEventType_NoteOff :
+ RealTimeStopNote(event->GetGroupID(), event->GetNoteID(),
+ event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_SustainOn :
+ group = GetElForGroupID (event->GetGroupID());
+ group->SustainOn(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_SustainOff :
+ group = GetElForGroupID (event->GetGroupID());
+ group->SustainOff(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_SostenutoOn :
+ group = GetElForGroupID (event->GetGroupID());
+ group->SostenutoOn(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_SostenutoOff :
+ group = GetElForGroupID (event->GetGroupID());
+ group->SostenutoOff(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_AllNotesOff :
+ group = GetElForGroupID (event->GetGroupID());
+ group->AllNotesOff(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_AllSoundOff :
+ group = GetElForGroupID (event->GetGroupID());
+ group->AllSoundOff(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_ResetAllControllers :
+ group = GetElForGroupID (event->GetGroupID());
+ group->ResetAllControllers(event->GetOffsetSampleFrame());
+ break;
+ }
+
+ mEventQueue.AdvanceReadPtr();
+ }
+}
+
+
+OSStatus AUInstrumentBase::Render( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames)
+{
+ PerformEvents(inTimeStamp);
+
+ AUScope &outputs = Outputs();
+ UInt32 numOutputs = outputs.GetNumberOfElements();
+ for (UInt32 j = 0; j < numOutputs; ++j)
+ {
+ GetOutput(j)->PrepareBuffer(inNumberFrames); // AUBase::DoRenderBus() only does this for the first output element
+ AudioBufferList& bufferList = GetOutput(j)->GetBufferList();
+ for (UInt32 k = 0; k < bufferList.mNumberBuffers; ++k)
+ {
+ memset(bufferList.mBuffers[k].mData, 0, bufferList.mBuffers[k].mDataByteSize);
+ }
+ }
+ UInt32 numGroups = Groups().GetNumberOfElements();
+ for (UInt32 j = 0; j < numGroups; ++j)
+ {
+ SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
+ OSStatus err = group->Render((SInt64)inTimeStamp.mSampleTime, inNumberFrames, outputs);
+ if (err) return err;
+ }
+ mAbsoluteSampleFrame += inNumberFrames;
+ return noErr;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUInstrumentBase::ValidFormat
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+bool AUInstrumentBase::ValidFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inNewFormat)
+{
+ // if the AU supports this, then we should just let this go through to the Init call
+ if (SupportedNumChannels (NULL))
+ return MusicDeviceBase::ValidFormat(inScope, inElement, inNewFormat);
+
+ bool isGood = MusicDeviceBase::ValidFormat (inScope, inElement, inNewFormat);
+ if (!isGood) return false;
+
+ // if we get to here, then the basic criteria is that the
+ // num channels cannot change on an existing bus
+ AUIOElement *el = GetIOElement (inScope, inElement);
+ return (el->GetStreamFormat().NumberChannels() == inNewFormat.NumberChannels());
+}
+
+
+bool AUInstrumentBase::StreamFormatWritable( AudioUnitScope scope,
+ AudioUnitElement element)
+{
+ return IsInitialized() ? false : true;
+}
+
+OSStatus AUInstrumentBase::RealTimeStartNote( SynthGroupElement *inGroup,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams)
+{
+ return noErr;
+}
+
+SynthPartElement * AUInstrumentBase::GetPartElement (AudioUnitElement inPartElement)
+{
+ AUScope & parts = Parts();
+ unsigned int numEls = parts.GetNumberOfElements();
+ for (unsigned int i = 0; i < numEls; ++i) {
+ SynthPartElement* el = reinterpret_cast<SynthPartElement*>(parts.GetElement(i));
+ if (el->GetIndex() == inPartElement) {
+ return el;
+ }
+ }
+ return NULL;
+}
+
+SynthGroupElement * AUInstrumentBase::GetElForGroupID (MusicDeviceGroupID inGroupID)
+{
+ AUScope & groups = Groups();
+ unsigned int numEls = groups.GetNumberOfElements();
+ SynthGroupElement* unassignedEl = NULL;
+
+ for (unsigned int i = 0; i < numEls; ++i) {
+ SynthGroupElement* el = reinterpret_cast<SynthGroupElement*>(groups.GetElement(i));
+ if (el->GroupID() == inGroupID)
+ return el;
+ if (el->GroupID() == SynthGroupElement::kUnassignedGroup) {
+ unassignedEl = el;
+ break; // we fill this up from the start of the group scope vector
+ }
+ }
+ if (unassignedEl) {
+ unassignedEl->SetGroupID(inGroupID);
+ return unassignedEl;
+ }
+ throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement);
+}
+
+OSStatus AUInstrumentBase::RealTimeStopNote(
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame)
+{
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::RealTimeStopNote ch %d id %d\n", inGroupID, inNoteInstanceID);
+#endif
+
+ SynthGroupElement *gp = (inGroupID == kMusicNoteEvent_Unused
+ ? GetElForNoteID (inNoteInstanceID)
+ : GetElForGroupID(inGroupID));
+ if (gp)
+ {
+ gp->NoteOff (inNoteInstanceID, inOffsetSampleFrame);
+ }
+
+ return noErr;
+}
+
+SynthGroupElement * AUInstrumentBase::GetElForNoteID (NoteInstanceID inNoteID)
+{
+#if DEBUG_PRINT
+ printf("GetElForNoteID id %u\n", inNoteID);
+#endif
+ AUScope & groups = Groups();
+ unsigned int numEls = groups.GetNumberOfElements();
+
+ for (unsigned int i = 0; i < numEls; ++i) {
+ SynthGroupElement* el = reinterpret_cast<SynthGroupElement*>(groups.GetElement(i));
+ if (el->GetNote(inNoteID) != NULL) // searches for any note state
+ return el;
+ }
+ throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement);
+}
+
+OSStatus AUInstrumentBase::StartNote( MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams)
+{
+ OSStatus err = noErr;
+
+ NoteInstanceID noteID;
+ if (outNoteInstanceID) {
+ noteID = NextNoteID();
+ *outNoteInstanceID = noteID;
+ } else
+ noteID = (UInt32)inParams.mPitch;
+
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::StartNote ch %u, key %u, offset %u\n", inGroupID, (unsigned) inParams.mPitch, inOffsetSampleFrame);
+#endif
+
+ if (InRenderThread ())
+ {
+ err = RealTimeStartNote(
+ GetElForGroupID(inGroupID),
+ noteID,
+ inOffsetSampleFrame,
+ inParams);
+ }
+ else
+ {
+ SynthEvent *event = mEventQueue.WriteItem();
+ if (!event) return -1; // queue full
+
+ event->Set(
+ SynthEvent::kEventType_NoteOn,
+ inGroupID,
+ noteID,
+ inOffsetSampleFrame,
+ &inParams
+ );
+
+ mEventQueue.AdvanceWritePtr();
+ }
+ return err;
+}
+
+OSStatus AUInstrumentBase::StopNote( MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame)
+{
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::StopNote ch %u, id %u, offset %u\n", (unsigned)inGroupID, (unsigned)inNoteInstanceID, inOffsetSampleFrame);
+#endif
+ OSStatus err = noErr;
+
+ if (InRenderThread ())
+ {
+ err = RealTimeStopNote(
+ inGroupID,
+ inNoteInstanceID,
+ inOffsetSampleFrame);
+ }
+ else
+ {
+ SynthEvent *event = mEventQueue.WriteItem();
+ if (!event) return -1; // queue full
+
+ event->Set(
+ SynthEvent::kEventType_NoteOff,
+ inGroupID,
+ inNoteInstanceID,
+ inOffsetSampleFrame,
+ NULL
+ );
+
+ mEventQueue.AdvanceWritePtr();
+ }
+ return err;
+}
+
+OSStatus AUInstrumentBase::SendPedalEvent(MusicDeviceGroupID inGroupID, UInt32 inEventType, UInt32 inOffsetSampleFrame)
+{
+
+ if (InRenderThread ())
+ {
+ SynthGroupElement *group = GetElForGroupID(inGroupID);
+ if (!group)
+ return kAudioUnitErr_InvalidElement;
+
+ switch (inEventType)
+ {
+ case SynthEvent::kEventType_SustainOn :
+ group->SustainOn(inOffsetSampleFrame);
+ break;
+ case SynthEvent::kEventType_SustainOff :
+ group->SustainOff(inOffsetSampleFrame);
+ break;
+ case SynthEvent::kEventType_SostenutoOn :
+ group->SostenutoOn(inOffsetSampleFrame);
+ break;
+ case SynthEvent::kEventType_SostenutoOff :
+ group->SostenutoOff(inOffsetSampleFrame);
+ break;
+ case SynthEvent::kEventType_AllNotesOff :
+ group->AllNotesOff(inOffsetSampleFrame);
+ mNumActiveNotes = CountActiveNotes();
+ break;
+ case SynthEvent::kEventType_AllSoundOff :
+ group->AllSoundOff(inOffsetSampleFrame);
+ mNumActiveNotes = CountActiveNotes();
+ break;
+ case SynthEvent::kEventType_ResetAllControllers :
+ group->ResetAllControllers(inOffsetSampleFrame);
+ break;
+ }
+ }
+ else
+ {
+ SynthEvent *event = mEventQueue.WriteItem();
+ if (!event) return -1; // queue full
+
+ event->Set(inEventType, inGroupID, 0, 0, NULL);
+
+ mEventQueue.AdvanceWritePtr();
+ }
+ return noErr;
+}
+
+OSStatus AUInstrumentBase::HandleControlChange( UInt8 inChannel,
+ UInt8 inController,
+ UInt8 inValue,
+ UInt32 inStartFrame)
+{
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::HandleControlChange ch %u ctlr: %u val: %u frm: %u\n", inChannel, inController, inValue, inStartFrame);
+#endif
+ SynthGroupElement *gp = GetElForGroupID(inChannel);
+ if (gp)
+ {
+ gp->ChannelMessage(inController, inValue);
+ }
+ else
+ return kAudioUnitErr_InvalidElement;
+ switch (inController)
+ {
+ case kMidiController_Sustain :
+ if (inValue >= 64)
+ SendPedalEvent(inChannel, SynthEvent::kEventType_SustainOn, inStartFrame);
+ else
+ SendPedalEvent(inChannel, SynthEvent::kEventType_SustainOff, inStartFrame);
+ break;
+ case kMidiController_Sostenuto :
+ if (inValue >= 64)
+ SendPedalEvent(inChannel, SynthEvent::kEventType_SostenutoOn, inStartFrame);
+ else
+ SendPedalEvent(inChannel, SynthEvent::kEventType_SostenutoOff, inStartFrame);
+ break;
+ case kMidiController_OmniModeOff:
+ case kMidiController_OmniModeOn:
+ case kMidiController_MonoModeOn:
+ case kMidiController_MonoModeOff:
+ HandleAllSoundOff(inChannel);
+ break;
+ }
+ return noErr;
+}
+
+OSStatus AUInstrumentBase::HandlePitchWheel( UInt8 inChannel,
+ UInt8 inPitch1, // LSB
+ UInt8 inPitch2, // MSB
+ UInt32 inStartFrame)
+{
+ SynthGroupElement *gp = GetElForGroupID(inChannel);
+ if (gp)
+ {
+ gp->ChannelMessage(kMidiMessage_PitchWheel, (inPitch2 << 7) | inPitch1);
+ return noErr;
+ }
+ else
+ return kAudioUnitErr_InvalidElement;
+}
+
+
+OSStatus AUInstrumentBase::HandleChannelPressure(UInt8 inChannel,
+ UInt8 inValue,
+ UInt32 inStartFrame)
+{
+ SynthGroupElement *gp = GetElForGroupID(inChannel);
+ if (gp)
+ {
+ gp->ChannelMessage(kMidiMessage_ChannelPressure, inValue);
+ return noErr;
+ }
+ else
+ return kAudioUnitErr_InvalidElement;
+}
+
+
+OSStatus AUInstrumentBase::HandleProgramChange( UInt8 inChannel,
+ UInt8 inValue)
+{
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::HandleProgramChange %u %u\n", inChannel, inValue);
+#endif
+ SynthGroupElement *gp = GetElForGroupID(inChannel);
+ if (gp)
+ {
+ gp->ChannelMessage(kMidiMessage_ProgramChange, inValue);
+ return noErr;
+ }
+ else
+ return kAudioUnitErr_InvalidElement;
+}
+
+
+OSStatus AUInstrumentBase::HandlePolyPressure( UInt8 inChannel,
+ UInt8 inKey,
+ UInt8 inValue,
+ UInt32 inStartFrame)
+{
+ SynthGroupElement *gp = GetElForGroupID(inChannel);
+ if (gp)
+ {
+ // Combine key and value into single argument. UGLY!
+ gp->ChannelMessage(kMidiMessage_PolyPressure, (inKey << 7) | inValue);
+ return noErr;
+ }
+ else
+ return kAudioUnitErr_InvalidElement;
+}
+
+
+OSStatus AUInstrumentBase::HandleResetAllControllers( UInt8 inChannel)
+{
+ return SendPedalEvent (inChannel, SynthEvent::kEventType_ResetAllControllers, 0);
+}
+
+
+OSStatus AUInstrumentBase::HandleAllNotesOff( UInt8 inChannel)
+{
+ return SendPedalEvent (inChannel, SynthEvent::kEventType_AllNotesOff, 0);
+}
+
+
+OSStatus AUInstrumentBase::HandleAllSoundOff( UInt8 inChannel)
+{
+ return SendPedalEvent (inChannel, SynthEvent::kEventType_AllSoundOff, 0);
+}
+
+SynthNote* AUInstrumentBase::GetAFreeNote(UInt32 inFrame)
+{
+#if DEBUG_PRINT_NOTE
+ printf("AUInstrumentBase::GetAFreeNote: %lu available\n", mFreeNotes.Length());
+#endif
+ SynthNote *note = mFreeNotes.mHead;
+ if (note)
+ {
+ mFreeNotes.RemoveNote(note);
+ return note;
+ }
+
+ return VoiceStealing(inFrame, true);
+}
+
+SynthNote* AUInstrumentBase::VoiceStealing(UInt32 inFrame, bool inKillIt)
+{
+
+#if DEBUG_PRINT_NOTE
+ printf("AUInstrumentBase::VoiceStealing\n");
+#endif
+ // free list was empty so we need to kill a note.
+ UInt32 startState = inKillIt ? kNoteState_FastReleased : kNoteState_Released;
+ for (UInt32 i = startState; i <= startState; --i)
+ {
+#if DEBUG_PRINT_NOTE
+ printf(" checking state %d...\n", i);
+#endif
+ UInt32 numGroups = Groups().GetNumberOfElements();
+ for (UInt32 j = 0; j < numGroups; ++j)
+ {
+ SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
+#if DEBUG_PRINT_NOTE
+ printf("\tsteal group %d size %d\n", j, group->mNoteList[i].Length());
+#endif
+ if (group->mNoteList[i].NotEmpty()) {
+#if DEBUG_PRINT_NOTE
+ printf("\t-- not empty\n");
+#endif
+ SynthNote *note = group->mNoteList[i].FindMostQuietNote();
+ if (inKillIt) {
+#if DEBUG_PRINT_NOTE
+ printf("\t--=== KILL ===---\n");
+#endif
+ note->Kill(inFrame);
+ group->mNoteList[i].RemoveNote(note);
+ if (i != kNoteState_FastReleased)
+ DecNumActiveNotes();
+ return note;
+ } else {
+#if DEBUG_PRINT_NOTE
+ printf("\t--=== FAST RELEASE ===---\n");
+#endif
+ group->mNoteList[i].RemoveNote(note);
+ note->FastRelease(inFrame);
+ group->mNoteList[kNoteState_FastReleased].AddNote(note);
+ DecNumActiveNotes(); // kNoteState_FastReleased counts as inactive for voice stealing purposes.
+ return NULL;
+ }
+ }
+ }
+ }
+#if DEBUG_PRINT_NOTE
+ printf("no notes to steal????\n");
+#endif
+ return NULL; // It should be impossible to get here. It means there were no notes to kill in any state.
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+AUMonotimbralInstrumentBase::AUMonotimbralInstrumentBase(
+ AudioComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups,
+ UInt32 numParts)
+ : AUInstrumentBase(inInstance, numInputs, numOutputs, numGroups, numParts)
+{
+}
+
+OSStatus AUMonotimbralInstrumentBase::RealTimeStartNote(
+ SynthGroupElement *inGroup,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams)
+{
+#if DEBUG_PRINT_RENDER
+ printf("AUMonotimbralInstrumentBase::RealTimeStartNote %d\n", inNoteInstanceID);
+#endif
+
+ if (NumActiveNotes() + 1 > MaxActiveNotes())
+ {
+ VoiceStealing(inOffsetSampleFrame, false);
+ }
+ SynthNote *note = GetAFreeNote(inOffsetSampleFrame);
+ if (!note) return -1;
+
+ SynthPartElement *part = GetPartElement (0); // Only one part for monotimbral
+
+ IncNumActiveNotes();
+ inGroup->NoteOn(note, part, inNoteInstanceID, inOffsetSampleFrame, inParams);
+
+ return noErr;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+OSStatus AUMultitimbralInstrumentBase::GetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus result = noErr;
+
+ switch (inID)
+ {
+#if !TARGET_OS_IPHONE
+ case kMusicDeviceProperty_PartGroup:
+ if (inScope != kAudioUnitScope_Part) return kAudioUnitErr_InvalidScope;
+ outDataSize = sizeof(UInt32);
+ outWritable = true;
+ break;
+#endif
+ default:
+ result = AUInstrumentBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+ }
+ return result;
+}
+
+OSStatus AUMultitimbralInstrumentBase::GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ OSStatus result = noErr;
+
+ switch (inID)
+ {
+#if !TARGET_OS_IPHONE
+ case kMusicDeviceProperty_PartGroup:
+ if (inScope != kAudioUnitScope_Group) return kAudioUnitErr_InvalidScope;
+ // ??
+ return -1; //unimpl
+ break;
+#endif
+ default:
+ result = AUInstrumentBase::GetProperty (inID, inScope, inElement, outData);
+ }
+
+ return result;
+}
+
+
+
+OSStatus AUMultitimbralInstrumentBase::SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ OSStatus result = noErr;
+
+ switch (inID)
+ {
+#if !TARGET_OS_IPHONE
+ case kMusicDeviceProperty_PartGroup:
+ if (inScope != kAudioUnitScope_Group) return kAudioUnitErr_InvalidScope;
+ // ??
+ return -1; //unimpl
+ break;
+#endif
+ default:
+ result = MusicDeviceBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
+ }
+
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h
new file mode 100644
index 0000000000..3ad7e03a66
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h
@@ -0,0 +1,269 @@
+/*
+ File: AUInstrumentBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUInstrumentBase__
+#define __AUInstrumentBase__
+
+#include <vector>
+#include <stdexcept>
+#include <AudioUnit/AudioUnit.h>
+#include <CoreAudio/CoreAudio.h>
+#include <libkern/OSAtomic.h>
+#include "MusicDeviceBase.h"
+#include "LockFreeFIFO.h"
+#include "SynthEvent.h"
+#include "SynthNote.h"
+#include "SynthElement.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+typedef LockFreeFIFOWithFree<SynthEvent> SynthEventQueue;
+
+class AUInstrumentBase : public MusicDeviceBase
+{
+public:
+ AUInstrumentBase(
+ AudioComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups = 16,
+ UInt32 numParts = 1);
+ virtual ~AUInstrumentBase();
+
+ virtual OSStatus Initialize();
+
+ /*! @method Parts */
+ AUScope & Parts() { return mPartScope; }
+
+ /*! @method GetPart */
+ AUElement * GetPart( AudioUnitElement inElement)
+ {
+ return mPartScope.SafeGetElement(inElement);
+ }
+
+ virtual AUScope * GetScopeExtended (AudioUnitScope inScope);
+
+ virtual AUElement * CreateElement( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ virtual void CreateExtendedElements();
+
+ virtual void Cleanup();
+
+ virtual OSStatus Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ virtual bool ValidFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inNewFormat);
+
+ virtual bool StreamFormatWritable( AudioUnitScope scope,
+ AudioUnitElement element);
+
+ virtual bool CanScheduleParameters() const { return false; }
+
+ virtual OSStatus Render( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames);
+
+ virtual OSStatus StartNote( MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams);
+
+ virtual OSStatus StopNote( MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame);
+
+ virtual OSStatus RealTimeStartNote( SynthGroupElement *inGroup,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams);
+
+ virtual OSStatus RealTimeStopNote( MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame);
+
+ virtual OSStatus HandleControlChange( UInt8 inChannel,
+ UInt8 inController,
+ UInt8 inValue,
+ UInt32 inStartFrame);
+
+ virtual OSStatus HandlePitchWheel( UInt8 inChannel,
+ UInt8 inPitch1,
+ UInt8 inPitch2,
+ UInt32 inStartFrame);
+
+ virtual OSStatus HandleChannelPressure( UInt8 inChannel,
+ UInt8 inValue,
+ UInt32 inStartFrame);
+
+ virtual OSStatus HandleProgramChange( UInt8 inChannel,
+ UInt8 inValue);
+
+ virtual OSStatus HandlePolyPressure( UInt8 inChannel,
+ UInt8 inKey,
+ UInt8 inValue,
+ UInt32 inStartFrame);
+
+ virtual OSStatus HandleResetAllControllers( UInt8 inChannel);
+
+ virtual OSStatus HandleAllNotesOff( UInt8 inChannel);
+
+ virtual OSStatus HandleAllSoundOff( UInt8 inChannel);
+
+ SynthNote* GetNote(UInt32 inIndex)
+ {
+ if (!mNotes)
+ throw std::runtime_error("no notes");
+ return (SynthNote*)((char*)mNotes + inIndex * mNoteSize);
+ }
+
+ SynthNote* GetAFreeNote(UInt32 inFrame);
+ void AddFreeNote(SynthNote* inNote);
+
+ friend class SynthGroupElement;
+protected:
+
+ UInt32 NextNoteID() { return OSAtomicIncrement32((int32_t *)&mNoteIDCounter); }
+
+
+ // call SetNotes in your Initialize() method to give the base class your note structures and to set the maximum
+ // number of active notes. inNoteData should be an array of size inMaxActiveNotes.
+ void SetNotes(UInt32 inNumNotes, UInt32 inMaxActiveNotes, SynthNote* inNotes, UInt32 inNoteSize);
+
+ void PerformEvents( const AudioTimeStamp & inTimeStamp);
+ OSStatus SendPedalEvent(MusicDeviceGroupID inGroupID, UInt32 inEventType, UInt32 inOffsetSampleFrame);
+ virtual SynthNote* VoiceStealing(UInt32 inFrame, bool inKillIt);
+ UInt32 MaxActiveNotes() const { return mMaxActiveNotes; }
+ UInt32 NumActiveNotes() const { return mNumActiveNotes; }
+ void IncNumActiveNotes() { ++mNumActiveNotes; }
+ void DecNumActiveNotes() { --mNumActiveNotes; }
+ UInt32 CountActiveNotes();
+
+ SynthPartElement * GetPartElement (AudioUnitElement inPartElement);
+
+ // this call throws if there's no assigned element for the group ID
+ virtual SynthGroupElement * GetElForGroupID (MusicDeviceGroupID inGroupID);
+ virtual SynthGroupElement * GetElForNoteID (NoteInstanceID inNoteID);
+
+ SInt64 mAbsoluteSampleFrame;
+
+
+private:
+
+ SInt32 mNoteIDCounter;
+
+ SynthEventQueue mEventQueue;
+
+ UInt32 mNumNotes;
+ UInt32 mNumActiveNotes;
+ UInt32 mMaxActiveNotes;
+ SynthNote* mNotes;
+ SynthNoteList mFreeNotes;
+ UInt32 mNoteSize;
+
+ AUScope mPartScope;
+ const UInt32 mInitNumPartEls;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class AUMonotimbralInstrumentBase : public AUInstrumentBase
+{
+public:
+ AUMonotimbralInstrumentBase(
+ AudioComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups = 16,
+ UInt32 numParts = 1);
+
+ virtual OSStatus RealTimeStartNote( SynthGroupElement *inGroup,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams);
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// this is a work in progress! The mono-timbral one is finished though!
+class AUMultitimbralInstrumentBase : public AUInstrumentBase
+{
+public:
+ AUMultitimbralInstrumentBase(
+ AudioComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups,
+ UInt32 numParts);
+
+ virtual OSStatus GetPropertyInfo( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ virtual OSStatus GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+
+ virtual OSStatus SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+
+private:
+
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#endif
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h
new file mode 100644
index 0000000000..ea6c4c26e1
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h
@@ -0,0 +1,168 @@
+/*
+ File: LockFreeFIFO.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include <libkern/OSAtomic.h>
+
+template <class ITEM>
+class LockFreeFIFOWithFree
+{
+ LockFreeFIFOWithFree(); // private, unimplemented.
+public:
+ LockFreeFIFOWithFree(UInt32 inMaxSize)
+ : mReadIndex(0), mWriteIndex(0), mFreeIndex(0)
+ {
+ //assert(IsPowerOfTwo(inMaxSize));
+ mItems = new ITEM[inMaxSize];
+ mMask = inMaxSize - 1;
+ }
+
+ ~LockFreeFIFOWithFree()
+ {
+ delete [] mItems;
+ }
+
+
+ void Reset()
+ {
+ FreeItems();
+ mReadIndex = 0;
+ mWriteIndex = 0;
+ mFreeIndex = 0;
+ }
+
+ ITEM* WriteItem()
+ {
+ //printf("WriteItem %d %d\n", mReadIndex, mWriteIndex);
+ FreeItems(); // free items on the write thread.
+ int32_t nextWriteIndex = (mWriteIndex + 1) & mMask;
+ if (nextWriteIndex == mFreeIndex) return NULL;
+ return &mItems[mWriteIndex];
+ }
+
+ ITEM* ReadItem()
+ {
+ //printf("ReadItem %d %d\n", mReadIndex, mWriteIndex);
+ if (mReadIndex == mWriteIndex) return NULL;
+ return &mItems[mReadIndex];
+ }
+ void AdvanceWritePtr() { OSAtomicCompareAndSwap32(mWriteIndex, (mWriteIndex + 1) & mMask, &mWriteIndex); }
+ void AdvanceReadPtr() { OSAtomicCompareAndSwap32(mReadIndex, (mReadIndex + 1) & mMask, &mReadIndex); }
+private:
+ ITEM* FreeItem()
+ {
+ if (mFreeIndex == mReadIndex) return NULL;
+ return &mItems[mFreeIndex];
+ }
+ void AdvanceFreePtr() { OSAtomicCompareAndSwap32(mFreeIndex, (mFreeIndex + 1) & mMask, &mFreeIndex); }
+
+ void FreeItems()
+ {
+ ITEM* item;
+ while ((item = FreeItem()) != NULL)
+ {
+ item->Free();
+ AdvanceFreePtr();
+ }
+ }
+
+ volatile int32_t mReadIndex, mWriteIndex, mFreeIndex;
+ int32_t mMask;
+ ITEM *mItems;
+};
+
+
+
+// Same as above but no free.
+
+template <class ITEM>
+class LockFreeFIFO
+{
+ LockFreeFIFO(); // private, unimplemented.
+public:
+ LockFreeFIFO(UInt32 inMaxSize)
+ : mReadIndex(0), mWriteIndex(0)
+ {
+ //assert(IsPowerOfTwo(inMaxSize));
+ mItems = new ITEM[inMaxSize];
+ mMask = inMaxSize - 1;
+ }
+
+ ~LockFreeFIFO()
+ {
+ delete [] mItems;
+ }
+
+ void Reset()
+ {
+ mReadIndex = 0;
+ mWriteIndex = 0;
+ }
+
+ ITEM* WriteItem()
+ {
+ int32_t nextWriteIndex = (mWriteIndex + 1) & mMask;
+ if (nextWriteIndex == mReadIndex) return NULL;
+ return &mItems[mWriteIndex];
+ }
+
+ ITEM* ReadItem()
+ {
+ if (mReadIndex == mWriteIndex) return NULL;
+ return &mItems[mReadIndex];
+ }
+
+ // the CompareAndSwap will always succeed. We use CompareAndSwap because it calls the PowerPC sync instruction,
+ // plus any processor bug workarounds for various CPUs.
+ void AdvanceWritePtr() { OSAtomicCompareAndSwap32(mWriteIndex, (mWriteIndex + 1) & mMask, &mWriteIndex); }
+ void AdvanceReadPtr() { OSAtomicCompareAndSwap32(mReadIndex, (mReadIndex + 1) & mMask, &mReadIndex); }
+
+private:
+
+ volatile int32_t mReadIndex, mWriteIndex;
+ int32_t mMask;
+ ITEM *mItems;
+};
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/MIDIControlHandler.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/MIDIControlHandler.h
new file mode 100644
index 0000000000..0f8003fcd5
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/MIDIControlHandler.h
@@ -0,0 +1,92 @@
+/*
+ File: MIDIControlHandler.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __MIDICONTROLHANDLER_H__
+#define __MIDICONTROLHANDLER_H__
+
+#include <CoreAudio/CoreAudio.h>
+
+/*! Abstract interface base class for classes which handle all incoming MIDI data */
+
+class MIDIControlHandler
+{
+public:
+ virtual ~MIDIControlHandler() {}
+ virtual void Reset() = 0; //! Restore all state to defaults
+ virtual bool SetProgramChange(UInt16 inProgram) = 0;
+ virtual bool SetPitchWheel(UInt16 inValue) = 0;
+ virtual bool SetChannelPressure(UInt8 inValue) = 0;
+ virtual bool SetPolyPressure(UInt8 inKey, UInt8 inValue) = 0;
+ virtual bool SetController(UInt8 inControllerNumber, UInt8 inValue) = 0;
+ virtual bool SetSysex(void *inSysexMsg) = 0;
+
+ virtual float GetPitchBend() const = 0;
+
+ /*! Default controller values. These represent MSB values unless indicated in the name */
+
+ enum
+ {
+ kDefault_Midpoint = 0x40, //! Used for all center-null-point controllers
+ kDefault_Volume = 100,
+ kDefault_Pan = kDefault_Midpoint,
+ kDefault_ModWheel = 0,
+ kDefault_Pitch = kDefault_Midpoint,
+ kDefault_Expression = 0x7f,
+ kDefault_ChannelPressure = 0,
+ kDefault_ReverbSend = 40,
+ kDefault_ChorusSend = 0,
+
+ kDefault_RPN_LSB = 0x7f,
+ kDefault_RPN_MSB = 0x7f,
+ kDefault_PitchBendRange = 2,
+ kDefault_FineTuning = kDefault_Midpoint,
+ kDefault_CoarseTuning = kDefault_Midpoint,
+ kDefault_ModDepthRange = 0,
+ kDefault_ModDepthRangeLSB = kDefault_Midpoint
+ };
+};
+
+#endif // __MIDICONTROLHANDLER_H__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp
new file mode 100644
index 0000000000..fd329f84e8
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp
@@ -0,0 +1,419 @@
+/*
+ File: SynthElement.cpp
+ Abstract: SynthElement.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "SynthElement.h"
+#include "AUInstrumentBase.h"
+#include "AUMIDIDefs.h"
+
+#undef DEBUG_PRINT
+#define DEBUG_PRINT 0
+#define DEBUG_PRINT_NOTE 0
+#define DEBUG_PRINT_RENDER 0
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+MidiControls::MidiControls()
+{
+ Reset();
+}
+
+void MidiControls::Reset()
+{
+ memset(mControls, 0, sizeof(mControls));
+ memset(mPolyPressure, 0, sizeof(mPolyPressure));
+ mMonoPressure = 0;
+ mProgramChange = 0;
+ mPitchBend = 0;
+ mActiveRPN = 0;
+ mActiveNRPN = 0;
+ mActiveRPValue = 0;
+ mActiveNRPValue = 0;
+ mControls[kMidiController_Pan] = 64;
+ mControls[kMidiController_Expression] = 127;
+ mPitchBendDepth = 24 << 7;
+ mFPitchBendDepth = 24.0f;
+ mFPitchBend = 0.0f;
+}
+
+
+SynthElement::SynthElement(AUInstrumentBase *audioUnit, UInt32 inElement)
+ : AUElement(audioUnit), mIndex(inElement)
+{
+}
+
+SynthElement::~SynthElement()
+{
+}
+
+SynthGroupElement::SynthGroupElement(AUInstrumentBase *audioUnit, UInt32 inElement, MIDIControlHandler *inHandler)
+ : SynthElement(audioUnit, inElement),
+ mCurrentAbsoluteFrame(-1),
+ mMidiControlHandler(inHandler),
+ mSustainIsOn(false), mSostenutoIsOn(false), mOutputBus(0), mGroupID(kUnassignedGroup)
+{
+ for (UInt32 i=0; i<kNumberOfSoundingNoteStates; ++i)
+ mNoteList[i].mState = (SynthNoteState) i;
+}
+
+SynthGroupElement::~SynthGroupElement()
+{
+ delete mMidiControlHandler;
+}
+
+void SynthGroupElement::SetGroupID (MusicDeviceGroupID inGroup)
+{
+ // can't re-assign a group once its been assigned
+ if (mGroupID != kUnassignedGroup) throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement);
+ mGroupID = inGroup;
+}
+
+void SynthGroupElement::Reset()
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::Reset\n");
+#endif
+ mMidiControlHandler->Reset();
+ for (UInt32 i=0; i<kNumberOfSoundingNoteStates; ++i)
+ mNoteList[i].Empty();
+}
+
+SynthPartElement::SynthPartElement(AUInstrumentBase *audioUnit, UInt32 inElement)
+ : SynthElement(audioUnit, inElement)
+{
+}
+
+// Return the SynthNote with the given inNoteID, if found. If unreleasedOnly is true, only look for
+// attacked and sostenutoed notes, otherwise search all states. Return state of found note via outNoteState.
+
+SynthNote *SynthGroupElement::GetNote(NoteInstanceID inNoteID, bool unreleasedOnly, UInt32 *outNoteState)
+{
+#if DEBUG_PRINT_RENDER
+ printf("SynthGroupElement::GetNote %d, unreleased = %d\n", inNoteID, unreleasedOnly);
+#endif
+ const UInt32 lastNoteState = unreleasedOnly ?
+ (mSostenutoIsOn ? kNoteState_Sostenutoed : kNoteState_Attacked)
+ : kNoteState_Released;
+ SynthNote *note = NULL;
+ // Search for notes in each successive state
+ for (UInt32 noteState = kNoteState_Attacked; noteState <= lastNoteState; ++noteState)
+ {
+ if (outNoteState) *outNoteState = noteState; // even if we find nothing
+ note = mNoteList[noteState].mHead;
+ while (note && note->mNoteID != inNoteID)
+ {
+#if DEBUG_PRINT_RENDER
+ printf(" checking %p id: %d\n", note, note->mNoteID);
+#endif
+ note = note->mNext;
+ }
+ if (note)
+ {
+#if DEBUG_PRINT_RENDER
+ printf(" found %p\n", note);
+#endif
+ break;
+ }
+ }
+ return note;
+}
+
+void SynthGroupElement::NoteOn(SynthNote *note,
+ SynthPartElement *part,
+ NoteInstanceID inNoteID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams)
+{
+#if DEBUG_PRINT_NOTE
+ printf("SynthGroupElement::NoteOn %d\n", inNoteID);
+#endif
+ // TODO: CONSIDER FIXING this to not need to initialize mCurrentAbsoluteFrame to -1.
+ UInt64 absoluteFrame = (mCurrentAbsoluteFrame == -1) ? inOffsetSampleFrame : mCurrentAbsoluteFrame + inOffsetSampleFrame;
+ if (note->AttackNote(part, this, inNoteID, absoluteFrame, inOffsetSampleFrame, inParams)) {
+ mNoteList[kNoteState_Attacked].AddNote(note);
+ }
+}
+
+void SynthGroupElement::NoteOff(NoteInstanceID inNoteID, UInt32 inFrame)
+{
+#if DEBUG_PRINT_NOTE
+ printf("SynthGroupElement::NoteOff %d\n", inNoteID);
+#endif
+ UInt32 noteState = kNoteState_Attacked;
+ SynthNote *note = GetNote(inNoteID, true, &noteState); // asking for unreleased only
+ if (note)
+ {
+#if DEBUG_PRINT_NOTE
+ printf(" old note state: %d\n", note->mState);
+#endif
+ if (noteState == kNoteState_Attacked)
+ {
+ mNoteList[noteState].RemoveNote(note);
+ if (mSustainIsOn) {
+ mNoteList[kNoteState_ReleasedButSustained].AddNote(note);
+ } else {
+ note->Release(inFrame);
+ mNoteList[kNoteState_Released].AddNote(note);
+ }
+#if DEBUG_PRINT_NOTE
+ printf(" new note state: %d\n", note->mState);
+#endif
+ }
+ else /* if (noteState == kNoteState_Sostenutoed) */
+ {
+ mNoteList[kNoteState_Sostenutoed].RemoveNote(note);
+ mNoteList[kNoteState_ReleasedButSostenutoed].AddNote(note);
+ }
+ }
+}
+
+void SynthGroupElement::NoteEnded(SynthNote *inNote, UInt32 inFrame)
+{
+#if DEBUG_PRINT_NOTE
+ printf("SynthGroupElement::NoteEnded: id %d state %d\n", inNote->mNoteID, inNote->mState);
+#endif
+ if (inNote->IsSounding()) {
+ SynthNoteList *list = &mNoteList[inNote->GetState()];
+ list->RemoveNote(inNote);
+ }
+
+ GetAUInstrument()->AddFreeNote(inNote);
+}
+
+void SynthGroupElement::NoteFastReleased(SynthNote *inNote)
+{
+#if DEBUG_PRINT_NOTE
+ printf("SynthGroupElement::NoteFastReleased id %d state %d\n", inNote->mNoteID, inNote->mState);
+#endif
+ if (inNote->IsActive()) {
+ mNoteList[inNote->GetState()].RemoveNote(inNote);
+ GetAUInstrument()->DecNumActiveNotes();
+ mNoteList[kNoteState_FastReleased].AddNote(inNote);
+ }
+ else {
+ Assert(true, "ASSERT FAILED: Attempting to fast-release non-active note");
+ }
+}
+
+bool SynthGroupElement::ChannelMessage(UInt16 controllerID, UInt16 inValue)
+{
+ bool handled = true;
+#if DEBUG_PRINT
+ printf("SynthGroupElement::ChannelMessage(0x%x, %u)\n", controllerID, inValue);
+#endif
+ // Sustain and sostenuto are "pedal events", and are handled during render cycle
+ if (controllerID <= kMidiController_RPN_MSB && controllerID != kMidiController_Sustain && controllerID != kMidiController_Sostenuto)
+ handled = mMidiControlHandler->SetController(controllerID, UInt8(inValue));
+ else
+ {
+ switch (controllerID)
+ {
+ case kMidiMessage_ProgramChange:
+ handled = mMidiControlHandler->SetProgramChange(inValue);
+ break;
+ case kMidiMessage_PitchWheel:
+ handled = mMidiControlHandler->SetPitchWheel(inValue);
+ break;
+ case kMidiMessage_ChannelPressure:
+#if DEBUG_PRINT
+ printf("SynthGroupElement::ChannelMessage: Channel Pressure %u\n", inValue);
+#endif
+ handled = mMidiControlHandler->SetChannelPressure(UInt8(inValue));
+ break;
+ case kMidiMessage_PolyPressure:
+ { UInt8 inKey = inValue >> 7;
+ UInt8 val = inValue & 0x7f;
+ handled = mMidiControlHandler->SetPolyPressure(inKey, val);
+ break;
+ }
+ default:
+ handled = false;
+ break;
+ }
+ }
+ return handled;
+}
+
+void SynthGroupElement::SostenutoOn(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::SostenutoOn\n");
+#endif
+ if (!mSostenutoIsOn) {
+ mMidiControlHandler->SetController(kMidiController_Sostenuto, 127);
+ mSostenutoIsOn = true;
+ mNoteList[kNoteState_Sostenutoed].TransferAllFrom(&mNoteList[kNoteState_Attacked], inFrame);
+ }
+}
+
+void SynthGroupElement::SostenutoOff(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::SostenutoOff\n");
+#endif
+ if (mSostenutoIsOn) {
+ mMidiControlHandler->SetController(kMidiController_Sostenuto, 0);
+ mSostenutoIsOn = false;
+ mNoteList[kNoteState_Attacked].TransferAllFrom(&mNoteList[kNoteState_Sostenutoed], inFrame);
+ if (mSustainIsOn)
+ mNoteList[kNoteState_ReleasedButSustained].TransferAllFrom(&mNoteList[kNoteState_ReleasedButSostenutoed], inFrame);
+ else
+ mNoteList[kNoteState_Released].TransferAllFrom(&mNoteList[kNoteState_ReleasedButSostenutoed], inFrame);
+ }
+}
+
+
+void SynthGroupElement::SustainOn(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+// printf("SynthGroupElement::SustainOn\n");
+#endif
+ if (!mSustainIsOn) {
+ mMidiControlHandler->SetController(kMidiController_Sustain, 127);
+ mSustainIsOn = true;
+ }
+}
+
+void SynthGroupElement::SustainOff(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+// printf("SynthGroupElement::SustainOff\n");
+#endif
+ if (mSustainIsOn) {
+ mMidiControlHandler->SetController(kMidiController_Sustain, 0);
+ mSustainIsOn = false;
+
+ mNoteList[kNoteState_Released].TransferAllFrom(&mNoteList[kNoteState_ReleasedButSustained], inFrame);
+ }
+}
+
+void SynthGroupElement::AllNotesOff(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::AllNotesOff\n");
+#endif
+ SynthNote *note;
+ for (UInt32 i=0 ; i<=kNoteState_Sostenutoed; ++i)
+ {
+ UInt32 newState = (i == kNoteState_Attacked) ?
+ kNoteState_Released : kNoteState_ReleasedButSostenutoed;
+ note = mNoteList[i].mHead;
+ while (note)
+ {
+ SynthNote *nextNote = note->mNext;
+
+ mNoteList[i].RemoveNote(note);
+ note->Release(inFrame);
+ mNoteList[newState].AddNote(note);
+
+ note = nextNote;
+ }
+ }
+}
+
+void SynthGroupElement::AllSoundOff(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::AllSoundOff\n");
+#endif
+ SynthNote *note;
+
+ for (UInt32 i=0 ; i<kNumberOfActiveNoteStates; ++i)
+ {
+ note = mNoteList[i].mHead;
+ while (note)
+ {
+ SynthNote *nextNote = note->mNext;
+
+ mNoteList[i].RemoveNote(note);
+ note->FastRelease(inFrame);
+ mNoteList[kNoteState_FastReleased].AddNote(note);
+ GetAUInstrument()->DecNumActiveNotes();
+ note = nextNote;
+ }
+ }
+}
+
+void SynthGroupElement::ResetAllControllers(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::ResetAllControllers\n");
+#endif
+ mMidiControlHandler->Reset();
+}
+
+OSStatus SynthGroupElement::Render(SInt64 inAbsoluteSampleFrame, UInt32 inNumberFrames, AUScope &outputs)
+{
+ // Avoid duplicate calls at same sample offset
+ if (inAbsoluteSampleFrame != mCurrentAbsoluteFrame)
+ {
+ mCurrentAbsoluteFrame = inAbsoluteSampleFrame;
+ AudioBufferList* buffArray[16];
+ UInt32 numOutputs = outputs.GetNumberOfElements();
+ for (UInt32 outBus = 0; outBus < numOutputs && outBus < 16; ++outBus)
+ {
+ buffArray[outBus] = &GetAudioUnit()->GetOutput(outBus)->GetBufferList();
+ }
+
+ for (UInt32 i=0 ; i<kNumberOfSoundingNoteStates; ++i)
+ {
+ SynthNote *note = mNoteList[i].mHead;
+ while (note)
+ {
+#if DEBUG_PRINT_RENDER
+ printf("SynthGroupElement::Render: state %d, note %p\n", i, note);
+#endif
+ SynthNote *nextNote = note->mNext;
+
+ OSStatus err = note->Render(inAbsoluteSampleFrame, inNumberFrames, buffArray, numOutputs);
+ if (err) return err;
+
+ note = nextNote;
+ }
+ }
+ }
+ return noErr;
+}
+
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h
new file mode 100644
index 0000000000..4ca3643106
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h
@@ -0,0 +1,227 @@
+/*
+ File: SynthElement.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __SynthElement__
+#define __SynthElement__
+
+#include <AudioUnit/AudioUnit.h>
+#include "MusicDeviceBase.h"
+#include "SynthNoteList.h"
+#include "MIDIControlHandler.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+class AUInstrumentBase;
+
+class SynthElement : public AUElement
+{
+public:
+ SynthElement(AUInstrumentBase *audioUnit, UInt32 inElement);
+ virtual ~SynthElement();
+
+ UInt32 GetIndex() const { return mIndex; }
+
+ AUInstrumentBase* GetAUInstrument() { return (AUInstrumentBase*)GetAudioUnit(); }
+
+private:
+ UInt32 mIndex;
+};
+
+class MidiControls : public MIDIControlHandler
+{
+ enum { kMaxControls = 128 };
+public:
+ MidiControls();
+ virtual ~MidiControls() {}
+ virtual void Reset();
+ virtual bool SetProgramChange(UInt16 inProgram) { mProgramChange = inProgram; return true; }
+ virtual bool SetPitchWheel(UInt16 inValue) {
+ mPitchBend = inValue;
+ mFPitchBend = (float)(((SInt16)mPitchBend - 8192) / 8192.);
+ return true;
+ }
+ virtual bool SetChannelPressure(UInt8 inValue) { mMonoPressure = inValue; return true; }
+ virtual bool SetPolyPressure(UInt8 inKey, UInt8 inValue) {
+ mPolyPressure[inKey] = inValue;
+ return true;
+ }
+ virtual bool SetController(UInt8 inControllerNumber, UInt8 inValue) {
+ if (inControllerNumber < kMaxControls) {
+ mControls[inControllerNumber] = inValue;
+ return true;
+ }
+ return false;
+ }
+ virtual bool SetSysex(void *inSysexMsg) { return false; }
+
+ virtual float GetPitchBend() const { return mFPitchBend * mFPitchBendDepth; }
+
+ SInt16 GetHiResControl(UInt32 inIndex) const
+ {
+ return ((mControls[inIndex] & 127) << 7) | (mControls[inIndex + 32] & 127);
+ }
+
+ float GetControl(UInt32 inIndex) const
+ {
+ if (inIndex < 32) {
+ return (float)(mControls[inIndex] + (mControls[inIndex + 32] / 127.));
+ } else {
+ return (float)mControls[inIndex];
+ }
+ }
+
+
+private:
+
+ UInt8 mControls[128];
+ UInt8 mPolyPressure[128];
+ UInt8 mMonoPressure;
+ UInt8 mProgramChange;
+ UInt16 mPitchBend;
+ UInt16 mActiveRPN;
+ UInt16 mActiveNRPN;
+ UInt16 mActiveRPValue;
+ UInt16 mActiveNRPValue;
+
+ UInt16 mPitchBendDepth;
+ float mFPitchBendDepth;
+ float mFPitchBend;
+
+ void SetHiResControl(UInt32 inIndex, UInt8 inMSB, UInt8 inLSB)
+ {
+ mControls[inIndex] = inMSB;
+ mControls[inIndex + 32] = inLSB;
+ }
+
+};
+
+
+class SynthGroupElement : public SynthElement
+{
+public:
+ enum {
+ kUnassignedGroup = 0xFFFFFFFF
+ };
+
+ SynthGroupElement(AUInstrumentBase *audioUnit, UInt32 inElement, MIDIControlHandler *inHandler);
+ virtual ~SynthGroupElement();
+
+ virtual void NoteOn(SynthNote *note, SynthPartElement *part, NoteInstanceID inNoteID, UInt32 inOffsetSampleFrame, const MusicDeviceNoteParams &inParams);
+ virtual void NoteOff(NoteInstanceID inNoteID, UInt32 inOffsetSampleFrame);
+ void SustainOn(UInt32 inFrame);
+ void SustainOff(UInt32 inFrame);
+ void SostenutoOn(UInt32 inFrame);
+ void SostenutoOff(UInt32 inFrame);
+
+ void NoteEnded(SynthNote *inNote, UInt32 inFrame);
+ void NoteFastReleased(SynthNote *inNote);
+
+ virtual bool ChannelMessage(UInt16 controlID, UInt16 controlValue);
+ virtual void AllNotesOff(UInt32 inFrame);
+ virtual void AllSoundOff(UInt32 inFrame);
+ void ResetAllControllers(UInt32 inFrame);
+
+ SynthNote * GetNote(NoteInstanceID inNoteID, bool unreleasedOnly=false, UInt32 *outNoteState=NULL);
+
+ void Reset();
+
+ virtual OSStatus Render(SInt64 inAbsoluteSampleFrame, UInt32 inNumberFrames, AUScope &outputs);
+
+ float GetPitchBend() const { return mMidiControlHandler->GetPitchBend(); }
+ SInt64 GetCurrentAbsoluteFrame() const { return mCurrentAbsoluteFrame; }
+
+ MusicDeviceGroupID GroupID () const { return mGroupID; }
+ virtual void SetGroupID (MusicDeviceGroupID inGroup);
+
+ MIDIControlHandler * GetMIDIControlHandler() const { return mMidiControlHandler; }
+
+protected:
+ SInt64 mCurrentAbsoluteFrame;
+ SynthNoteList mNoteList[kNumberOfSoundingNoteStates];
+ MIDIControlHandler *mMidiControlHandler;
+
+private:
+ friend class AUInstrumentBase;
+ friend class AUMonotimbralInstrumentBase;
+ friend class AUMultitimbralInstrumentBase;
+
+ bool mSustainIsOn;
+ bool mSostenutoIsOn;
+ UInt32 mOutputBus;
+ MusicDeviceGroupID mGroupID;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct SynthKeyZone
+{
+ UInt8 mLoNote;
+ UInt8 mHiNote;
+ UInt8 mLoVelocity;
+ UInt8 mHiVelocity;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const UInt32 kUnlimitedPolyphony = 0xFFFFFFFF;
+
+class SynthPartElement : public SynthElement
+{
+public:
+ SynthPartElement(AUInstrumentBase *audioUnit, UInt32 inElement);
+
+ UInt32 GetGroupIndex() const { return mGroupIndex; }
+ bool InRange(Float32 inNote, Float32 inVelocity);
+
+ UInt32 GetMaxPolyphony() const { return mMaxPolyphony; }
+ void SetMaxPolyphony(UInt32 inMaxPolyphony) { mMaxPolyphony = inMaxPolyphony; }
+
+private:
+ UInt32 mGroupIndex;
+ UInt32 mPatchIndex;
+ UInt32 mMaxPolyphony;
+ SynthKeyZone mKeyZone;
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h
new file mode 100644
index 0000000000..9c27aee04f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h
@@ -0,0 +1,145 @@
+/*
+ File: SynthEvent.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+/* You can either fill in code here or remove this and create or add new files. */
+
+#ifndef __SynthEvent__
+#define __SynthEvent__
+
+#include <AudioUnit/AudioUnit.h>
+#include <CoreAudio/CoreAudio.h>
+#include "MusicDeviceBase.h"
+#include <stdexcept>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+class SynthEvent
+{
+public:
+ enum {
+ kEventType_NoteOn = 1,
+ kEventType_NoteOff = 2,
+ kEventType_SustainOn = 3,
+ kEventType_SustainOff = 4,
+ kEventType_SostenutoOn = 5,
+ kEventType_SostenutoOff = 6,
+ kEventType_AllNotesOff = 7,
+ kEventType_AllSoundOff = 8,
+ kEventType_ResetAllControllers = 9
+ };
+
+
+ SynthEvent() {}
+ ~SynthEvent() {}
+
+ void Set(
+ UInt32 inEventType,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams* inNoteParams
+ )
+ {
+ mEventType = inEventType;
+ mGroupID = inGroupID;
+ mNoteID = inNoteID;
+ mOffsetSampleFrame = inOffsetSampleFrame;
+
+ if (inNoteParams)
+ {
+ UInt32 paramSize = offsetof(MusicDeviceNoteParams, mControls) + (inNoteParams->argCount-2)*sizeof(NoteParamsControlValue);
+ mNoteParams = inNoteParams->argCount > 3
+ ? (MusicDeviceNoteParams*)malloc(paramSize)
+ : &mSmallNoteParams;
+ memcpy(mNoteParams, inNoteParams, paramSize);
+ }
+ else
+ mNoteParams = NULL;
+ }
+
+
+ void Free()
+ {
+ if (mNoteParams)
+ {
+ if (mNoteParams->argCount > 3)
+ free(mNoteParams);
+ mNoteParams = NULL;
+ }
+ }
+
+ UInt32 GetEventType() const { return mEventType; }
+ MusicDeviceGroupID GetGroupID() const { return mGroupID; }
+ NoteInstanceID GetNoteID() const { return mNoteID; }
+ UInt32 GetOffsetSampleFrame() const { return mOffsetSampleFrame; }
+
+ MusicDeviceNoteParams* GetParams() const { return mNoteParams; }
+
+ UInt32 GetArgCount() const { return mNoteParams->argCount; }
+ UInt32 NumberParameters() const { return mNoteParams->argCount - 2; }
+
+ Float32 GetNote() const { return mNoteParams->mPitch; }
+ Float32 GetVelocity() const { return mNoteParams->mVelocity; }
+
+ NoteParamsControlValue GetParameter(UInt32 inIndex) const
+ {
+ if (inIndex >= NumberParameters())
+ throw std::runtime_error("index out of range");
+ return mNoteParams->mControls[inIndex];
+ }
+
+private:
+ UInt32 mEventType;
+ MusicDeviceGroupID mGroupID;
+ NoteInstanceID mNoteID;
+ UInt32 mOffsetSampleFrame;
+ MusicDeviceNoteParams* mNoteParams;
+ MusicDeviceNoteParams mSmallNoteParams; // inline a small one to eliminate malloc for the simple case.
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp
new file mode 100644
index 0000000000..96a24d33c2
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp
@@ -0,0 +1,140 @@
+/*
+ File: SynthNote.cpp
+ Abstract: SynthNote.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "SynthNote.h"
+#include "SynthElement.h"
+#include "AUInstrumentBase.h"
+
+bool SynthNote::AttackNote(
+ SynthPartElement * inPart,
+ SynthGroupElement * inGroup,
+ NoteInstanceID inNoteID,
+ UInt64 inAbsoluteSampleFrame,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams)
+{
+#if DEBUG_PRINT
+ printf("SynthNote::AttackNote %lu %lu abs frame %llu rel frame %lu\n", (UInt32)inGroup->GroupID(), (UInt32)inNoteID, inAbsoluteSampleFrame, inOffsetSampleFrame);
+#endif
+ mPart = inPart;
+ mGroup = inGroup;
+ mNoteID = inNoteID;
+
+ mAbsoluteStartFrame = inAbsoluteSampleFrame;
+ mRelativeStartFrame = inOffsetSampleFrame;
+ mRelativeReleaseFrame = -1;
+ mRelativeKillFrame = -1;
+
+ mPitch = inParams.mPitch;
+ mVelocity = inParams.mVelocity;
+
+
+ return Attack(inParams);
+}
+
+
+void SynthNote::Reset()
+{
+ mPart = 0;
+ mGroup = 0;
+ mAbsoluteStartFrame = 0;
+ mRelativeStartFrame = 0;
+ mRelativeReleaseFrame = 0;
+ mRelativeKillFrame = 0;
+}
+
+void SynthNote::Kill(UInt32 inFrame)
+{
+ mRelativeKillFrame = inFrame;
+}
+
+void SynthNote::Release(UInt32 inFrame)
+{
+ mRelativeReleaseFrame = inFrame;
+}
+
+void SynthNote::FastRelease(UInt32 inFrame)
+{
+ mRelativeReleaseFrame = inFrame;
+}
+
+double SynthNote::TuningA() const
+{
+ return 440.0;
+}
+
+double SynthNote::Frequency()
+{
+ return TuningA() * pow(2., (mPitch - 69. + GetPitchBend()) / 12.);
+}
+
+double SynthNote::SampleRate()
+{
+ return GetAudioUnit()->GetOutput(0)->GetStreamFormat().mSampleRate;
+}
+
+AUInstrumentBase* SynthNote::GetAudioUnit() const
+{
+ return (AUInstrumentBase*)mGroup->GetAudioUnit();
+}
+
+Float32 SynthNote::GetGlobalParameter(AudioUnitParameterID inParamID) const
+{
+ return mGroup->GetAudioUnit()->Globals()->GetParameter(inParamID);
+}
+
+void SynthNote::NoteEnded(UInt32 inFrame)
+{
+ mGroup->NoteEnded(this, inFrame);
+ mNoteID = 0xFFFFFFFF;
+}
+
+float SynthNote::GetPitchBend() const
+{
+ return mGroup->GetPitchBend();
+}
+
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h
new file mode 100644
index 0000000000..cec6377217
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h
@@ -0,0 +1,187 @@
+/*
+ File: SynthNote.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __SynthNote__
+#define __SynthNote__
+
+#include <AudioUnit/AudioUnit.h>
+#include <CoreAudio/CoreAudio.h>
+#include "MusicDeviceBase.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+enum SynthNoteState {
+ kNoteState_Attacked = 0,
+ kNoteState_Sostenutoed = 1,
+ kNoteState_ReleasedButSostenutoed = 2,
+ kNoteState_ReleasedButSustained = 3,
+ kNoteState_Released = 4,
+ kNoteState_FastReleased = 5,
+ kNoteState_Free = 6,
+ kNumberOfActiveNoteStates = 5,
+ kNumberOfSoundingNoteStates = 6,
+ kNumberOfNoteStates = 7,
+ kNoteState_Unset = kNumberOfNoteStates
+};
+
+/*
+ This table describes the state transitions for SynthNotes
+
+ EVENT CURRENT STATE NEW STATE
+ note on free attacked
+ note off attacked (and sustain on) released but sustained
+ note off attacked released
+ note off sostenutoed released but sostenutoed
+ sustain on -- no changes --
+ sustain off released but sustained released
+ sostenuto on attacked sostenutoed
+ sostenuto off sostenutoed attacked
+ sostenuto off released but sostenutoed (and sustain on) released but sustained
+ sostenuto off released but sostenutoed released
+ end of note any state free
+ soft voice stealing any state fast released
+ hard voice stealing any state free
+
+ soft voice stealing happens when there is a note on event and NumActiveNotes > MaxActiveNotes
+ hard voice stealing happens when there is a note on event and NumActiveNotes == NumNotes (no free notes)
+ voice stealing removes the quietest note in the highest numbered state that has sounding notes.
+*/
+
+class SynthGroupElement;
+class SynthPartElement;
+class AUInstrumentBase;
+
+struct SynthNote
+{
+ SynthNote() :
+ mPrev(0), mNext(0), mPart(0), mGroup(0),
+ mNoteID(0xffffffff),
+ mState(kNoteState_Unset),
+ mAbsoluteStartFrame(0),
+ mRelativeStartFrame(0),
+ mRelativeReleaseFrame(-1),
+ mRelativeKillFrame(-1),
+ mPitch(0.0f),
+ mVelocity(0.0f)
+ {
+ }
+
+ virtual ~SynthNote() {}
+
+ virtual void Reset();
+ //! Returns true if active note resulted from this call, otherwise false
+ virtual bool AttackNote(
+ SynthPartElement * inPart,
+ SynthGroupElement * inGroup,
+ NoteInstanceID inNoteID,
+ UInt64 inAbsoluteSampleFrame,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams
+ );
+
+ virtual OSStatus Render(UInt64 inAbsoluteSampleFrame, UInt32 inNumFrames, AudioBufferList** inBufferList, UInt32 inOutBusCount) = 0;
+ //! Returns true if active note resulted from this call, otherwise false
+ virtual bool Attack(const MusicDeviceNoteParams &inParams) = 0;
+ virtual void Kill(UInt32 inFrame); // voice is being stolen.
+ virtual void Release(UInt32 inFrame);
+ virtual void FastRelease(UInt32 inFrame);
+ virtual Float32 Amplitude() = 0; // used for finding quietest note for voice stealing.
+
+ virtual void NoteEnded(UInt32 inFrame);
+
+ SynthGroupElement* GetGroup() const { return mGroup; }
+ SynthPartElement* GetPart() const { return mPart; }
+
+ AUInstrumentBase* GetAudioUnit() const;
+
+ Float32 GetGlobalParameter(AudioUnitParameterID inParamID) const;
+
+ NoteInstanceID GetNoteID() const { return mNoteID; }
+ SynthNoteState GetState() const { return mState; }
+ UInt8 GetMidiKey() const { return (UInt8) mPitch; }
+ UInt8 GetMidiVelocity() const { return (UInt8) mVelocity; }
+
+ Boolean IsSounding() const { return mState < kNumberOfSoundingNoteStates; }
+ Boolean IsActive() const { return mState < kNumberOfActiveNoteStates; }
+ UInt64 GetAbsoluteStartFrame() const { return mAbsoluteStartFrame; }
+ SInt32 GetRelativeStartFrame() const { return mRelativeStartFrame; }
+ SInt32 GetRelativeReleaseFrame() const { return mRelativeReleaseFrame; }
+ SInt32 GetRelativeKillFrame() const { return mRelativeKillFrame; }
+
+ void ListRemove() { mPrev = mNext = 0; } // only use when lists will be reset.
+
+ float GetPitchBend() const;
+ double TuningA() const;
+
+ Float32 GetPitch() const { return mPitch; } // returns raw pitch from MusicDeviceNoteParams
+ virtual double Frequency(); // returns the frequency of note + pitch bend.
+ virtual double SampleRate();
+
+ // linked list pointers
+ SynthNote *mPrev;
+ SynthNote *mNext;
+
+ friend class SynthGroupElement;
+ friend struct SynthNoteList;
+protected:
+ void SetState(SynthNoteState inState) { mState = inState; }
+private:
+ SynthPartElement* mPart;
+ SynthGroupElement* mGroup;
+
+ NoteInstanceID mNoteID;
+ SynthNoteState mState;
+ UInt64 mAbsoluteStartFrame;
+ SInt32 mRelativeStartFrame;
+ SInt32 mRelativeReleaseFrame;
+ SInt32 mRelativeKillFrame;
+
+ Float32 mPitch;
+ Float32 mVelocity;
+};
+
+#endif
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp
new file mode 100644
index 0000000000..849abd266b
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp
@@ -0,0 +1,93 @@
+/*
+ File: SynthNoteList.cpp
+ Abstract: SynthNoteList.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "SynthNoteList.h"
+#include <stdexcept>
+
+void SynthNoteList::SanityCheck() const
+{
+ if (mState >= kNoteState_Unset) {
+ throw std::runtime_error("SanityCheck: mState is bad");
+ }
+
+ if (mHead == NULL) {
+ if (mTail != NULL)
+ throw std::runtime_error("SanityCheck: mHead is NULL but not mTail");
+ return;
+ }
+ if (mTail == NULL) {
+ throw std::runtime_error("SanityCheck: mTail is NULL but not mHead");
+ }
+
+ if (mHead->mPrev) {
+ throw std::runtime_error("SanityCheck: mHead has a mPrev");
+ }
+ if (mTail->mNext) {
+ throw std::runtime_error("SanityCheck: mTail has a mNext");
+ }
+
+ SynthNote *note = mHead;
+ while (note)
+ {
+ if (note->mState != mState)
+ throw std::runtime_error("SanityCheck: note in wrong state");
+ if (note->mNext) {
+ if (note->mNext->mPrev != note)
+ throw std::runtime_error("SanityCheck: bad link 1");
+ } else {
+ if (mTail != note)
+ throw std::runtime_error("SanityCheck: note->mNext is nil, but mTail != note");
+ }
+ if (note->mPrev) {
+ if (note->mPrev->mNext != note)
+ throw std::runtime_error("SanityCheck: bad link 2");
+ } else {
+ if (mHead != note)
+ throw std::runtime_error("SanityCheck: note->mPrev is nil, but mHead != note");
+ }
+ note = note->mNext;
+ }
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h
new file mode 100644
index 0000000000..47a3593018
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h
@@ -0,0 +1,232 @@
+/*
+ File: SynthNoteList.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __SynthNoteList__
+#define __SynthNoteList__
+
+#include "SynthNote.h"
+
+#if DEBUG
+#ifndef DEBUG_PRINT
+ #define DEBUG_PRINT 0
+#endif
+ #define USE_SANITY_CHECK 0
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+struct SynthNoteList
+{
+ SynthNoteList() : mState(kNoteState_Unset), mHead(0), mTail(0) {}
+
+ bool NotEmpty() const { return mHead != NULL; }
+ bool IsEmpty() const { return mHead == NULL; }
+ void Empty() {
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ mHead = mTail = NULL;
+ }
+
+ UInt32 Length() const {
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ UInt32 length = 0;
+ for (SynthNote* note = mHead; note; note = note->mNext)
+ length++;
+ return length;
+ };
+
+ void AddNote(SynthNote *inNote)
+ {
+#if DEBUG_PRINT
+ printf("AddNote(inNote=%p) to state: %lu\n", inNote, mState);
+#endif
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ inNote->SetState(mState);
+ inNote->mNext = mHead;
+ inNote->mPrev = NULL;
+
+ if (mHead) { mHead->mPrev = inNote; mHead = inNote; }
+ else mHead = mTail = inNote;
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ }
+
+ void RemoveNote(SynthNote *inNote)
+ {
+#if DEBUG_PRINT
+ printf("RemoveNote(inNote=%p) from state: %lu\n", inNote, mState);
+#endif
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ if (inNote->mPrev) inNote->mPrev->mNext = inNote->mNext;
+ else mHead = inNote->mNext;
+
+ if (inNote->mNext) inNote->mNext->mPrev = inNote->mPrev;
+ else mTail = inNote->mPrev;
+
+ inNote->mPrev = 0;
+ inNote->mNext = 0;
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ }
+
+ void TransferAllFrom(SynthNoteList *inNoteList, UInt32 inFrame)
+ {
+#if DEBUG_PRINT
+ printf("TransferAllFrom: from state %lu into state %lu\n", inNoteList->mState, mState);
+#endif
+#if USE_SANITY_CHECK
+ SanityCheck();
+ inNoteList->SanityCheck();
+#endif
+ if (!inNoteList->mTail) return;
+
+ if (mState == kNoteState_Released)
+ {
+ for (SynthNote* note = inNoteList->mHead; note; note = note->mNext)
+ {
+#if DEBUG_PRINT
+ printf("TransferAllFrom: releasing note %p\n", note);
+#endif
+ note->Release(inFrame);
+ note->SetState(mState);
+ }
+ }
+ else
+ {
+ for (SynthNote* note = inNoteList->mHead; note; note = note->mNext)
+ {
+ note->SetState(mState);
+ }
+ }
+
+ inNoteList->mTail->mNext = mHead;
+
+ if (mHead) mHead->mPrev = inNoteList->mTail;
+ else mTail = inNoteList->mTail;
+
+ mHead = inNoteList->mHead;
+
+ inNoteList->mHead = NULL;
+ inNoteList->mTail = NULL;
+#if USE_SANITY_CHECK
+ SanityCheck();
+ inNoteList->SanityCheck();
+#endif
+ }
+
+ SynthNote* FindOldestNote()
+ {
+#if DEBUG_PRINT
+ printf("FindOldestNote\n");
+#endif
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ UInt64 minStartFrame = -1;
+ SynthNote* oldestNote = NULL;
+ for (SynthNote* note = mHead; note; note = note->mNext)
+ {
+ if (note->mAbsoluteStartFrame < minStartFrame)
+ {
+ oldestNote = note;
+ minStartFrame = note->mAbsoluteStartFrame;
+ }
+ }
+ return oldestNote;
+ }
+
+ SynthNote* FindMostQuietNote()
+ {
+#if DEBUG_PRINT
+ printf("FindMostQuietNote\n");
+#endif
+ Float32 minAmplitude = 1e9f;
+ UInt64 minStartFrame = -1;
+ SynthNote* mostQuietNote = NULL;
+ for (SynthNote* note = mHead; note; note = note->mNext)
+ {
+ Float32 amp = note->Amplitude();
+#if DEBUG_PRINT
+ printf(" amp %g minAmplitude %g\n", amp, minAmplitude);
+#endif
+ if (amp < minAmplitude)
+ {
+ mostQuietNote = note;
+ minAmplitude = amp;
+ minStartFrame = note->mAbsoluteStartFrame;
+ }
+ else if (amp == minAmplitude && note->mAbsoluteStartFrame < minStartFrame)
+ {
+ // use earliest start time as a tie breaker
+ mostQuietNote = note;
+ minStartFrame = note->mAbsoluteStartFrame;
+ }
+ }
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ return mostQuietNote;
+ }
+
+ void SanityCheck() const;
+
+ SynthNoteState mState;
+ SynthNote * mHead;
+ SynthNote * mTail;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h
new file mode 100644
index 0000000000..741be00fe0
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h
@@ -0,0 +1,88 @@
+/*
+ File: AUViewLocalizedStringKeys.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUViewLocalizedStringKeys_h__
+#define __AUViewLocalizedStringKeys_h__
+
+// ACCESS POINT:
+#define kLocalizedStringBundle_AUView CFSTR("com.apple.audio.units.Components")
+#define kLocalizedStringTable_AUView CFSTR("CustomUI")
+
+// UNLOCALIZED STRINGS:
+ #define kAUViewUnlocalizedString_TitleSeparator CFSTR(": ")
+
+// Generic View:
+ #define kAUViewLocalizedStringKey_AudioUnit CFSTR("Audio Unit")
+ #define kAUViewLocalizedStringKey_Manufacturer CFSTR("Manufacturer")
+
+ #define kAUViewLocalizedStringKey_FactoryPreset CFSTR("Factory Preset")
+
+ #define kAUViewLocalizedStringKey_Properties CFSTR("Properties")
+ #define kAUViewLocalizedStringKey_Parameters CFSTR("Parameters")
+
+ #define kAUViewLocalizedStringKey_Standard CFSTR("Standard")
+ #define kAUViewLocalizedStringKey_Expert CFSTR("Expert")
+
+// AULoadCPU:
+ #define kAUViewLocalizedStringKey_RestrictCPULoad CFSTR("Restrict CPU Load")
+ #define kAUViewLocalizedStringKey_PercentSymbol CFSTR("%")
+ #define kAUViewLocalizedStringKey_NotApplicable CFSTR("n/a")
+
+// AUDiskStreamingCheckbox:
+ #define kAUViewLocalizedStringKey_StreamFromDisk CFSTR("Stream From Disk")
+
+// AURenderQualityPopup:
+ #define kAUViewLocalizedStringKey_RenderQuality CFSTR("Render Quality")
+ #define kAUViewLocalizedStringKey_Maximum CFSTR("Maximum")
+ #define kAUViewLocalizedStringKey_High CFSTR("High")
+ #define kAUViewLocalizedStringKey_Medium CFSTR("Medium")
+ #define kAUViewLocalizedStringKey_Low CFSTR("Low")
+ #define kAUViewLocalizedStringKey_Minimum CFSTR("Minimum")
+
+// AUChannelLayoutPopUp:
+ #define kAUViewLocalizedStringKey_AudioChannelLayout CFSTR("Audio Channel Layout")
+
+#endif //__AUViewLocalizedStringKeys_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp
new file mode 100644
index 0000000000..010082fc3f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp
@@ -0,0 +1,466 @@
+/*
+ File: AUEffectBase.cpp
+ Abstract: AUEffectBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUEffectBase.h"
+
+/*
+ This class does not deal as well as it should with N-M effects...
+
+ The problem areas are (if the channels don't match):
+ ProcessInPlace if the channels don't match - there will be problems if InputChan != OutputChan
+ Bypass - its just passing the buffers through when not processing them
+
+ This will be fixed in a future update...
+*/
+
+//_____________________________________________________________________________
+//
+AUEffectBase::AUEffectBase( AudioComponentInstance audioUnit,
+ bool inProcessesInPlace ) :
+ AUBase(audioUnit, 1, 1), // 1 in bus, 1 out bus
+ mBypassEffect(false),
+ mParamSRDep (false),
+ mProcessesInPlace(inProcessesInPlace),
+ mMainOutput(NULL), mMainInput(NULL)
+#if TARGET_OS_IPHONE
+ , mOnlyOneKernel(false)
+#endif
+{
+}
+
+//_____________________________________________________________________________
+//
+AUEffectBase::~AUEffectBase()
+{
+ Cleanup();
+}
+
+//_____________________________________________________________________________
+//
+void AUEffectBase::Cleanup()
+{
+ for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end(); ++it)
+ delete *it;
+
+ mKernelList.clear();
+ mMainOutput = NULL;
+ mMainInput = NULL;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUEffectBase::Initialize()
+{
+ // get our current numChannels for input and output
+ SInt16 auNumInputs = (SInt16) GetInput(0)->GetStreamFormat().mChannelsPerFrame;
+ SInt16 auNumOutputs = (SInt16) GetOutput(0)->GetStreamFormat().mChannelsPerFrame;
+
+ // does the unit publish specific information about channel configurations?
+ const AUChannelInfo *auChannelConfigs = NULL;
+ UInt32 numIOconfigs = SupportedNumChannels(&auChannelConfigs);
+
+ if ((numIOconfigs > 0) && (auChannelConfigs != NULL))
+ {
+ bool foundMatch = false;
+ for (UInt32 i = 0; (i < numIOconfigs) && !foundMatch; ++i)
+ {
+ SInt16 configNumInputs = auChannelConfigs[i].inChannels;
+ SInt16 configNumOutputs = auChannelConfigs[i].outChannels;
+ if ((configNumInputs < 0) && (configNumOutputs < 0))
+ {
+ // unit accepts any number of channels on input and output
+ if (((configNumInputs == -1) && (configNumOutputs == -2))
+ || ((configNumInputs == -2) && (configNumOutputs == -1)))
+ {
+ foundMatch = true;
+ // unit accepts any number of channels on input and output IFF they are the same number on both scopes
+ }
+ else if (((configNumInputs == -1) && (configNumOutputs == -1)) && (auNumInputs == auNumOutputs))
+ {
+ foundMatch = true;
+ // unit has specified a particular number of channels on both scopes
+ }
+ else
+ continue;
+ }
+ else
+ {
+ // the -1 case on either scope is saying that the unit doesn't care about the
+ // number of channels on that scope
+ bool inputMatch = (auNumInputs == configNumInputs) || (configNumInputs == -1);
+ bool outputMatch = (auNumOutputs == configNumOutputs) || (configNumOutputs == -1);
+ if (inputMatch && outputMatch)
+ foundMatch = true;
+ }
+ }
+ if (!foundMatch)
+ return kAudioUnitErr_FormatNotSupported;
+ }
+ else
+ {
+ // there is no specifically published channel info
+ // so for those kinds of effects, the assumption is that the channels (whatever their number)
+ // should match on both scopes
+ if ((auNumOutputs != auNumInputs) || (auNumOutputs == 0))
+ {
+ return kAudioUnitErr_FormatNotSupported;
+ }
+ }
+
+ MaintainKernels();
+
+ mMainOutput = GetOutput(0);
+ mMainInput = GetInput(0);
+
+ const CAStreamBasicDescription& format = GetStreamFormat(kAudioUnitScope_Output, 0);
+ format.IdentifyCommonPCMFormat(mCommonPCMFormat, NULL);
+ mBytesPerFrame = format.mBytesPerFrame;
+
+ return noErr;
+}
+
+OSStatus AUEffectBase::Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end(); ++it) {
+ AUKernelBase *kernel = *it;
+ if (kernel != NULL)
+ kernel->Reset();
+ }
+
+ return AUBase::Reset(inScope, inElement);
+}
+
+OSStatus AUEffectBase::GetPropertyInfo (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ if (inScope == kAudioUnitScope_Global) {
+ switch (inID) {
+ case kAudioUnitProperty_BypassEffect:
+ outWritable = true;
+ outDataSize = sizeof (UInt32);
+ return noErr;
+ case kAudioUnitProperty_InPlaceProcessing:
+ outWritable = true;
+ outDataSize = sizeof (UInt32);
+ return noErr;
+ }
+ }
+ return AUBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+}
+
+
+OSStatus AUEffectBase::GetProperty (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ if (inScope == kAudioUnitScope_Global) {
+ switch (inID) {
+ case kAudioUnitProperty_BypassEffect:
+ *((UInt32*)outData) = (IsBypassEffect() ? 1 : 0);
+ return noErr;
+ case kAudioUnitProperty_InPlaceProcessing:
+ *((UInt32*)outData) = (mProcessesInPlace ? 1 : 0);
+ return noErr;
+ }
+ }
+ return AUBase::GetProperty (inID, inScope, inElement, outData);
+}
+
+
+OSStatus AUEffectBase::SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ if (inScope == kAudioUnitScope_Global) {
+ switch (inID) {
+ case kAudioUnitProperty_BypassEffect:
+ {
+ if (inDataSize < sizeof(UInt32))
+ return kAudioUnitErr_InvalidPropertyValue;
+
+ bool tempNewSetting = *((UInt32*)inData) != 0;
+ // we're changing the state of bypass
+ if (tempNewSetting != IsBypassEffect())
+ {
+ if (!tempNewSetting && IsBypassEffect() && IsInitialized()) // turning bypass off and we're initialized
+ Reset(0, 0);
+ SetBypassEffect (tempNewSetting);
+ }
+ return noErr;
+ }
+ case kAudioUnitProperty_InPlaceProcessing:
+ mProcessesInPlace = (*((UInt32*)inData) != 0);
+ return noErr;
+ }
+ }
+ return AUBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
+}
+
+
+void AUEffectBase::MaintainKernels()
+{
+#if TARGET_OS_IPHONE
+ UInt32 nKernels = mOnlyOneKernel ? 1 : GetNumberOfChannels();
+#else
+ UInt32 nKernels = GetNumberOfChannels();
+#endif
+
+ if (mKernelList.size() < nKernels) {
+ mKernelList.reserve(nKernels);
+ for (UInt32 i = (UInt32)mKernelList.size(); i < nKernels; ++i)
+ mKernelList.push_back(NewKernel());
+ } else {
+ while (mKernelList.size() > nKernels) {
+ AUKernelBase *kernel = mKernelList.back();
+ delete kernel;
+ mKernelList.pop_back();
+ }
+ }
+
+ for(unsigned int i = 0; i < nKernels; i++ )
+ {
+ if(mKernelList[i]) {
+ mKernelList[i]->SetChannelNum (i);
+ }
+ }
+}
+
+bool AUEffectBase::StreamFormatWritable( AudioUnitScope scope,
+ AudioUnitElement element)
+{
+ return IsInitialized() ? false : true;
+}
+
+OSStatus AUEffectBase::ChangeStreamFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inPrevFormat,
+ const CAStreamBasicDescription & inNewFormat)
+{
+ OSStatus result = AUBase::ChangeStreamFormat(inScope, inElement, inPrevFormat, inNewFormat);
+ if (result == noErr)
+ {
+ // for the moment this only dependency we know about
+ // where a parameter's range may change is with the sample rate
+ // and effects are only publishing parameters in the global scope!
+ if (GetParamHasSampleRateDependency() && fnotequal(inPrevFormat.mSampleRate, inNewFormat.mSampleRate))
+ PropertyChanged(kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0);
+ }
+
+ return result;
+}
+
+
+// ____________________________________________________________________________
+//
+// This method is called (potentially repeatedly) by ProcessForScheduledParams()
+// in order to perform the actual DSP required for this portion of the entire buffer
+// being processed. The entire buffer can be divided up into smaller "slices"
+// according to the timestamps on the scheduled parameters...
+//
+OSStatus AUEffectBase::ProcessScheduledSlice( void *inUserData,
+ UInt32 inStartFrameInBuffer,
+ UInt32 inSliceFramesToProcess,
+ UInt32 inTotalBufferFrames )
+{
+ ScheduledProcessParams &sliceParams = *((ScheduledProcessParams*)inUserData);
+
+ AudioUnitRenderActionFlags &actionFlags = *sliceParams.actionFlags;
+ AudioBufferList &inputBufferList = *sliceParams.inputBufferList;
+ AudioBufferList &outputBufferList = *sliceParams.outputBufferList;
+
+ UInt32 channelSize = inSliceFramesToProcess * mBytesPerFrame;
+ // fix the size of the buffer we're operating on before we render this slice of time
+ for(unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
+ inputBufferList.mBuffers[i].mDataByteSize = inputBufferList.mBuffers[i].mNumberChannels * channelSize;
+ }
+
+ for(unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
+ outputBufferList.mBuffers[i].mDataByteSize = outputBufferList.mBuffers[i].mNumberChannels * channelSize;
+ }
+ // process the buffer
+ OSStatus result = ProcessBufferLists(actionFlags, inputBufferList, outputBufferList, inSliceFramesToProcess );
+
+ // we just partially processed the buffers, so increment the data pointers to the next part of the buffer to process
+ for(unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
+ inputBufferList.mBuffers[i].mData =
+ (char *)inputBufferList.mBuffers[i].mData + inputBufferList.mBuffers[i].mNumberChannels * channelSize;
+ }
+
+ for(unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
+ outputBufferList.mBuffers[i].mData =
+ (char *)outputBufferList.mBuffers[i].mData + outputBufferList.mBuffers[i].mNumberChannels * channelSize;
+ }
+
+ return result;
+}
+
+// ____________________________________________________________________________
+//
+
+OSStatus AUEffectBase::Render( AudioUnitRenderActionFlags &ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 nFrames)
+{
+ if (!HasInput(0))
+ return kAudioUnitErr_NoConnection;
+
+ OSStatus result = noErr;
+
+ result = mMainInput->PullInput(ioActionFlags, inTimeStamp, 0 /* element */, nFrames);
+
+ if (result == noErr)
+ {
+ if(ProcessesInPlace() && mMainOutput->WillAllocateBuffer())
+ {
+ mMainOutput->SetBufferList(mMainInput->GetBufferList() );
+ }
+
+ if (ShouldBypassEffect())
+ {
+ // leave silence bit alone
+
+ if(!ProcessesInPlace() )
+ {
+ mMainInput->CopyBufferContentsTo (mMainOutput->GetBufferList());
+ }
+ }
+ else
+ {
+ if(mParamList.size() == 0 )
+ {
+ // this will read/write silence bit
+ result = ProcessBufferLists(ioActionFlags, mMainInput->GetBufferList(), mMainOutput->GetBufferList(), nFrames);
+ }
+ else
+ {
+ // deal with scheduled parameters...
+
+ AudioBufferList &inputBufferList = mMainInput->GetBufferList();
+ AudioBufferList &outputBufferList = mMainOutput->GetBufferList();
+
+ ScheduledProcessParams processParams;
+ processParams.actionFlags = &ioActionFlags;
+ processParams.inputBufferList = &inputBufferList;
+ processParams.outputBufferList = &outputBufferList;
+
+ // divide up the buffer into slices according to scheduled params then
+ // do the DSP for each slice (ProcessScheduledSlice() called for each slice)
+ result = ProcessForScheduledParams( mParamList,
+ nFrames,
+ &processParams );
+
+
+ // fixup the buffer pointers to how they were before we started
+ UInt32 channelSize = nFrames * mBytesPerFrame;
+ for(unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
+ UInt32 size = inputBufferList.mBuffers[i].mNumberChannels * channelSize;
+ inputBufferList.mBuffers[i].mData = (char *)inputBufferList.mBuffers[i].mData - size;
+ inputBufferList.mBuffers[i].mDataByteSize = size;
+ }
+
+ for(unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
+ UInt32 size = outputBufferList.mBuffers[i].mNumberChannels * channelSize;
+ outputBufferList.mBuffers[i].mData = (char *)outputBufferList.mBuffers[i].mData - size;
+ outputBufferList.mBuffers[i].mDataByteSize = size;
+ }
+ }
+ }
+
+ if ( (ioActionFlags & kAudioUnitRenderAction_OutputIsSilence) && !ProcessesInPlace() )
+ {
+ AUBufferList::ZeroBuffer(mMainOutput->GetBufferList() );
+ }
+ }
+
+ return result;
+}
+
+
+OSStatus AUEffectBase::ProcessBufferLists(
+ AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioBufferList & inBuffer,
+ AudioBufferList & outBuffer,
+ UInt32 inFramesToProcess )
+{
+ if (ShouldBypassEffect())
+ return noErr;
+
+ // interleaved (or mono)
+ switch (mCommonPCMFormat) {
+ case CAStreamBasicDescription::kPCMFormatFloat32 :
+ ProcessBufferListsT<Float32>(ioActionFlags, inBuffer, outBuffer, inFramesToProcess);
+ break;
+ case CAStreamBasicDescription::kPCMFormatFixed824 :
+ ProcessBufferListsT<SInt32>(ioActionFlags, inBuffer, outBuffer, inFramesToProcess);
+ break;
+ case CAStreamBasicDescription::kPCMFormatInt16 :
+ ProcessBufferListsT<SInt16>(ioActionFlags, inBuffer, outBuffer, inFramesToProcess);
+ break;
+ default :
+ throw CAException(kAudio_UnimplementedError);
+ }
+
+ return noErr;
+}
+
+Float64 AUEffectBase::GetSampleRate()
+{
+ return GetOutput(0)->GetStreamFormat().mSampleRate;
+}
+
+UInt32 AUEffectBase::GetNumberOfChannels()
+{
+ return GetOutput(0)->GetStreamFormat().mChannelsPerFrame;
+}
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.h
new file mode 100644
index 0000000000..13ba96b393
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.h
@@ -0,0 +1,377 @@
+/*
+ File: AUEffectBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUEffectBase_h__
+#define __AUEffectBase_h__
+
+#include "AUBase.h"
+#include "AUSilentTimeout.h"
+#include "CAException.h"
+
+class AUKernelBase;
+
+// Base class for an effect with one input stream, one output stream,
+// any number of channels.
+ /*! @class AUEffectBase */
+class AUEffectBase : public AUBase {
+public:
+ /*! @ctor AUEffectBase */
+ AUEffectBase( AudioComponentInstance audioUnit,
+ bool inProcessesInPlace = true );
+ /*! @dtor ~AUEffectBase */
+ ~AUEffectBase();
+
+ /*! @method Initialize */
+ virtual OSStatus Initialize();
+
+ /*! @method Cleanup */
+ virtual void Cleanup();
+
+
+ /*! @method Reset */
+ virtual OSStatus Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ /*! @method GetPropertyInfo */
+ virtual OSStatus GetPropertyInfo (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ /*! @method GetProperty */
+ virtual OSStatus GetProperty (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+
+ /*! @method SetProperty */
+ virtual OSStatus SetProperty(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+
+ /*! @method StreamFormatWritable */
+ virtual bool StreamFormatWritable (AudioUnitScope scope,
+ AudioUnitElement element);
+
+ /*! @method ChangeStreamFormat */
+ virtual OSStatus ChangeStreamFormat (
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inPrevFormat,
+ const CAStreamBasicDescription & inNewFormat);
+
+ /*! @method Render */
+ virtual OSStatus Render(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames);
+
+ // our virtual methods
+
+ // If your unit processes N to N channels, and there are no interactions between channels,
+ // it can override NewKernel to create a mono processing object per channel. Otherwise,
+ // don't override NewKernel, and instead, override ProcessBufferLists.
+ /*! @method NewKernel */
+ virtual AUKernelBase * NewKernel() { return NULL; }
+
+ /*! @method ProcessBufferLists */
+ virtual OSStatus ProcessBufferLists(
+ AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioBufferList & inBuffer,
+ AudioBufferList & outBuffer,
+ UInt32 inFramesToProcess );
+
+ // convenience format accessors (use output 0's format)
+ /*! @method GetSampleRate */
+ Float64 GetSampleRate();
+
+ /*! @method GetNumberOfChannels */
+ UInt32 GetNumberOfChannels();
+
+ // convenience wrappers for accessing parameters in the global scope
+ /*! @method SetParameter */
+ using AUBase::SetParameter;
+ void SetParameter( AudioUnitParameterID paramID,
+ AudioUnitParameterValue value)
+ {
+ Globals()->SetParameter(paramID, value);
+ }
+
+ /*! @method GetParameter */
+ using AUBase::GetParameter;
+ AudioUnitParameterValue GetParameter( AudioUnitParameterID paramID )
+ {
+ return Globals()->GetParameter(paramID );
+ }
+
+ /*! @method CanScheduleParameters */
+ virtual bool CanScheduleParameters() const { return true; }
+
+ /*! @method IsBypassEffect */
+ // This is used for the property value - to reflect to the UI if an effect is bypassed
+ bool IsBypassEffect () { return mBypassEffect; }
+
+protected:
+
+ /*! @method MaintainKernels */
+ void MaintainKernels();
+
+ /*! @method ShouldBypassEffect */
+ // This is used in the render call to see if an effect is bypassed
+ // It can return a different status than IsBypassEffect (though it MUST take that into account)
+ virtual bool ShouldBypassEffect () { return IsBypassEffect(); }
+
+public:
+ /*! @method SetBypassEffect */
+ virtual void SetBypassEffect (bool inFlag) { mBypassEffect = inFlag; }
+
+ /*! @method SetParamHasSampleRateDependency */
+ void SetParamHasSampleRateDependency (bool inFlag)
+ {
+ mParamSRDep = inFlag;
+ }
+
+ /*! @method GetParamHasSampleRateDependency */
+ bool GetParamHasSampleRateDependency () const { return mParamSRDep; }
+
+ struct ScheduledProcessParams // pointer passed in as void* userData param for ProcessScheduledSlice()
+ {
+ AudioUnitRenderActionFlags *actionFlags;
+ AudioBufferList *inputBufferList;
+ AudioBufferList *outputBufferList;
+ };
+
+ virtual OSStatus ProcessScheduledSlice( void *inUserData,
+ UInt32 inStartFrameInBuffer,
+ UInt32 inSliceFramesToProcess,
+ UInt32 inTotalBufferFrames );
+
+
+ bool ProcessesInPlace() const {return mProcessesInPlace;};
+ void SetProcessesInPlace(bool inProcessesInPlace) {mProcessesInPlace = inProcessesInPlace;};
+
+ typedef std::vector<AUKernelBase *> KernelList;
+
+
+
+protected:
+ /*! @var mKernelList */
+ KernelList mKernelList;
+
+ AUKernelBase* GetKernel(UInt32 index) { return mKernelList[index]; }
+
+ /*! @method IsInputSilent */
+ bool IsInputSilent (AudioUnitRenderActionFlags inActionFlags, UInt32 inFramesToProcess)
+ {
+ bool inputSilent = (inActionFlags & kAudioUnitRenderAction_OutputIsSilence) != 0;
+
+ // take latency and tail time into account when propagating the silent bit
+ UInt32 silentTimeoutFrames = UInt32(GetSampleRate() * (GetLatency() + GetTailTime()));
+ mSilentTimeout.Process (inFramesToProcess, silentTimeoutFrames, inputSilent);
+ return inputSilent;
+ }
+
+#if TARGET_OS_IPHONE
+ void SetOnlyOneKernel(bool inUseOnlyOneKernel) { mOnlyOneKernel = inUseOnlyOneKernel; } // set in ctor of subclass that wants it.
+#endif
+
+ template <typename T>
+ void ProcessBufferListsT(
+ AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioBufferList & inBuffer,
+ AudioBufferList & outBuffer,
+ UInt32 inFramesToProcess );
+
+ CAStreamBasicDescription::CommonPCMFormat GetCommonPCMFormat() const { return mCommonPCMFormat; }
+
+
+private:
+ /*! @var mBypassEffect */
+ bool mBypassEffect;
+ /*! @var mParamSRDep */
+ bool mParamSRDep;
+
+ /*! @var mProcessesInplace */
+ bool mProcessesInPlace;
+
+ /*! @var mSilentTimeout */
+ AUSilentTimeout mSilentTimeout;
+
+ /*! @var mMainOutput */
+ AUOutputElement * mMainOutput;
+
+ /*! @var mMainInput */
+ AUInputElement * mMainInput;
+
+#if TARGET_OS_IPHONE
+ /*! @var mOnlyOneKernel */
+ bool mOnlyOneKernel;
+#endif
+
+ /*! @var mCommonPCMFormat */
+ CAStreamBasicDescription::CommonPCMFormat mCommonPCMFormat;
+ UInt32 mBytesPerFrame;
+};
+
+
+// Base class for a "kernel", an object that performs DSP on one channel of an interleaved stream.
+ /*! @class AUKernelBase */
+class AUKernelBase {
+public:
+ /*! @ctor AUKernelBase */
+ AUKernelBase(AUEffectBase *inAudioUnit ) :
+ mAudioUnit(inAudioUnit) { }
+
+ /*! @dtor ~AUKernelBase */
+ virtual ~AUKernelBase() { }
+
+ /*! @method Reset */
+ virtual void Reset() { }
+
+ /*! @method Process */
+ virtual void Process( const Float32 * inSourceP,
+ Float32 * inDestP,
+ UInt32 inFramesToProcess,
+ UInt32 inNumChannels,
+ bool & ioSilence) { throw CAException(kAudio_UnimplementedError ); }
+
+ /*! @method Process */
+ virtual void Process( const SInt32 * inSourceP,
+ SInt32 * inDestP,
+ UInt32 inFramesToProcess,
+ UInt32 inNumChannels,
+ bool & ioSilence) { throw CAException(kAudio_UnimplementedError ); }
+
+ /*! @method Process */
+ virtual void Process( const SInt16 * inSourceP,
+ SInt16 * inDestP,
+ UInt32 inFramesToProcess,
+ UInt32 inNumChannels,
+ bool & ioSilence) { throw CAException(kAudio_UnimplementedError ); }
+
+ /*! @method GetSampleRate */
+ Float64 GetSampleRate()
+ {
+ return mAudioUnit->GetSampleRate();
+ }
+
+ /*! @method GetParameter */
+ AudioUnitParameterValue GetParameter (AudioUnitParameterID paramID)
+ {
+ return mAudioUnit->GetParameter(paramID);
+ }
+
+ void SetChannelNum (UInt32 inChan) { mChannelNum = inChan; }
+ UInt32 GetChannelNum () { return mChannelNum; }
+
+protected:
+ /*! @var mAudioUnit */
+ AUEffectBase * mAudioUnit;
+ UInt32 mChannelNum;
+
+};
+
+template <typename T>
+void AUEffectBase::ProcessBufferListsT(
+ AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioBufferList & inBuffer,
+ AudioBufferList & outBuffer,
+ UInt32 inFramesToProcess )
+{
+ bool ioSilence;
+
+ bool silentInput = IsInputSilent (ioActionFlags, inFramesToProcess);
+ ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
+
+ // call the kernels to handle either interleaved or deinterleaved
+ if (inBuffer.mNumberBuffers == 1) {
+ if (inBuffer.mBuffers[0].mNumberChannels == 0)
+ throw CAException(kAudio_ParamError);
+
+ for (UInt32 channel = 0; channel < mKernelList.size(); ++channel) {
+ AUKernelBase *kernel = mKernelList[channel];
+
+ if (kernel == NULL) continue;
+ ioSilence = silentInput;
+
+ // process each interleaved channel individually
+ kernel->Process(
+ (const T *)inBuffer.mBuffers[0].mData + channel,
+ (T *)outBuffer.mBuffers[0].mData + channel,
+ inFramesToProcess,
+ inBuffer.mBuffers[0].mNumberChannels,
+ ioSilence);
+
+ if (!ioSilence)
+ ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence;
+ }
+ } else {
+ for (UInt32 channel = 0; channel < mKernelList.size(); ++channel) {
+ AUKernelBase *kernel = mKernelList[channel];
+
+ if (kernel == NULL) continue;
+
+ ioSilence = silentInput;
+ const AudioBuffer *srcBuffer = &inBuffer.mBuffers[channel];
+ AudioBuffer *destBuffer = &outBuffer.mBuffers[channel];
+
+ kernel->Process(
+ (const T *)srcBuffer->mData,
+ (T *)destBuffer->mData,
+ inFramesToProcess,
+ 1,
+ ioSilence);
+
+ if (!ioSilence)
+ ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence;
+ }
+ }
+}
+
+
+#endif // __AUEffectBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp
new file mode 100644
index 0000000000..e5e358d685
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp
@@ -0,0 +1,495 @@
+/*
+ File: AUMIDIBase.cpp
+ Abstract: AUMIDIBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUMIDIBase.h"
+#include <CoreMIDI/CoreMIDI.h>
+#include "CAXException.h"
+
+//temporaray location
+enum
+{
+ kMidiMessage_NoteOff = 0x80,
+ kMidiMessage_NoteOn = 0x90,
+ kMidiMessage_PolyPressure = 0xA0,
+ kMidiMessage_ControlChange = 0xB0,
+ kMidiMessage_ProgramChange = 0xC0,
+ kMidiMessage_ChannelPressure = 0xD0,
+ kMidiMessage_PitchWheel = 0xE0,
+
+ kMidiController_AllSoundOff = 120,
+ kMidiController_ResetAllControllers = 121,
+ kMidiController_AllNotesOff = 123
+};
+
+AUMIDIBase::AUMIDIBase(AUBase* inBase)
+ : mAUBaseInstance (*inBase)
+{
+#if CA_AUTO_MIDI_MAP
+ mMapManager = new CAAUMIDIMapManager();
+#endif
+}
+
+AUMIDIBase::~AUMIDIBase()
+{
+#if CA_AUTO_MIDI_MAP
+ if (mMapManager)
+ delete mMapManager;
+#endif
+}
+
+#if TARGET_API_MAC_OSX
+OSStatus AUMIDIBase::DelegateGetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus result = noErr;
+
+ switch (inID) {
+#if !TARGET_OS_IPHONE
+ case kMusicDeviceProperty_MIDIXMLNames:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ if (GetXMLNames(NULL) == noErr) {
+ outDataSize = sizeof(CFURLRef);
+ outWritable = false;
+ } else
+ result = kAudioUnitErr_InvalidProperty;
+ break;
+#endif
+#if CA_AUTO_MIDI_MAP
+ case kAudioUnitProperty_AllParameterMIDIMappings:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ outWritable = true;
+ outDataSize = sizeof (AUParameterMIDIMapping)*mMapManager->NumMaps();
+ result = noErr;
+ break;
+
+ case kAudioUnitProperty_HotMapParameterMIDIMapping:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ outWritable = true;
+ outDataSize = sizeof (AUParameterMIDIMapping);
+ result = noErr;
+ break;
+
+ case kAudioUnitProperty_AddParameterMIDIMapping:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ outWritable = true;
+ outDataSize = sizeof (AUParameterMIDIMapping);
+ result = noErr;
+ break;
+
+ case kAudioUnitProperty_RemoveParameterMIDIMapping:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ outWritable = true;
+ outDataSize = sizeof (AUParameterMIDIMapping);
+ result = noErr;
+ break;
+#endif
+
+ default:
+ result = kAudioUnitErr_InvalidProperty;
+ break;
+ }
+ return result;
+
+#if CA_AUTO_MIDI_MAP || (!TARGET_OS_IPHONE)
+InvalidScope:
+ return kAudioUnitErr_InvalidScope;
+InvalidElement:
+ return kAudioUnitErr_InvalidElement;
+#endif
+}
+
+OSStatus AUMIDIBase::DelegateGetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ OSStatus result;
+
+ switch (inID) {
+#if !TARGET_OS_IPHONE
+ case kMusicDeviceProperty_MIDIXMLNames:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ result = GetXMLNames((CFURLRef *)outData);
+ break;
+#endif
+#if CA_AUTO_MIDI_MAP
+ case kAudioUnitProperty_AllParameterMIDIMappings:{
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ AUParameterMIDIMapping* maps = (static_cast<AUParameterMIDIMapping*>(outData));
+ mMapManager->GetMaps(maps);
+// printf ("GETTING MAPS\n");
+// mMapManager->Print();
+ result = noErr;
+ break;
+ }
+
+ case kAudioUnitProperty_HotMapParameterMIDIMapping:{
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ AUParameterMIDIMapping * map = (static_cast<AUParameterMIDIMapping*>(outData));
+ mMapManager->GetHotParameterMap (*map);
+ result = noErr;
+ break;
+ }
+#endif
+
+ default:
+ result = kAudioUnitErr_InvalidProperty;
+ break;
+ }
+ return result;
+
+#if CA_AUTO_MIDI_MAP || (!TARGET_OS_IPHONE)
+InvalidScope:
+ return kAudioUnitErr_InvalidScope;
+InvalidElement:
+ return kAudioUnitErr_InvalidElement;
+#endif
+}
+
+OSStatus AUMIDIBase::DelegateSetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ OSStatus result;
+
+ switch (inID) {
+#if CA_AUTO_MIDI_MAP
+ case kAudioUnitProperty_AddParameterMIDIMapping:{
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ AUParameterMIDIMapping * maps = (AUParameterMIDIMapping*)inData;
+ mMapManager->SortedInsertToParamaterMaps (maps, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance);
+ mAUBaseInstance.PropertyChanged (kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0);
+ result = noErr;
+ break;
+ }
+
+ case kAudioUnitProperty_RemoveParameterMIDIMapping:{
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ AUParameterMIDIMapping * maps = (AUParameterMIDIMapping*)inData;
+ bool didChange;
+ mMapManager->SortedRemoveFromParameterMaps(maps, (inDataSize / sizeof(AUParameterMIDIMapping)), didChange);
+ if (didChange)
+ mAUBaseInstance.PropertyChanged (kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0);
+ result = noErr;
+ break;
+ }
+
+ case kAudioUnitProperty_HotMapParameterMIDIMapping:{
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ AUParameterMIDIMapping & map = *((AUParameterMIDIMapping*)inData);
+ mMapManager->SetHotMapping (map);
+ result = noErr;
+ break;
+ }
+ case kAudioUnitProperty_AllParameterMIDIMappings:{
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ AUParameterMIDIMapping * mappings = (AUParameterMIDIMapping*)inData;
+ mMapManager->ReplaceAllMaps (mappings, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance);
+ result = noErr;
+ break;
+ }
+#endif
+
+ default:
+ result = kAudioUnitErr_InvalidProperty;
+ break;
+ }
+ return result;
+#if CA_AUTO_MIDI_MAP
+ InvalidScope:
+ return kAudioUnitErr_InvalidScope;
+ InvalidElement:
+ return kAudioUnitErr_InvalidElement;
+#endif
+}
+
+
+
+#endif //TARGET_API_MAC_OSX
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#pragma mark ____MidiDispatch
+
+
+inline const Byte * NextMIDIEvent(const Byte *event, const Byte *end)
+{
+ Byte c = *event;
+ switch (c >> 4) {
+ default: // data byte -- assume in sysex
+ while ((*++event & 0x80) == 0 && event < end)
+ ;
+ break;
+ case 0x8:
+ case 0x9:
+ case 0xA:
+ case 0xB:
+ case 0xE:
+ event += 3;
+ break;
+ case 0xC:
+ case 0xD:
+ event += 2;
+ break;
+ case 0xF:
+ switch (c) {
+ case 0xF0:
+ while ((*++event & 0x80) == 0 && event < end)
+ ;
+ break;
+ case 0xF1:
+ case 0xF3:
+ event += 2;
+ break;
+ case 0xF2:
+ event += 3;
+ break;
+ default:
+ ++event;
+ break;
+ }
+ }
+ return (event >= end) ? end : event;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUMIDIBase::HandleMIDIPacketList
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+OSStatus AUMIDIBase::HandleMIDIPacketList(const MIDIPacketList *pktlist)
+{
+ if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
+
+ int nPackets = pktlist->numPackets;
+ const MIDIPacket *pkt = pktlist->packet;
+
+ while (nPackets-- > 0) {
+ const Byte *event = pkt->data, *packetEnd = event + pkt->length;
+ long startFrame = (long)pkt->timeStamp;
+ while (event < packetEnd) {
+ Byte status = event[0];
+ if (status & 0x80) {
+ // really a status byte (not sysex continuation)
+ HandleMidiEvent(status & 0xF0, status & 0x0F, event[1], event[2], static_cast<UInt32>(startFrame));
+ // note that we're generating a bogus channel number for system messages (0xF0-FF)
+ }
+ event = NextMIDIEvent(event, packetEnd);
+ }
+ pkt = reinterpret_cast<const MIDIPacket *>(packetEnd);
+ }
+ return noErr;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUMIDIBase::HandleMidiEvent
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+OSStatus AUMIDIBase::HandleMidiEvent(UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
+{
+ if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
+
+#if CA_AUTO_MIDI_MAP
+// you potentially have a choice to make here - if a param mapping matches, do you still want to process the
+// MIDI event or not. The default behaviour is to continue on with the MIDI event.
+ if (mMapManager->HandleHotMapping (status, channel, data1, mAUBaseInstance)) {
+ mAUBaseInstance.PropertyChanged (kAudioUnitProperty_HotMapParameterMIDIMapping, kAudioUnitScope_Global, 0);
+ }
+ else {
+ mMapManager->FindParameterMapEventMatch(status, channel, data1, data2, inStartFrame, mAUBaseInstance);
+ }
+#endif
+
+ OSStatus result = noErr;
+
+ switch(status)
+ {
+ case kMidiMessage_NoteOn:
+ if(data2)
+ {
+ result = HandleNoteOn(channel, data1, data2, inStartFrame);
+ }
+ else
+ {
+ // zero velocity translates to note off
+ result = HandleNoteOff(channel, data1, data2, inStartFrame);
+ }
+ break;
+
+ case kMidiMessage_NoteOff:
+ result = HandleNoteOff(channel, data1, data2, inStartFrame);
+ break;
+
+ default:
+ result = HandleNonNoteEvent (status, channel, data1, data2, inStartFrame);
+ break;
+ }
+
+ return result;
+}
+
+OSStatus AUMIDIBase::HandleNonNoteEvent (UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
+{
+ OSStatus result = noErr;
+
+ switch (status)
+ {
+ case kMidiMessage_PitchWheel:
+ result = HandlePitchWheel(channel, data1, data2, inStartFrame);
+ break;
+
+ case kMidiMessage_ProgramChange:
+ result = HandleProgramChange(channel, data1);
+ break;
+
+ case kMidiMessage_ChannelPressure:
+ result = HandleChannelPressure(channel, data1, inStartFrame);
+ break;
+
+ case kMidiMessage_ControlChange:
+ {
+ switch (data1) {
+ case kMidiController_AllNotesOff:
+ result = HandleAllNotesOff(channel);
+ break;
+
+ case kMidiController_ResetAllControllers:
+ result = HandleResetAllControllers(channel);
+ break;
+
+ case kMidiController_AllSoundOff:
+ result = HandleAllSoundOff(channel);
+ break;
+
+ default:
+ result = HandleControlChange(channel, data1, data2, inStartFrame);
+ break;
+ }
+ break;
+ }
+ case kMidiMessage_PolyPressure:
+ result = HandlePolyPressure (channel, data1, data2, inStartFrame);
+ break;
+ }
+ return result;
+}
+
+OSStatus AUMIDIBase::SysEx (const UInt8 * inData,
+ UInt32 inLength)
+{
+ if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
+
+ return HandleSysEx(inData, inLength );
+}
+
+
+
+#if TARGET_OS_MAC
+ #if __LP64__
+ // comp instance, parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index + 1];
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
+ #endif
+#elif TARGET_OS_WIN32
+ // (no comp instance), parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index];
+#endif
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+OSStatus AUMIDIBase::ComponentEntryDispatch( ComponentParameters * params,
+ AUMIDIBase * This)
+{
+ if (This == NULL) return kAudio_ParamError;
+
+ OSStatus result;
+
+ switch (params->what) {
+ case kMusicDeviceMIDIEventSelect:
+ {
+ PARAM(UInt32, pbinStatus, 0, 4);
+ PARAM(UInt32, pbinData1, 1, 4);
+ PARAM(UInt32, pbinData2, 2, 4);
+ PARAM(UInt32, pbinOffsetSampleFrame, 3, 4);
+ result = This->MIDIEvent(pbinStatus, pbinData1, pbinData2, pbinOffsetSampleFrame);
+ }
+ break;
+ case kMusicDeviceSysExSelect:
+ {
+ PARAM(const UInt8 *, pbinData, 0, 2);
+ PARAM(UInt32, pbinLength, 1, 2);
+ result = This->SysEx(pbinData, pbinLength);
+ }
+ break;
+
+ default:
+ result = badComponentSelector;
+ break;
+ }
+
+ return result;
+}
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h
new file mode 100644
index 0000000000..40c6a77695
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h
@@ -0,0 +1,213 @@
+/*
+ File: AUMIDIBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUMIDIBase_h__
+#define __AUMIDIBase_h__
+
+#include "AUBase.h"
+
+#if CA_AUTO_MIDI_MAP
+ #include "CAAUMIDIMapManager.h"
+#endif
+
+struct MIDIPacketList;
+
+// ________________________________________________________________________
+// MusicDeviceBase
+//
+ /*! @class AUMIDIBase */
+class AUMIDIBase {
+public:
+ // this is NOT a copy constructor!
+ /*! @ctor AUMIDIBase */
+ AUMIDIBase(AUBase* inBase);
+ /*! @dtor ~AUMIDIBase */
+ virtual ~AUMIDIBase();
+
+ /*! @method MIDIEvent */
+ virtual OSStatus MIDIEvent( UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame)
+ {
+ UInt32 strippedStatus = inStatus & 0xf0;
+ UInt32 channel = inStatus & 0x0f;
+
+ return HandleMidiEvent(strippedStatus, channel, inData1, inData2, inOffsetSampleFrame);
+ }
+
+ /*! @method HandleMIDIPacketList */
+ OSStatus HandleMIDIPacketList(const MIDIPacketList *pktlist);
+
+ /*! @method SysEx */
+ virtual OSStatus SysEx( const UInt8 * inData,
+ UInt32 inLength);
+
+#if TARGET_API_MAC_OSX
+ /*! @method DelegateGetPropertyInfo */
+ virtual OSStatus DelegateGetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ /*! @method DelegateGetProperty */
+ virtual OSStatus DelegateGetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+
+ /*! @method DelegateSetProperty */
+ virtual OSStatus DelegateSetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+#endif
+
+protected:
+ // MIDI dispatch
+ /*! @method HandleMidiEvent */
+ virtual OSStatus HandleMidiEvent( UInt8 inStatus,
+ UInt8 inChannel,
+ UInt8 inData1,
+ UInt8 inData2,
+ UInt32 inStartFrame);
+
+ /*! @method HandleNonNoteEvent */
+ virtual OSStatus HandleNonNoteEvent ( UInt8 status,
+ UInt8 channel,
+ UInt8 data1,
+ UInt8 data2,
+ UInt32 inStartFrame);
+
+#if TARGET_API_MAC_OSX
+ /*! @method GetXMLNames */
+ virtual OSStatus GetXMLNames(CFURLRef *outNameDocument)
+ { return kAudioUnitErr_InvalidProperty; } // if not overridden, it's unsupported
+#endif
+
+// channel messages
+ /*! @method HandleNoteOn */
+ virtual OSStatus HandleNoteOn( UInt8 inChannel,
+ UInt8 inNoteNumber,
+ UInt8 inVelocity,
+ UInt32 inStartFrame) { return noErr; }
+
+ /*! @method HandleNoteOff */
+ virtual OSStatus HandleNoteOff( UInt8 inChannel,
+ UInt8 inNoteNumber,
+ UInt8 inVelocity,
+ UInt32 inStartFrame) { return noErr; }
+
+ /*! @method HandleControlChange */
+ virtual OSStatus HandleControlChange( UInt8 inChannel,
+ UInt8 inController,
+ UInt8 inValue,
+ UInt32 inStartFrame) { return noErr; }
+
+ /*! @method HandlePitchWheel */
+ virtual OSStatus HandlePitchWheel( UInt8 inChannel,
+ UInt8 inPitch1,
+ UInt8 inPitch2,
+ UInt32 inStartFrame) { return noErr; }
+
+ /*! @method HandleChannelPressure */
+ virtual OSStatus HandleChannelPressure( UInt8 inChannel,
+ UInt8 inValue,
+ UInt32 inStartFrame) { return noErr; }
+
+ /*! @method HandleProgramChange */
+ virtual OSStatus HandleProgramChange( UInt8 inChannel,
+ UInt8 inValue) { return noErr; }
+
+ /*! @method HandlePolyPressure */
+ virtual OSStatus HandlePolyPressure( UInt8 inChannel,
+ UInt8 inKey,
+ UInt8 inValue,
+ UInt32 inStartFrame) { return noErr; }
+
+ /*! @method HandleResetAllControllers */
+ virtual OSStatus HandleResetAllControllers(UInt8 inChannel) { return noErr; }
+
+ /*! @method HandleAllNotesOff */
+ virtual OSStatus HandleAllNotesOff( UInt8 inChannel) { return noErr; }
+
+ /*! @method HandleAllSoundOff */
+ virtual OSStatus HandleAllSoundOff( UInt8 inChannel) { return noErr; }
+
+
+//System messages
+ /*! @method HandleSysEx */
+ virtual OSStatus HandleSysEx( const UInt8 * inData,
+ UInt32 inLength ) { return noErr; }
+
+#if CA_AUTO_MIDI_MAP
+ /* map manager */
+ CAAUMIDIMapManager *GetMIDIMapManager() {return mMapManager;};
+
+#endif
+
+
+private:
+ /*! @var mAUBaseInstance */
+ AUBase & mAUBaseInstance;
+
+#if CA_AUTO_MIDI_MAP
+ /* map manager */
+ CAAUMIDIMapManager * mMapManager;
+#endif
+
+public:
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ // component dispatcher
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch( ComponentParameters *params,
+ AUMIDIBase *This);
+#endif
+};
+
+#endif // __AUMIDIBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp
new file mode 100644
index 0000000000..dfe307c9eb
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp
@@ -0,0 +1,164 @@
+/*
+ File: AUMIDIEffectBase.cpp
+ Abstract: AUMIDIEffectBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUMIDIEffectBase.h"
+
+// compatibility with older OS SDK releases
+typedef OSStatus
+(*TEMP_MusicDeviceMIDIEventProc)( void * inComponentStorage,
+ UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame);
+
+static OSStatus AUMIDIEffectBaseMIDIEvent(void * inComponentStorage,
+ UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame);
+
+AUMIDIEffectBase::AUMIDIEffectBase( AudioComponentInstance inInstance,
+ bool inProcessesInPlace )
+ : AUEffectBase(inInstance, inProcessesInPlace),
+ AUMIDIBase(this)
+{
+}
+
+OSStatus AUMIDIEffectBase::GetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus result;
+
+ result = AUEffectBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = AUMIDIBase::DelegateGetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+
+ return result;
+}
+
+OSStatus AUMIDIEffectBase::GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ OSStatus result;
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ if (inID == kAudioUnitProperty_FastDispatch) {
+ if (inElement == kMusicDeviceMIDIEventSelect) {
+ *(TEMP_MusicDeviceMIDIEventProc *)outData = AUMIDIEffectBaseMIDIEvent;
+ return noErr;
+ }
+ return kAudioUnitErr_InvalidElement;
+ }
+#endif
+
+ result = AUEffectBase::GetProperty (inID, inScope, inElement, outData);
+
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = AUMIDIBase::DelegateGetProperty (inID, inScope, inElement, outData);
+
+ return result;
+}
+
+OSStatus AUMIDIEffectBase::SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+
+ OSStatus result = AUEffectBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
+
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = AUMIDIBase::DelegateSetProperty (inID, inScope, inElement, inData, inDataSize);
+
+ return result;
+}
+
+
+#if !TARGET_OS_IPHONE
+OSStatus AUMIDIEffectBase::ComponentEntryDispatch(ComponentParameters * params,
+ AUMIDIEffectBase * This)
+{
+ if (This == NULL) return paramErr;
+
+ OSStatus result;
+
+ switch (params->what) {
+ case kMusicDeviceMIDIEventSelect:
+ case kMusicDeviceSysExSelect:
+ result = AUMIDIBase::ComponentEntryDispatch (params, This);
+ break;
+ default:
+ result = AUEffectBase::ComponentEntryDispatch(params, This);
+ break;
+ }
+
+ return result;
+}
+#endif
+
+// fast dispatch
+static OSStatus AUMIDIEffectBaseMIDIEvent(void * inComponentStorage,
+ UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame)
+{
+ OSStatus result = noErr;
+ try {
+ AUMIDIEffectBase *This = static_cast<AUMIDIEffectBase *>(inComponentStorage);
+ if (This == NULL) return paramErr;
+ result = This->AUMIDIBase::MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
+ }
+ COMPONENT_CATCH
+ return result;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h
new file mode 100644
index 0000000000..b38f506d6c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h
@@ -0,0 +1,104 @@
+/*
+ File: AUMIDIEffectBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUMIDIEffectBase_h__
+#define __AUMIDIEffectBase_h__
+
+#include "AUMIDIBase.h"
+#include "AUEffectBase.h"
+
+// ________________________________________________________________________
+// AUMIDIEffectBase
+//
+ /*! @class AUMIDIEffectBase */
+class AUMIDIEffectBase : public AUEffectBase, public AUMIDIBase {
+public:
+ /*! @ctor AUMIDIEffectBase */
+ AUMIDIEffectBase( AudioComponentInstance inInstance,
+ bool inProcessesInPlace = false );
+ /*! @method MIDIEvent */
+ virtual OSStatus MIDIEvent(UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame)
+ {
+ return AUMIDIBase::MIDIEvent (inStatus, inData1, inData2, inOffsetSampleFrame);
+ }
+
+ /*! @method SysEx */
+ virtual OSStatus SysEx(const UInt8 * inData,
+ UInt32 inLength)
+ {
+ return AUMIDIBase::SysEx (inData, inLength);
+ }
+
+ /*! @method GetPropertyInfo */
+ virtual OSStatus GetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ /*! @method GetProperty */
+ virtual OSStatus GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+ /*! @method SetProperty */
+ virtual OSStatus SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+#if !TARGET_OS_IPHONE
+ // component dispatcher
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch( ComponentParameters * params,
+ AUMIDIEffectBase * This);
+#endif
+};
+
+#endif // __AUMIDIEffectBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp
new file mode 100644
index 0000000000..591c43ab8c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp
@@ -0,0 +1,76 @@
+/*
+ File: AUOutputBase.cpp
+ Abstract: AUOutputBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+#include "AUOutputBase.h"
+
+OSStatus AUOutputBase::ComponentEntryDispatch(ComponentParameters *params, AUOutputBase *This)
+{
+ if (This == NULL) return paramErr;
+
+ OSStatus result;
+
+ switch (params->what) {
+ case kAudioOutputUnitStartSelect:
+ {
+ result = This->Start();
+ }
+ break;
+
+ case kAudioOutputUnitStopSelect:
+ {
+ result = This->Stop();
+ }
+ break;
+
+ default:
+ result = badComponentSelector;
+ break;
+ }
+
+ return result;
+}
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.h
new file mode 100644
index 0000000000..8e5399b911
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.h
@@ -0,0 +1,82 @@
+/*
+ File: AUOutputBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUOutputBase_h__
+#define __AUOutputBase_h__
+
+#include "AUBase.h"
+
+// ________________________________________________________________________
+// AUOutputBase
+// this is now a mix-in rather than an AUBase subclass
+
+ /*! @class AUOutputBase */
+class AUOutputBase {
+public:
+ /*! @ctor AUOutputBase */
+ AUOutputBase(AUBase *inBase) : mAUBaseInstance(*inBase) { }
+ virtual ~AUOutputBase() { }
+
+ // additional component entry points
+ /*! @method Start */
+ virtual OSStatus Start() = 0;
+
+ /*! @method Stop */
+ virtual OSStatus Stop() = 0;
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ // component dispatcher
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch( ComponentParameters * params,
+ AUOutputBase * This);
+#endif
+
+private:
+ /*! @var mAUBaseInstance */
+ AUBase & mAUBaseInstance;
+};
+
+#endif // __AUOutputBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp
new file mode 100644
index 0000000000..f1e2f248ab
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp
@@ -0,0 +1,706 @@
+/*
+ File: AUPannerBase.cpp
+ Abstract: AUPannerBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUPannerBase.h"
+#include "CABundleLocker.h"
+#include <AudioToolbox/AudioToolbox.h>
+#include <Accelerate/Accelerate.h>
+
+static bool sLocalized = false;
+
+static CFStringRef kPanner_Azimuth_Name = CFSTR("azimuth");
+static CFStringRef kPanner_Elevation_Name = CFSTR("elevation");
+static CFStringRef kPanner_Distance_Name = CFSTR("distance");
+
+static CFStringRef kPanner_CoordScale_Name = CFSTR("coordinate scale");
+static CFStringRef kPanner_RefDistance_Name = CFSTR("reference distance");
+static CFStringRef kPanner_Gain_Name = CFSTR("gain");
+
+static Float32 kPannerParamDefault_Azimuth = 0.;
+static Float32 kPannerParamDefault_Elevation = 0.;
+static Float32 kPannerParamDefault_Distance = 1.;
+
+static Float32 kPannerParamDefault_CoordScale = 10.;
+static Float32 kPannerParamDefault_RefDistance = 1.;
+static Float32 kPannerParamDefault_Gain = 1.;
+
+//_____________________________________________________________________________
+//
+AUPannerBase::AUPannerBase(AudioComponentInstance inAudioUnit)
+ : AUBase(inAudioUnit, 1, 1), mBypassEffect(false)
+{
+ {
+ CABundleLocker lock;
+ if (!sLocalized)
+ {
+ CFBundleRef bundle = CFBundleGetBundleWithIdentifier( CFSTR("com.apple.audio.units.Components") );
+ if (bundle != NULL)
+ {
+ kPanner_Azimuth_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Azimuth_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_Elevation_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Elevation_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_Distance_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Distance_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+
+ kPanner_CoordScale_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_CoordScale_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_RefDistance_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_RefDistance_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_Gain_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Gain_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+
+ }
+
+ sLocalized = true;
+ }
+ }
+
+ CreateElements();
+
+ SetParameter(kPannerParam_Azimuth, kPannerParamDefault_Azimuth);
+ SetParameter(kPannerParam_Elevation, kPannerParamDefault_Elevation);
+ SetParameter(kPannerParam_Distance, kPannerParamDefault_Distance);
+
+ SetParameter(kPannerParam_CoordScale, kPannerParamDefault_CoordScale);
+ SetParameter(kPannerParam_RefDistance, kPannerParamDefault_RefDistance);
+ SetParameter(kPannerParam_Gain, kPannerParamDefault_Gain);
+}
+
+//_____________________________________________________________________________
+//
+AUPannerBase::~AUPannerBase()
+{
+ Cleanup();
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Initialize */
+OSStatus AUPannerBase::Initialize()
+{
+ OSStatus err = noErr;
+ AllocBypassMatrix();
+ err = UpdateBypassMatrix();
+ return err;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method AllocBypassMatrix */
+void AUPannerBase::AllocBypassMatrix()
+{
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ mBypassMatrix.alloc(inChannels * outChannels, true);
+}
+
+static AudioChannelLayoutTag DefaultTagForNumberOfChannels(UInt32 inNumberChannels)
+{
+ switch (inNumberChannels) {
+ case 1: return kAudioChannelLayoutTag_Mono;
+ case 2: return kAudioChannelLayoutTag_Stereo;
+ case 4: return kAudioChannelLayoutTag_Quadraphonic;
+ case 5: return kAudioChannelLayoutTag_AudioUnit_5_0;
+ case 6: return kAudioChannelLayoutTag_AudioUnit_6_0;
+ case 7: return kAudioChannelLayoutTag_AudioUnit_7_0;
+ case 8: return kAudioChannelLayoutTag_AudioUnit_8;
+
+ default: return 0xFFFF0000 | inNumberChannels;
+ }
+}
+
+//_____________________________________________________________________________
+//
+/*! @method UpdateBypassMatrix */
+OSStatus AUPannerBase::SetDefaultChannelLayoutsIfNone()
+{
+ OSStatus err = noErr;
+
+ // if layout has not been set, then guess layout from number of channels
+ UInt32 inChannels = GetNumberOfInputChannels();
+ AudioChannelLayout inputLayoutSubstitute;
+ const AudioChannelLayout* inputLayout = &GetInputLayout();
+ if (inputLayout == NULL || inputLayout->mChannelLayoutTag == 0) {
+ inputLayout = &inputLayoutSubstitute;
+ inputLayoutSubstitute.mNumberChannelDescriptions = 0;
+ inputLayoutSubstitute.mChannelBitmap = 0;
+ inputLayoutSubstitute.mChannelLayoutTag = DefaultTagForNumberOfChannels(inChannels);
+
+ mInputLayout = &inputLayoutSubstitute;
+ err = SetAudioChannelLayout(kAudioUnitScope_Input, 0, &GetInputLayout());
+ if (err) return err;
+ }
+
+ // if layout has not been set, then guess layout from number of channels
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ AudioChannelLayout outputLayoutSubstitute;
+ const AudioChannelLayout* outputLayout = &GetOutputLayout();
+ if (outputLayout == NULL || outputLayout->mChannelLayoutTag == 0) {
+ outputLayout = &outputLayoutSubstitute;
+ outputLayoutSubstitute.mNumberChannelDescriptions = 0;
+ outputLayoutSubstitute.mChannelBitmap = 0;
+ outputLayoutSubstitute.mChannelLayoutTag = DefaultTagForNumberOfChannels(outChannels);
+
+ mOutputLayout = &outputLayoutSubstitute;
+ err = SetAudioChannelLayout(kAudioUnitScope_Output, 0, &GetOutputLayout());
+ if (err) return err;
+ }
+
+ return err;
+}
+
+
+
+OSStatus AUPannerBase::UpdateBypassMatrix()
+{
+ OSStatus err = SetDefaultChannelLayoutsIfNone();
+ if (err) return err;
+
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+
+ const AudioChannelLayout* inoutACL[2];
+
+ inoutACL[0] = &GetInputLayout();
+ inoutACL[1] = &GetOutputLayout();
+
+ mBypassMatrix.alloc(inChannels * outChannels, true);
+
+ UInt32 propSize = inChannels * outChannels * sizeof(Float32);
+
+ err = AudioFormatGetProperty(kAudioFormatProperty_MatrixMixMap, sizeof(inoutACL), inoutACL, &propSize, mBypassMatrix());
+ if (err) {
+ // if there is an error, use a diagonal matrix.
+ Float32* bypass = mBypassMatrix();
+ for (UInt32 chan = 0; chan < std::min(inChannels, outChannels); ++chan)
+ {
+ float *amp = bypass + (chan * outChannels + chan);
+ *amp = 1.;
+ }
+ }
+
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Cleanup */
+void AUPannerBase::Cleanup()
+{
+
+}
+
+
+//_____________________________________________________________________________
+//
+/*! @method Reset */
+OSStatus AUPannerBase::Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ return AUBase::Reset(inScope, inElement);
+}
+
+//_____________________________________________________________________________
+//
+/*! @method GetParameterInfo */
+OSStatus AUPannerBase::GetParameterInfo( AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ AudioUnitParameterInfo &outParameterInfo )
+{
+ OSStatus result = noErr;
+
+ outParameterInfo.flags = kAudioUnitParameterFlag_IsWritable
+ + kAudioUnitParameterFlag_IsReadable;
+
+ if (inScope == kAudioUnitScope_Global) {
+
+ switch(inParameterID)
+ {
+ case kPannerParam_Azimuth:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Azimuth_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Degrees;
+ outParameterInfo.minValue = -180.;
+ outParameterInfo.maxValue = 180;
+ outParameterInfo.defaultValue = kPannerParamDefault_Azimuth;
+ break;
+
+ case kPannerParam_Elevation:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Elevation_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Degrees;
+ outParameterInfo.minValue = -90.;
+ outParameterInfo.maxValue = 90;
+ outParameterInfo.defaultValue = kPannerParamDefault_Elevation;
+ break;
+
+ case kPannerParam_Distance:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Distance_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
+ outParameterInfo.minValue = 0.0;
+ outParameterInfo.maxValue = 1.;
+ outParameterInfo.defaultValue = kPannerParamDefault_Distance;
+ outParameterInfo.flags += kAudioUnitParameterFlag_IsHighResolution;
+ //outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
+ break;
+
+ case kPannerParam_CoordScale:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_CoordScale_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Meters;
+ outParameterInfo.minValue = 0.01;
+ outParameterInfo.maxValue = 1000.;
+ outParameterInfo.defaultValue = kPannerParamDefault_CoordScale;
+ outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
+ break;
+
+ case kPannerParam_RefDistance:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_RefDistance_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Meters;
+ outParameterInfo.minValue = 0.01;
+ outParameterInfo.maxValue = 1000.;
+ outParameterInfo.defaultValue = kPannerParamDefault_RefDistance;
+ outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
+ break;
+
+ case kPannerParam_Gain:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Gain_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
+ outParameterInfo.minValue = 0.;
+ outParameterInfo.maxValue = 1.;
+ outParameterInfo.defaultValue = kPannerParamDefault_Gain;
+ break;
+
+ default:
+ result = kAudioUnitErr_InvalidParameter;
+ break;
+ }
+ } else {
+ result = kAudioUnitErr_InvalidParameter;
+ }
+
+ return result;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::GetParameter( AudioUnitParameterID inParamID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ Float32 & outValue)
+{
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ outValue = Globals()->GetParameter(inParamID);
+
+ return noErr;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::SetParameter( AudioUnitParameterID inParamID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ Float32 inValue,
+ UInt32 inBufferOffsetInFrames)
+{
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ Globals()->SetParameter(inParamID, inValue);
+
+ return noErr;
+}
+
+
+
+//_____________________________________________________________________________
+//
+/*! @method GetPropertyInfo */
+OSStatus AUPannerBase::GetPropertyInfo (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus err = noErr;
+ switch (inID) {
+ case kAudioUnitProperty_BypassEffect:
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ outWritable = true;
+ outDataSize = sizeof (UInt32);
+ break;
+ default:
+ err = AUBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);
+ }
+ return err;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method GetProperty */
+OSStatus AUPannerBase::GetProperty (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ OSStatus err = noErr;
+ switch (inID)
+ {
+ case kAudioUnitProperty_BypassEffect:
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ *((UInt32*)outData) = (IsBypassEffect() ? 1 : 0);
+ break;
+ default:
+ err = AUBase::GetProperty(inID, inScope, inElement, outData);
+ }
+ return err;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method SetProperty */
+OSStatus AUPannerBase::SetProperty(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ switch (inID)
+ {
+ case kAudioUnitProperty_BypassEffect:
+ if (inDataSize < sizeof(UInt32))
+ return kAudioUnitErr_InvalidPropertyValue;
+ bool tempNewSetting = *((UInt32*)inData) != 0;
+ // we're changing the state of bypass
+ if (tempNewSetting != IsBypassEffect())
+ {
+ if (!tempNewSetting && IsBypassEffect() && IsInitialized()) // turning bypass off and we're initialized
+ Reset(0, 0);
+ SetBypassEffect (tempNewSetting);
+ }
+ return noErr;
+ }
+ return AUBase::SetProperty(inID, inScope, inElement, inData, inDataSize);
+}
+
+
+//_____________________________________________________________________________
+//
+/*! @method StreamFormatWritable */
+bool AUPannerBase::StreamFormatWritable (AudioUnitScope scope,
+ AudioUnitElement element)
+{
+ return true;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method ChangeStreamFormat */
+OSStatus AUPannerBase::ChangeStreamFormat (
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inPrevFormat,
+ const CAStreamBasicDescription & inNewFormat)
+{
+ if (inScope == kAudioUnitScope_Input && !InputChannelConfigIsSupported(inNewFormat.NumberChannels()))
+ return kAudioUnitErr_FormatNotSupported;
+
+ if (inScope == kAudioUnitScope_Output && !OutputChannelConfigIsSupported(inNewFormat.NumberChannels()))
+ return kAudioUnitErr_FormatNotSupported;
+
+ if (inNewFormat.NumberChannels() != inPrevFormat.NumberChannels())
+ RemoveAudioChannelLayout(inScope, inElement);
+
+ return AUBase::ChangeStreamFormat(inScope, inElement, inPrevFormat, inNewFormat);
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Render */
+OSStatus AUPannerBase::Render(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames)
+{
+ if (IsBypassEffect())
+ return BypassRender(ioActionFlags, inTimeStamp, inNumberFrames);
+ else
+ return PannerRender(ioActionFlags, inTimeStamp, inNumberFrames);
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Render */
+OSStatus AUPannerBase::BypassRender(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames)
+{
+ AudioUnitRenderActionFlags xflags = 0;
+ OSStatus result = PullInput(0, xflags, inTimeStamp, inNumberFrames);
+ if (result) return false;
+ bool isSilent = xflags & kAudioUnitRenderAction_OutputIsSilence;
+
+ AudioBufferList& outputBufferList = GetOutput(0)->GetBufferList();
+ AUBufferList::ZeroBuffer(outputBufferList);
+
+ if (!isSilent)
+ {
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ Float32* bypass = mBypassMatrix();
+ for (UInt32 outChan = 0; outChan < outChannels; ++outChan)
+ {
+ float* outData = GetOutput(0)->GetChannelData(outChan);
+
+ for (UInt32 inChan = 0; inChan < inChannels; ++inChan)
+ {
+ float* inData = GetInput(0)->GetChannelData(inChan);
+ float *amp = bypass + (inChan * outChannels + outChan);
+ vDSP_vsma(inData, 1, amp, outData, 1, outData, 1, inNumberFrames);
+ }
+ }
+ }
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+UInt32 AUPannerBase::GetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayout * outLayoutPtr,
+ Boolean & outWritable)
+{
+ SetDefaultChannelLayoutsIfNone();
+
+ outWritable = true;
+
+ CAAudioChannelLayout* caacl = NULL;
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ caacl = &mInputLayout;
+ break;
+ case kAudioUnitScope_Output:
+ caacl = &mOutputLayout;
+ break;
+ default:
+ COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+ }
+
+ if (inElement != 0)
+ COMPONENT_THROW(kAudioUnitErr_InvalidElement);
+
+ UInt32 size = caacl->IsValid() ? caacl->Size() : 0;
+ if (size > 0 && outLayoutPtr)
+ memcpy(outLayoutPtr, &caacl->Layout(), size);
+
+ return size;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::RemoveAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ CAAudioChannelLayout* caacl = NULL;
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ caacl = &mInputLayout;
+ break;
+ case kAudioUnitScope_Output:
+ caacl = &mOutputLayout;
+ break;
+ default:
+ return kAudioUnitErr_InvalidScope;
+ }
+
+ if (inElement != 0)
+ return kAudioUnitErr_InvalidElement;
+
+ *caacl = NULL;
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::SetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const AudioChannelLayout * inLayout)
+{
+ if (!inLayout)
+ return RemoveAudioChannelLayout(inScope, inElement);
+
+ if (!ChannelLayoutTagIsSupported(inScope, inElement, inLayout->mChannelLayoutTag))
+ return kAudioUnitErr_FormatNotSupported;
+
+ CAAudioChannelLayout* caacl = NULL;
+ UInt32 currentChannels;
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ caacl = &mInputLayout;
+ currentChannels = GetNumberOfInputChannels();
+ break;
+ case kAudioUnitScope_Output:
+ caacl = &mOutputLayout;
+ currentChannels = GetNumberOfOutputChannels();
+ break;
+ default:
+ return kAudioUnitErr_InvalidScope;
+ }
+
+ if (inElement != 0)
+ return kAudioUnitErr_InvalidElement;
+
+ UInt32 numChannelsInLayout = CAAudioChannelLayout::NumberChannels(*inLayout);
+ if (currentChannels != numChannelsInLayout)
+ return kAudioUnitErr_InvalidPropertyValue;
+
+ *caacl = inLayout;
+ if (IsInitialized())
+ UpdateBypassMatrix();
+
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+UInt32 AUPannerBase::GetChannelLayoutTags( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag* outTags)
+{
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ if (outTags) {
+ outTags[0] = kAudioChannelLayoutTag_Mono;
+ outTags[1] = kAudioChannelLayoutTag_Stereo;
+ outTags[2] = kAudioChannelLayoutTag_Ambisonic_B_Format;
+ }
+ return 3;
+ case kAudioUnitScope_Output:
+ if (outTags) {
+ outTags[0] = kAudioChannelLayoutTag_Stereo;
+ outTags[1] = kAudioChannelLayoutTag_Quadraphonic;
+ outTags[2] = kAudioChannelLayoutTag_AudioUnit_5_0;
+ outTags[3] = kAudioChannelLayoutTag_AudioUnit_6_0;
+ outTags[4] = kAudioChannelLayoutTag_AudioUnit_7_0;
+ outTags[5] = kAudioChannelLayoutTag_AudioUnit_7_0_Front;
+ outTags[6] = kAudioChannelLayoutTag_AudioUnit_8;
+ }
+ return 7;
+ default: {
+ OSStatus err = kAudioUnitErr_InvalidScope;
+ throw err;
+ }
+ }
+}
+
+
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::ChannelConfigIsSupported()
+{
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ const AUChannelInfo* cinfo = NULL;
+ UInt32 numConfigs = SupportedNumChannels(&cinfo);
+ for (UInt32 i = 0; i < numConfigs; ++i)
+ {
+ if (cinfo[i].inChannels == (SInt16)inChannels && cinfo[i].outChannels == (SInt16)outChannels)
+ return true;
+ }
+ return false;
+}
+
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::InputChannelConfigIsSupported(UInt32 inNumberChannels)
+{
+ const AUChannelInfo* cinfo = NULL;
+ UInt32 numConfigs = SupportedNumChannels(&cinfo);
+ for (UInt32 i = 0; i < numConfigs; ++i)
+ {
+ if (cinfo[i].inChannels == (SInt16)inNumberChannels)
+ return true;
+ }
+ return false;
+}
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::OutputChannelConfigIsSupported(UInt32 inNumberChannels)
+{
+ const AUChannelInfo* cinfo = NULL;
+ UInt32 numConfigs = SupportedNumChannels(&cinfo);
+ for (UInt32 i = 0; i < numConfigs; ++i)
+ {
+ if (cinfo[i].outChannels == (SInt16)inNumberChannels)
+ return true;
+ }
+ return false;
+}
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::ChannelLayoutTagIsSupported( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag inTag)
+{
+ UInt32 numTags = GetChannelLayoutTags(inScope, inElement, NULL);
+ CAAutoFree<AudioChannelLayoutTag> tags(numTags);
+ GetChannelLayoutTags(inScope, inElement, tags());
+
+ for (UInt32 i = 0; i < numTags; ++i)
+ {
+ if (tags[i] == inTag)
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.h
new file mode 100644
index 0000000000..3184830523
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.h
@@ -0,0 +1,272 @@
+/*
+ File: AUPannerBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUPannerBase_h__
+#define __AUPannerBase_h__
+
+#include "AUBase.h"
+#include <math.h>
+#include "CAAutoDisposer.h"
+#include "CAAudioChannelLayout.h"
+
+
+/*! @class AUPannerBase */
+class AUPannerBase : public AUBase
+{
+public:
+/*! @ctor AUPannerBase */
+ AUPannerBase(AudioComponentInstance inAudioUnit);
+/*! @dtor ~AUPannerBase */
+ virtual ~AUPannerBase();
+
+ /*! @method Initialize */
+ virtual OSStatus Initialize();
+
+ /*! @method Cleanup */
+ virtual void Cleanup();
+
+
+ /*! @method Reset */
+ virtual OSStatus Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ /*! @method CanScheduleParameters */
+ virtual bool CanScheduleParameters() const { return false; }
+
+ /*! @method GetParameterInfo */
+ virtual OSStatus GetParameterInfo( AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ AudioUnitParameterInfo &outParameterInfo );
+
+
+ /*! @method GetPropertyInfo */
+ virtual OSStatus GetPropertyInfo (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ /*! @method GetProperty */
+ virtual OSStatus GetProperty (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+
+ /*! @method SetProperty */
+ virtual OSStatus SetProperty(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+
+
+ /*! @method StreamFormatWritable */
+ virtual bool StreamFormatWritable (AudioUnitScope scope,
+ AudioUnitElement element);
+
+ /*! @method ChangeStreamFormat */
+ virtual OSStatus ChangeStreamFormat (
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inPrevFormat,
+ const CAStreamBasicDescription & inNewFormat);
+
+
+ /*! @method IsBypassEffect */
+ // This is used for the property value - to reflect to the UI if an effect is bypassed
+ bool IsBypassEffect () { return mBypassEffect; }
+
+ /*! @method SetBypassEffect */
+ virtual void SetBypassEffect (bool inFlag) { mBypassEffect = inFlag; }
+
+
+ /*! @method Render */
+ virtual OSStatus Render(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames);
+
+ /*! @method Render */
+ virtual OSStatus PannerRender(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames) = 0;
+
+ /*! @method BypassRender */
+ virtual OSStatus BypassRender(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames);
+
+
+ /*! @method GetAudioChannelLayout */
+ virtual UInt32 GetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayout * outLayoutPtr,
+ Boolean & outWritable);
+
+ /*! @method SetAudioChannelLayout */
+ virtual OSStatus SetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const AudioChannelLayout * inLayout);
+
+ /*! @method RemoveAudioChannelLayout */
+ virtual OSStatus RemoveAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ /*! @method GetChannelLayoutTags */
+ virtual UInt32 GetChannelLayoutTags( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag* outTags);
+
+ /*! @method GetNumberOfInputChannels */
+ UInt32 GetNumberOfInputChannels() { return ((AUIOElement*)Inputs().SafeGetElement(0))->NumberChannels(); };
+ /*! @method GetNumberOfOutputChannels */
+ UInt32 GetNumberOfOutputChannels() { return ((AUIOElement*)Outputs().SafeGetElement(0))->NumberChannels(); }
+
+ /*! @method GetParameter */
+ virtual OSStatus GetParameter( AudioUnitParameterID inParamID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ Float32 & outValue);
+
+ /*! @method SetParameter */
+ virtual OSStatus SetParameter( AudioUnitParameterID inParamID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ Float32 inValue,
+ UInt32 inBufferOffsetInFrames);
+
+ // convenience wrappers for accessing parameters in the global scope
+ /*! @method SetParameter */
+ void SetParameter( UInt32 inParamID,
+ Float32 inValue)
+ {
+ OSStatus err = SetParameter(inParamID, kAudioUnitScope_Global, 0, inValue, 0);
+ if (err) throw err;
+ }
+
+ /*! @method GetParameter */
+ Float32 GetParameter( UInt32 inParamID )
+ {
+ Float32 outValue = 0.;
+ OSStatus err = GetParameter(inParamID, kAudioUnitScope_Global, 0, outValue);
+ if (err) throw err;
+ return outValue;
+ }
+
+ /*! @method InputChannelConfigIsSupported */
+ bool InputChannelConfigIsSupported(UInt32 inNumberChannels);
+ /*! @method OutputChannelConfigIsSupported */
+ bool OutputChannelConfigIsSupported(UInt32 inNumberChannels);
+ /*! @method ChannelConfigIsSupported */
+ bool ChannelConfigIsSupported();
+
+ /*! @method SupportsTail */
+ virtual bool SupportsTail () { return true; }
+ /*! @method GetTailTime */
+ virtual Float64 GetTailTime() { return 0; }
+
+
+ /*! @method GetGain */
+ Float32 GetGain() { return GetParameter(kPannerParam_Gain); }
+ /*! @method GetTailTime */
+ Float32 GetAzimuth() { return GetParameter(kPannerParam_Azimuth); }
+ /*! @method GetElevation */
+ Float32 GetElevation() { return GetParameter(kPannerParam_Elevation); }
+ /*! @method GetDistance */
+ Float32 GetDistance() { return GetParameter(kPannerParam_Distance); }
+ /*! @method GetCoordScale */
+ Float32 GetCoordScale() { return GetParameter(kPannerParam_CoordScale); }
+ /*! @method GetRefDistance */
+ Float32 GetRefDistance() { return GetParameter(kPannerParam_RefDistance); }
+
+ /*! @method SetGain */
+ void SetGain(Float32 inValue) { SetParameter(kPannerParam_Gain, inValue); }
+ /*! @method SetAzimuth */
+ void SetAzimuth(Float32 inValue) { SetParameter(kPannerParam_Azimuth, inValue); }
+ /*! @method SetElevation */
+ void SetElevation(Float32 inValue) { SetParameter(kPannerParam_Elevation, inValue); }
+ /*! @method SetDistance */
+ void SetDistance(Float32 inValue) { SetParameter(kPannerParam_Distance, inValue); }
+ /*! @method SetCoordScale */
+ void SetCoordScale(Float32 inValue) { SetParameter(kPannerParam_CoordScale, inValue); }
+ /*! @method SetRefDistance */
+ void SetRefDistance(Float32 inValue) { SetParameter(kPannerParam_RefDistance, inValue); }
+
+protected:
+ /*! @method ShouldBypassEffect */
+ // This is used in the render call to see if an effect is bypassed
+ // It can return a different status than IsBypassEffect (though it MUST take that into account)
+ virtual bool ShouldBypassEffect () { return IsBypassEffect(); }
+
+ /*! @method AllocBypassMatrix */
+ void AllocBypassMatrix();
+
+ /*! @method UpdateBypassMatrix */
+ OSStatus UpdateBypassMatrix();
+
+ /*! @method SetDefaultChannelLayoutsIfNone */
+ OSStatus SetDefaultChannelLayoutsIfNone();
+
+ /*! @method ChannelLayoutTagIsSupported */
+ bool ChannelLayoutTagIsSupported( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag inTag);
+
+ const AudioChannelLayout& GetInputLayout() const { return mInputLayout.Layout(); }
+ const AudioChannelLayout& GetOutputLayout() const { return mOutputLayout.Layout(); }
+
+private:
+
+ /*! @var UpdateBypassMatrix */
+ bool mBypassEffect;
+ /*! @var mBypassMatrix */
+ CAAutoFree<Float32> mBypassMatrix;
+ /*! @var mInputLayout */
+ CAAudioChannelLayout mInputLayout;
+ /*! @var mOutputLayout */
+ CAAudioChannelLayout mOutputLayout;
+};
+
+#endif /* __AUPannerBase_h__ */
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp
new file mode 100644
index 0000000000..28e4d366bc
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp
@@ -0,0 +1,354 @@
+/*
+ File: MusicDeviceBase.cpp
+ Abstract: MusicDeviceBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "MusicDeviceBase.h"
+
+// compatibility with older OS SDK releases
+typedef OSStatus
+(*TEMP_MusicDeviceMIDIEventProc)( void * inComponentStorage,
+ UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame);
+
+typedef OSStatus
+(*TEMP_MusicDeviceStartNoteProc)( void * inComponentStorage,
+ MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams * inParams);
+
+typedef OSStatus
+(*TEMP_MusicDeviceStopNoteProc)(void * inComponentStorage,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame);
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+
+static OSStatus MusicDeviceBaseMIDIEvent(void * inComponentStorage,
+ UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame);
+
+static OSStatus MusicDeviceBaseStartNote( void * inComponentStorage,
+ MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams * inParams);
+
+static OSStatus MusicDeviceBaseStopNote(void * inComponentStorage,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame);
+
+#endif
+
+MusicDeviceBase::MusicDeviceBase(AudioComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups)
+ : AUBase(inInstance, numInputs, numOutputs, numGroups),
+ AUMIDIBase(this)
+{
+}
+
+OSStatus MusicDeviceBase::GetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus result;
+
+ switch (inID)
+ {
+#if !TARGET_OS_IPHONE
+ case kMusicDeviceProperty_InstrumentCount:
+ if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
+ outDataSize = sizeof(UInt32);
+ outWritable = false;
+ result = noErr;
+ break;
+#endif
+ default:
+ result = AUBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = AUMIDIBase::DelegateGetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+ break;
+ }
+ return result;
+}
+
+OSStatus MusicDeviceBase::GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ OSStatus result;
+
+ switch (inID)
+ {
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ case kAudioUnitProperty_FastDispatch:
+ if (!IsCMgrObject()) return kAudioUnitErr_InvalidProperty;
+ if (inElement == kMusicDeviceMIDIEventSelect) {
+ *(TEMP_MusicDeviceMIDIEventProc *)outData = MusicDeviceBaseMIDIEvent;
+ return noErr;
+ }
+ else if (inElement == kMusicDeviceStartNoteSelect) {
+ *(TEMP_MusicDeviceStartNoteProc *)outData = MusicDeviceBaseStartNote;
+ return noErr;
+ }
+ else if (inElement == kMusicDeviceStopNoteSelect) {
+ *(TEMP_MusicDeviceStopNoteProc *)outData = MusicDeviceBaseStopNote;
+ return noErr;
+ }
+ return kAudioUnitErr_InvalidElement;
+#endif
+
+#if !TARGET_OS_IPHONE
+ case kMusicDeviceProperty_InstrumentCount:
+ if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
+ return GetInstrumentCount (*(UInt32*)outData);
+#endif
+ default:
+ result = AUBase::GetProperty (inID, inScope, inElement, outData);
+
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = AUMIDIBase::DelegateGetProperty (inID, inScope, inElement, outData);
+ }
+
+ return result;
+}
+
+
+OSStatus MusicDeviceBase::SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+
+{
+
+ OSStatus result = AUBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
+
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = AUMIDIBase::DelegateSetProperty (inID, inScope, inElement, inData, inDataSize);
+
+ return result;
+}
+
+// For a MusicDevice that doesn't support separate instruments (ie. is mono-timbral)
+// then this call should return an instrument count of zero and noErr
+OSStatus MusicDeviceBase::GetInstrumentCount (UInt32 &outInstCount) const
+{
+ outInstCount = 0;
+ return noErr;
+}
+
+OSStatus MusicDeviceBase::HandleNoteOn( UInt8 inChannel,
+ UInt8 inNoteNumber,
+ UInt8 inVelocity,
+ UInt32 inStartFrame)
+{
+ MusicDeviceNoteParams params;
+ params.argCount = 2;
+ params.mPitch = inNoteNumber;
+ params.mVelocity = inVelocity;
+ return StartNote (kMusicNoteEvent_UseGroupInstrument, inChannel, NULL, inStartFrame, params);
+}
+
+OSStatus MusicDeviceBase::HandleNoteOff( UInt8 inChannel,
+ UInt8 inNoteNumber,
+ UInt8 inVelocity,
+ UInt32 inStartFrame)
+{
+ return StopNote (inChannel, inNoteNumber, inStartFrame);
+}
+
+OSStatus
+MusicDeviceBase::HandleStartNoteMessage (MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams * inParams)
+{
+ if (inParams == NULL || outNoteInstanceID == NULL) return kAudio_ParamError;
+
+ if (!IsInitialized()) return kAudioUnitErr_Uninitialized;
+
+ return StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
+}
+
+#if TARGET_OS_MAC
+ #if __LP64__
+ // comp instance, parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index + 1];
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
+ #endif
+#elif TARGET_OS_WIN32
+ // (no comp instance), parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index];
+#endif
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+OSStatus MusicDeviceBase::ComponentEntryDispatch( ComponentParameters * params,
+ MusicDeviceBase * This)
+{
+ if (This == NULL) return kAudio_ParamError;
+
+ OSStatus result;
+
+ switch (params->what) {
+ case kMusicDeviceMIDIEventSelect:
+ case kMusicDeviceSysExSelect:
+ {
+ result = AUMIDIBase::ComponentEntryDispatch (params, This);
+ }
+ break;
+ case kMusicDevicePrepareInstrumentSelect:
+ {
+ PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
+ result = This->PrepareInstrument(inInstrument);
+ }
+ break;
+ case kMusicDeviceReleaseInstrumentSelect:
+ {
+ PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
+ result = This->ReleaseInstrument(inInstrument);
+ }
+ break;
+ case kMusicDeviceStartNoteSelect:
+ {
+ PARAM(MusicDeviceInstrumentID, pbinInstrument, 0, 5);
+ PARAM(MusicDeviceGroupID, pbinGroupID, 1, 5);
+ PARAM(NoteInstanceID *, pboutNoteInstanceID, 2, 5);
+ PARAM(UInt32, pbinOffsetSampleFrame, 3, 5);
+ PARAM(const MusicDeviceNoteParams *, pbinParams, 4, 5);
+ result = This->HandleStartNoteMessage(pbinInstrument, pbinGroupID, pboutNoteInstanceID, pbinOffsetSampleFrame, pbinParams);
+ }
+ break;
+ case kMusicDeviceStopNoteSelect:
+ {
+ PARAM(MusicDeviceGroupID, pbinGroupID, 0, 3);
+ PARAM(NoteInstanceID, pbinNoteInstanceID, 1, 3);
+ PARAM(UInt32, pbinOffsetSampleFrame, 2, 3);
+ result = This->StopNote(pbinGroupID, pbinNoteInstanceID, pbinOffsetSampleFrame);
+ }
+ break;
+
+ default:
+ result = AUBase::ComponentEntryDispatch(params, This);
+ break;
+ }
+
+ return result;
+}
+#endif
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+
+// fast dispatch
+static OSStatus MusicDeviceBaseMIDIEvent(void * inComponentStorage,
+ UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame)
+{
+ OSStatus result = noErr;
+ try {
+ MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
+ if (This == NULL) return kAudio_ParamError;
+ result = This->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+OSStatus MusicDeviceBaseStartNote( void * inComponentStorage,
+ MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams * inParams)
+{
+ OSStatus result = noErr;
+ try {
+ if (inParams == NULL || outNoteInstanceID == NULL) return kAudio_ParamError;
+ MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
+ if (This == NULL) return kAudio_ParamError;
+ result = This->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+OSStatus MusicDeviceBaseStopNote(void * inComponentStorage,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame)
+{
+ OSStatus result = noErr;
+ try {
+ MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
+ if (This == NULL) return kAudio_ParamError;
+ result = This->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h
new file mode 100644
index 0000000000..4850b8f0cb
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h
@@ -0,0 +1,126 @@
+/*
+ File: MusicDeviceBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __MusicDeviceBase_h__
+#define __MusicDeviceBase_h__
+
+#include "AUMIDIBase.h"
+
+// ________________________________________________________________________
+// MusicDeviceBase
+//
+
+/*! @class MusicDeviceBase */
+class MusicDeviceBase : public AUBase, public AUMIDIBase {
+public:
+ /*! @ctor MusicDeviceBase */
+ MusicDeviceBase( AudioComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups = 0);
+
+
+ virtual OSStatus MIDIEvent( UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame)
+ {
+ return AUMIDIBase::MIDIEvent (inStatus, inData1, inData2, inOffsetSampleFrame);
+ }
+
+ /*! @method SysEx */
+ virtual OSStatus SysEx( const UInt8 * inData,
+ UInt32 inLength)
+ {
+ return AUMIDIBase::SysEx (inData, inLength);
+ }
+
+ /*! @method GetPropertyInfo */
+ virtual OSStatus GetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ /*! @method GetProperty */
+ virtual OSStatus GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+
+ /*! @method SetProperty */
+ virtual OSStatus SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+
+ /*! @method HandleNoteOn */
+ virtual OSStatus HandleNoteOn( UInt8 inChannel,
+ UInt8 inNoteNumber,
+ UInt8 inVelocity,
+ UInt32 inStartFrame);
+
+ /*! @method HandleNoteOff */
+ virtual OSStatus HandleNoteOff( UInt8 inChannel,
+ UInt8 inNoteNumber,
+ UInt8 inVelocity,
+ UInt32 inStartFrame);
+
+ /*! @method GetInstrumentCount */
+ virtual OSStatus GetInstrumentCount ( UInt32 &outInstCount) const;
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ // component dispatcher
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch( ComponentParameters * params,
+ MusicDeviceBase * This);
+#endif
+private:
+ OSStatus HandleStartNoteMessage (MusicDeviceInstrumentID inInstrument, MusicDeviceGroupID inGroupID, NoteInstanceID *outNoteInstanceID, UInt32 inOffsetSampleFrame, const MusicDeviceNoteParams *inParams);
+};
+
+#endif // __MusicDeviceBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp
new file mode 100644
index 0000000000..2316807138
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp
@@ -0,0 +1,125 @@
+/*
+ File: AUBaseHelper.cpp
+ Abstract: AUBaseHelper.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUBaseHelper.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnitProperties.h>
+#else
+ #include <AudioUnitProperties.h>
+#endif
+
+OSStatus GetFileRefPath (CFDictionaryRef parent, CFStringRef frKey, CFStringRef * fPath)
+{
+ static CFStringRef kFRString = CFSTR (kAUPresetExternalFileRefs);
+
+ const void* frVal = CFDictionaryGetValue(parent, kFRString);
+ if (!frVal) return kAudioUnitErr_InvalidPropertyValue;
+
+ const void* frString = CFDictionaryGetValue ((CFDictionaryRef)frVal, frKey);
+ if (!frString) return kAudioUnitErr_InvalidPropertyValue;
+
+ if (fPath)
+ *fPath = (CFStringRef)frString;
+
+ return noErr;
+}
+
+CFMutableDictionaryRef CreateFileRefDict (CFStringRef fKey, CFStringRef fPath, CFMutableDictionaryRef fileRefDict)
+{
+ if (!fileRefDict)
+ fileRefDict = CFDictionaryCreateMutable (NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ CFDictionarySetValue (fileRefDict, fKey, fPath);
+
+ return fileRefDict;
+}
+
+#if TARGET_OS_MAC
+// check if the URL can be accessed for reading/writing. Returns 0 if yes, or the error value.
+int AccessURLAsset(const CFURLRef inURL, int mode)
+{
+ char path[PATH_MAX];
+ if (CFURLGetFileSystemRepresentation(inURL, TRUE, (UInt8 *)path, PATH_MAX) == FALSE)
+ return kAudio_FileNotFoundError;
+ // check whether we have access
+ int ret = access(path, mode);
+// syslog(LOG_CRIT, "access() error is %d for \"%s\".\n", ret, path);
+ if (ret == 0) return 0;
+ switch (errno) {
+ case EACCES:
+ case EPERM:
+ return -54; /*permission denied error*/
+ case ENOENT:
+ case ENOTDIR:
+ case ELOOP:
+ return kAudio_FileNotFoundError;
+ default:
+ return errno;
+ }
+}
+#endif
+
+#if DEBUG
+//_____________________________________________________________________________
+//
+void PrintAUParamEvent (AudioUnitParameterEvent& event, FILE* f)
+{
+ bool isRamp = event.eventType == kParameterEvent_Ramped;
+ fprintf (f, "\tParamID=%ld,Scope=%ld,Element=%ld\n", (long)event.parameter, (long)event.scope, (long)event.element);
+ fprintf (f, "\tEvent Type:%s,", (isRamp ? "ramp" : "immediate"));
+ if (isRamp)
+ fprintf (f, "start=%ld,dur=%ld,startValue=%f,endValue=%f\n",
+ (long)event.eventValues.ramp.startBufferOffset, (long)event.eventValues.ramp.durationInFrames,
+ event.eventValues.ramp.startValue, event.eventValues.ramp.endValue);
+ else
+ fprintf (f, "start=%ld,value=%f\n",
+ (long)event.eventValues.immediate.bufferOffset,
+ event.eventValues.immediate.value);
+ fprintf (f, "- - - - - - - - - - - - - - - -\n");
+}
+#endif
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.h
new file mode 100644
index 0000000000..310a8df620
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.h
@@ -0,0 +1,75 @@
+/*
+ File: AUBaseHelper.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUBaseHelper_h__
+#define __AUBaseHelper_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CoreFoundation.h>
+ #include <AudioUnit/AUComponent.h>
+#else
+ #include <CoreFoundation.h>
+ #include <AUComponent.h>
+#endif
+
+#include "AUBase.h"
+
+// helpers for dealing with the file-references dictionary in an AUPreset
+OSStatus GetFileRefPath (CFDictionaryRef parent, CFStringRef frKey, CFStringRef * fPath);
+
+// if fileRefDict is NULL, this call creates one
+// if not NULL, then the key value is added to it
+CFMutableDictionaryRef CreateFileRefDict (CFStringRef fKey, CFStringRef fPath, CFMutableDictionaryRef fileRefDict);
+
+int AccessURLAsset(const CFURLRef inURL, int mode);
+
+#if DEBUG
+ void PrintAUParamEvent (AudioUnitParameterEvent& event, FILE* f);
+#endif
+
+
+
+#endif // __AUBaseHelper_h__ \ No newline at end of file
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.cpp
new file mode 100644
index 0000000000..36bb41fa58
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.cpp
@@ -0,0 +1,219 @@
+/*
+ File: AUBuffer.cpp
+ Abstract: AUBuffer.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUBuffer.h"
+#include <stdlib.h>
+
+AUBufferList::~AUBufferList()
+{
+ Deallocate();
+ if (mPtrs)
+ free(mPtrs);
+}
+
+// a * b + c
+static UInt32 SafeMultiplyAddUInt32(UInt32 a, UInt32 b, UInt32 c)
+{
+ if (a == 0 || b == 0) return c; // prevent zero divide
+
+ if (a > (0xFFFFFFFF - c) / b)
+ throw std::bad_alloc();
+
+ return a * b + c;
+}
+
+void AUBufferList::Allocate(const CAStreamBasicDescription &format, UInt32 nFrames)
+{
+ UInt32 nStreams;
+ if (format.IsInterleaved()) {
+ nStreams = 1;
+ } else {
+ nStreams = format.mChannelsPerFrame;
+ }
+
+ // careful -- the I/O thread could be running!
+ if (nStreams > mAllocatedStreams) {
+ size_t theHeaderSize = sizeof(AudioBufferList) - sizeof(AudioBuffer);
+ mPtrs = (AudioBufferList *)CA_realloc(mPtrs,
+ SafeMultiplyAddUInt32(nStreams, sizeof(AudioBuffer), theHeaderSize));
+ mAllocatedStreams = nStreams;
+ }
+ UInt32 bytesPerStream = SafeMultiplyAddUInt32(nFrames, format.mBytesPerFrame, 0xF) & ~0xF;
+ UInt32 nBytes = SafeMultiplyAddUInt32(nStreams, bytesPerStream, 0);
+ if (nBytes > mAllocatedBytes) {
+ if (mExternalMemory) {
+ mExternalMemory = false;
+ mMemory = NULL;
+ }
+ mMemory = (Byte *)CA_realloc(mMemory, nBytes);
+ mAllocatedBytes = nBytes;
+ }
+ mAllocatedFrames = nFrames;
+ mPtrState = kPtrsInvalid;
+}
+
+void AUBufferList::Deallocate()
+{
+ mAllocatedStreams = 0;
+ mAllocatedFrames = 0;
+ mAllocatedBytes = 0;
+// this causes a world of hurt if someone upstream disconnects during I/O (SysSoundGraph)
+/* if (mPtrs) {
+ printf("deallocating bufferlist %08X\n", int(mPtrs));
+ free(mPtrs);
+ mPtrs = NULL;
+ } */
+ if (mMemory) {
+ if (mExternalMemory)
+ mExternalMemory = false;
+ else
+ free(mMemory);
+ mMemory = NULL;
+ }
+ mPtrState = kPtrsInvalid;
+}
+
+AudioBufferList & AUBufferList::PrepareBuffer(const CAStreamBasicDescription &format, UInt32 nFrames)
+{
+ if (nFrames > mAllocatedFrames)
+ COMPONENT_THROW(kAudioUnitErr_TooManyFramesToProcess);
+
+ UInt32 nStreams;
+ UInt32 channelsPerStream;
+ if (format.IsInterleaved()) {
+ nStreams = 1;
+ channelsPerStream = format.mChannelsPerFrame;
+ } else {
+ nStreams = format.mChannelsPerFrame;
+ channelsPerStream = 1;
+ if (nStreams > mAllocatedStreams)
+ COMPONENT_THROW(kAudioUnitErr_FormatNotSupported);
+ }
+
+ AudioBufferList *abl = mPtrs;
+ abl->mNumberBuffers = nStreams;
+ AudioBuffer *buf = abl->mBuffers;
+ Byte *mem = mMemory;
+ UInt32 streamInterval = (mAllocatedFrames * format.mBytesPerFrame + 0xF) & ~0xF;
+ UInt32 bytesPerBuffer = nFrames * format.mBytesPerFrame;
+ for ( ; nStreams--; ++buf) {
+ buf->mNumberChannels = channelsPerStream;
+ buf->mData = mem;
+ buf->mDataByteSize = bytesPerBuffer;
+ mem += streamInterval;
+ }
+ if (UInt32(mem - mMemory) > mAllocatedBytes)
+ COMPONENT_THROW(kAudioUnitErr_TooManyFramesToProcess);
+ mPtrState = kPtrsToMyMemory;
+ return *mPtrs;
+}
+
+AudioBufferList & AUBufferList::PrepareNullBuffer(const CAStreamBasicDescription &format, UInt32 nFrames)
+{
+ UInt32 nStreams;
+ UInt32 channelsPerStream;
+ if (format.IsInterleaved()) {
+ nStreams = 1;
+ channelsPerStream = format.mChannelsPerFrame;
+ } else {
+ nStreams = format.mChannelsPerFrame;
+ channelsPerStream = 1;
+ if (nStreams > mAllocatedStreams)
+ COMPONENT_THROW(kAudioUnitErr_FormatNotSupported);
+ }
+ AudioBufferList *abl = mPtrs;
+ abl->mNumberBuffers = nStreams;
+ AudioBuffer *buf = abl->mBuffers;
+ UInt32 bytesPerBuffer = nFrames * format.mBytesPerFrame;
+ for ( ; nStreams--; ++buf) {
+ buf->mNumberChannels = channelsPerStream;
+ buf->mData = NULL;
+ buf->mDataByteSize = bytesPerBuffer;
+ }
+ mPtrState = kPtrsToExternalMemory;
+ return *mPtrs;
+}
+
+// this should NOT be called while I/O is in process
+void AUBufferList::UseExternalBuffer(const CAStreamBasicDescription &format, const AudioUnitExternalBuffer &buf)
+{
+ UInt32 alignedSize = buf.size & ~0xF;
+ if (mMemory != NULL && alignedSize >= mAllocatedBytes) {
+ // don't accept the buffer if we already have one and it's big enough
+ // if we don't already have one, we don't need one
+ Byte *oldMemory = mMemory;
+ mMemory = buf.buffer;
+ mAllocatedBytes = alignedSize;
+ // from Allocate(): nBytes = nStreams * nFrames * format.mBytesPerFrame;
+ // thus: nFrames = nBytes / (nStreams * format.mBytesPerFrame)
+ mAllocatedFrames = mAllocatedBytes / (format.NumberChannelStreams() * format.mBytesPerFrame);
+ mExternalMemory = true;
+ free(oldMemory);
+ }
+}
+
+#if DEBUG
+void AUBufferList::PrintBuffer(const char *label, int subscript, const AudioBufferList &abl, UInt32 nFrames, bool asFloats)
+{
+ printf(" %s [%d] 0x%08lX:\n", label, subscript, long(&abl));
+ const AudioBuffer *buf = abl.mBuffers;
+ for (UInt32 i = 0; i < abl.mNumberBuffers; ++buf, ++i) {
+ printf(" [%2d] %5dbytes %dch @ %p: ", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData);
+ if (buf->mData != NULL) {
+ UInt32 nSamples = nFrames * buf->mNumberChannels;
+ for (UInt32 j = 0; j < nSamples; ++j) {
+ if (nSamples > 16 && (j % 16) == 0)
+ printf("\n\t");
+ if (asFloats)
+ printf(" %6.3f", ((float *)buf->mData)[j]);
+ else
+ printf(" %08X", (unsigned)((UInt32 *)buf->mData)[j]);
+ }
+ }
+ printf("\n");
+ }
+}
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.h
new file mode 100644
index 0000000000..64ea4c3971
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.h
@@ -0,0 +1,267 @@
+/*
+ File: AUBuffer.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUBuffer_h__
+#define __AUBuffer_h__
+
+#include <TargetConditionals.h>
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnit.h>
+#else
+ #include <AudioUnit.h>
+#endif
+
+#include <string.h>
+#include "CAStreamBasicDescription.h"
+#include "CAAutoDisposer.h"
+#include "CADebugMacros.h"
+
+// make this usable outside the stricter context of AudiUnits
+#ifndef COMPONENT_THROW
+ #define COMPONENT_THROW(err) \
+ do { DebugMessage(#err); throw static_cast<OSStatus>(err); } while (0)
+#endif
+
+
+ /*! @class AUBufferList */
+class AUBufferList {
+ enum EPtrState {
+ kPtrsInvalid,
+ kPtrsToMyMemory,
+ kPtrsToExternalMemory
+ };
+public:
+ /*! @ctor AUBufferList */
+ AUBufferList() : mPtrState(kPtrsInvalid), mExternalMemory(false), mPtrs(NULL), mMemory(NULL),
+ mAllocatedStreams(0), mAllocatedFrames(0), mAllocatedBytes(0) { }
+ /*! @dtor ~AUBufferList */
+ ~AUBufferList();
+
+ /*! @method PrepareBuffer */
+ AudioBufferList & PrepareBuffer(const CAStreamBasicDescription &format, UInt32 nFrames);
+ /*! @method PrepareNullBuffer */
+ AudioBufferList & PrepareNullBuffer(const CAStreamBasicDescription &format, UInt32 nFrames);
+
+ /*! @method SetBufferList */
+ AudioBufferList & SetBufferList(const AudioBufferList &abl) {
+ if (mAllocatedStreams < abl.mNumberBuffers)
+ COMPONENT_THROW(-1);
+ mPtrState = kPtrsToExternalMemory;
+ memcpy(mPtrs, &abl, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl);
+ return *mPtrs;
+ }
+
+ /*! @method SetBuffer */
+ void SetBuffer(UInt32 index, const AudioBuffer &ab) {
+ if (mPtrState == kPtrsInvalid || index >= mPtrs->mNumberBuffers)
+ COMPONENT_THROW(-1);
+ mPtrState = kPtrsToExternalMemory;
+ mPtrs->mBuffers[index] = ab;
+ }
+
+ /*! @method InvalidateBufferList */
+ void InvalidateBufferList() { mPtrState = kPtrsInvalid; }
+
+ /*! @method GetBufferList */
+ AudioBufferList & GetBufferList() const {
+ if (mPtrState == kPtrsInvalid)
+ COMPONENT_THROW(-1);
+ return *mPtrs;
+ }
+
+ /*! @method CopyBufferListTo */
+ void CopyBufferListTo(AudioBufferList &abl) const {
+ if (mPtrState == kPtrsInvalid)
+ COMPONENT_THROW(-1);
+ memcpy(&abl, mPtrs, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl);
+ }
+
+ /*! @method CopyBufferContentsTo */
+ void CopyBufferContentsTo(AudioBufferList &abl) const {
+ if (mPtrState == kPtrsInvalid)
+ COMPONENT_THROW(-1);
+ const AudioBuffer *srcbuf = mPtrs->mBuffers;
+ AudioBuffer *destbuf = abl.mBuffers;
+
+ for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++srcbuf, ++destbuf) {
+ if (i >= mPtrs->mNumberBuffers) // duplicate last source to additional outputs [4341137]
+ --srcbuf;
+ if (destbuf->mData != srcbuf->mData)
+ memmove(destbuf->mData, srcbuf->mData, srcbuf->mDataByteSize);
+ destbuf->mDataByteSize = srcbuf->mDataByteSize;
+ }
+ }
+
+ /*! @method Allocate */
+ void Allocate(const CAStreamBasicDescription &format, UInt32 nFrames);
+ /*! @method Deallocate */
+ void Deallocate();
+
+ /*! @method UseExternalBuffer */
+ void UseExternalBuffer(const CAStreamBasicDescription &format, const AudioUnitExternalBuffer &buf);
+
+ // AudioBufferList utilities
+ /*! @method ZeroBuffer */
+ static void ZeroBuffer(AudioBufferList &abl) {
+ AudioBuffer *buf = abl.mBuffers;
+ for (UInt32 i = abl.mNumberBuffers ; i--; ++buf)
+ memset(buf->mData, 0, buf->mDataByteSize);
+ }
+#if DEBUG
+ /*! @method PrintBuffer */
+ static void PrintBuffer(const char *label, int subscript, const AudioBufferList &abl, UInt32 nFrames = 8, bool asFloats = true);
+#endif
+
+ /*! @method GetAllocatedFrames */
+ UInt32 GetAllocatedFrames() const { return mAllocatedFrames; }
+
+private:
+ /*! @ctor AUBufferList */
+ AUBufferList(AUBufferList &) { } // prohibit copy constructor
+
+ /*! @var mPtrState */
+ EPtrState mPtrState;
+ /*! @var mExternalMemory */
+ bool mExternalMemory;
+ /*! @var mPtrs */
+ AudioBufferList * mPtrs;
+ /*! @var mMemory */
+ Byte * mMemory;
+ /*! @var mAllocatedStreams */
+ UInt32 mAllocatedStreams;
+ /*! @var mAllocatedFrames */
+ UInt32 mAllocatedFrames;
+ /*! @var mAllocatedBytes */
+ UInt32 mAllocatedBytes;
+};
+
+
+// Allocates an array of samples (type T), to be optimally aligned for the processor
+ /*! @class TAUBuffer */
+template <class T>
+class TAUBuffer {
+public:
+ enum {
+ kAlignInterval = 0x10,
+ kAlignMask = kAlignInterval - 1
+ };
+
+ /*! @ctor TAUBuffer.0 */
+ TAUBuffer() : mMemObject(NULL), mAlignedBuffer(NULL), mBufferSizeBytes(0)
+ {
+ }
+
+ /*! @ctor TAUBuffer.1 */
+ TAUBuffer(UInt32 numElems, UInt32 numChannels) : mMemObject(NULL), mAlignedBuffer(NULL),
+ mBufferSizeBytes(0)
+ {
+ Allocate(numElems, numChannels);
+ }
+
+ /*! @dtor ~TAUBuffer */
+ ~TAUBuffer()
+ {
+ Deallocate();
+ }
+
+ /*! @method Allocate */
+ void Allocate(UInt32 numElems) // can also re-allocate
+ {
+ UInt32 reqSize = numElems * sizeof(T);
+
+ if (mMemObject != NULL && reqSize == mBufferSizeBytes)
+ return; // already allocated
+
+ mBufferSizeBytes = reqSize;
+ mMemObject = CA_realloc(mMemObject, reqSize);
+ UInt32 misalign = (uintptr_t)mMemObject & kAlignMask;
+ if (misalign) {
+ mMemObject = CA_realloc(mMemObject, reqSize + kAlignMask);
+ mAlignedBuffer = (T *)((char *)mMemObject + kAlignInterval - misalign);
+ } else
+ mAlignedBuffer = (T *)mMemObject;
+ }
+
+ /*! @method Deallocate */
+ void Deallocate()
+ {
+ if (mMemObject == NULL) return; // so this method has no effect if we're using
+ // an external buffer
+
+ free(mMemObject);
+ mMemObject = NULL;
+ mAlignedBuffer = NULL;
+ mBufferSizeBytes = 0;
+ }
+
+ /*! @method AllocateClear */
+ void AllocateClear(UInt32 numElems) // can also re-allocate
+ {
+ Allocate(numElems);
+ Clear();
+ }
+
+ /*! @method Clear */
+ void Clear()
+ {
+ memset(mAlignedBuffer, 0, mBufferSizeBytes);
+ }
+
+ // accessors
+
+ /*! @method operator T *()@ */
+ operator T *() { return mAlignedBuffer; }
+
+private:
+ /*! @var mMemObject */
+ void * mMemObject; // null when using an external buffer
+ /*! @var mAlignedBuffer */
+ T * mAlignedBuffer; // always valid once allocated
+ /*! @var mBufferSizeBytes */
+ UInt32 mBufferSizeBytes;
+};
+
+#endif // __AUBuffer_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h
new file mode 100644
index 0000000000..f628a915e1
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h
@@ -0,0 +1,155 @@
+/*
+ File: AUInputFormatConverter.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUInputFormatConverter_h__
+#define __AUInputFormatConverter_h__
+
+#include "FormatConverterClient.h"
+#include "AUTimestampGenerator.h"
+
+// ____________________________________________________________________________
+// AUInputFormatConverter
+//
+// Subclass of FormatConverterClient that applies a format conversion
+// to an input of an AudioUnit.
+ /*! @class AUInputFormatConverter */
+class AUInputFormatConverter : public FormatConverterClient {
+public:
+ /*! @ctor AUInputFormatConverter */
+ AUInputFormatConverter(AUBase *hostAU, int inputBus) :
+ mHost(hostAU),
+ mHostBus(inputBus),
+ mPreviousSilentFrames(0x1000)
+ {
+#if DEBUG
+ mTimestampGenerator.mVerbosity = 0;
+ strcpy(mTimestampGenerator.mDebugName, "AUConverter");
+#endif
+ }
+
+ // need to subsequently call Initialize, with the desired formats
+
+ /*! @dtor ~AUInputFormatConverter */
+ ~AUInputFormatConverter()
+ {
+ }
+
+ virtual OSStatus Initialize(const AudioStreamBasicDescription &src, const AudioStreamBasicDescription &dest)
+ {
+ OSStatus err = FormatConverterClient::Initialize(src, dest);
+ if (err) return err;
+ mIsPCMToPCM = (src.mFormatID == kAudioFormatLinearPCM) && (dest.mFormatID == kAudioFormatLinearPCM);
+ mHasSRC = (fnonzero(src.mSampleRate) && fnonzero(dest.mSampleRate) && fnotequal(src.mSampleRate, dest.mSampleRate));
+ return ca_noErr;
+ }
+
+ virtual OSStatus Reset()
+ {
+ mPreviousSilentFrames = 0x1000;
+ mTimestampGenerator.Reset();
+ return FormatConverterClient::Reset();
+ }
+
+ void SetStartInputTimeAtZero(bool b)
+ {
+ mTimestampGenerator.SetStartInputAtZero(b);
+ }
+
+ /*! @method FillComplexBuffer */
+ OSStatus AUFillComplexBuffer(const AudioTimeStamp & inTimeStamp,
+ UInt32 & ioOutputDataPacketSize,
+ AudioBufferList & outOutputData,
+ AudioStreamPacketDescription* outPacketDescription,
+ bool& outSilence)
+ {
+ mTimestampGenerator.AddOutputTime(inTimeStamp, ioOutputDataPacketSize, mOutputFormat.mSampleRate);
+ mSilentOutput = true;
+ OSStatus err = FillComplexBuffer(ioOutputDataPacketSize, outOutputData, outPacketDescription);
+ if (mSilentOutput) {
+ if (!mIsPCMToPCM || (mHasSRC && mPreviousSilentFrames < 32))
+ mSilentOutput = false;
+ mPreviousSilentFrames += ioOutputDataPacketSize;
+ } else
+ mPreviousSilentFrames = 0;
+ outSilence = mSilentOutput;
+ return err;
+ }
+
+ /*! @method FormatConverterInputProc */
+ virtual OSStatus FormatConverterInputProc(
+ UInt32 & ioNumberDataPackets,
+ AudioBufferList & ioData,
+ AudioStreamPacketDescription** outDataPacketDescription)
+ {
+ OSStatus err = ca_noErr;
+
+ AudioUnitRenderActionFlags actionFlags = 0;
+ AUInputElement *input = mHost->GetInput(mHostBus);
+ *ioNumberDataPackets = std::min(*ioNumberDataPackets, This->mHost->GetMaxFramesPerSlice());
+ const AudioTimeStamp &inputTime = mTimestampGenerator.GenerateInputTime(ioNumberDataPackets, mInputFormat.mSampleRate);
+ err = input->PullInput(actionFlags, inputTime, mHostBus, ioNumberDataPackets);
+ if (!err) {
+ input->CopyBufferListTo(ioData);
+ if (!(actionFlags & kAudioUnitRenderAction_OutputIsSilence))
+ mSilentOutput = false;
+ }
+ return err;
+ }
+
+protected:
+ /*! @var mHost */
+ AUBase * mHost;
+ /*! @var mHostBus */
+ int mHostBus;
+
+ AUTimestampGenerator mTimestampGenerator;
+ bool mIsPCMToPCM;
+ bool mHasSRC;
+ bool mSilentOutput;
+ UInt32 mPreviousSilentFrames;
+};
+
+#endif // __AUInputFormatConverter_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUMIDIDefs.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUMIDIDefs.h
new file mode 100644
index 0000000000..e83c0e7e8d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUMIDIDefs.h
@@ -0,0 +1,138 @@
+/*
+ File: AUMIDIDefs.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUMIDIDefs_h__
+#define __AUMIDIDefs_h__
+
+#if !defined(__TMidiMessage) /* DAS HACK */
+enum
+{
+ kMidiMessage_NoteOff = 0x80,
+ kMidiMessage_NoteOn = 0x90,
+ kMidiMessage_PolyPressure = 0xA0,
+ kMidiMessage_ControlChange = 0xB0,
+ kMidiMessage_ProgramChange = 0xC0,
+ kMidiMessage_ChannelPressure = 0xD0,
+ kMidiMessage_PitchWheel = 0xE0,
+ kMidiMessage_SysEx = 0xF0,
+ kMidiMessage_SysEx_End = 0xF7,
+ kMidiMessage_MetaEvent = 0xFF
+};
+#endif
+
+enum
+{
+ kMidiController_BankSelect = 0,
+ kMidiController_ModWheel = 1,
+ kMidiController_Breath = 2,
+ kMidiController_Foot = 4,
+ kMidiController_PortamentoTime = 5,
+ kMidiController_DataEntry = 6,
+ kMidiController_Volume = 7,
+ kMidiController_Balance = 8,
+ kMidiController_Pan = 10,
+ kMidiController_Expression = 11,
+
+ // these controls have a (0-63) == off, (64-127) == on
+ kMidiController_Sustain = 64, //hold1
+ kMidiController_Portamento = 65,
+ kMidiController_Sostenuto = 66,
+ kMidiController_Soft = 67,
+ kMidiController_LegatoPedal = 68,
+ kMidiController_Hold2Pedal = 69,
+ kMidiController_FilterResonance = 71,
+ kMidiController_ReleaseTime = 72,
+ kMidiController_AttackTime = 73,
+ kMidiController_Brightness = 74,
+ kMidiController_DecayTime = 75,
+ kMidiController_VibratoRate = 76,
+ kMidiController_VibratoDepth = 77,
+ kMidiController_VibratoDelay = 78,
+
+ // these controls have a 0-127 range and in MIDI they have no LSB (so fractional values are lost in MIDI)
+ kMidiController_ReverbLevel = 91,
+ kMidiController_ChorusLevel = 93,
+
+ kMidiController_RPN_LSB = 100,
+ kMidiController_RPN_MSB = 101,
+
+ kMidiController_AllSoundOff = 120,
+ kMidiController_ResetAllControllers = 121,
+ kMidiController_AllNotesOff = 123,
+ kMidiController_OmniModeOff = 124,
+ kMidiController_OmniModeOn = 125,
+ kMidiController_MonoModeOn = 126,
+ kMidiController_MonoModeOff = 127
+};
+
+// RPN values
+enum
+{
+ kMidiControllerValue_RPNPitchBendSensitivity = 0,
+ kMidiControllerValue_RPNChannelFineTuning = 1,
+ kMidiControllerValue_RPNChannelCoarseTuning = 2,
+ kMidiControllerValue_RPNModDepthRange = 5,
+ kMidiControllerValue_RPNNull = 0x3fff //! 0x7f/0x7f
+};
+
+// GM2 Sound Bank Constants
+enum
+{
+ kGM2MelodicBank = 0x7900,
+ kGM2PercussionBank = 0x7800,
+ kGSPercussionBank = 0x7f00,
+ kXGSFXBank = 0x7E00,
+ kXGPercussionBank = kGSPercussionBank,
+ kBankMSBMask = 0xff00
+};
+
+enum
+{
+ kMSBController_MidPoint = 0x40
+};
+
+#endif // __AUMIDIDefs_h__
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUSilentTimeout.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUSilentTimeout.h
new file mode 100644
index 0000000000..9fbd3e1f23
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUSilentTimeout.h
@@ -0,0 +1,93 @@
+/*
+ File: AUSilentTimeout.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUSilentTimeout
+#define __AUSilentTimeout
+
+class AUSilentTimeout
+{
+public:
+ AUSilentTimeout()
+ : mTimeoutCounter(0),
+ mResetTimer(true)
+ {};
+
+ void Process(UInt32 inFramesToProcess, UInt32 inTimeoutLimit, bool &ioSilence )
+ {
+ if(ioSilence )
+ {
+ if(mResetTimer )
+ {
+ mTimeoutCounter = inTimeoutLimit;
+ mResetTimer = false;
+ }
+
+ if(mTimeoutCounter > 0 )
+ {
+ mTimeoutCounter -= inFramesToProcess;
+ ioSilence = false;
+ }
+ }
+ else
+ {
+ // signal to reset the next time we receive silence
+ mResetTimer = true;
+ }
+ }
+
+ void Reset()
+ {
+ mResetTimer = true;
+ };
+
+
+
+private:
+ SInt32 mTimeoutCounter;
+ bool mResetTimer;
+};
+
+#endif // __AUSilentTimeout
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp
new file mode 100644
index 0000000000..7c57a81ede
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp
@@ -0,0 +1,203 @@
+/*
+ File: AUTimestampGenerator.cpp
+ Abstract: AUTimestampGenerator.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUTimestampGenerator.h"
+#include "CAMath.h"
+
+#if DEBUG
+static double DebugHostTime(const AudioTimeStamp &ts)
+{
+ static UInt64 baseHostTime = 0;
+ if (!(ts.mFlags & kAudioTimeStampHostTimeValid))
+ return -1.;
+ if (baseHostTime == 0)
+ baseHostTime = ts.mHostTime;
+ return double(SInt64(ts.mHostTime) - SInt64(baseHostTime)) * CAHostTimeBase::GetInverseFrequency();
+}
+#endif
+
+void AUTimestampGenerator::AddOutputTime(const AudioTimeStamp &inTimeStamp, Float64 expectedDeltaFrames, double outputSampleRate, double rateScalarAdj)
+{
+ mState.mRateScalarAdj = rateScalarAdj;
+ mState.mLastOutputTime = mState.mCurrentOutputTime;
+ mState.mInputSampleTimeForOutputPull = mState.mNextInputSampleTime;
+ mState.mCurrentOutputTime = inTimeStamp;
+
+ if (mState.mBypassed)
+ return;
+
+ if (mState.mHostTimeDiscontinuityCorrection && !(mState.mCurrentOutputTime.mFlags & kAudioTimeStampHostTimeValid) && (mState.mLastOutputTime.mFlags & kAudioTimeStampHostTimeValid)) {
+ // no host time here but we had one last time, interpolate one
+ double rateScalar = (mState.mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid) ? mState.mCurrentOutputTime.mRateScalar : 1.0;
+ Float64 deltaSamples = mState.mCurrentOutputTime.mSampleTime - mState.mLastOutputTime.mSampleTime;
+ mState.mCurrentOutputTime.mHostTime = mState.mLastOutputTime.mHostTime +
+ UInt64(CAHostTimeBase::GetFrequency() * deltaSamples * rateScalar / outputSampleRate);
+ mState.mCurrentOutputTime.mFlags |= kAudioTimeStampHostTimeValid;
+#if DEBUG
+ if (mVerbosity > 1)
+ printf("synthesized host time: %.3f (%.3f + %.f smp @ %.f Hz, rs %.3f\n", DebugHostTime(mState.mCurrentOutputTime), DebugHostTime(mState.mLastOutputTime), deltaSamples, outputSampleRate, rateScalar);
+#endif
+ }
+ // copy rate scalar
+ if (rateScalarAdj != 1.0) {
+ if (mState.mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid)
+ mState.mCurrentOutputTime.mRateScalar *= rateScalarAdj;
+ else {
+ mState.mCurrentOutputTime.mRateScalar = rateScalarAdj;
+ mState.mCurrentOutputTime.mFlags |= kAudioTimeStampRateScalarValid;
+ }
+ }
+
+ if (mFirstTime) {
+ mFirstTime = false;
+ mState.mDiscontinuous = false;
+ mState.mDiscontinuityDeltaSamples = 0.;
+ if (!mState.mStartInputAtZero) {
+ mState.mNextInputSampleTime = mState.mCurrentOutputTime.mSampleTime;
+ mState.mInputSampleTimeForOutputPull = mState.mNextInputSampleTime;
+ }
+ } else {
+ mState.mDiscontinuous = fnotequal(mState.mCurrentOutputTime.mSampleTime, mState.mNextOutputSampleTime);
+ mState.mDiscontinuityDeltaSamples = mState.mCurrentOutputTime.mSampleTime - mState.mNextOutputSampleTime;
+ // time should never go backwards...
+ if (mState.mDiscontinuityDeltaSamples < 0.)
+ mState.mDiscontinuityDeltaSamples = 0.;
+#if DEBUG
+ if (mVerbosity > 1)
+ if (mState.mDiscontinuous)
+ printf("%-20.20s: *** DISCONTINUOUS, got " TSGFMT ", expected " TSGFMT "\n", mDebugName, (SInt64)mState.mCurrentOutputTime.mSampleTime, (SInt64)mState.mNextOutputSampleTime);
+#endif
+ }
+ mState.mNextOutputSampleTime = mState.mCurrentOutputTime.mSampleTime + expectedDeltaFrames;
+}
+
+const AudioTimeStamp & AUTimestampGenerator::GenerateInputTime(Float64 framesToAdvance, double inputSampleRate, bool advanceHostTime)
+{
+ if (mState.mBypassed)
+ return mState.mCurrentOutputTime;
+
+ double inputSampleTime;
+
+ mState.mCurrentInputTime.mFlags = kAudioTimeStampSampleTimeValid;
+ double rateScalar = 1.0;
+
+ // propagate rate scalar
+ if (mState.mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid) {
+ mState.mCurrentInputTime.mFlags |= kAudioTimeStampRateScalarValid;
+ mState.mCurrentInputTime.mRateScalar = rateScalar = mState.mCurrentOutputTime.mRateScalar;
+ }
+
+ // propagate host time and sample time
+ if (mState.mCurrentOutputTime.mFlags & kAudioTimeStampHostTimeValid) {
+ mState.mCurrentInputTime.mFlags |= kAudioTimeStampHostTimeValid;
+ if (advanceHostTime) {
+ Float64 deltaSamples = mState.mNextInputSampleTime - mState.mInputSampleTimeForOutputPull;
+ Float64 deltaSeconds = (deltaSamples / inputSampleRate) * mState.mRateScalarAdj;
+ UInt64 deltaHostTime = (UInt64)(deltaSeconds * CAHostTimeBase::GetFrequency());
+ mState.mCurrentInputTime.mHostTime = mState.mCurrentOutputTime.mHostTime + deltaHostTime;
+ } else {
+ mState.mCurrentInputTime.mHostTime = mState.mCurrentOutputTime.mHostTime;
+ }
+ if (mState.mHostTimeDiscontinuityCorrection && mState.mDiscontinuous && (mState.mLastOutputTime.mFlags & kAudioTimeStampHostTimeValid)) {
+ // we had a discontinuous output time, need to resync by interpolating
+ // a sample time that is appropriate to the host time
+ UInt64 deltaHostTime = mState.mCurrentOutputTime.mHostTime - mState.mLastOutputTime.mHostTime;
+ double deltaSeconds = double(deltaHostTime) * CAHostTimeBase::GetInverseFrequency();
+ // samples/second * seconds = samples
+ double deltaSamples = floor(inputSampleRate / rateScalar * deltaSeconds + 0.5);
+ double lastInputSampleTime = mState.mCurrentInputTime.mSampleTime;
+ inputSampleTime = lastInputSampleTime + deltaSamples;
+#if DEBUG
+ if (mVerbosity > 1)
+ printf("%-20.20s: adjusted input time: " TSGFMT " -> " TSGFMT " (SR=%.3f, rs=%.3f)\n", mDebugName, (SInt64)lastInputSampleTime, (SInt64)inputSampleTime, inputSampleRate, rateScalar);
+#endif
+ mState.mDiscontinuous = false;
+ } else {
+ inputSampleTime = mState.mNextInputSampleTime;
+ }
+ } else {
+ // we don't know the host time, so we can't do much
+ inputSampleTime = mState.mNextInputSampleTime;
+ }
+
+ if (!mState.mHostTimeDiscontinuityCorrection && fnonzero(mState.mDiscontinuityDeltaSamples))
+ {
+ // we had a discontinuous output time, need to resync by propagating the
+ // detected discontinuity, taking the rate scalar adjustment into account
+ inputSampleTime += floor(mState.mDiscontinuityDeltaSamples / mState.mRateScalarAdj + 0.5);
+
+#if DEBUG
+ if (mVerbosity > 1)
+ printf("%-20.20s: adjusted input time: %.0f -> %.0f (SR=%.3f, rs=%.3f, delta=%.0f)\n", mDebugName, mState.mNextInputSampleTime, inputSampleTime, inputSampleRate, mState.mRateScalarAdj, mState.mDiscontinuityDeltaSamples);
+#endif
+
+ mState.mDiscontinuityDeltaSamples = 0.;
+ }
+
+
+ // propagate word clock
+ if (mState.mCurrentOutputTime.mFlags & kAudioTimeStampWordClockTimeValid) {
+ mState.mCurrentInputTime.mFlags |= kAudioTimeStampWordClockTimeValid;
+ mState.mCurrentInputTime.mWordClockTime = mState.mCurrentOutputTime.mWordClockTime;
+ }
+
+ // propagate SMPTE time
+ if (mState.mCurrentOutputTime.mFlags & kAudioTimeStampSMPTETimeValid) {
+ mState.mCurrentInputTime.mFlags |= kAudioTimeStampSMPTETimeValid;
+ mState.mCurrentInputTime.mSMPTETime = mState.mCurrentOutputTime.mSMPTETime;
+ }
+
+ // store the input sample time and expected next input time
+ mState.mCurrentInputTime.mSampleTime = inputSampleTime;
+ mState.mNextInputSampleTime = inputSampleTime + framesToAdvance;
+
+#if DEBUG
+ if (mVerbosity > 0) {
+ printf("%-20.20s: out = " TSGFMT " (%10.3fs) in = " TSGFMT " (%10.3fs) delta = " TSGFMT " advance = " TSGFMT "\n", mDebugName, (SInt64)mState.mCurrentOutputTime.mSampleTime, DebugHostTime(mState.mCurrentOutputTime), (SInt64)inputSampleTime, DebugHostTime(mState.mCurrentInputTime), (SInt64)(mState.mCurrentOutputTime.mSampleTime - inputSampleTime), (SInt64)framesToAdvance);
+ }
+#endif
+ return mState.mCurrentInputTime;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h
new file mode 100644
index 0000000000..cfd8456dfb
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h
@@ -0,0 +1,163 @@
+/*
+ File: AUTimestampGenerator.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUTimestampGenerator_h__
+#define __AUTimestampGenerator_h__
+
+#include <math.h>
+#include "CAHostTimeBase.h"
+#include <stdio.h>
+
+#define TSGFMT "0x%10qx"
+//#define TSGFMT "%10qd"
+
+// This class generates a continuously increasing series of timestamps based
+// on a series of potentially discontinuous timestamps (as can be delivered from
+// CoreAudio in the event of an overload or major engine change).
+// N.B.: "output" = downstream (source) timestamp
+// "input" = upstream (derived) timestamp
+class AUTimestampGenerator {
+public:
+ AUTimestampGenerator(bool hostTimeDiscontinuityCorrection = false)
+ {
+ mState.mStartInputAtZero = true;
+ mState.mBypassed = false;
+ mState.mHostTimeDiscontinuityCorrection = hostTimeDiscontinuityCorrection;
+#if DEBUG
+ mVerbosity = 0;
+ snprintf(mDebugName, sizeof(mDebugName), "tsg @ %p", this);
+#endif
+ // CAHostTimeBase should be used instead of the calls in <CoreAudio/HostTime.h>
+ // we make this call here to ensure that this is initialized, otherwise the first time
+ // you do actually call CAHostTimeBase to do work, can be on the render thread, and lead to unwanted VM faults
+ CAHostTimeBase::GetFrequency();
+ Reset();
+ }
+
+ void SetStartInputAtZero(bool b) { mState.mStartInputAtZero = b; }
+ bool GetStartInputAtZero() const { return mState.mStartInputAtZero; }
+
+ // bypassing is intended for a narrow special case. the upstream sample time will always be the same as the downstream time.
+ void SetBypassed(bool b) { mState.mBypassed = b; }
+ bool GetBypassed() const { return mState.mBypassed; }
+
+ // Call this to reset the timeline.
+ void Reset()
+ {
+ mState.mCurrentInputTime.mSampleTime = 0.;
+ mState.mNextInputSampleTime = 0.;
+ mState.mCurrentOutputTime.mSampleTime = 0.;
+ mState.mNextOutputSampleTime = 0.;
+ mState.mLastOutputTime.mFlags = 0;
+ mState.mRateScalarAdj = 1.;
+
+ mFirstTime = true;
+#if DEBUG
+ if (mVerbosity)
+ printf("%-20.20s: Reset\n", mDebugName);
+#endif
+ }
+
+ // Call this once per render cycle with the downstream timestamp.
+ // expectedDeltaFrames is the expected difference between the current and NEXT
+ // downstream timestamps.
+ // sampleRate is the OUTPUT sample rate.
+ void AddOutputTime(const AudioTimeStamp &inTimeStamp, Float64 expectedDeltaFrames, double outputSampleRate, double rateScalarAdj=1.0);
+
+ // Call this once per render cycle to obtain the upstream timestamp.
+ // framesToAdvance is the number of frames the input timeline is to be
+ // advanced during this render cycle.
+ // sampleRate is the INPUT sample rate.
+ const AudioTimeStamp & GenerateInputTime(Float64 framesToAdvance, double inputSampleRate, bool advanceHostTime = false);
+
+ // this can be called to override the setting of the next input sample time in GenerateInputTime
+ void Advance(Float64 framesToAdvance)
+ {
+#if DEBUG
+ if (mVerbosity > 1)
+ printf("%-20.20s: ADVANCE in = " TSGFMT " advance = " TSGFMT "\n", mDebugName, (SInt64)mState.mCurrentInputTime.mSampleTime, (SInt64)framesToAdvance);
+#endif
+ mState.mNextInputSampleTime = mState.mCurrentInputTime.mSampleTime + framesToAdvance;
+ }
+
+ struct State {
+ AudioTimeStamp mCurrentInputTime;
+ Float64 mNextInputSampleTime;
+ Float64 mNextOutputSampleTime;
+ Float64 mInputSampleTimeForOutputPull;
+
+ AudioTimeStamp mLastOutputTime;
+ AudioTimeStamp mCurrentOutputTime;
+
+ bool mStartInputAtZero; // if true, input timeline starts at 0, else it starts
+ // synced with the output timeline
+ bool mDiscontinuous;
+ bool mBypassed;
+ Float64 mDiscontinuityDeltaSamples;
+
+ double mRateScalarAdj;
+
+ bool mHostTimeDiscontinuityCorrection; // If true, propagate timestamp discontinuities using host time.
+ };
+
+ void GetState(State& outState) const { outState = mState; }
+ void SetState(State const& inState) { mState = inState; mFirstTime = false; }
+
+private:
+
+ struct State mState;
+
+ bool mFirstTime;
+
+#if DEBUG
+public:
+ int mVerbosity;
+ char mDebugName[64];
+#endif
+};
+
+
+#endif // __AUTimestampGenerator_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.cpp b/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.cpp
new file mode 100644
index 0000000000..c2c8468bd9
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.cpp
@@ -0,0 +1,169 @@
+/*
+ File: AUOutputBL.cpp
+ Abstract: AUOutputBL.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUOutputBL.h"
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AUComponent.h>
+#else
+ #include <AUComponent.h>
+#endif
+/*
+struct AudioBufferList
+{
+ UInt32 mNumberBuffers;
+ AudioBuffer mBuffers[1];
+};
+struct AudioBuffer
+{
+ UInt32 mNumberChannels; // number of interleaved channels in the buffer
+ UInt32 mDataByteSize; // the size of the buffer pointed to by mData
+ void* mData; // the pointer to the buffer
+};
+*/
+
+AUOutputBL::AUOutputBL (const CAStreamBasicDescription &inDesc, UInt32 inDefaultNumFrames)
+ : mFormat (inDesc),
+ mBufferMemory(NULL),
+ mBufferList (NULL),
+ mNumberBuffers (0), // keep this here, so can ensure integrity of ABL
+ mBufferSize (0),
+ mFrames(inDefaultNumFrames)
+{
+ mNumberBuffers = mFormat.IsInterleaved() ? 1 : mFormat.NumberChannels();
+ mBufferList = reinterpret_cast<AudioBufferList*>(new Byte[offsetof(AudioBufferList, mBuffers) + (mNumberBuffers * sizeof(AudioBuffer))]);
+}
+
+AUOutputBL::~AUOutputBL()
+{
+ if (mBufferMemory)
+ delete[] mBufferMemory;
+
+ if (mBufferList)
+ delete [] (Byte *)mBufferList;
+}
+
+void AUOutputBL::Prepare (UInt32 inNumFrames, bool inWantNullBufferIfAllocated)
+{
+ UInt32 channelsPerBuffer = mFormat.IsInterleaved() ? mFormat.NumberChannels() : 1;
+
+ if (mBufferMemory == NULL || inWantNullBufferIfAllocated)
+ {
+ mBufferList->mNumberBuffers = mNumberBuffers;
+ AudioBuffer *buf = &mBufferList->mBuffers[0];
+ for (UInt32 i = 0; i < mNumberBuffers; ++i, ++buf) {
+ buf->mNumberChannels = channelsPerBuffer;
+ buf->mDataByteSize = mFormat.FramesToBytes (inNumFrames);
+ buf->mData = NULL;
+ }
+ }
+ else
+ {
+ UInt32 nBytes = mFormat.FramesToBytes (inNumFrames);
+ if ((nBytes * mNumberBuffers) > AllocatedBytes())
+ throw OSStatus(kAudioUnitErr_TooManyFramesToProcess);
+
+ mBufferList->mNumberBuffers = mNumberBuffers;
+ AudioBuffer *buf = &mBufferList->mBuffers[0];
+ Byte* p = mBufferMemory;
+ for (UInt32 i = 0; i < mNumberBuffers; ++i, ++buf) {
+ buf->mNumberChannels = channelsPerBuffer;
+ buf->mDataByteSize = nBytes;
+ buf->mData = p;
+ p += mBufferSize;
+ }
+ }
+}
+
+
+void AUOutputBL::Allocate (UInt32 inNumFrames)
+{
+ if (inNumFrames)
+ {
+ UInt32 nBytes = mFormat.FramesToBytes (inNumFrames);
+
+ if (nBytes <= AllocatedBytes())
+ return;
+
+ // align successive buffers for Altivec and to take alternating
+ // cache line hits by spacing them by odd multiples of 16
+ if (mNumberBuffers > 1)
+ nBytes = (nBytes + (0x10 - (nBytes & 0xF))) | 0x10;
+
+ mBufferSize = nBytes;
+
+ UInt32 memorySize = mBufferSize * mNumberBuffers;
+ Byte *newMemory = new Byte[memorySize];
+ memset(newMemory, 0, memorySize); // make buffer "hot"
+
+ Byte *oldMemory = mBufferMemory;
+ mBufferMemory = newMemory;
+ delete[] oldMemory;
+
+ mFrames = inNumFrames;
+ }
+ else
+ {
+ if (mBufferMemory) {
+ delete [] mBufferMemory;
+ mBufferMemory = NULL;
+ }
+ mBufferSize = 0;
+ mFrames = 0;
+ }
+}
+
+#if DEBUG
+void AUOutputBL::Print()
+{
+ printf ("AUOutputBL::Print\n");
+ mFormat.Print();
+ printf ("Num Buffers:%d, mFrames:%d, allocatedMemory:%c\n", (int)mBufferList->mNumberBuffers, (int)mFrames, (mBufferMemory != NULL ? 'T' : 'F'));
+ AudioBuffer *buf = &mBufferList->mBuffers[0];
+ for (UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i, ++buf)
+ printf ("\tBuffer:%d, Size:%d, Chans:%d, Buffer:%p\n", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData);
+}
+#endif
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.h b/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.h
new file mode 100644
index 0000000000..0baad3a579
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.h
@@ -0,0 +1,118 @@
+/*
+ File: AUOutputBL.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUOutputBL_h__
+#define __AUOutputBL_h__
+
+#include "CAStreamBasicDescription.h"
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+#else
+#endif
+
+// ____________________________________________________________________________
+//
+// AUOutputBL - Simple Buffer List wrapper targetted to use with retrieving AU output
+// Works in one of two ways (both adjustable)... Can use it with NULL pointers, or allocate
+// memory to receive the data in.
+
+// Before using this with any call to AudioUnitRender, it needs to be Prepared
+// as some calls to AudioUnitRender can reset the ABL
+
+class AUOutputBL {
+public:
+
+ // you CANNOT use one of these - it will crash!
+// AUOutputBL ();
+
+ // this is the constructor that you use
+ // it can't be reset once you've constructed it
+ AUOutputBL (const CAStreamBasicDescription &inDesc, UInt32 inDefaultNumFrames = 512);
+ ~AUOutputBL();
+
+ void Prepare ()
+ {
+ Prepare (mFrames);
+ }
+
+ // this version can throw if this is an allocted ABL and inNumFrames is > AllocatedFrames()
+ // you can set the bool to true if you want a NULL buffer list even if allocated
+ // inNumFrames must be a valid number (will throw if inNumFrames is 0)
+ void Prepare (UInt32 inNumFrames, bool inWantNullBufferIfAllocated = false);
+
+ AudioBufferList* ABL() { return mBufferList; }
+
+ // You only need to call this if you want to allocate a buffer list
+ // if you want an empty buffer list, just call Prepare()
+ // if you want to dispose previously allocted memory, pass in 0
+ // then you either have an empty buffer list, or you can re-allocate
+ // Memory is kept around if an Allocation request is less than what is currently allocated
+ void Allocate (UInt32 inNumberFrames);
+
+ UInt32 AllocatedFrames() const { return mFrames; }
+
+ const CAStreamBasicDescription& GetFormat() const { return mFormat; }
+
+#if DEBUG
+ void Print();
+#endif
+
+private:
+ UInt32 AllocatedBytes () const { return (mBufferSize * mNumberBuffers); }
+
+ CAStreamBasicDescription mFormat;
+ Byte* mBufferMemory;
+ AudioBufferList* mBufferList;
+ UInt32 mNumberBuffers;
+ UInt32 mBufferSize;
+ UInt32 mFrames;
+
+// don't want to copy these.. can if you want, but more code to write!
+ AUOutputBL () {}
+ AUOutputBL (const AUOutputBL &c);
+ AUOutputBL& operator= (const AUOutputBL& c);
+};
+
+#endif // __AUOutputBL_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.cpp b/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.cpp
new file mode 100644
index 0000000000..87d7848790
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.cpp
@@ -0,0 +1,139 @@
+/*
+ File: AUParamInfo.cpp
+ Abstract: AUParamInfo.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUParamInfo.h"
+#include "CAXException.h"
+
+AUParamInfo::AUParamInfo (AudioUnit inAU,
+ bool inIncludeExpert,
+ bool inIncludeReadOnly,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement)
+ : mAU (inAU),
+ mNumParams (0),
+ mParamListID(NULL),
+ mScope (inScope),
+ mElement (inElement)
+{
+ UInt32 size;
+ OSStatus result = AudioUnitGetPropertyInfo(mAU, kAudioUnitProperty_ParameterList, inScope, mElement, &size, NULL);
+ if (size == 0 || result) return;
+
+ int nparams = size / sizeof(AudioUnitPropertyID);
+ mParamListID = new AudioUnitParameterID[nparams];
+
+ memset (mParamListID, 0xFF, size);
+
+ AudioUnitParameterID *paramList = new AudioUnitParameterID[nparams];
+
+ result = AudioUnitGetProperty(mAU, kAudioUnitProperty_ParameterList, mScope, mElement, paramList, &size);
+ if (result) {
+ delete [] mParamListID;
+ delete [] paramList;
+ mParamListID = NULL;
+ return;
+ }
+
+ ParameterMap params;
+ for (int i = 0; i < nparams; ++i)
+ {
+ CAAUParameter auvp (mAU, paramList[i], mScope, mElement); // took out only using global scope in CAAUParameter creation
+ const AudioUnitParameterInfo &paramInfo = auvp.ParamInfo();
+
+ // don't include if parameter can't be read or written
+ if (!(paramInfo.flags & kAudioUnitParameterFlag_IsWritable)
+ && !(paramInfo.flags & kAudioUnitParameterFlag_IsReadable))
+ continue;
+
+ // only include if expert params wanted
+ if (!inIncludeExpert && auvp.IsExpert())
+ continue;
+
+ // only include if read only params are wanted
+ if (!(paramInfo.flags & kAudioUnitParameterFlag_IsWritable)
+ && (paramInfo.flags & kAudioUnitParameterFlag_IsReadable))
+ {
+ if (!inIncludeReadOnly)
+ continue;
+ }
+
+ mParamListID[mNumParams] = paramList[i];
+ mNumParams++;
+
+ // ok - if we're here, then we have a parameter we are going to display.
+ UInt32 clump = 0;
+ auvp.GetClumpID (clump);
+ mParams[clump].push_back (auvp);
+ }
+
+ delete [] paramList;
+}
+
+AUParamInfo::~AUParamInfo()
+{
+ delete [] mParamListID;
+}
+
+UInt32 AUParamInfo::NumParamsForClump (UInt32 inClump) const
+{
+ ParameterMap::const_iterator it = mParams.find(inClump);
+ if (it != mParams.end())
+ return static_cast<UInt32>((*it).second.size());
+ return 0;
+}
+
+const CAAUParameter* AUParamInfo::GetParamInfo (AudioUnitParameterID inParamID) const
+{
+ for (ParameterMap::const_iterator it = mParams.begin(); it != mParams.end(); ++it) {
+ const ParameterList &list = (*it).second;
+ for (ParameterList::const_iterator iter = list.begin(); iter != list.end(); ++iter) {
+ if (inParamID == (*iter).mParameterID) {
+ return &(*iter);
+ }
+ }
+ }
+ return NULL;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.h b/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.h
new file mode 100644
index 0000000000..d15fbfeb2d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.h
@@ -0,0 +1,112 @@
+/*
+ File: AUParamInfo.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include <map>
+#include <vector>
+#include <AudioUnit/AudioUnit.h>
+#include "CAAUParameter.h"
+
+/*
+ The ParameterMap returned by the Map() method is a map where
+ - the key is the clumpID
+ - the value is a ParameterList (vector<CAAUParameter>)
+
+ If you have parameters on multiple scopes (or elements within a scope), then you should create one of these
+ for each scope-element pair
+*/
+
+class AUParamInfo {
+
+public:
+ typedef std::vector <CAAUParameter> ParameterList;
+ typedef std::map <UInt32, ParameterList, std::less<UInt32> > ParameterMap;
+
+
+
+ AUParamInfo (AudioUnit inAU,
+ bool inIncludeExpert,
+ bool inIncludeReadOnly,
+ AudioUnitScope inScope = kAudioUnitScope_Global,
+ AudioUnitElement inElement = 0);
+
+ ~AUParamInfo();
+
+ const ParameterMap& Map () const { return mParams; }
+
+ // some convenience methods
+ UInt32 NumParams () const { return mNumParams; }
+
+ AudioUnitParameterID ParamID (UInt32 inIndex) const
+ {
+ if (inIndex < mNumParams) return mParamListID[inIndex];
+ return 0xFFFFFFFF;
+ }
+
+ UInt32 NumClumps () const { return static_cast<UInt32>(mParams.size()); }
+
+ UInt32 NumParamsForClump (UInt32 inClump) const;
+
+ // returns NULL if there's no info for the parameter
+ const CAAUParameter* GetParamInfo (AudioUnitParameterID inParamID) const;
+
+ AudioUnitScope GetScope () const { return mScope; }
+ AudioUnitElement GetElement () const { return mElement; }
+
+private:
+
+ AudioUnit mAU;
+ UInt32 mNumParams;
+ AudioUnitParameterID * mParamListID;
+
+ ParameterMap mParams;
+ AudioUnitScope mScope;
+ AudioUnitElement mElement;
+
+ // disallow
+ AUParamInfo () {}
+ AUParamInfo (const AUParamInfo &c) {}
+ AUParamInfo& operator= (const AUParamInfo& c) { return *this; }
+};
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.cpp
new file mode 100644
index 0000000000..4e72b22858
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.cpp
@@ -0,0 +1,227 @@
+/*
+ File: CAAUMIDIMap.cpp
+ Abstract: CAAUMIDIMap.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CAAUMIDIMap.h"
+#include <pthread.h>
+
+struct AllMidiTransformers
+{
+ MIDILinearTransformer linearTrans;
+ MIDILogTransformer logTrans;
+ MIDIExpTransformer expTrans;
+ MIDISqrtTransformer sqrtTrans;
+ MIDISquareTransformer squareTrans;
+ MIDICubeRtTransformer cubeRtTrans;
+ MIDICubeTransformer cubeTrans;
+};
+
+AllMidiTransformers* gAllMidiTransformers = NULL;
+
+#if TARGET_OS_MAC
+static pthread_once_t sOnce = PTHREAD_ONCE_INIT;
+
+static void InitAllMidiTransformers()
+{
+ gAllMidiTransformers = new AllMidiTransformers();
+}
+
+static void CheckInitAllMidiTransformers()
+{
+ pthread_once(&sOnce, InitAllMidiTransformers);
+}
+#endif
+
+MIDIValueTransformer * CAAUMIDIMap::GetTransformer (UInt32 inFlags)
+{
+#if TARGET_OS_MAC
+ if (gAllMidiTransformers == NULL)
+ CheckInitAllMidiTransformers();
+#else
+ if (gAllMidiTransformers == NULL)
+ gAllMidiTransformers = new AllMidiTransformers();
+#endif
+
+ if (AudioUnitDisplayTypeIsLogarithmic(inFlags))
+ return &gAllMidiTransformers->logTrans;
+ else if (AudioUnitDisplayTypeIsExponential(inFlags))
+ return &gAllMidiTransformers->expTrans;
+ else if (AudioUnitDisplayTypeIsSquareRoot(inFlags))
+ return &gAllMidiTransformers->sqrtTrans;
+ else if (AudioUnitDisplayTypeIsSquared(inFlags))
+ return &gAllMidiTransformers->squareTrans;
+ else if (AudioUnitDisplayTypeIsCubed(inFlags))
+ return &gAllMidiTransformers->cubeTrans;
+ else if (AudioUnitDisplayTypeIsCubeRoot(inFlags))
+ return &gAllMidiTransformers->cubeRtTrans;
+ else
+ return &gAllMidiTransformers->linearTrans;
+}
+
+// The CALLER of this method must ensure that the status byte's MIDI Command matches!!!
+bool CAAUMIDIMap::MIDI_Matches (UInt8 inChannel, UInt8 inData1, UInt8 inData2, Float32 &outLinear) const
+{
+ // see if the channels match first
+ SInt8 chan = Channel();
+ // channel matches (if chan is less than zero, "Any Channel" flag is set)
+ if (chan >= 0 && chan != inChannel)
+ return false;
+
+ // match the special cases first
+ if (IsKeyEvent()) {
+ // we're using this key event as an on/off type switch
+ if (IsBipolar()) {
+ if (IsKeyPressure()){
+ if (IsBipolar_OnValue()) {
+ if (inData2 > 63) {
+ outLinear = 1;
+ return true;
+ }
+ } else {
+ if (inData2 < 64) {
+ outLinear = 0;
+ return true;
+ }
+ }
+ return false;
+ }
+ else {
+ if (IsBipolar_OnValue()) {
+ if (inData1 > 63) {
+ outLinear = 1;
+ return true;
+ }
+ } else {
+ if (inData1 < 64) {
+ outLinear = 0;
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+ if (IsAnyNote()) {
+// not quite sure how to interpret this...
+ if (IsKeyPressure())
+ outLinear = inData2 / 127.0;
+ else
+ outLinear = inData1 / 127.0;
+ return true;
+ }
+ if (mData1 == inData1) {
+ if (IsKeyPressure())
+ outLinear = inData2 / 127.0;
+ else
+ outLinear = 1;
+ return true;
+ }
+ return false;
+ }
+ else if (IsControlChange()) {
+ // controller ID matches
+ if (mData1 == inData1) {
+ if (IsBipolar()) {
+ if (IsBipolar_OnValue()) {
+ if (inData2 > 63) {
+ outLinear = 1;
+ return true;
+ }
+ } else {
+ if (inData2 < 64) {
+ outLinear = 0;
+ return true;
+ }
+ }
+ return false;
+ }
+ //printf("this in midi matches %X with ", this);
+ outLinear = inData2 / 127.;
+ return true;
+ }
+ return false;
+ }
+
+ // this just matches on the patch change value itself...
+ if (IsPatchChange()) {
+ if (mData1 == inData1) {
+ outLinear = 1;
+ return true;
+ }
+ return false;
+ }
+
+ // finally, for the other two, just check the bi-polar matching conditions
+ // pitch bend and after touch
+ if (IsBipolar()) {
+ if (IsBipolar_OnValue()) {
+ if (inData1 > 63) {
+ outLinear = 1;
+ return true;
+ }
+ } else {
+ if (inData1 < 64) {
+ outLinear = 0;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ if (IsPitchBend()) {
+ UInt16 value = (inData2 << 7) | inData1;
+ outLinear = value / 16383.;
+ }
+ else if (IsChannelPressure()) {
+ outLinear = inData1 / 127.0;
+ }
+
+ return true;
+}
+
+
+void CAAUMIDIMap::Print () const
+{
+ printf ("CAAUMIDIMap:%p, (%u/%u), mParamID %d, IsValid:%c, Status:0x%X, mData1 %d, Flags:0x%X\n", this, (unsigned int)mScope, (unsigned int)mElement, (int)mParameterID, (IsValid() ? 'T' : 'F'), mStatus, mData1, (int)mFlags);
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.h b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.h
new file mode 100644
index 0000000000..a53fdf70dc
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.h
@@ -0,0 +1,541 @@
+/*
+ File: CAAUMIDIMap.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAAUMIDIMap_h_
+#define __CAAUMIDIMap_h_
+
+#include <AudioUnit/AudioUnitProperties.h>
+#include <algorithm>
+
+/*
+enum {
+ kAUParameterMIDIMapping_AnyChannelFlag = (1L << 0),
+ // If this flag is set and mStatus is a MIDI channel message, then the MIDI channel number
+ // in the status byte is ignored; the mapping is from the specified MIDI message on ANY channel.
+
+ kAUParameterMIDIMapping_AnyNoteFlag = (1L << 1),
+ // If this flag is set and mStatus is a Note On, Note Off, or Polyphonic Pressure message,
+ // the message's note number is ignored; the mapping is from ANY note number.
+
+ kAUParameterMIDIMapping_SubRange = (1L << 2),
+ // set this flag if the midi control should map only to a sub-range of the parameter's value
+ // then specify that range in the mSubRangeMin and mSubRangeMax members
+
+ kAUParameterMIDIMapping_Toggle = (1L << 3),
+ // this is only useful for boolean typed parameters. When set, it means that the parameter's
+ // value should be toggled (if true, become false and vice versa) when the represented MIDI message
+ // is received
+
+ kAUParameterMIDIMapping_Bipolar = (1L << 4),
+ // this can be set to when mapping a MIDI Controller to indicate that the parameter (typically a boolean
+ // style parameter) will only have its value changed to either the on or off state of a MIDI controller message
+ // (0 < 64 is off, 64 < 127 is on) such as the sustain pedal. The seeting of the next flag
+ // (kAUParameterMIDIMapping_Bipolar_On) determine whether the parameter is mapped to the on or off
+ // state of the controller
+ kAUParameterMIDIMapping_Bipolar_On = (1L << 5)
+ // only a valid flag if kAUParameterMIDIMapping_Bipolar is set
+};
+
+// The reserved fields here are being used to reserve space (as well as align to 64 bit size) for future use
+// When/If these fields are used, the names of the fields will be changed to reflect their functionality
+// so, apps should NOT refer to these reserved fields directly by name
+typedef struct AUParameterMIDIMapping
+{
+ AudioUnitScope mScope;
+ AudioUnitElement mElement;
+ AudioUnitParameterID mParameterID;
+ UInt32 mFlags;
+ Float32 mSubRangeMin;
+ Float32 mSubRangeMax;
+ UInt8 mStatus;
+ UInt8 mData1;
+ UInt8 reserved1; // MUST be set to zero
+ UInt8 reserved2; // MUST be set to zero
+ UInt32 reserved3; // MUST be set to zero
+} AUParameterMIDIMapping;
+*/
+
+/*
+Parameter To MIDI Mapping Properties
+These properties are used to:
+Describe a current set of mappings between MIDI messages and Parameter value setting
+Create a mapping between a parameter and a MIDI message through either:
+- explicitly adding (or removing) the mapping
+- telling the AU to hot-map the next MIDI message to a specified Parameter
+ The same MIDI Message can map to one or more parameters
+ One Parameter can be mapped from multiple MIDI messages
+
+ In general usage, these properties only apply to AU's that implement the MIDI API
+ AU Instruments (type=='aumu') and Music Effects (type == 'aumf')
+
+ These properties are used in the Global scope. The scope and element members of the structure describe
+ the scope and element of the parameter. In all usages, mScope, mElement and mParameterID must be
+ correctly specified.
+
+
+ * The AUParameterMIDIMapping Structure
+
+ Command mStatus mData1
+ Note Off 0x8n Note Num
+ Note On 0x9n Note Num
+ Key Pressure 0xAn Note Num
+ Control Change 0xBn ControllerID
+ Patch Change 0xCn Patch Num
+ Channel Pressure DxDn 0 (Unused)
+ Pitch Bend 0xEn 0 (Unused)
+
+ (where n is 0-0xF to correspond to MIDI channels 1-16)
+
+ Details:
+
+ In general MIDI Commands can be mapped to either a specific channel as specified in the mStatus bit.
+ If the kAUParameterMIDIMapping_AnyChannelFlag bit is set mStatus is a MIDI channel message, then the
+ MIDI channel number in the status byte is ignored; the mapping is from the specified MIDI message on ANY channel.
+
+ For note commands (note on, note off, key pressure), the MIDI message can trigger either with just a specific
+ note number, or any note number if the kAUParameterMIDIMapping_AnyNoteFlag bit is set. In these instances, the
+ note number is used as the trigger value (for instance, a note message could be used to set the
+ cut off frequency of a filter).
+
+ The Properties:
+
+ kAudioUnitProperty_AllParameterMIDIMappings array of AUParameterMIDIMapping (read/write)
+ This property is used to both retreive and set the current mapping state between (some/many/all of) its parameters
+ and MIDI messages. When set, it should replace any previous mapped settings the AU had.
+
+ If this property is implemented by a non-MIDI capable AU (such as an 'aufx' type), then the property is
+ read only, and recommends a suggested set of mappings for the host to perform. In this case, it is the
+ host's responsibility to map MIDI message to the AU parameters. As described previously, there are a set
+ of default mappings (see AudioToolbox/AUMIDIController.h) that the host can recommend to the user
+ in this circumstance.
+
+ This property's size will be very dynamic, depending on the number of mappings currently in affect, so the
+ caller should always get the size of the property first before retrieving it. The AU should return an error
+ if the caller doesn't provide enough space to return all of the current mappings.
+
+ kAudioUnitProperty_AddParameterMIDIMapping array of AUParameterMIDIMapping (write only)
+ This property is used to Add mappings to the existing set of mappings the AU possesses. It does NOT replace
+ any existing mappings.
+
+ kAudioUnitProperty_RemoveParameterMIDIMapping array of AUParameterMIDIMapping (write only)
+ This property is used to remove the specified mappings from the AU. If a mapping is specified that does not
+ currently exist in the AU, then it should just be ignored.
+
+ kAudioUnitProperty_HotMapParameterMIDIMapping AUParameterMIDIMapping (read/write)
+ This property is used in two ways, determined by the value supplied by the caller.
+ (1) If a mapping struct is provided, then that struct provides *all* of the information that the AU should
+ use to map the parameter, *except* for the MIDI message. The AU should then listen for the next MIDI message
+ and associate that MIDI message with the supplied AUParameter mapping. When this MIDI message is received and
+ the mapping made, the AU should also issue a notification on this property
+ (kAudioUnitProperty_HotMapParameterMIDIMapping) to indicate to the host that the mapping has been made. The host
+ can then retrieve the mapping that was made by getting the value of this property.
+
+ To avoid possible confusion, it is recommended that once the host has retrieved this mapping (if it is
+ presenting a UI to describe the mappings for example), that it then clears the mapping state as described next.
+
+ Thus, the only time this property will return a valid value is when the AU has made a mapping. If the AU's mapping
+ state has been cleared (or it has not been asked to make a mapping), then the AU should return
+ kAudioUnitErr_InvalidPropertyValue if the host tries to read this value.
+
+ (2) If the value passed in is NULL, then if the AU had a parameter that it was in the process of mapping, it
+ should disregard that (stop listening to the MIDI messages to create a mapping) and discard the partially
+ mapped struct. If the value is NULL and the AU is not in the process of mapping, the AU can ignore the request.
+
+ At all times, the _AllMappings property will completely describe the current known state of the AU's mappings
+ of MIDI messages to parameters.
+*/
+
+
+/*
+ When mapping, it is recommended that LSB controllers are in general not mapped (ie. the controller range of 32 < 64)
+ as many host parsers will map 14 bit control values. If you know (or can present an option) that the host deals with
+ 7 bit controllers only, then these controller ID's can be mapped of course.
+*/
+
+
+struct MIDIValueTransformer {
+ virtual double tolinear(double) = 0;
+ virtual double fromlinear(double) = 0;
+#if DEBUG
+ // suppress warning
+ virtual ~MIDIValueTransformer() { }
+#endif
+};
+
+struct MIDILinearTransformer : public MIDIValueTransformer {
+ virtual double tolinear(double x) { return x; }
+ virtual double fromlinear(double x) { return x; }
+};
+
+struct MIDILogTransformer : public MIDIValueTransformer {
+ virtual double tolinear(double x) { return log(std::max(x, .00001)); }
+ virtual double fromlinear(double x) { return exp(x); }
+};
+
+struct MIDIExpTransformer : public MIDIValueTransformer {
+ virtual double tolinear(double x) { return exp(x); }
+ virtual double fromlinear(double x) { return log(std::max(x, .00001)); }
+};
+
+struct MIDISqrtTransformer : public MIDIValueTransformer {
+ virtual double tolinear(double x) { return x < 0. ? -(sqrt(-x)) : sqrt(x); }
+ virtual double fromlinear(double x) { return x < 0. ? -(x * x) : x * x; }
+};
+
+struct MIDISquareTransformer : public MIDIValueTransformer {
+ virtual double tolinear(double x) { return x < 0. ? -(x * x) : x * x; }
+ virtual double fromlinear(double x) { return x < 0. ? -(sqrt(-x)) : sqrt(x); }
+};
+
+struct MIDICubeRtTransformer : public MIDIValueTransformer {
+ virtual double tolinear(double x) { return x < 0. ? -(pow(-x, 1./3.)) : pow(x, 1./3.); }
+ virtual double fromlinear(double x) { return x * x * x; }
+};
+
+struct MIDICubeTransformer : public MIDIValueTransformer {
+ virtual double tolinear(double x) { return x * x * x; }
+ virtual double fromlinear(double x) { return x < 0. ? -(pow(-x, 1./3.)) : pow(x, 1./3.); }
+};
+
+
+class CAAUMIDIMap : public AUParameterMIDIMapping {
+
+public:
+// variables for more efficient parsing of MIDI to Param value
+ Float32 mMinValue;
+ Float32 mMaxValue;
+ MIDIValueTransformer *mTransType;
+
+// methods
+ static MIDIValueTransformer *GetTransformer (UInt32 inFlags);
+
+ CAAUMIDIMap() { memset(this, 0, sizeof(CAAUMIDIMap)); }
+ CAAUMIDIMap (const AUParameterMIDIMapping& inMap)
+ {
+ memset(this, 0, sizeof(CAAUMIDIMap));
+ memcpy (this, &inMap, sizeof(inMap));
+ }
+ CAAUMIDIMap (AudioUnitScope inScope, AudioUnitElement inElement, AudioUnitParameterID inParam)
+ {
+ memset(this, 0, sizeof(CAAUMIDIMap));
+ mScope = inScope;
+ mElement = inElement;
+ mParameterID = inParam;
+ }
+
+
+ bool IsValid () const { return mStatus != 0; }
+
+ // returns -1 if any channel bit is set
+ SInt32 Channel () const { return IsAnyChannel() ? -1 : (mStatus & 0xF); }
+ bool IsAnyChannel () const {
+ return mFlags & kAUParameterMIDIMapping_AnyChannelFlag;
+ }
+ // preserves the existing channel info in the status byte
+ // preserves any previously set mFlags value
+ void SetAnyChannel (bool inFlag)
+ {
+ if (inFlag)
+ mFlags |= kAUParameterMIDIMapping_AnyChannelFlag;
+ else
+ mFlags &= ~kAUParameterMIDIMapping_AnyChannelFlag;
+ }
+
+ bool IsAnyNote () const {
+ return (mFlags & kAUParameterMIDIMapping_AnyNoteFlag) != 0;
+ }
+ // preserves the existing key num in the mData1 byte
+ // preserves any previously set mFlags value
+ void SetAnyNote (bool inFlag)
+ {
+ if (inFlag)
+ mFlags |= kAUParameterMIDIMapping_AnyNoteFlag;
+ else
+ mFlags &= ~kAUParameterMIDIMapping_AnyNoteFlag;
+ }
+
+ bool IsToggle() const { return (mFlags & kAUParameterMIDIMapping_Toggle) != 0; }
+ void SetToggle (bool inFlag)
+ {
+ if (inFlag)
+ mFlags |= kAUParameterMIDIMapping_Toggle;
+ else
+ mFlags &= ~kAUParameterMIDIMapping_Toggle;
+ }
+
+ bool IsBipolar() const { return (mFlags & kAUParameterMIDIMapping_Bipolar) != 0; }
+ // inUseOnValue is valid ONLY if inFlag is true
+ void SetBipolar (bool inFlag, bool inUseOnValue = false)
+ {
+ if (inFlag) {
+ mFlags |= kAUParameterMIDIMapping_Bipolar;
+ if (inUseOnValue)
+ mFlags |= kAUParameterMIDIMapping_Bipolar_On;
+ else
+ mFlags &= ~kAUParameterMIDIMapping_Bipolar_On;
+ } else {
+ mFlags &= ~kAUParameterMIDIMapping_Bipolar;
+ mFlags &= ~kAUParameterMIDIMapping_Bipolar_On;
+ }
+ }
+ bool IsBipolar_OnValue () const { return (mFlags & kAUParameterMIDIMapping_Bipolar_On) != 0; }
+
+ bool IsSubRange () const { return (mFlags & kAUParameterMIDIMapping_SubRange) != 0; }
+ void SetSubRange (Float32 inStartValue, Float32 inStopValue)
+ {
+ mFlags |= kAUParameterMIDIMapping_SubRange;
+
+ mSubRangeMin = inStartValue;
+ mSubRangeMax = inStopValue;
+ }
+
+ void SetParamRange(Float32 minValue, Float32 maxValue)
+ {
+ mMinValue = minValue;
+ mMaxValue = maxValue;
+ }
+
+ // this will retain the subrange values previously set.
+ void SetSubRange (bool inFlag)
+ {
+ if (inFlag)
+ mFlags |= kAUParameterMIDIMapping_SubRange;
+ else
+ mFlags &= ~kAUParameterMIDIMapping_SubRange;
+ }
+
+ bool IsAnyValue() const{return !IsBipolar();}
+ bool IsOnValue() const{return IsBipolar_OnValue();}
+ bool IsOffValue() const{return IsBipolar();}
+
+ bool IsNoteOff () const { return ((mStatus & 0xF0) == 0x80); }
+ bool IsNoteOn () const { return ((mStatus & 0xF0) == 0x90); }
+
+ bool IsKeyPressure () const { return ((mStatus & 0xF0) == 0xA0); }
+
+ bool IsKeyEvent () const { return (mStatus > 0x7F) && (mStatus < 0xB0); }
+
+ bool IsPatchChange () const { return ((mStatus & 0xF0) == 0xC0); }
+ bool IsChannelPressure () const { return ((mStatus & 0xF0) == 0xD0); }
+ bool IsPitchBend () const { return ((mStatus & 0xF0) == 0xE0); }
+ bool IsControlChange () const { return ((mStatus & 0xF0) == 0xB0); }
+
+
+ void SetControllerOnValue(){SetBipolar(true,true);}
+ void SetControllerOffValue(){SetBipolar(true,false);}
+ void SetControllerAnyValue(){SetBipolar(false,false);}
+
+ // All of these Set calls will reset the mFlags field based on the
+ // anyChannel param value
+ void SetNoteOff (UInt8 key, SInt8 channel, bool anyChannel = false)
+ {
+ mStatus = 0x80 | (channel & 0xF);
+ mData1 = key;
+ mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+
+ }
+
+ void SetNoteOn (UInt8 key, SInt8 channel, bool anyChannel = false)
+ {
+ mStatus = 0x90 | (channel & 0xF);
+ mData1 = key;
+ mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+ }
+
+ void SetPolyKey (UInt8 key, SInt8 channel, bool anyChannel = false)
+ {
+ mStatus = 0xA0 | (channel & 0xF);
+ mData1 = key;
+ mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+ }
+
+ void SetControlChange (UInt8 controllerID, SInt8 channel, bool anyChannel = false)
+ {
+ mStatus = 0xB0 | (channel & 0xF);
+ mData1 = controllerID;
+ mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+ }
+
+ void SetPatchChange (UInt8 patchChange, SInt8 channel, bool anyChannel = false)
+ {
+ mStatus = 0xC0 | (channel & 0xF);
+ mData1 = patchChange;
+ mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+ }
+
+ void SetChannelPressure (SInt8 channel, bool anyChannel = false)
+ {
+ mStatus = 0xD0 | (channel & 0xF);
+ mData1 = 0;
+ mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+ }
+
+ void SetPitchBend (SInt8 channel, bool anyChannel = false)
+ {
+ mStatus = 0xE0 | (channel & 0xF);
+ mData1 = 0;
+ mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+ }
+
+
+ Float32 ParamValueFromMIDILinear (Float32 inLinearValue) const
+ {
+ Float32 low, high;
+ if (IsSubRange()){
+ low = mSubRangeMin;
+ high = mSubRangeMax;
+ }
+ else {
+ low = mMinValue;
+ high = mMaxValue;
+ }
+
+
+ // WE ARE ASSUMING YOU HAVE SET THIS UP PROPERLY!!!!! (or this will crash cause it will be NULL)
+ return (Float32)mTransType->fromlinear((inLinearValue * (high - low)) + low);
+ }
+
+
+ // The CALLER of this method must ensure that the status byte's MIDI Command (ignoring the channel) matches!!!
+ bool MIDI_Matches (UInt8 inChannel, UInt8 inData1, UInt8 inData2, Float32 &outLinear) const;
+
+ void Print () const;
+
+ void Save (CFPropertyListRef &outData) const;
+ void Restore (CFDictionaryRef inData);
+
+ static void SaveAsMapPList (AudioUnit inUnit,
+ const AUParameterMIDIMapping * inMappings,
+ UInt32 inNumMappings,
+ CFPropertyListRef &outData,
+ CFStringRef inName = NULL);
+
+ // inNumMappings describes how much memory is allocated in outMappings
+ static void RestoreFromMapPList (const CFDictionaryRef inData,
+ AUParameterMIDIMapping * outMappings,
+ UInt32 inNumMappings);
+
+ static UInt32 NumberOfMaps (const CFDictionaryRef inData);
+};
+
+
+ // these sorting operations sort for run-time efficiency based on the MIDI messages
+inline bool operator== (const CAAUMIDIMap &a, const CAAUMIDIMap &b)
+{
+ // ignore channel first
+ return (((a.mStatus & 0xF0) == (b.mStatus & 0xF0))
+ && (a.mData1 == b.mData1)
+ && ((a.mStatus & 0xF) == (b.mStatus & 0xf)) // now compare the channel
+ && (a.mParameterID == b.mParameterID)
+ && (a.mElement == b.mElement)
+ && (a.mScope == b.mScope));
+
+ // reserved field comparisons - ignored until/if they are used
+}
+
+inline bool operator< (const CAAUMIDIMap &a, const CAAUMIDIMap &b)
+{
+ if ((a.mStatus & 0xF0) != (b.mStatus & 0xF0))
+ return ((a.mStatus & 0xF0) < (b.mStatus & 0xF0));
+
+ if (a.mData1 != b.mData1)
+ return (a.mData1 < b.mData1);
+
+ if ((a.mStatus & 0xF) != (b.mStatus & 0xf)) // now compare the channel
+ return ((a.mStatus & 0xF) < (b.mStatus & 0xf));
+
+// reserved field comparisons - ignored until/if they are used
+
+// we're sorting this by MIDI, so we don't really care how the rest is sorted
+ return ((a.mParameterID < b.mParameterID)
+ && (a.mElement < b.mElement)
+ && (a.mScope < b.mScope));
+}
+
+
+
+class CompareMIDIMap {
+ int compare (const CAAUMIDIMap &a, const CAAUMIDIMap &b)
+ {
+ if ((a.mStatus & 0xF0) < (b.mStatus & 0xF0))
+ return -1;
+ if ((a.mStatus & 0xF0) > (b.mStatus & 0xF0))
+ return 1;
+
+ // note event
+ if (a.mStatus < 0xB0 || a.mStatus >= 0xD0)
+ return 0;
+ if (a.mData1 > b.mData1) return 1;
+ if (a.mData1 < b.mData1) return -1;
+ return 0;
+ }
+
+public:
+ bool operator() (const CAAUMIDIMap &a, const CAAUMIDIMap &b) {
+ return compare (a, b) < 0;
+ }
+ bool Finish (const CAAUMIDIMap &a, const CAAUMIDIMap &b) {
+ return compare (a, b) != 0;
+ }
+};
+
+
+/*
+ usage: To find potential mapped events for a given status byte, where mMMapEvents is a sorted vec
+ CompareMIDIMap comparObj;
+ sortVecIter lower_iter = std::lower_bound(mMMapEvents.begin(), mMMapEvents.end(), inStatusByte, compareObj);
+ for (;lower_iter < mMMapEvents.end(); ++lower_iter) {
+ // then, see if we go out of the status byte range, using the Finish method
+ if (compareObj.Finish(map, tempMap)) // tempMap is a CAAUMIDIMap object with the status/dataByte 1 set
+ break;
+ // ...
+ }
+
+ in the for loop you call the MIDI_Matches call, to see if the MIDI event matches a given AUMIDIParam mapping
+ special note: you HAVE to transform note on (with vel zero) events to the note off status byte
+*/
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.cpp
new file mode 100644
index 0000000000..b24ff9945c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.cpp
@@ -0,0 +1,233 @@
+/*
+ File: CAAUMIDIMapManager.cpp
+ Abstract: CAAUMIDIMapManager.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CAAUMIDIMapManager.h"
+#include <AudioToolbox/AudioUnitUtilities.h>
+
+CAAUMIDIMapManager::CAAUMIDIMapManager()
+{
+ hotMapping = false;
+}
+
+static void FillInMap (CAAUMIDIMap &map, AUBase &That)
+{
+ AudioUnitParameterInfo info;
+ That.GetParameterInfo (map.mScope, map.mParameterID, info);
+
+ if (map.IsSubRange()) {
+ map.mMinValue = map.mSubRangeMin;
+ map.mMaxValue = map.mSubRangeMax;
+ } else {
+ map.mMinValue = info.minValue;
+ map.mMaxValue = info.maxValue;
+ }
+
+ map.mTransType = CAAUMIDIMap::GetTransformer(info.flags);
+}
+
+OSStatus CAAUMIDIMapManager::SortedInsertToParamaterMaps (AUParameterMIDIMapping *maps, UInt32 inNumMaps, AUBase &That)
+{
+ for (unsigned int i = 0; i < inNumMaps; ++i)
+ {
+ CAAUMIDIMap map(maps[i]);
+
+ FillInMap (map, That);
+
+ int idx = FindParameterIndex (maps[i]);
+ if (idx > -1)
+ mParameterMaps.erase(mParameterMaps.begin() + idx);
+
+ // least disruptive place to put this is at the end
+ mParameterMaps.push_back(map);
+ }
+
+ std::sort(mParameterMaps.begin(), mParameterMaps.end(), CompareMIDIMap());
+
+ return noErr;
+}
+
+void CAAUMIDIMapManager::GetHotParameterMap(AUParameterMIDIMapping &outMap )
+{
+ outMap = mHotMap;
+}
+
+void CAAUMIDIMapManager::SortedRemoveFromParameterMaps(AUParameterMIDIMapping *maps, UInt32 inNumMaps, bool &outMapDidChange)
+{
+ if (hotMapping) {
+ hotMapping = false;
+ }
+
+ outMapDidChange = false;
+ for (unsigned int i = 0; i < inNumMaps; ++i) {
+ int idx = FindParameterIndex (maps[i]);
+ if (idx > -1) {
+ //mParameterMaps[idx].Print();
+ mParameterMaps.erase(mParameterMaps.begin() + idx);
+ outMapDidChange = true;
+ }
+ }
+}
+
+void CAAUMIDIMapManager::ReplaceAllMaps (AUParameterMIDIMapping* inMappings, UInt32 inNumMaps, AUBase &That)
+{
+ mParameterMaps.clear();
+
+ for (unsigned int i = 0; i < inNumMaps; ++i) {
+ CAAUMIDIMap mapping(inMappings[i]);
+
+ FillInMap (mapping, That);
+ mParameterMaps.push_back (mapping);
+ }
+
+ std::sort(mParameterMaps.begin(),mParameterMaps.end(), CompareMIDIMap());
+}
+
+bool CAAUMIDIMapManager::HandleHotMapping(UInt8 inStatus,
+ UInt8 inChannel,
+ UInt8 inData1,
+ AUBase &That)
+{ //used to set the hot map info
+
+ if (inStatus == 0xf0) return false;
+
+ if (!hotMapping) return false;
+ hotMapping = false;
+
+ mHotMap.mStatus = inStatus | inChannel;
+ mHotMap.mData1 = inData1;
+
+ SortedInsertToParamaterMaps (&mHotMap, 1, That);
+ return true;
+}
+
+#if DEBUG
+
+void CAAUMIDIMapManager::Print()
+{
+ for ( ParameterMaps::iterator i = mParameterMaps.begin(); i < mParameterMaps.end(); ++i) {
+ CAAUMIDIMap* listmap = &(*i);
+ listmap->Print();
+ }
+}
+
+#endif // DEBUG
+
+void CAAUMIDIMapManager::GetMaps(AUParameterMIDIMapping* maps)
+{
+ int i = 0;
+ for ( ParameterMaps::iterator iter = mParameterMaps.begin(); iter < mParameterMaps.end(); ++iter, ++i) {
+ AUParameterMIDIMapping &listmap = (*iter);
+ maps[i] = listmap;
+ }
+}
+
+int CAAUMIDIMapManager::FindParameterIndex (AUParameterMIDIMapping &inMap)
+{
+ //used to get back hot mapping and one at a time maps, for ui
+
+ int idx = 0;
+ for ( ParameterMaps::iterator i = mParameterMaps.begin(); i < mParameterMaps.end(); ++i) {
+ CAAUMIDIMap & listmap = (*i);
+ if ( (listmap.mParameterID == inMap.mParameterID) &&
+ (listmap.mScope == inMap.mScope) &&
+ (listmap.mElement == inMap.mElement) )
+ {
+ return idx;
+ }
+ idx++;
+ }
+ return -1;
+}
+
+bool CAAUMIDIMapManager::FindParameterMapEventMatch( UInt8 inStatus,
+ UInt8 inChannel,
+ UInt8 inData1,
+ UInt8 inData2,
+ UInt32 inBufferOffset,
+ AUBase& inAUBase)
+{
+ bool ret_value = false;
+
+ if (inStatus == 0x90 && !inData2)
+ inStatus = 0x80 | inChannel;
+
+ //used to test for midi matches once map is made
+ CAAUMIDIMap tempMap;
+ tempMap.mStatus = inStatus | inChannel;
+ tempMap.mData1 = inData1;
+
+ CompareMIDIMap compareObj;
+
+ AudioUnitEvent event;
+ event.mEventType = kAudioUnitEvent_ParameterValueChange;
+ event.mArgument.mParameter.mAudioUnit = inAUBase.GetComponentInstance();
+
+ ParameterMaps::iterator lower_iter =
+ std::lower_bound(mParameterMaps.begin(), mParameterMaps.end(), tempMap, compareObj);
+
+ while (lower_iter < mParameterMaps.end())
+ {
+ CAAUMIDIMap & map = (*lower_iter);
+ if (compareObj.Finish(map, tempMap))
+ break;
+
+ Float32 value;
+ if (map.MIDI_Matches(inChannel, inData1, inData2, value))
+ {
+ inAUBase.SetParameter ( map.mParameterID, map.mScope, map.mElement,
+ map.ParamValueFromMIDILinear(value), inBufferOffset);
+
+ event.mArgument.mParameter.mParameterID = map.mParameterID;
+ event.mArgument.mParameter.mScope = map.mScope;
+ event.mArgument.mParameter.mElement = map.mElement;
+
+ AUEventListenerNotify(NULL, NULL, &event);
+ ret_value = true;
+ }
+ ++lower_iter;
+ }
+ return ret_value;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.h b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.h
new file mode 100644
index 0000000000..8926d8f6e1
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.h
@@ -0,0 +1,102 @@
+/*
+ File: CAAUMIDIMapManager.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAAUMIDIMapManager_h_
+#define __CAAUMIDIMapManager_h_
+
+#include "AUBase.h"
+#include "CAAUMIDIMap.h"
+#include <vector>
+#include <AudioToolbox/AudioUnitUtilities.h>
+
+class CAAUMIDIMapManager {
+
+protected:
+
+ typedef std::vector<CAAUMIDIMap> ParameterMaps;
+ ParameterMaps mParameterMaps;
+
+ bool hotMapping;
+ AUParameterMIDIMapping mHotMap;
+
+public:
+
+ CAAUMIDIMapManager();
+
+ UInt32 NumMaps(){return static_cast<UInt32>(mParameterMaps.size());}
+ void GetMaps(AUParameterMIDIMapping* maps);
+
+ int FindParameterIndex(AUParameterMIDIMapping &map);
+
+ void GetHotParameterMap(AUParameterMIDIMapping &outMap);
+
+ void SortedRemoveFromParameterMaps (AUParameterMIDIMapping *maps, UInt32 inNumMaps, bool &outMapDidChange);
+ OSStatus SortedInsertToParamaterMaps (AUParameterMIDIMapping *maps, UInt32 inNumMaps, AUBase &That);
+
+ void ReplaceAllMaps (AUParameterMIDIMapping* inMappings, UInt32 inNumMaps, AUBase &That);
+
+ bool IsHotMapping(){return hotMapping;}
+ void SetHotMapping (AUParameterMIDIMapping &inMap){hotMapping = true; mHotMap = inMap; }
+
+ bool HandleHotMapping( UInt8 inStatus,
+ UInt8 inChannel,
+ UInt8 inData1,
+ AUBase &That);
+
+
+ bool FindParameterMapEventMatch(UInt8 inStatus,
+ UInt8 inChannel,
+ UInt8 inData1,
+ UInt8 inData2,
+ UInt32 inBufferOffset,
+ AUBase& inAUBase);
+#if DEBUG
+ void Print();
+#endif
+};
+
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.cpp
new file mode 100644
index 0000000000..2d8fe18341
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.cpp
@@ -0,0 +1,400 @@
+/*
+ File: CAAUParameter.cpp
+ Abstract: CAAUParameter.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CAAUParameter.h"
+
+CAAUParameter::CAAUParameter()
+{
+ memset(this, 0, sizeof(CAAUParameter));
+}
+
+CAAUParameter::CAAUParameter(AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element)
+{
+ memset(this, 0, sizeof(CAAUParameter));
+ Init (au, param, scope, element);
+}
+
+CAAUParameter::CAAUParameter (AudioUnitParameter &inParam)
+{
+ memset(this, 0, sizeof(CAAUParameter));
+ Init (inParam.mAudioUnit, inParam.mParameterID, inParam.mScope, inParam.mElement);
+}
+
+CAAUParameter::CAAUParameter(const CAAUParameter &a)
+{
+ memset(this, 0, sizeof(CAAUParameter));
+ *this = a;
+}
+
+CAAUParameter & CAAUParameter::operator = (const CAAUParameter &a)
+{
+ if (mParamName) CFRelease(mParamName);
+ if (mParamTag) CFRelease(mParamTag);
+ if (mNamedParams) CFRelease(mNamedParams);
+
+ memcpy(this, &a, sizeof(CAAUParameter));
+
+ if (mParamName) CFRetain(mParamName);
+ if (mParamTag) CFRetain(mParamTag);
+ if (mNamedParams) CFRetain(mNamedParams);
+
+ return *this;
+}
+
+CAAUParameter::~CAAUParameter()
+{
+ if (mParamName) CFRelease(mParamName);
+ if (mParamTag) CFRelease(mParamTag);
+ if (mNamedParams) CFRelease (mNamedParams);
+}
+
+void CAAUParameter::Init (AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element)
+{
+ mAudioUnit = au;
+ mParameterID = param;
+ mScope = scope;
+ mElement = element;
+
+ UInt32 propertySize = sizeof(mParamInfo);
+ OSStatus err = AudioUnitGetProperty(au, kAudioUnitProperty_ParameterInfo,
+ scope, param, &mParamInfo, &propertySize);
+ if (err)
+ memset(&mParamInfo, 0, sizeof(mParamInfo));
+ if (mParamInfo.flags & kAudioUnitParameterFlag_HasCFNameString) {
+ mParamName = mParamInfo.cfNameString;
+ if (!(mParamInfo.flags & kAudioUnitParameterFlag_CFNameRelease))
+ CFRetain (mParamName);
+ } else
+ mParamName = CFStringCreateWithCString(NULL, mParamInfo.name, kCFStringEncodingUTF8);
+
+ const char* str = 0;
+ switch (mParamInfo.unit)
+ {
+ case kAudioUnitParameterUnit_Boolean:
+ str = "T/F";
+ break;
+ case kAudioUnitParameterUnit_Percent:
+ case kAudioUnitParameterUnit_EqualPowerCrossfade:
+ str = "%";
+ break;
+ case kAudioUnitParameterUnit_Seconds:
+ str = "Secs";
+ break;
+ case kAudioUnitParameterUnit_SampleFrames:
+ str = "Samps";
+ break;
+ case kAudioUnitParameterUnit_Phase:
+ case kAudioUnitParameterUnit_Degrees:
+ str = "Degr.";
+ break;
+ case kAudioUnitParameterUnit_Hertz:
+ str = "Hz";
+ break;
+ case kAudioUnitParameterUnit_Cents:
+ case kAudioUnitParameterUnit_AbsoluteCents:
+ str = "Cents";
+ break;
+ case kAudioUnitParameterUnit_RelativeSemiTones:
+ str = "S-T";
+ break;
+ case kAudioUnitParameterUnit_MIDINoteNumber:
+ case kAudioUnitParameterUnit_MIDIController:
+ str = "MIDI";
+ //these are inclusive, so add one value here
+ mNumIndexedParams = short(mParamInfo.maxValue+1 - mParamInfo.minValue);
+ break;
+ case kAudioUnitParameterUnit_Decibels:
+ str = "dB";
+ break;
+ case kAudioUnitParameterUnit_MixerFaderCurve1:
+ case kAudioUnitParameterUnit_LinearGain:
+ str = "Gain";
+ break;
+ case kAudioUnitParameterUnit_Pan:
+ str = "L/R";
+ break;
+ case kAudioUnitParameterUnit_Meters:
+ str = "Mtrs";
+ break;
+ case kAudioUnitParameterUnit_Octaves:
+ str = "8ve";
+ break;
+ case kAudioUnitParameterUnit_BPM:
+ str = "BPM";
+ break;
+ case kAudioUnitParameterUnit_Beats:
+ str = "Beats";
+ break;
+ case kAudioUnitParameterUnit_Milliseconds:
+ str = "msecs";
+ break;
+ case kAudioUnitParameterUnit_Ratio:
+ str = "Ratio";
+ break;
+ case kAudioUnitParameterUnit_Indexed:
+ {
+ propertySize = sizeof(mNamedParams);
+ err = AudioUnitGetProperty (au,
+ kAudioUnitProperty_ParameterValueStrings,
+ scope,
+ param,
+ &mNamedParams,
+ &propertySize);
+ if (!err && mNamedParams) {
+ mNumIndexedParams = CFArrayGetCount(mNamedParams);
+ } else {
+ //these are inclusive, so add one value here
+ mNumIndexedParams = short(mParamInfo.maxValue+1 - mParamInfo.minValue);
+ }
+ str = NULL;
+ }
+ break;
+ case kAudioUnitParameterUnit_CustomUnit:
+ {
+ CFStringRef unitName = mParamInfo.unitName;
+ static char paramStr[256];
+ CFStringGetCString (unitName, paramStr, 256, kCFStringEncodingUTF8);
+ if (mParamInfo.flags & kAudioUnitParameterFlag_CFNameRelease)
+ CFRelease (unitName);
+ str = paramStr;
+ break;
+ }
+ case kAudioUnitParameterUnit_Generic:
+ case kAudioUnitParameterUnit_Rate:
+ default:
+ str = NULL;
+ break;
+ }
+
+ if (str)
+ mParamTag = CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8);
+ else
+ mParamTag = NULL;
+}
+
+
+Float32 CAAUParameter::GetValue() const
+{
+ Float32 value = 0.;
+ //OSStatus err =
+ AudioUnitGetParameter(mAudioUnit, mParameterID, mScope, mElement, &value);
+ return value;
+}
+
+CFStringRef CreateLocalizedStringForParameterValue ( double inParameterValue,
+ const CAAUParameter * inParameter,
+ UInt32 inDigits,
+ UInt32 minDigits) {
+ if (!inParameter) return nil;
+
+ AudioUnitParameterInfo info = inParameter->ParamInfo();
+ int pow10;
+
+ switch (info.unit) {
+ case kAudioUnitParameterUnit_Hertz:
+ // number of significant digits based on value
+ pow10 = int(log10(fmax(inParameterValue, .000001)));
+ break;
+ default:
+ // number of significant digits based on parameter range
+ pow10 = int(log10(fmax(double(info.maxValue - info.minValue), .000001)));
+ break;
+ }
+
+ // pow10 range nDigitsAfterDecimal
+ // -2 .0100-.0999 4
+ // -1 .100-.999 3
+ // 0 1.00-9.99 2
+ // 1 10.0-99.9 1
+ // 2 100-999 0
+ // 3 1000-9990 -1
+ // 4 10000-99900 -2
+
+ int nDigitsAfterDecimal = inDigits - (pow10 + 1);
+ if (nDigitsAfterDecimal < 0)
+ nDigitsAfterDecimal = 0; // the least number of digits possible is zero
+
+ if (info.flags & kAudioUnitParameterFlag_IsHighResolution)
+ nDigitsAfterDecimal = 4;
+
+ CFLocaleRef currentLocale = CFLocaleCopyCurrent();
+ CFNumberFormatterRef numberFormatter = CFNumberFormatterCreate (NULL, currentLocale, kCFNumberFormatterDecimalStyle);
+
+ CFNumberRef maxFractionDigits = CFNumberCreate (NULL, kCFNumberIntType, &nDigitsAfterDecimal);
+
+ if (nDigitsAfterDecimal > 0)
+ nDigitsAfterDecimal = minDigits;
+
+ CFNumberRef minFractionDigits = CFNumberCreate (NULL, kCFNumberIntType, &nDigitsAfterDecimal);
+
+ CFNumberFormatterSetProperty (numberFormatter, kCFNumberFormatterMinFractionDigits, minFractionDigits);
+ CFNumberFormatterSetProperty (numberFormatter, kCFNumberFormatterMaxFractionDigits, maxFractionDigits);
+ CFStringRef formattedNumberString = CFNumberFormatterCreateStringWithValue (NULL, numberFormatter, kCFNumberDoubleType, &inParameterValue);
+
+ CFRelease(currentLocale);
+ CFRelease(numberFormatter);
+ CFRelease(maxFractionDigits);
+ CFRelease(minFractionDigits);
+
+ return formattedNumberString;
+}
+
+CFStringRef CreateLocalizedStringForParameterValue ( double inParameterValue,
+ const CAAUParameter * inParameter,
+ UInt32 inDigits) {
+ return CreateLocalizedStringForParameterValue (inParameterValue, inParameter, inDigits, 1);
+}
+
+double ValueForLocalizedParameterString (CFStringRef string, const CAAUParameter * inParameter) {
+ CFLocaleRef currentLocale = CFLocaleCopyCurrent();
+ CFNumberFormatterRef numberFormatter = CFNumberFormatterCreate (NULL, currentLocale, kCFNumberFormatterDecimalStyle);
+
+ double value = 0;
+ Boolean worked = CFNumberFormatterGetValueFromString (numberFormatter, string, NULL, kCFNumberDoubleType, &value);
+
+ CFRelease(currentLocale);
+ CFRelease(numberFormatter);
+
+ if (worked)
+ return value;
+ else {
+ AudioUnitParameterInfo info = inParameter->ParamInfo();
+ return info.defaultValue;
+ }
+}
+
+CFStringRef CAAUParameter::GetStringFromValueCopy(const Float32 *value) const
+{
+ if (HasNamedParams())
+ {
+ Float32 val = (value == NULL ? GetValue() : *value);
+ int index = int(mParamInfo.minValue) + int(val);
+ CFStringRef str = GetParamName (index);
+ if (str) {
+ CFRetain (str);
+ return str;
+ }
+ }
+ else if (ValuesHaveStrings())
+ {
+ AudioUnitParameterStringFromValue stringValue;
+ stringValue.inParamID = mParameterID;
+ stringValue.inValue = value;
+ stringValue.outString = NULL;
+ UInt32 propertySize = sizeof(stringValue);
+
+ OSStatus err = AudioUnitGetProperty (mAudioUnit,
+ kAudioUnitProperty_ParameterStringFromValue,
+ mScope,
+ 0,
+ &stringValue,
+ &propertySize);
+
+ if (!err && stringValue.outString != NULL)
+ return stringValue.outString;
+ }
+
+ Float32 val = (value == NULL ? GetValue() : *value);
+ AudioUnitParameterUnit unit = this->ParamInfo().unit;
+ if (unit == kAudioUnitParameterUnit_Cents || unit == kAudioUnitParameterUnit_AbsoluteCents)
+ return CreateLocalizedStringForParameterValue(val, this, 4, 0);
+ else
+ return CreateLocalizedStringForParameterValue(val, this, 4);
+}
+
+Float32 CAAUParameter::GetValueFromString(CFStringRef str) const
+{
+ if (ValuesHaveStrings())
+ {
+ AudioUnitParameterValueFromString valueString;
+ valueString.inParamID = mParameterID;
+ valueString.inString = str;
+ UInt32 propertySize = sizeof(valueString);
+
+ OSStatus err = AudioUnitGetProperty (mAudioUnit,
+ kAudioUnitProperty_ParameterValueFromString,
+ mScope,
+ 0,
+ &valueString,
+ &propertySize);
+
+ if (!err) {
+ return valueString.outValue;
+ }
+ }
+
+ return (Float32) ValueForLocalizedParameterString(str, this);
+}
+
+void CAAUParameter::SetValue( AUParameterListenerRef inListener,
+ void * inObject,
+ Float32 inValue) const
+{
+ // clip inValue as: maxValue >= inValue >= minValue before setting
+ Float32 valueToSet = inValue;
+ if (valueToSet > mParamInfo.maxValue)
+ valueToSet = mParamInfo.maxValue;
+ if (valueToSet < mParamInfo.minValue)
+ valueToSet = mParamInfo.minValue;
+
+ AUParameterSet(inListener, inObject, this, valueToSet, 0);
+}
+
+#if DEBUG
+void CAAUParameter::Print() const
+{
+ UInt32 clump = 0;
+ GetClumpID (clump);
+
+ UInt32 len = static_cast<UInt32>(CFStringGetLength(mParamName));
+ char* chars = (char*)malloc (len * 2); // give us plenty of room for unichar chars
+ if (!CFStringGetCString (mParamName, chars, len * 2, kCFStringEncodingUTF8))
+ chars[0] = 0;
+
+ printf ("ID: %ld, Clump: %u, Name: %s\n", (long unsigned int) mParameterID, (unsigned int) clump, chars);
+ free (chars);
+}
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.h b/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.h
new file mode 100644
index 0000000000..f8b5733d8c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.h
@@ -0,0 +1,191 @@
+/*
+ File: CAAUParameter.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAAUParameter_h__
+#define __CAAUParameter_h__
+
+#include <AudioToolbox/AudioUnitUtilities.h>
+
+// ____________________________________________________________________________
+// CAAUParameter
+// complete parameter specification
+ /*! @class CAAUParameter */
+class CAAUParameter : public AudioUnitParameter {
+public:
+ /*! @ctor CAAUParameter.0 */
+ CAAUParameter();
+ /*! @ctor CAAUParameter.1 */
+ CAAUParameter(AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element);
+ /*! @ctor CAAUParameter.2 */
+ CAAUParameter(AudioUnitParameter &inParam);
+ /*! @ctor CAAUParameter.3 */
+ CAAUParameter(const CAAUParameter &a);
+ /*! @dtor ~CAAUParameter */
+ ~CAAUParameter();
+
+ /*! @method operator <@ */
+ bool operator < (const CAAUParameter &a) const
+ {
+ return memcmp(this, &a, sizeof(AudioUnitParameter)) < 0;
+ }
+
+ /*! @method operator ==@ */
+ bool operator == (const CAAUParameter &a) const
+ {
+ return !memcmp(this, &a, sizeof(AudioUnitParameter));
+ }
+
+ /*! @method operator =@ */
+ CAAUParameter & operator = (const CAAUParameter &a);
+
+ /*! @method GetValue */
+ Float32 GetValue() const;
+ /*! @method SetValue */
+ void SetValue( AUParameterListenerRef inListener,
+ void * inObject,
+ Float32 inValue) const;
+
+ /*! @method GetName */
+ CFStringRef GetName() const { return mParamName; }
+ // borrowed reference!
+
+ /*! @method GetStringFromValueCopy */
+ CFStringRef GetStringFromValueCopy(const Float32 *value = NULL) const;
+ // returns a copy of the name of the current parameter value
+ // or null if there is no name associated
+ // caller must release
+ /*! @method ValuesHaveStrings */
+ bool ValuesHaveStrings () const
+ {
+ return (mParamInfo.flags & kAudioUnitParameterFlag_ValuesHaveStrings) != 0;
+ }
+
+ /*! @method GetValueFromString */
+ Float32 GetValueFromString (CFStringRef str) const;
+ // caller must release
+
+ /*! @method ParamInfo */
+ const AudioUnitParameterInfo &
+ ParamInfo() const { return mParamInfo; }
+
+ /*! @method GetParamTag */
+ CFStringRef GetParamTag() const { return mParamTag; }
+ // this may return null! -
+ // in which case there is no descriptive tag for the parameter
+
+ /*! @method GetParamName */
+ CFStringRef GetParamName (int inIndex) const
+ // this can return null if there is no name for the parameter
+ {
+ return (mNamedParams && inIndex < mNumIndexedParams)
+ ? (CFStringRef) CFArrayGetValueAtIndex(mNamedParams, inIndex)
+ : 0;
+ }
+
+ /*! @method GetNumIndexedParams */
+ int GetNumIndexedParams () const { return mNumIndexedParams; }
+
+ /*! @method IsIndexedParam */
+ bool IsIndexedParam () const { return mNumIndexedParams != 0; }
+
+ /*! @method HasNamedParams */
+ bool HasNamedParams () const { return IsIndexedParam() && mNamedParams; }
+
+ /*! @method GetClumpID */
+ bool GetClumpID (UInt32 &outClumpID) const
+ {
+ if (mParamInfo.flags & kAudioUnitParameterFlag_HasClump) {
+ outClumpID = mParamInfo.clumpID;
+ return true;
+ }
+ return false;
+ }
+
+ /*! @method HasDisplayTransformation */
+ bool HasDisplayTransformation () const
+ {
+ return GetAudioUnitParameterDisplayType (mParamInfo.flags);
+ }
+
+ /*! @method IsExpert */
+ bool IsExpert () const
+ {
+ return mParamInfo.flags & kAudioUnitParameterFlag_ExpertMode;
+ }
+#if DEBUG
+ void Print () const;
+#endif
+
+ // these methods are defined in CAPersistence.cpp
+ // they will persist and restore only the scope, element and param ID's of the AudioUnitParameter
+ // however, this is sufficient to be able to save/restore a CAAUParameter object
+ void Save (CFPropertyListRef &outData) const;
+
+ static void Save (const AudioUnitParameter &inParam, CFPropertyListRef &outData);
+
+ static OSStatus Restore (const CFPropertyListRef inData, AudioUnitParameter &outParam);
+
+protected:
+ // cached parameter info
+ /*! @var mParamInfo */
+ AudioUnitParameterInfo mParamInfo;
+ /*! @var mParamName */
+ CFStringRef mParamName;
+ /*! @var mParamTag */
+ CFStringRef mParamTag;
+ /*! @var mNumIndexedParams */
+ short mNumIndexedParams;
+ /*! @var mNamedParams */
+ CFArrayRef mNamedParams;
+
+private:
+ void Init (AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element);
+
+};
+
+
+
+#endif // __CAAUParameter_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.cpp
new file mode 100644
index 0000000000..1cda39c99d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.cpp
@@ -0,0 +1,707 @@
+/*
+ File: CAAUProcessor.cpp
+ Abstract: CAAUProcessor.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CAAUProcessor.h"
+#include "CAXException.h"
+
+static OSStatus SilenceInputCallback (void *inRefCon,
+ AudioUnitRenderActionFlags *ioActionFlags,
+ const AudioTimeStamp *inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList *ioData)
+{
+ AudioBuffer *buf = ioData->mBuffers;
+ for (UInt32 i = ioData->mNumberBuffers; i--; ++buf)
+ memset((Byte *)buf->mData, 0, buf->mDataByteSize);
+
+ //provide a hint that our input data is silent.
+ *ioActionFlags &= kAudioUnitRenderAction_OutputIsSilence;
+ return noErr;
+}
+
+static AURenderCallbackStruct sSilentCallback = { SilenceInputCallback, NULL };
+
+
+CAAUProcessor::CAAUProcessor (const CAComponent& inComp)
+ : mPreflightABL(NULL)
+{
+ OSStatus result = CAAudioUnit::Open (inComp, mUnit);
+ if (result)
+ throw result;
+ memset (&mUserCallback, 0, sizeof (AURenderCallbackStruct));
+ mMaxTailTime = 10.;
+}
+
+CAAUProcessor::~CAAUProcessor ()
+{
+ if (mPreflightABL)
+ delete mPreflightABL;
+}
+
+inline OSStatus SetInputCallback (CAAudioUnit &inUnit, AURenderCallbackStruct &inInputCallback)
+{
+ return inUnit.SetProperty (kAudioUnitProperty_SetRenderCallback,
+ kAudioUnitScope_Input,
+ 0,
+ &inInputCallback,
+ sizeof(inInputCallback));
+}
+
+static AURenderCallbackStruct sRenderCallback;
+static OSStatus PrerollRenderProc ( void * /*inRefCon*/,
+ AudioUnitRenderActionFlags * /*inActionFlags*/,
+ const AudioTimeStamp * /*inTimeStamp*/,
+ UInt32 /*inBusNumber*/,
+ UInt32 /*inNumFrames*/,
+ AudioBufferList *ioData)
+{
+ AudioBuffer *buf = ioData->mBuffers;
+ for (UInt32 i = ioData->mNumberBuffers; i--; ++buf)
+ memset((Byte *)buf->mData, 0, buf->mDataByteSize);
+
+ return noErr;
+}
+
+OSStatus Preroll (CAAudioUnit & inAU, UInt32 inFrameSize)
+{
+ CAStreamBasicDescription desc;
+ OSStatus result = inAU.GetFormat (kAudioUnitScope_Input, 0, desc);
+ bool hasInput = false;
+ //we have input
+ if (result == noErr)
+ {
+ sRenderCallback.inputProc = PrerollRenderProc;
+ sRenderCallback.inputProcRefCon = 0;
+
+ result = inAU.SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
+ 0, &sRenderCallback, sizeof(sRenderCallback));
+ if (result) return result;
+ hasInput = true;
+ }
+
+ AudioUnitRenderActionFlags flags = 0;
+ AudioTimeStamp time;
+ memset (&time, 0, sizeof(time));
+ time.mFlags = kAudioTimeStampSampleTimeValid;
+
+ CAStreamBasicDescription outputFormat;
+ ca_require_noerr (result = inAU.GetFormat (kAudioUnitScope_Output, 0, outputFormat), home);
+ {
+ AUOutputBL list (outputFormat, inFrameSize);
+ list.Prepare ();
+
+ result = inAU.Render (&flags, &time, 0, inFrameSize, list.ABL());
+ if (result) { printf("A result %d\n", (int)result); goto home; }
+ }
+
+home:
+ if (hasInput) {
+ // remove our installed callback
+ sRenderCallback.inputProc = 0;
+ sRenderCallback.inputProcRefCon = 0;
+
+ inAU.SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
+ 0, &sRenderCallback, sizeof(sRenderCallback));
+ }
+ return result;
+}
+
+
+OSStatus CAAUProcessor::EstablishInputCallback (AURenderCallbackStruct &inInputCallback)
+{
+ OSStatus result = SetInputCallback (mUnit, inInputCallback);
+ if (!result)
+ memcpy (&mUserCallback, &inInputCallback, sizeof(AURenderCallbackStruct));
+ else
+ memset (&mUserCallback, 0, sizeof (AURenderCallbackStruct));
+ return result;
+}
+
+OSStatus CAAUProcessor::SetAUPreset (CFPropertyListRef inPreset)
+{
+ return mUnit.SetProperty (kAudioUnitProperty_ClassInfo,
+ kAudioUnitScope_Global,
+ 0,
+ &inPreset,
+ sizeof(inPreset));
+}
+
+OSStatus CAAUProcessor::SetAUPresetIndex (SInt32 inPresetIndex)
+{
+ AUPreset aup;
+ aup.presetName = NULL;
+ aup.presetNumber = inPresetIndex;
+ return mUnit.SetPresentPreset(aup);
+}
+
+
+OSStatus CAAUProcessor::SetParameter (AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+ Float32 value, UInt32 bufferOffsetFrames)
+{
+ return mUnit.SetParameter(inID, scope, element, value, bufferOffsetFrames);
+}
+
+
+UInt32 CAAUProcessor::MaxFramesPerRender () const
+{
+ UInt32 maxFrames;
+ UInt32 propSize = sizeof (maxFrames);
+ if (mUnit.GetProperty (kAudioUnitProperty_MaximumFramesPerSlice,
+ kAudioUnitScope_Global, 0, &maxFrames, &propSize))
+ {
+ return 0;
+ }
+ return maxFrames;
+}
+
+OSStatus CAAUProcessor::SetMaxFramesPerRender (UInt32 inMaxFrames)
+{
+ return mUnit.SetProperty (kAudioUnitProperty_MaximumFramesPerSlice,
+ kAudioUnitScope_Global, 0, &inMaxFrames, sizeof(inMaxFrames));
+}
+
+OSStatus CAAUProcessor::Initialize (const CAStreamBasicDescription &inInputDesc,
+ const CAStreamBasicDescription &inOutputDesc,
+ UInt64 inNumInputSamples)
+{
+ return DoInitialisation (inInputDesc, inOutputDesc, inNumInputSamples, MaxFramesPerRender());
+}
+
+OSStatus CAAUProcessor::Reinitialize (UInt32 inNewMaxFrames)
+{
+ OSStatus result;
+ CAStreamBasicDescription inputDesc, outputDesc;
+
+ ca_require_noerr (result = mUnit.GetFormat (kAudioUnitScope_Input, 0, inputDesc), home);
+ ca_require_noerr (result = mUnit.GetFormat (kAudioUnitScope_Output, 0, outputDesc), home);
+
+ ca_require_noerr (result = DoInitialisation (inputDesc, outputDesc, mNumInputSamples, inNewMaxFrames), home);
+
+home:
+ return result;
+}
+
+
+OSStatus CAAUProcessor::DoInitialisation (const CAStreamBasicDescription &inInputFormat,
+ const CAStreamBasicDescription &inOutputFormat,
+ UInt64 inNumInputSamples,
+ UInt32 inMaxFrames)
+{
+ OSStatus result;
+
+ if (inNumInputSamples == 0 && IsOfflineAU())
+ return kAudioUnitErr_InvalidOfflineRender;
+
+ mNumInputSamples = inNumInputSamples;
+
+ // first check that we can do this number of channels
+ if (mUnit.CanDo (inInputFormat.NumberChannels(), inOutputFormat.NumberChannels()) == false)
+ ca_require_noerr (result = kAudioUnitErr_FailedInitialization, home);
+
+ // just uninitialise the AU as a matter of course
+ ca_require_noerr (result = mUnit.Uninitialize(), home);
+
+ ca_require_noerr (result = mUnit.SetFormat (kAudioUnitScope_Input, 0, inInputFormat), home);
+ ca_require_noerr (result = mUnit.SetFormat (kAudioUnitScope_Output, 0, inOutputFormat), home);
+ ca_require_noerr (result = SetMaxFramesPerRender (inMaxFrames), home);
+
+#if !TARGET_OS_IPHONE
+ // if we're any AU but an offline AU, we should tell it that we've processing offline
+ if (!IsOfflineAU()) {
+ UInt32 isOffline = (IsOfflineContext() ? 1 : 0);
+ // don't care whether this succeeds of fails as many AU's don't care about this
+ // but the ones that do its important that they are told their render context
+ mUnit.SetProperty (kAudioUnitProperty_OfflineRender, kAudioUnitScope_Global, 0, &isOffline, sizeof(isOffline));
+ } else {
+ // tell the offline unit how many input samples we wish to process...
+ mUnit.SetProperty (kAudioUnitOfflineProperty_InputSize,
+ kAudioUnitScope_Global, 0,
+ &mNumInputSamples, sizeof(mNumInputSamples));
+ }
+#endif
+
+ ca_require_noerr (result = mUnit.Initialize(), home);
+
+ ca_require_noerr (result = SetInputCallback (mUnit, mUserCallback), home);
+
+ // finally reset our time stamp
+ // the time stamp we use with the AU Render - only sample count is valid
+ memset (&mRenderTimeStamp, 0, sizeof(mRenderTimeStamp));
+ mRenderTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
+
+ // now, if we're NOT an offline AU, preflighting is not required
+ // if we are an offline AU, we should preflight.. an offline AU will tell us when its preflighting is done
+ mPreflightDone = false;
+
+ if (mPreflightABL) {
+ delete mPreflightABL;
+ mPreflightABL = NULL;
+ }
+
+ mPreflightABL = new AUOutputBL (inOutputFormat);
+
+ mLastPercentReported = 0;
+
+home:
+ return result;
+}
+
+void CAAUProcessor::CalculateRemainderSamples (Float64 inSampleRate)
+{
+ mLatencySamples = 0;
+ mTailSamplesToProcess = 0;
+ mTailSamples = 0;
+ mTailSamplesRemaining = 0;
+ return;
+
+ // nothing to do because we're not processing offline
+ if (IsOfflineContext() == false) return;
+
+ // because an offline unit has some indeterminancy about what it does with the input samples
+ // it is *required* to deal internally with both latency and tail
+ if (!IsOfflineAU())
+ {
+ // when offline we need to deal with both latency and tail
+
+ // if the AU has latency - how many samples at the start will be zero?
+ // we'll end up chucking these away.
+ Float64 renderTimeProps;
+ UInt32 propSize = sizeof (renderTimeProps);
+ OSStatus result = mUnit.GetProperty (kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0,
+ &renderTimeProps, &propSize);
+
+ Float64 latencySamples = 0;
+ if (result == noErr) // we have latency to deal with - its reported in seconds
+ latencySamples = renderTimeProps * inSampleRate;
+
+ // AU tail
+ // if the AU has a tail - we'll pull that many zeroes through at the end to flush
+ // out this tail - think of a decaying digital delay or reverb...
+ result = mUnit.GetProperty (kAudioUnitProperty_TailTime, kAudioUnitScope_Global, 0,
+ &renderTimeProps, &propSize);
+ if (renderTimeProps > mMaxTailTime)
+ renderTimeProps = mMaxTailTime;
+ Float64 tailSamples = 0;
+ if (result == noErr)
+ tailSamples = renderTimeProps * inSampleRate;
+
+ // this dictates how many samples at the end we need to pull through...
+ // we add latency to tail because we throw the latency samples away from the start of the rendering
+ // and we have to pull that many samples after the end of course to get the last of the original data
+ // then to that is added the tail of the effect...
+ mTailSamplesToProcess = UInt32(tailSamples + latencySamples);
+ mTailSamples = UInt32(tailSamples);
+ mLatencySamples = UInt32(latencySamples);
+ }
+}
+
+#if !TARGET_OS_IPHONE
+CFStringRef CAAUProcessor::GetOLPreflightName () const
+{
+ if (OfflineAUNeedsPreflight())
+ {
+ CFStringRef str;
+ UInt32 size = sizeof(str);
+ OSStatus result = mUnit.GetProperty (kAudioUnitOfflineProperty_PreflightName,
+ kAudioUnitScope_Global, 0,
+ &str, &size);
+ return result ? NULL : str;
+ }
+ return NULL; // says NO to preflighting
+}
+
+bool CAAUProcessor::OfflineAUNeedsPreflight () const
+{
+ if (IsOfflineAU()) {
+ UInt32 preflightRequirements;
+ UInt32 size = sizeof(preflightRequirements);
+ OSStatus result = mUnit.GetProperty (kAudioUnitOfflineProperty_PreflightRequirements,
+ kAudioUnitScope_Global, 0,
+ &preflightRequirements, &size);
+ if (result)
+ return false;
+ return preflightRequirements;
+ }
+ return false;
+}
+#endif
+
+OSStatus CAAUProcessor::Preflight (bool inProcessPreceedingTail)
+{
+ printf(">>>>CAAUProcessor::Preflight\n");
+ //we're preflighting again, so reset ourselves
+ if (mPreflightDone) {
+ mPreflightDone = false;
+ // the time stamp we use with the AU Render - only sample count is valid
+ memset (&mRenderTimeStamp, 0, sizeof(mRenderTimeStamp));
+ mRenderTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
+ mUnit.GlobalReset();
+ }
+
+ Float64 sampleRate;
+ OSStatus result = mUnit.GetSampleRate (kAudioUnitScope_Output, 0, sampleRate);
+ CalculateRemainderSamples (sampleRate);
+
+ UInt32 numFrames = MaxFramesPerRender();
+ if (numFrames == 0)
+ return kAudioUnitErr_InvalidProperty;
+
+ if (!IsOfflineAU())
+ {
+ if ((IsOfflineContext() == false && inProcessPreceedingTail) || IsOfflineContext())
+ {
+ // re-establish the user's input callback
+ ca_require_noerr (result = SetInputCallback (mUnit, mUserCallback), home);
+
+ // Consume the number of input samples indicated by the AU's latency or tail
+ // based on whether the AU is being used in an offline context or not.
+
+ UInt32 latSamps = IsOfflineContext() ? mLatencySamples : mTailSamples;
+ printf("latSamps %d\n", (int)latSamps);
+ latSamps = 0;
+ while (latSamps > 0)
+ {
+ if (latSamps < numFrames)
+ numFrames = latSamps;
+
+ // process the samples (the unit's input callback will read the samples
+ // from the file and convert them to float for processing
+ AudioUnitRenderActionFlags renderFlags = 0;
+ mPreflightABL->Prepare();
+ result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, numFrames, mPreflightABL->ABL());
+ if (result) { printf("B result %d\n", (int)result); goto home; }
+
+ mRenderTimeStamp.mSampleTime += numFrames;
+ latSamps -= numFrames;
+ }
+ if (IsOfflineContext())
+ mRenderTimeStamp.mSampleTime = mLatencySamples;
+ }
+ else
+ {
+ // processing real-time but not processing preceeding tail, so we should preroll the AU
+ ca_require_noerr (result = Preroll(mUnit, numFrames), home);
+
+ // re-establish the user's input callback
+ ca_require_noerr (result = SetInputCallback (mUnit, mUserCallback), home);
+
+ mRenderTimeStamp.mSampleTime = 0;
+ }
+ }
+#if !TARGET_OS_IPHONE
+ else
+ {
+ // re-establish the user's input callback
+ ca_require_noerr (result = SetInputCallback (mUnit, mUserCallback), home);
+
+ UInt32 preflightRequirements;
+ UInt32 size; size = sizeof(preflightRequirements);
+ ca_require_noerr (result = mUnit.GetProperty (kAudioUnitOfflineProperty_PreflightRequirements,
+ kAudioUnitScope_Global, 0,
+ &preflightRequirements, &size), home);
+
+ // 0 indicates none, otherwise optional or required -> we do it for either
+ if (preflightRequirements)
+ {
+ for (;;) {
+ // here we need to do the preflight loop - we don't expect any data back, but have to
+ // give the offline unit all of its input data to allow it to prepare its processing
+ AudioUnitRenderActionFlags renderFlags = kAudioOfflineUnitRenderAction_Preflight;
+ mPreflightABL->Prepare();
+ result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, numFrames, mPreflightABL->ABL());
+ if (result) { printf("C result %d\n", (int)result); goto home; }
+ mRenderTimeStamp.mSampleTime += numFrames;
+
+ if (renderFlags & kAudioOfflineUnitRenderAction_Complete)
+ break;
+ }
+ }
+ // the time stamp we use with the AU Render - only sample count is valid
+ mRenderTimeStamp.mSampleTime = 0;
+ }
+#endif
+
+ if (result == noErr) {
+ mPreflightDone = true;
+ }
+
+home:
+ printf("<<<<CAAUProcessor::Preflight\n");
+ return result;
+}
+
+#if !TARGET_OS_IPHONE
+OSStatus CAAUProcessor::OfflineAUPreflight (UInt32 inNumFrames, bool &outIsDone)
+{
+ if (!IsOfflineAU())
+ return -50/*paramErr*/;
+ if (mNumInputSamples == 0)
+ return -50/*paramErr*/;
+
+ UInt32 preflightRequirements;
+ UInt32 size = sizeof(preflightRequirements);
+ OSStatus result;
+ ca_require_noerr (result = mUnit.GetProperty (kAudioUnitOfflineProperty_PreflightRequirements,
+ kAudioUnitScope_Global, 0,
+ &preflightRequirements, &size), home);
+
+ // 0 indicates none, otherwise optional or required -> we do it for either
+ if (preflightRequirements)
+ {
+ AudioUnitRenderActionFlags renderFlags = kAudioOfflineUnitRenderAction_Preflight;
+ mPreflightABL->Prepare();
+ result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, inNumFrames, mPreflightABL->ABL());
+ if (result) { printf("D result %d\n", (int)result); goto home; }
+ mRenderTimeStamp.mSampleTime += inNumFrames;
+
+ if (renderFlags & kAudioOfflineUnitRenderAction_Complete) {
+ outIsDone = true;
+ mRenderTimeStamp.mSampleTime = 0;
+ mPreflightDone = true;
+ mLastPercentReported = 0;
+ }
+ }
+ else
+ {
+ outIsDone = true;
+ mRenderTimeStamp.mSampleTime = 0;
+ mPreflightDone = true;
+ mLastPercentReported = 0;
+ }
+
+home:
+ return result;
+}
+#endif
+
+void SetBufferListToNumFrames (AudioBufferList &list, UInt32 inNumFrames)
+{
+ for (unsigned int i = 0; i < list.mNumberBuffers; ++i) {
+ AudioBuffer &buf = list.mBuffers[i];
+ if (buf.mDataByteSize > 0)
+ buf.mDataByteSize = inNumFrames * sizeof (Float32);
+ }
+}
+
+OSStatus CAAUProcessor::Render (AudioBufferList *ioData,
+ UInt32 &ioNumFrames,
+ bool &outIsSilence,
+ bool *outOLCompleted,
+ bool *outOLRequiresPostProcess)
+{
+ if (IsOfflineContext())
+ {
+ if (!mPreflightDone)
+ return kAudioUnitErr_InvalidOfflineRender;
+
+ // YES - this is correct!!! you have to provide both if rendering in an offline Context
+ *outOLCompleted = false;
+ *outOLRequiresPostProcess = false;
+
+ if (!IsOfflineAU() && !mUnit.Comp().Desc().IsFConv())
+ {
+ // have we processed the input we expect too?
+ // in an offline case, we want to create output that matches the input
+ // for an OfflineAU type, it manages this internally, so we don't have to do anything
+ // for a FormatConverter AU, we don't know and can't tell, so we can't do anything here
+ // for any other AU type (effect, instrument) the Prime assumption is that it will
+ // ask for the same number of frames of input as it is asked to output
+ // so we can ask what it is doing, and get a sample accurate output (which is input + tail time)
+ if (mRenderTimeStamp.mSampleTime + ioNumFrames >= InputSampleCount())
+ {
+ // if we fall into here, we have just a partial number of input samples left
+ // (less input less than what we've been asked to produce output for.
+ *outOLCompleted = true;
+ // we require post processing if we've got some tail (or latency) samples to flush through
+ *outOLRequiresPostProcess = mTailSamplesToProcess > 0;
+ if (InputSampleCount() > mRenderTimeStamp.mSampleTime) {
+ ioNumFrames = (UInt32)(InputSampleCount() - mRenderTimeStamp.mSampleTime);
+ } else {
+ ioNumFrames = 0;
+ }
+ mTailSamplesRemaining = mTailSamplesToProcess;
+ // we've got no input samples to process this time.
+ SetBufferListToNumFrames (*ioData, ioNumFrames);
+ if (ioNumFrames == 0) {
+ if (*outOLRequiresPostProcess)
+ SetInputCallback (mUnit, sSilentCallback);
+ else
+ mUnit.GlobalReset (); //flush this out, as we're done with this phase
+ return noErr;
+ }
+ }
+ }
+ AudioUnitRenderActionFlags renderFlags = IsOfflineAU() ? kAudioOfflineUnitRenderAction_Render : 0;
+ OSStatus result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, ioNumFrames, ioData);
+ if (result) { printf("E result %d\n", (int)result); }
+ if (result) {
+ if (mUnit.Comp().Desc().IsFConv()) {
+ // this is the only way we can tell we're done with a FormatConverter AU
+ // - ie. client returns an error from input
+ result = noErr;
+ *outOLCompleted = true;
+ *outOLRequiresPostProcess = mTailSamplesToProcess > 0;
+ ioNumFrames = 0;
+ SetBufferListToNumFrames (*ioData, ioNumFrames);
+ } else
+ return result;
+ }
+// for (UInt32 i = 0; i < ioNumFrames; ++i) {
+// union {
+// float f;
+// unsigned char c[4];
+// } u;
+// u.f = ((float*)(ioData->mBuffers[0].mData))[i];
+// printf("aup out %4d %14.10f %02X %02X %02X %02X\n", (int)i, u.f, u.c[0], u.c[1], u.c[2], u.c[3]);
+// }
+ mRenderTimeStamp.mSampleTime += ioNumFrames;
+ outIsSilence = (renderFlags & kAudioUnitRenderAction_OutputIsSilence);
+
+ // if we're an Offline AU type, it will set this flag on completion of its processing
+ if (renderFlags & kAudioOfflineUnitRenderAction_Complete) {
+ // we now need to calculate how many frames we rendered.
+ // as we're dealing with PCM non-interleaved buffers, we can calculate the numFrames simply
+ ioNumFrames = ioData->mBuffers[0].mDataByteSize / sizeof(Float32);
+ *outOLCompleted = true;
+ *outOLRequiresPostProcess = false;
+ mUnit.GlobalReset (); //flush this out, as we're done with this phase
+ } else {
+ if (*outOLCompleted) {
+ if (*outOLRequiresPostProcess)
+ result = SetInputCallback (mUnit, sSilentCallback);
+ else
+ mUnit.GlobalReset (); //flush this out, as we're done with this phase
+ }
+ }
+
+ return result;
+ }
+
+// rendering in a RT context:
+ AudioUnitRenderActionFlags renderFlags = 0;
+ OSStatus result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, ioNumFrames, ioData);
+ if (result) { printf("F result %d\n", (int)result); }
+ if (!result) {
+ mRenderTimeStamp.mSampleTime += ioNumFrames;
+ outIsSilence = (renderFlags & kAudioUnitRenderAction_OutputIsSilence);
+ }
+// for (UInt32 i = 0; i < ioNumFrames; ++i) {
+// union {
+// float f;
+// unsigned char c[4];
+// } u;
+// u.f = ((float*)(ioData->mBuffers[0].mData))[i];
+// printf("aup out %4d %14.10f %02X %02X %02X %02X\n", (int)i, u.f, u.c[0], u.c[1], u.c[2], u.c[3]);
+// }
+
+ return result;
+}
+
+OSStatus CAAUProcessor::PostProcess (AudioBufferList *ioData,
+ UInt32 &ioNumFrames,
+ bool &outIsSilence,
+ bool &outDone)
+{
+ if (IsOfflineAU() || !IsOfflineContext())
+ return kAudioUnitErr_CannotDoInCurrentContext;
+
+ outDone = false;
+
+ // we've got less samples to process than we've been asked to process
+ if (mTailSamplesRemaining <= SInt32(ioNumFrames)) {
+ outDone = true;
+ ioNumFrames = mTailSamplesRemaining > 0 ? mTailSamplesRemaining : 0;
+ SetBufferListToNumFrames (*ioData, ioNumFrames);
+ if (ioNumFrames == 0)
+ return noErr;
+ }
+
+ AudioUnitRenderActionFlags renderFlags = 0;
+ OSStatus result;
+ result = mUnit.Render (&renderFlags, &mRenderTimeStamp, 0, ioNumFrames, ioData);
+ if (result) { printf("G result %d\n", (int)result); goto home; }
+ mRenderTimeStamp.mSampleTime += ioNumFrames;
+ mTailSamplesRemaining -= ioNumFrames;
+ outIsSilence = (renderFlags & kAudioUnitRenderAction_OutputIsSilence);
+
+ if (outDone) {
+ ca_require_noerr (result = SetInputCallback (mUnit, mUserCallback), home);
+ mUnit.GlobalReset (); //flush this out, as we're done with this phase
+ }
+home:
+ return result;
+}
+
+#if !TARGET_OS_IPHONE
+Float32 CAAUProcessor::GetOLPercentComplete ()
+{
+ if (!IsOfflineContext())
+ return 0;
+
+ Float32 percentDone = mLastPercentReported;
+
+ if (IsOfflineAU())
+ {
+ // we get the output size every time, as this can change as parameters are changed
+ UInt64 numOutputSamples = mNumInputSamples;
+ UInt32 propSize = sizeof(numOutputSamples);
+ mUnit.GetProperty (kAudioUnitOfflineProperty_OutputSize,
+ kAudioUnitScope_Global, 0, &numOutputSamples, &propSize);
+
+ percentDone = (mRenderTimeStamp.mSampleTime / Float64(numOutputSamples)) * 100.;
+ }
+ else
+ {
+ percentDone = (mRenderTimeStamp.mSampleTime / Float64(mNumInputSamples + mTailSamples)) * 100.;
+ }
+
+ if (percentDone > mLastPercentReported)
+ mLastPercentReported = percentDone;
+
+ return mLastPercentReported;
+}
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.h b/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.h
new file mode 100644
index 0000000000..f0fb34574d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.h
@@ -0,0 +1,293 @@
+/*
+ File: CAAUProcessor.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAAUProcessor_h__
+#define __CAAUProcessor_h__
+
+#include <AudioToolbox/AudioToolbox.h>
+#include "CAStreamBasicDescription.h"
+#include "CAAudioUnit.h"
+#include "AUOutputBL.h"
+
+#if TARGET_OS_IPHONE
+ #include <AssertMacros.h>
+#endif
+/*
+ This class wraps an AU (using the CAAudioUnit helper class) to use that AU for processing data
+ It can be used in a RealTime context (rendering data with RT constraints) or in an OffLine context
+ such as using an AU to process data that is stored in a file, and on which there are no
+ RT constraints to be imposed.
+
+ Order of operations:
+ Create an instance
+ Establish an Input Callback
+ Initialize the AU to the audio formats and whether it is going to process in an offline or RT context
+ Preflight
+
+ while (...)
+ Render // based on your calling context
+
+ PostProcess if needed (only in OL case)
+
+ After any initialization, preflighting is required.
+
+ Parameter Values on the AU should be set just before each call to Render. The sampleFrameOffsets
+ supplied when setting those values are an offset into that next render buffer's numFrames.
+
+ RT vs OT is determined by whether the inputSampleCount is set during Initialization, thus
+ this class can move the AU between RT and OL contexts. If you are using an AU of type 'auol'
+ (Offline), then it cannot be used in a RT context.
+
+ The CAAUProcessor will only call your Input Callback for input when it needs valid input.
+ This input callback will contain a sample time that indicates where within your input
+ you should read data from, where after preflighting, the first output data produces is for
+ the output sample count of zero.
+
+ MaxFrames should be set before initialisation (or is also passed in to the Reinitialize API)
+
+ If RT, then PostProcessing will *never* be required, nor will Render ever return an isDone value
+ If OL, then Render will at some point return isDone==true, and then also indicate if PostProcessing is required
+
+ If using a Format Converter AU in offline context, then the only way for it to determine that you've finished
+ is for the Input callback to return an error. This means ultimately, that you'll have potentially longer output
+ than you should have. The only way to manage this is for the caller to know the relationship between
+ input to output samples that will be required, and to call Render for just that amount of output samples
+ then return an error, so the tail and latency can be processed.
+
+ Tail and Latency are *only* calculated at initialisation.. Some AU's may change these properties based on
+ either different presets or parameter settings... Ideally, this class should listen to those properties
+ and recalculate its values based on those changes.
+*/
+
+class CAAUProcessor {
+public:
+ // by default this is set to process offline
+ CAAUProcessor (const CAComponent& inComp);
+ ~CAAUProcessor ();
+
+ CAAudioUnit& AU() { return mUnit; }
+ const CAAudioUnit& AU() const { return mUnit; }
+
+#pragma mark __Setup APIs
+ bool IsOfflineContext () const { return mNumInputSamples != 0; }
+
+ // this contains the callback and client data that the AU
+ // uses to call when it needs input
+ OSStatus EstablishInputCallback (AURenderCallbackStruct &inInputCallback);
+
+ OSStatus SetAUPreset (CFPropertyListRef inPreset);
+ OSStatus SetAUPresetIndex (SInt32 inPresetIndex);
+
+ OSStatus SetParameter (AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+ Float32 value, UInt32 bufferOffsetFrames = 0);
+
+ // a result of zero here signifies an error
+ UInt32 MaxFramesPerRender () const;
+
+ // this call can return an error if the AU is initialized - see Reinitialize
+ OSStatus SetMaxFramesPerRender (UInt32 inMaxFrames);
+
+ // Prepares the AU for processing at the specified format
+ // only doing n-n channel processing here.. could extend this for n-m channel processing easily enough
+ // if you are processing using an Offline AU, you HAVE to specify the numInputSamples to process
+ // if you are processing real-time, then inNumInputSamples should be zero
+ OSStatus Initialize (const CAStreamBasicDescription &inIODesc, UInt64 inNumInputSamples = 0)
+ {
+ return Initialize (inIODesc, inIODesc, inNumInputSamples);
+ }
+ OSStatus Initialize (const CAStreamBasicDescription &inInputDesc,
+ const CAStreamBasicDescription &inOutputDesc,
+ UInt64 inNumInputSamples = 0);
+
+ // takes the existing format state of the AU, but resets the AUProcessor so that:
+ // applies an optional new number of max frames
+ // the AUProcessor will have to be Preflighted again after this call
+ // Use this when you want to keep the same formats, same input sample count,
+ // but want to re-initialize the AU to use a new num max frames and prepare it
+ // appropriately...
+ OSStatus Reinitialize (UInt32 inNewMaxFrames);
+
+
+
+#pragma mark __Render APIs
+ // Preflighting - you HAVE to preflight
+ // returns noErr when preflighting is done
+
+ // Offline Context:
+ // Offline AU's require preflighting, even if they will end up doing no work.
+ // In the case where the AU is offline the latency samples are trimmed and not returned
+ // from the consequent Render calls
+
+ // If you are NOT an offline AU then the first time Render is called,
+ // there will need to be some consumption of the input before you will get any valid output data.
+ // This is determined by the value of the AU's reported latency. So, in this case preflight
+ // will consume those initial samples and then return.
+ // Your InputCallback MUST provide the initial data that is to be processed.
+
+ // RealTime Context:
+ // (1 No priming. In this case inProcessPreceedingTail is false (the default) and no
+ // processing is done on the AU. However, because preflight is the first time that Rendering
+ // is called on an AU we can presume that this is outside the context of the processing that
+ // is occuring in the host application. To avoid taking page faults, priming cold memory, etc.
+ // when the AU *is* consequently used to render real data, the AU is prerolled and reset if this is the case.
+
+ // (2) Prime the AU's buffers with input data that preceeds the portion of audio you
+ // want to process. This amount of input data is equivalent to the tail time of the AU
+ // which expresses how long it takes for an sample on input to disappear from the output
+ // (Think of a delay or a reverb)
+ // So, by setting inProcessPreceedingTail to true, the preflight call will consume
+ // the tail time samples of input (which should be valid input BEFORE the data to be processed)
+ // So, your input proc here will HAVE to read samples from the preceeding input. The time
+ // stamps to your input proc in this case can be interpreted as 0 is the start of the preceeding data
+ // and you'll need to read up to the numSamples of tail time of the preceeding data.
+ // It discards the output results of the preflighting. If you don't have any previous data
+ // with which to prepare the AU, then you do NOT need to take this path and can do the step below.
+
+ // In both of these cases the inital latency frames are *not* trimmed from
+ // the output that will be generated by a consequent call to render.
+ OSStatus Preflight (bool inProcessPreceedingTail = false);
+
+ // this can be used with an OfflineAU to do a gradual preflight (so you could for instance,
+ // present a progress indicator. The Preflight call will do it all at once.
+ // If you break out of the preflight before you are done, then you HAVE to reinitialise the AU
+ // before you can either do another preflight or do a render, otherwise the Render call will produce
+ // invalid results.
+ OSStatus OfflineAUPreflight (UInt32 inNumFrames, bool &outIsDone);
+
+ // Here's the major stage that produces output.
+ // You pass in two bool flags and an ioNumFrames....
+
+ // So ioNumFrames will be *untouched* if outOLCompleted == false
+ // if outOLCompleted is true, ioNumFrames contains the number of valid frames within the ioData data that are valid data
+ // (ioData's pointers and sizes will also have been resized to match these number of frames)
+ // outOLRequiresPostProcess should also be checked when outOLCompleted is true,
+ // to see if any post-processing is required
+ // if rendering in a RT context, then neither outOLCompleted or outOLRequiresPostProcess is required
+ // if rendering in an OL context, both must be specified.
+ // Caller MUST provide an ABL that is set up in the previously specified output format
+
+ // If you receive kAudioUnitErr_InvalidOfflineRender when dealing with an OfflineAU Type, then you have either not
+ // preflighted it (and the AU requires it) or you have changed some state (its num input samples, its start offest)
+ // and it needs to be re-preflighted. In that case, preflight the AU again first.
+ OSStatus Render (AudioBufferList *ioData,
+ UInt32 &ioNumFrames,
+ bool &outIsSilence,
+ bool *outOLCompleted = NULL,
+ bool *outOLRequiresPostProcess = NULL);
+
+ // call this method if outOLRequiresPostProcess returned true upon rendering completion
+ OSStatus PostProcess (AudioBufferList *ioData, UInt32 &ioNumFrames, bool &outIsSilence, bool &outDone);
+
+ // This method returns how many input samples will need to be provided before
+ // valid output data is produced.
+ UInt32 LatencySampleCount () const { return mLatencySamples; }
+
+ UInt32 TailSampleCount () const { return mTailSamples; }
+
+ UInt64 InputSampleCount () const { return mNumInputSamples; }
+
+ // the class maintains the TimeStamp from render call to render call
+ // this value is the sample count that will be used in the *next* render call
+ Float64 SampleTime () const { return mRenderTimeStamp.mSampleTime; }
+
+ // in some settings (for instance a delay with 100% feedback) tail time is essentially infinite
+ // so you should safeguard the final OL render stage (post process) which is aimed at pulling the tail through
+ // default is 10 seconds
+ Float64 GetMaxTailTime () const { return mMaxTailTime; }
+
+ // this ONLY takes affect when you initialise the processor, it doesn't change that AU's tail time,
+ // but just the max amount of time that this object will allow the AU to post-process data
+ // set this to 0, to use the AU's tail time with no adjustment
+ void SetMaxTailTime (Float64 inTailTimeSecs) { mMaxTailTime = inTailTimeSecs; }
+
+#if !TARGET_OS_IPHONE
+ // if this is NULL, then there is no explicit (optional or required) preflight requirement of the AU
+ // if this is valid, then the AU either requires or optionally requires preflighting. The default
+ // behaviour in this case is that the processor will preflight. This name can be used to preset
+ // to the user. If the AU doesn't present a name, but preflighting is optional/required, then the
+ // processor return "Preflight" as its string.
+ // the String should be released by the caller.
+ CFStringRef GetOLPreflightName () const;
+
+ // Returns true if this is processor is an offline AU, and that AU (whether optional or required)
+ // needs preflighting
+ bool OfflineAUNeedsPreflight () const;
+
+ // this provides a rough approximation of the progress of an Offline Processing operation (both for the
+ // preflight and the render phases)
+ Float32 GetOLPercentComplete ();
+#endif
+
+private:
+ CAAudioUnit mUnit;
+ UInt32 mLatencySamples;
+ UInt32 mTailSamples;
+ UInt32 mTailSamplesToProcess;
+ UInt64 mNumInputSamples;
+ AudioTimeStamp mRenderTimeStamp;
+ bool mPreflightDone;
+ AUOutputBL * mPreflightABL;
+ SInt32 mTailSamplesRemaining;
+ AURenderCallbackStruct mUserCallback;
+ Float64 mMaxTailTime;
+ Float32 mLastPercentReported;
+
+ bool IsOfflineAU () const { return mUnit.Comp().Desc().IsOffline(); }
+
+ void CalculateRemainderSamples (Float64 inSampleRate);
+
+ OSStatus DoInitialisation (const CAStreamBasicDescription &inInputFormat,
+ const CAStreamBasicDescription &inOutputFormat,
+ UInt64 inNumInputSamples,
+ UInt32 inMaxFrames);
+
+ // stop automatic copying of this object
+ CAAUProcessor () {}
+ CAAUProcessor (const CAAUProcessor &c) {}
+ CAAUProcessor& operator= (const CAAUProcessor& c) { return *this; }
+};
+
+#endif //__CAAUProcessor_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAtomic.h b/libs/appleutility/CoreAudio/PublicUtility/CAAtomic.h
new file mode 100644
index 0000000000..c9a611bf7a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAtomic.h
@@ -0,0 +1,305 @@
+/*
+ File: CAAtomic.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+/*
+ This file implements all Atomic operations using Interlocked functions specified in
+ Winbase.h
+NOTE: According to Microsoft documentation, all Interlocked functions generates a
+full barrier.
+ On Windows:
+ As the Interlocked functions returns the Old value, Extra checks and operations
+ are made after the atomic operation to return value consistent with OSX counterparts.
+*/
+#ifndef __CAAtomic_h__
+#define __CAAtomic_h__
+
+#if TARGET_OS_WIN32
+ #include <windows.h>
+ #include <intrin.h>
+ #pragma intrinsic(_InterlockedOr)
+ #pragma intrinsic(_InterlockedAnd)
+#else
+ #include <CoreFoundation/CFBase.h>
+ #include <libkern/OSAtomic.h>
+#endif
+
+inline void CAMemoryBarrier()
+{
+#if TARGET_OS_WIN32
+ MemoryBarrier();
+#else
+ OSMemoryBarrier();
+#endif
+}
+
+inline SInt32 CAAtomicAdd32Barrier(SInt32 theAmt, volatile SInt32* theValue)
+{
+#if TARGET_OS_WIN32
+ long lRetVal = InterlockedExchangeAdd((volatile long*)theValue, theAmt);
+ // InterlockedExchangeAdd returns the original value which differs from OSX version.
+ // At this point the addition would have occured and hence returning the new value
+ // to keep it sync with OSX.
+ return lRetVal + theAmt;
+#else
+ return OSAtomicAdd32Barrier(theAmt, (volatile int32_t *)theValue);
+#endif
+}
+
+inline SInt32 CAAtomicOr32Barrier(UInt32 theMask, volatile UInt32* theValue)
+{
+#if TARGET_OS_WIN32
+ // InterlockedAnd macro is not defined in x86 platform, and hence using the intrinsic
+ // function instead.
+ long j = _InterlockedOr((volatile long*)theValue, theMask);
+ // _InterlockedOr returns the original value which differs from OSX version.
+ // Returning the new value similar to OSX
+ return (SInt32)(j | theMask);
+#else
+ return OSAtomicOr32Barrier(theMask, (volatile uint32_t *)theValue);
+#endif
+}
+
+inline SInt32 CAAtomicAnd32Barrier(UInt32 theMask, volatile UInt32* theValue)
+{
+#if TARGET_OS_WIN32
+// InterlockedAnd macro is not defined in x86 platform, and hence using the intrinsic
+// function instead.
+ long j = _InterlockedAnd((volatile long*)theValue, theMask);
+ // _InterlockedAnd returns the original value which differs from OSX version.
+ // Returning the new value similar to OSX
+ return (SInt32)(j & theMask);
+#else
+ return OSAtomicAnd32Barrier(theMask, (volatile uint32_t *)theValue);
+#endif
+}
+
+inline bool CAAtomicCompareAndSwap32Barrier(SInt32 oldValue, SInt32 newValue, volatile SInt32 *theValue)
+{
+#if TARGET_OS_WIN32
+ // InterlockedCompareExchange returns the old value. But we need to return bool value.
+ long lRetVal = InterlockedCompareExchange((volatile long*)theValue, newValue, oldValue);
+// Hence we check if the new value is set and if it is we return true else false.
+// If theValue is equal to oldValue then the swap happens. Otherwise swap doesn't happen.
+ return (oldValue == lRetVal);
+#else
+ return OSAtomicCompareAndSwap32Barrier(oldValue, newValue, (volatile int32_t *)theValue);
+#endif
+}
+
+
+inline SInt32 CAAtomicIncrement32(volatile SInt32* theValue)
+{
+#if TARGET_OS_WIN32
+ return (SInt32)InterlockedIncrement((volatile long*)theValue);
+#else
+ return OSAtomicIncrement32((volatile int32_t *)theValue);
+#endif
+}
+
+inline SInt32 CAAtomicDecrement32(volatile SInt32* theValue)
+{
+#if TARGET_OS_WIN32
+ return (SInt32)InterlockedDecrement((volatile long*)theValue);
+#else
+ return OSAtomicDecrement32((volatile int32_t *)theValue);
+#endif
+}
+
+inline SInt32 CAAtomicIncrement32Barrier(volatile SInt32* theValue)
+{
+#if TARGET_OS_WIN32
+ return CAAtomicIncrement32(theValue);
+#else
+ return OSAtomicIncrement32Barrier((volatile int32_t *)theValue);
+#endif
+}
+
+inline SInt32 CAAtomicDecrement32Barrier(volatile SInt32* theValue)
+{
+#if TARGET_OS_WIN32
+ return CAAtomicDecrement32(theValue);
+#else
+ return OSAtomicDecrement32Barrier((volatile int32_t *)theValue);
+#endif
+}
+
+inline bool CAAtomicTestAndClearBarrier(int bitToClear, void* theAddress)
+{
+#if TARGET_OS_WIN32
+ BOOL bOldVal = InterlockedBitTestAndReset((long*)theAddress, bitToClear);
+ return (bOldVal ? true : false);
+#else
+ return OSAtomicTestAndClearBarrier(bitToClear, (volatile void *)theAddress);
+#endif
+}
+
+inline bool CAAtomicTestAndClear(int bitToClear, void* theAddress)
+{
+#if TARGET_OS_WIN32
+ BOOL bOldVal = CAAtomicTestAndClearBarrier(bitToClear, (long*)theAddress);
+ return (bOldVal ? true : false);
+#else
+ return OSAtomicTestAndClear(bitToClear, (volatile void *)theAddress);
+#endif
+}
+
+inline bool CAAtomicTestAndSetBarrier(int bitToSet, void* theAddress)
+{
+#if TARGET_OS_WIN32
+ BOOL bOldVal = InterlockedBitTestAndSet((long*)theAddress, bitToSet);
+ return (bOldVal ? true : false);
+#else
+ return OSAtomicTestAndSetBarrier(bitToSet, (volatile void *)theAddress);
+#endif
+}
+
+// int32_t flavors -- for C++ only since we can't overload in C
+// CFBase.h defines SInt32 as signed int which is similar to int32_t. If CFBase.h is included, then
+// this will generate redefinition error. But on Mac, CFBase.h, still includes MacTypes.h where
+// SInt32 is defined as signed long so this would work there.
+// So in order to fix the redefinition errors, we define these functions only if MacTypes.h is included.
+#if defined(__cplusplus) && defined(__MACTYPES__) && !__LP64__
+inline int32_t CAAtomicAdd32Barrier(int32_t theAmt, volatile int32_t* theValue)
+{
+ return CAAtomicAdd32Barrier(theAmt, (volatile SInt32 *)theValue);
+}
+
+inline int32_t CAAtomicOr32Barrier(uint32_t theMask, volatile uint32_t* theValue)
+{
+ return CAAtomicOr32Barrier(theMask, (volatile UInt32 *)theValue);
+}
+
+inline int32_t CAAtomicAnd32Barrier(uint32_t theMask, volatile uint32_t* theValue)
+{
+ return CAAtomicAnd32Barrier(theMask, (volatile UInt32 *)theValue);
+}
+
+inline bool CAAtomicCompareAndSwap32Barrier(int32_t oldValue, int32_t newValue, volatile int32_t *theValue)
+{
+ return CAAtomicCompareAndSwap32Barrier(oldValue, newValue, (volatile SInt32 *)theValue);
+}
+
+inline int32_t CAAtomicIncrement32(volatile int32_t* theValue)
+{
+ return CAAtomicIncrement32((volatile SInt32 *)theValue);
+}
+
+inline int32_t CAAtomicDecrement32(volatile int32_t* theValue)
+{
+ return CAAtomicDecrement32((volatile SInt32 *)theValue);
+}
+
+inline int32_t CAAtomicIncrement32Barrier(volatile int32_t* theValue)
+{
+ return CAAtomicIncrement32Barrier((volatile SInt32 *)theValue);
+}
+
+inline int32_t CAAtomicDecrement32Barrier(volatile int32_t* theValue)
+{
+ return CAAtomicDecrement32Barrier((volatile SInt32 *)theValue);
+}
+#endif // __cplusplus && !__LP64__
+
+#if __LP64__
+inline bool CAAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue )
+{
+ return OSAtomicCompareAndSwap64Barrier(__oldValue, __newValue, __theValue);
+}
+#endif
+
+inline bool CAAtomicCompareAndSwapPtrBarrier(void *__oldValue, void *__newValue, volatile void ** __theValue)
+{
+#if __LP64__
+ return CAAtomicCompareAndSwap64Barrier((int64_t)__oldValue, (int64_t)__newValue, (int64_t *)__theValue);
+#else
+ return CAAtomicCompareAndSwap32Barrier((int32_t)__oldValue, (int32_t)__newValue, (int32_t *)__theValue);
+#endif
+}
+
+/* Spinlocks. These use memory barriers as required to synchronize access to shared
+ * memory protected by the lock. The lock operation spins, but employs various strategies
+ * to back off if the lock is held, making it immune to most priority-inversion livelocks.
+ * The try operation immediately returns false if the lock was held, true if it took the
+ * lock. The convention is that unlocked is zero, locked is nonzero.
+ */
+#define CA_SPINLOCK_INIT 0
+
+typedef int32_t CASpinLock;
+
+bool CASpinLockTry( volatile CASpinLock *__lock );
+void CASpinLockLock( volatile CASpinLock *__lock );
+void CASpinLockUnlock( volatile CASpinLock *__lock );
+
+inline void CASpinLockLock( volatile CASpinLock *__lock )
+{
+#if TARGET_OS_MAC
+ OSSpinLockLock(__lock);
+#else
+ while (CAAtomicTestAndSetBarrier(0, (void*)__lock))
+ usleep(1000); // ???
+#endif
+}
+
+inline void CASpinLockUnlock( volatile CASpinLock *__lock )
+{
+#if TARGET_OS_MAC
+ OSSpinLockUnlock(__lock);
+#else
+ CAAtomicTestAndClearBarrier(0, (void*)__lock);
+#endif
+}
+
+inline bool CASpinLockTry( volatile CASpinLock *__lock )
+{
+#if TARGET_OS_MAC
+ return OSSpinLockTry(__lock);
+#else
+ return (CAAtomicTestAndSetBarrier(0, (void*)__lock) == 0);
+#endif
+}
+
+
+#endif // __CAAtomic_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAtomicStack.h b/libs/appleutility/CoreAudio/PublicUtility/CAAtomicStack.h
new file mode 100644
index 0000000000..8d40fc5d27
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAtomicStack.h
@@ -0,0 +1,239 @@
+/*
+ File: CAAtomicStack.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAAtomicStack_h__
+#define __CAAtomicStack_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <libkern/OSAtomic.h>
+#else
+ #include <CAAtomic.h>
+#endif
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
+ #include <CoreServices/CoreServices.h>
+#endif
+
+// linked list LIFO or FIFO (pop_all_reversed) stack, elements are pushed and popped atomically
+// class T must implement T *& next().
+template <class T>
+class TAtomicStack {
+public:
+ TAtomicStack() : mHead(NULL) { }
+
+ // non-atomic routines, for use when initializing/deinitializing, operate NON-atomically
+ void push_NA(T *item)
+ {
+ item->next() = mHead;
+ mHead = item;
+ }
+
+ T * pop_NA()
+ {
+ T *result = mHead;
+ if (result)
+ mHead = result->next();
+ return result;
+ }
+
+ bool empty() const { return mHead == NULL; }
+
+ T * head() { return mHead; }
+
+ // atomic routines
+ void push_atomic(T *item)
+ {
+ T *head_;
+ do {
+ head_ = mHead;
+ item->next() = head_;
+ } while (!compare_and_swap(head_, item, &mHead));
+ }
+
+ void push_multiple_atomic(T *item)
+ // pushes entire linked list headed by item
+ {
+ T *head_, *p = item, *tail;
+ // find the last one -- when done, it will be linked to head
+ do {
+ tail = p;
+ p = p->next();
+ } while (p);
+ do {
+ head_ = mHead;
+ tail->next() = head_;
+ } while (!compare_and_swap(head_, item, &mHead));
+ }
+
+ T * pop_atomic_single_reader()
+ // this may only be used when only one thread may potentially pop from the stack.
+ // if multiple threads may pop, this suffers from the ABA problem.
+ // <rdar://problem/4606346> TAtomicStack suffers from the ABA problem
+ {
+ T *result;
+ do {
+ if ((result = mHead) == NULL)
+ break;
+ } while (!compare_and_swap(result, result->next(), &mHead));
+ return result;
+ }
+
+ T * pop_atomic()
+ // This is inefficient for large linked lists.
+ // prefer pop_all() to a series of calls to pop_atomic.
+ // push_multiple_atomic has to traverse the entire list.
+ {
+ T *result = pop_all();
+ if (result) {
+ T *next = result->next();
+ if (next)
+ // push all the remaining items back onto the stack
+ push_multiple_atomic(next);
+ }
+ return result;
+ }
+
+ T * pop_all()
+ {
+ T *result;
+ do {
+ if ((result = mHead) == NULL)
+ break;
+ } while (!compare_and_swap(result, NULL, &mHead));
+ return result;
+ }
+
+ T* pop_all_reversed()
+ {
+ TAtomicStack<T> reversed;
+ T *p = pop_all(), *next;
+ while (p != NULL) {
+ next = p->next();
+ reversed.push_NA(p);
+ p = next;
+ }
+ return reversed.mHead;
+ }
+
+ static bool compare_and_swap(T *oldvalue, T *newvalue, T **pvalue)
+ {
+#if TARGET_OS_MAC
+ #if __LP64__
+ return ::OSAtomicCompareAndSwap64Barrier(int64_t(oldvalue), int64_t(newvalue), (int64_t *)pvalue);
+ #elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ return ::OSAtomicCompareAndSwap32Barrier(int32_t(oldvalue), int32_t(newvalue), (int32_t *)pvalue);
+ #else
+ return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue);
+ #endif
+#else
+ //return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue);
+ return CAAtomicCompareAndSwap32Barrier(SInt32(oldvalue), SInt32(newvalue), (SInt32*)pvalue);
+#endif
+ }
+
+protected:
+ T * mHead;
+};
+
+#if ((MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) && !TARGET_OS_WIN32)
+#include <libkern/OSAtomic.h>
+
+class CAAtomicStack {
+public:
+ CAAtomicStack(size_t nextPtrOffset) : mNextPtrOffset(nextPtrOffset) {
+ /*OSQueueHead h = OS_ATOMIC_QUEUE_INIT; mHead = h;*/
+ mHead.opaque1 = 0; mHead.opaque2 = 0;
+ }
+ // a subset of the above
+ void push_atomic(void *p) { OSAtomicEnqueue(&mHead, p, mNextPtrOffset); }
+ void push_NA(void *p) { push_atomic(p); }
+
+ void * pop_atomic() { return OSAtomicDequeue(&mHead, mNextPtrOffset); }
+ void * pop_atomic_single_reader() { return pop_atomic(); }
+ void * pop_NA() { return pop_atomic(); }
+
+private:
+ OSQueueHead mHead;
+ size_t mNextPtrOffset;
+};
+
+// a more efficient subset of TAtomicStack using OSQueue.
+template <class T>
+class TAtomicStack2 {
+public:
+ TAtomicStack2() {
+ /*OSQueueHead h = OS_ATOMIC_QUEUE_INIT; mHead = h;*/
+ mHead.opaque1 = 0; mHead.opaque2 = 0;
+ mNextPtrOffset = -1;
+ }
+ void push_atomic(T *item) {
+ if (mNextPtrOffset < 0) {
+ T **pnext = &item->next(); // hack around offsetof not working with C++
+ mNextPtrOffset = (Byte *)pnext - (Byte *)item;
+ }
+ OSAtomicEnqueue(&mHead, item, mNextPtrOffset);
+ }
+ void push_NA(T *item) { push_atomic(item); }
+
+ T * pop_atomic() { return (T *)OSAtomicDequeue(&mHead, mNextPtrOffset); }
+ T * pop_atomic_single_reader() { return pop_atomic(); }
+ T * pop_NA() { return pop_atomic(); }
+
+ // caution: do not try to implement pop_all_reversed here. the writer could add new elements
+ // while the reader is trying to pop old ones!
+
+private:
+ OSQueueHead mHead;
+ ssize_t mNextPtrOffset;
+};
+
+#else
+
+#define TAtomicStack2 TAtomicStack
+
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED && !TARGET_OS_WIN32
+
+#endif // __CAAtomicStack_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp
new file mode 100644
index 0000000000..d3644ed2e4
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp
@@ -0,0 +1,239 @@
+/*
+ File: CAAudioBufferList.cpp
+ Abstract: CAAudioBufferList.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CAAudioBufferList.h"
+#include "CADebugMacros.h"
+#include "CALogMacros.h"
+#include <stdlib.h>
+#include <string.h>
+
+//=============================================================================
+// CAAudioBufferList
+//=============================================================================
+
+AudioBufferList* CAAudioBufferList::Create(UInt32 inNumberBuffers)
+{
+ UInt32 theSize = CalculateByteSize(inNumberBuffers);
+ AudioBufferList* theAnswer = static_cast<AudioBufferList*>(calloc(1, theSize));
+ if(theAnswer != NULL)
+ {
+ theAnswer->mNumberBuffers = inNumberBuffers;
+ }
+ return theAnswer;
+}
+
+void CAAudioBufferList::Destroy(AudioBufferList* inBufferList)
+{
+ free(inBufferList);
+}
+
+UInt32 CAAudioBufferList::CalculateByteSize(UInt32 inNumberBuffers)
+{
+ UInt32 theSize = SizeOf32(AudioBufferList) - SizeOf32(AudioBuffer);
+ theSize += inNumberBuffers * SizeOf32(AudioBuffer);
+ return theSize;
+}
+
+UInt32 CAAudioBufferList::GetTotalNumberChannels(const AudioBufferList& inBufferList)
+{
+ UInt32 theAnswer = 0;
+
+ for(UInt32 theIndex = 0; theIndex < inBufferList.mNumberBuffers; ++theIndex)
+ {
+ theAnswer += inBufferList.mBuffers[theIndex].mNumberChannels;
+ }
+
+ return theAnswer;
+}
+
+bool CAAudioBufferList::GetBufferForChannel(const AudioBufferList& inBufferList, UInt32 inChannel, UInt32& outBufferNumber, UInt32& outBufferChannel)
+{
+ bool theAnswer = false;
+ UInt32 theIndex = 0;
+
+ while((theIndex < inBufferList.mNumberBuffers) && (inChannel >= inBufferList.mBuffers[theIndex].mNumberChannels))
+ {
+ inChannel -= inBufferList.mBuffers[theIndex].mNumberChannels;
+ ++theIndex;
+ }
+
+ if(theIndex < inBufferList.mNumberBuffers)
+ {
+ outBufferNumber = theIndex;
+ outBufferChannel = inChannel;
+ theAnswer = true;
+ }
+
+ return theAnswer;
+}
+
+void CAAudioBufferList::Clear(AudioBufferList& outBufferList)
+{
+ // assumes that "0" is actually the 0 value for this stream format
+ for(UInt32 theBufferIndex = 0; theBufferIndex < outBufferList.mNumberBuffers; ++theBufferIndex)
+ {
+ if(outBufferList.mBuffers[theBufferIndex].mData != NULL)
+ {
+ memset(outBufferList.mBuffers[theBufferIndex].mData, 0, outBufferList.mBuffers[theBufferIndex].mDataByteSize);
+ }
+ }
+}
+
+void CAAudioBufferList::Copy(const AudioBufferList& inSource, UInt32 inStartingSourceChannel, AudioBufferList& outDestination, UInt32 inStartingDestinationChannel)
+{
+ // This is a brute force copy method that can handle ABL's that have different buffer layouts
+ // This means that this method is probably not the fastest way to do this for all cases.
+ // This method also assumes that both the source and destination sample formats are Float32
+
+ UInt32 theInputChannel = inStartingSourceChannel;
+ UInt32 theNumberInputChannels = GetTotalNumberChannels(inSource);
+ UInt32 theOutputChannel = inStartingDestinationChannel;
+ UInt32 theNumberOutputChannels = GetTotalNumberChannels(outDestination);
+
+ UInt32 theInputBufferIndex = 0;
+ UInt32 theInputBufferChannel = 0;
+ UInt32 theOutputBufferIndex = 0;
+ UInt32 theOutputBufferChannel = 0;
+ while((theInputChannel < theNumberInputChannels) && (theOutputChannel < theNumberOutputChannels))
+ {
+ GetBufferForChannel(inSource, theInputChannel, theInputBufferIndex, theInputBufferChannel);
+
+ GetBufferForChannel(inSource, theOutputChannel, theOutputBufferIndex, theOutputBufferChannel);
+
+ CopyChannel(inSource.mBuffers[theInputBufferIndex], theInputBufferChannel, outDestination.mBuffers[theOutputBufferIndex], theOutputBufferChannel);
+
+ ++theInputChannel;
+ ++theOutputChannel;
+ }
+}
+
+void CAAudioBufferList::CopyChannel(const AudioBuffer& inSource, UInt32 inSourceChannel, AudioBuffer& outDestination, UInt32 inDestinationChannel)
+{
+ // set up the stuff for the loop
+ UInt32 theNumberFramesToCopy = outDestination.mDataByteSize / (outDestination.mNumberChannels * SizeOf32(Float32));
+ const Float32* theSource = static_cast<const Float32*>(inSource.mData);
+ Float32* theDestination = static_cast<Float32*>(outDestination.mData);
+
+ // loop through the data and copy the samples
+ while(theNumberFramesToCopy > 0)
+ {
+ // copy the data
+ theDestination[inDestinationChannel] = theSource[inSourceChannel];
+
+ // adjust the pointers
+ --theNumberFramesToCopy;
+ theSource += inSource.mNumberChannels;
+ theDestination += outDestination.mNumberChannels;
+ }
+}
+
+void CAAudioBufferList::Sum(const AudioBufferList& inSourceBufferList, AudioBufferList& ioSummedBufferList)
+{
+ // assumes that the buffers are Float32 samples and the listst have the same layout
+ // this is a lame algorithm, by the way. it could at least be unrolled a couple of times
+ for(UInt32 theBufferIndex = 0; theBufferIndex < ioSummedBufferList.mNumberBuffers; ++theBufferIndex)
+ {
+ Float32* theSourceBuffer = static_cast<Float32*>(inSourceBufferList.mBuffers[theBufferIndex].mData);
+ Float32* theSummedBuffer = static_cast<Float32*>(ioSummedBufferList.mBuffers[theBufferIndex].mData);
+ UInt32 theNumberSamplesToMix = ioSummedBufferList.mBuffers[theBufferIndex].mDataByteSize / SizeOf32(Float32);
+ if((theSourceBuffer != NULL) && (theSummedBuffer != NULL) && (theNumberSamplesToMix > 0))
+ {
+ while(theNumberSamplesToMix > 0)
+ {
+ *theSummedBuffer += *theSourceBuffer;
+ ++theSummedBuffer;
+ ++theSourceBuffer;
+ --theNumberSamplesToMix;
+ }
+ }
+ }
+}
+
+bool CAAudioBufferList::HasData(AudioBufferList& inBufferList)
+{
+ bool hasData = false;
+ for(UInt32 theBufferIndex = 0; !hasData && (theBufferIndex < inBufferList.mNumberBuffers); ++theBufferIndex)
+ {
+ if(inBufferList.mBuffers[theBufferIndex].mData != NULL)
+ {
+ UInt32* theBuffer = (UInt32*)inBufferList.mBuffers[theBufferIndex].mData;
+ UInt32 theNumberSamples = inBufferList.mBuffers[theBufferIndex].mDataByteSize / SizeOf32(UInt32);
+ for(UInt32 theSampleIndex = 0; !hasData && (theSampleIndex < theNumberSamples); ++theSampleIndex)
+ {
+ hasData = theBuffer[theSampleIndex] != 0;
+ }
+ }
+ }
+ return hasData;
+}
+
+#if CoreAudio_Debug
+void CAAudioBufferList::PrintToLog(const AudioBufferList& inBufferList)
+{
+ PrintInt(" Number streams: ", inBufferList.mNumberBuffers);
+
+ for(UInt32 theIndex = 0; theIndex < inBufferList.mNumberBuffers; ++theIndex)
+ {
+ PrintIndexedInt(" Channels in stream", theIndex + 1, inBufferList.mBuffers[theIndex].mNumberChannels);
+ PrintIndexedInt(" Buffer size of stream", theIndex + 1, inBufferList.mBuffers[theIndex].mDataByteSize);
+ }
+}
+#endif
+
+const AudioBufferList* CAAudioBufferList::GetEmptyBufferList()
+{
+ static bool sInitializer = false;
+ static AudioBufferList sEmptyABL;
+ if(!sInitializer)
+ {
+ memset(&sEmptyABL, 0, sizeof(AudioBufferList));
+ }
+ return &sEmptyABL;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.h
new file mode 100644
index 0000000000..70614f3eb6
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.h
@@ -0,0 +1,108 @@
+/*
+ File: CAAudioBufferList.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAAudioBufferList_h__)
+#define __CAAudioBufferList_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+#include "CAException.h"
+#include "CADebugMacros.h"
+
+//=============================================================================
+// Types
+//=============================================================================
+
+typedef AudioBufferList* AudioBufferListPtr;
+
+//=============================================================================
+// CAAudioBufferList
+//=============================================================================
+
+struct CAAudioBufferList
+{
+
+// Construction/Destruction
+public:
+ static AudioBufferList* Create(UInt32 inNumberBuffers);
+ static void Destroy(AudioBufferList* inBufferList);
+ static UInt32 CalculateByteSize(UInt32 inNumberBuffers);
+
+// Operations
+public:
+ static UInt32 GetTotalNumberChannels(const AudioBufferList& inBufferList);
+ static bool GetBufferForChannel(const AudioBufferList& inBufferList, UInt32 inChannel, UInt32& outBufferNumber, UInt32& outBufferChannel);
+ static void Clear(AudioBufferList& outBufferList);
+ static void Copy(const AudioBufferList& inSource, UInt32 inStartingSourceChannel, AudioBufferList& outDestination, UInt32 inStartingDestinationChannel);
+ static void CopyChannel(const AudioBuffer& inSource, UInt32 inSourceChannel, AudioBuffer& outDestination, UInt32 inDestinationChannel);
+ static void Sum(const AudioBufferList& inSourceBufferList, AudioBufferList& ioSummedBufferList);
+ static bool HasData(AudioBufferList& inBufferList);
+#if CoreAudio_Debug
+ static void PrintToLog(const AudioBufferList& inBufferList);
+#endif
+
+ static const AudioBufferList* GetEmptyBufferList();
+
+};
+
+// Declare a variably-sized AudioBufferList on the stack
+#define STACK_ABL(name, nbufs) \
+ ThrowIf(nbufs < 1 || nbufs > 64, CAException(kAudio_ParamError), "STACK_ABL: invalid number of buffers") \
+ const size_t name##_ByteSize = sizeof(AudioBufferList) + (nbufs - 1) * sizeof(AudioBuffer); \
+ AudioBufferList &name = *(AudioBufferList *)alloca(name##_ByteSize); \
+ name.mNumberBuffers = nbufs;
+
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.cpp
new file mode 100644
index 0000000000..74753598db
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.cpp
@@ -0,0 +1,153 @@
+/*
+ File: CAAudioChannelLayout.cpp
+ Abstract: CAAudioChannelLayout.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+// Self Include
+#include "CAAudioChannelLayout.h"
+#include "CAAutoDisposer.h"
+#include <stdlib.h>
+#include <string.h>
+
+//=============================================================================
+// CAAudioChannelLayout
+//=============================================================================
+
+AudioChannelLayout* CAAudioChannelLayout::Create(UInt32 inNumberChannelDescriptions)
+{
+ UInt32 theSize = CalculateByteSize(inNumberChannelDescriptions);
+ AudioChannelLayout* theAnswer = static_cast<AudioChannelLayout*>(CA_calloc(1, theSize));
+ if(theAnswer != NULL)
+ {
+ SetAllToUnknown(*theAnswer, inNumberChannelDescriptions);
+ }
+ return theAnswer;
+}
+
+void CAAudioChannelLayout::Destroy(AudioChannelLayout* inChannelLayout)
+{
+ free(inChannelLayout);
+}
+
+void CAAudioChannelLayout::SetAllToUnknown(AudioChannelLayout& outChannelLayout, UInt32 inNumberChannelDescriptions)
+{
+ outChannelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
+ outChannelLayout.mChannelBitmap = 0;
+ outChannelLayout.mNumberChannelDescriptions = inNumberChannelDescriptions;
+ for(UInt32 theChannelIndex = 0; theChannelIndex < inNumberChannelDescriptions; ++theChannelIndex)
+ {
+ outChannelLayout.mChannelDescriptions[theChannelIndex].mChannelLabel = kAudioChannelLabel_Unknown;
+ outChannelLayout.mChannelDescriptions[theChannelIndex].mChannelFlags = 0;
+ outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[0] = 0;
+ outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[1] = 0;
+ outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[2] = 0;
+ }
+}
+
+bool operator== (const AudioChannelLayout &x, const AudioChannelLayout &y)
+{
+ // compare based on the number of channel descriptions present
+ // (this may be too strict a comparison if all you care about are matching layout tags)
+ UInt32 theSize1 = CAAudioChannelLayout::CalculateByteSize(x.mNumberChannelDescriptions);
+ UInt32 theSize2 = CAAudioChannelLayout::CalculateByteSize(y.mNumberChannelDescriptions);
+
+ if (theSize1 != theSize2)
+ return false;
+
+ return !memcmp (&x, &y, theSize1);
+}
+
+bool operator!= (const AudioChannelLayout &x, const AudioChannelLayout &y)
+{
+ return !(x == y);
+}
+
+// counting the one bits in a word
+inline UInt32 CountOnes(UInt32 x)
+{
+ // secret magic algorithm for counting bits in a word.
+ UInt32 t;
+ x = x - ((x >> 1) & 0x55555555);
+ t = ((x >> 2) & 0x33333333);
+ x = (x & 0x33333333) + t;
+ x = (x + (x >> 4)) & 0x0F0F0F0F;
+ x = x + (x << 8);
+ x = x + (x << 16);
+ return x >> 24;
+}
+
+UInt32 CAAudioChannelLayout::NumberChannels (const AudioChannelLayout& inLayout)
+{
+ if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions)
+ return inLayout.mNumberChannelDescriptions;
+
+ if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
+ return CountOnes (inLayout.mChannelBitmap);
+
+ return AudioChannelLayoutTag_GetNumberOfChannels(inLayout.mChannelLayoutTag);
+}
+
+void CAShowAudioChannelLayout (FILE* file, const AudioChannelLayout *layout)
+{
+ if (layout == NULL)
+ {
+ fprintf (file, "\tNULL layout\n");
+ return;
+ }
+ fprintf (file, "\tTag=0x%X, ", (int)layout->mChannelLayoutTag);
+ if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
+ fprintf (file, "Using Bitmap:0x%X\n", (int)layout->mChannelBitmap);
+ else {
+ fprintf (file, "Num Chan Descs=%d\n", (int)layout->mNumberChannelDescriptions);
+ const AudioChannelDescription *desc = layout->mChannelDescriptions;
+ for (unsigned int i = 0; i < layout->mNumberChannelDescriptions; ++i, ++desc) {
+ fprintf (file, "\t\tLabel=%d, Flags=0x%X, ", (int)desc->mChannelLabel, (int)desc->mChannelFlags);
+ fprintf (file, "[az=%f,el=%f,dist=%f]\n", desc->mCoordinates[0], desc->mCoordinates[1], desc->mCoordinates[2]);
+ }
+ }
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.h
new file mode 100644
index 0000000000..4307054aee
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.h
@@ -0,0 +1,199 @@
+/*
+ File: CAAudioChannelLayout.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAAudioChannelLayout_h__)
+#define __CAAudioChannelLayout_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include <CoreAudioTypes.h>
+ #include <CoreFoundation.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "CADebugMacros.h"
+#include "CAAutoDisposer.h"
+
+#if !HAL_Build
+ #include "CAReferenceCounted.h"
+#endif
+
+//=============================================================================
+// CAAudioChannelLayout
+//=============================================================================
+
+bool operator== (const AudioChannelLayout &x, const AudioChannelLayout &y);
+bool operator!= (const AudioChannelLayout &x, const AudioChannelLayout &y);
+
+extern "C" void CAShowAudioChannelLayout (FILE* file, const AudioChannelLayout *layout);
+
+class CAAudioChannelLayout
+{
+// static Construction/Destruction
+public:
+ static AudioChannelLayout* Create(UInt32 inNumberChannelDescriptions);
+ static void Destroy(AudioChannelLayout* inChannelLayout);
+ static UInt32 CalculateByteSize(UInt32 inNumberChannelDescriptions) {
+ return SizeOf32(AudioChannelLayout) - SizeOf32(AudioChannelDescription) + (inNumberChannelDescriptions * SizeOf32(AudioChannelDescription));
+ }
+ static void SetAllToUnknown(AudioChannelLayout& outChannelLayout, UInt32 inNumberChannelDescriptions);
+ static UInt32 NumberChannels(const AudioChannelLayout& inLayout);
+
+#if !HAL_Build
+// object methods
+public:
+ CAAudioChannelLayout ();
+
+ CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround);
+ // if inChooseSurround is false, then symmetrical speaker arrangements
+ // are chosen in place of surround layouts if there is a choice
+ // This call chooses layouts based on the expected defaults in
+ // AudioUnit usage
+ CAAudioChannelLayout (AudioChannelLayoutTag inTag);
+ CAAudioChannelLayout (const CAAudioChannelLayout &c);
+ CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout);
+ ~CAAudioChannelLayout();
+
+ CAAudioChannelLayout& operator= (const AudioChannelLayout* inChannelLayout);
+ CAAudioChannelLayout& operator= (const CAAudioChannelLayout& c);
+ bool operator== (const CAAudioChannelLayout &c) const;
+ bool operator!= (const CAAudioChannelLayout &c) const;
+
+ void SetWithTag(AudioChannelLayoutTag inTag);
+
+ bool IsValid() const { return NumberChannels() > 0; }
+ UInt32 Size() const { return mLayout ? mLayout->Size() : 0; }
+
+ UInt32 NumberChannels() const { return mLayout ? mLayout->NumberChannels() : 0; }
+
+ AudioChannelLayoutTag Tag() const { return Layout().mChannelLayoutTag; }
+ const AudioChannelLayout& Layout() const { return mLayout->Layout(); }
+ operator const AudioChannelLayout *() const { return &Layout(); }
+
+ void Print () const { Print (stdout); }
+ void Print (FILE* file) const;
+
+ OSStatus Save (CFPropertyListRef *outData) const;
+ OSStatus Restore (CFPropertyListRef &inData);
+
+private:
+ class RefCountedLayout : public CAReferenceCounted {
+ void * operator new(size_t /* size */, size_t aclSize)
+ {
+ return CA_malloc(sizeof(RefCountedLayout) - sizeof(AudioChannelLayout) + aclSize);
+ }
+
+ void operator delete(void *mem)
+ {
+ free(mem);
+ }
+
+
+ RefCountedLayout(UInt32 inDataSize) :
+ mByteSize(inDataSize)
+ {
+ memset(&mACL, 0, inDataSize);
+ }
+
+ public:
+ static RefCountedLayout *CreateWithNumberChannelDescriptions(unsigned nChannels) {
+ size_t size = CAAudioChannelLayout::CalculateByteSize(nChannels);
+ return new(size) RefCountedLayout((UInt32)size);
+ }
+
+ static RefCountedLayout *CreateWithLayout(const AudioChannelLayout *layout) {
+ size_t size = CAAudioChannelLayout::CalculateByteSize(layout->mNumberChannelDescriptions);
+ RefCountedLayout *acl = new(size) RefCountedLayout((UInt32)size);
+ memcpy(&acl->mACL, layout, size);
+ return acl;
+ }
+ static RefCountedLayout *CreateWithLayoutTag(AudioChannelLayoutTag layoutTag) {
+ RefCountedLayout *acl = CreateWithNumberChannelDescriptions(0);
+ acl->mACL.mChannelLayoutTag = layoutTag;
+ return acl;
+ }
+
+ const AudioChannelLayout & Layout() const { return mACL; }
+
+ UInt32 Size () const { return mByteSize; }
+
+ UInt32 NumberChannels() { return CAAudioChannelLayout::NumberChannels(Layout()); }
+
+ private:
+ const UInt32 mByteSize;
+ AudioChannelLayout mACL;
+ // * * * mACL is variable length and thus must be last * * *
+
+ // only the constructors can change the actual state of the layout
+ friend CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround);
+ friend OSStatus CAAudioChannelLayout::Restore (CFPropertyListRef &inData);
+ friend CAAudioChannelLayout& CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout);
+ friend void CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag);
+
+ AudioChannelLayout * GetLayout() { return &mACL; }
+
+ private:
+ // prohibited methods: private and unimplemented.
+ RefCountedLayout();
+ RefCountedLayout(const RefCountedLayout& c);
+ RefCountedLayout& operator=(const RefCountedLayout& c);
+ };
+
+ RefCountedLayout *mLayout;
+#endif // HAL_Build
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayoutObject.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayoutObject.cpp
new file mode 100644
index 0000000000..009d4b3b5e
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayoutObject.cpp
@@ -0,0 +1,210 @@
+/*
+ File: CAAudioChannelLayoutObject.cpp
+ Abstract: CAAudioChannelLayoutObject.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CAAudioChannelLayout.h"
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioToolbox/AudioFormat.h>
+#else
+ #include <AudioFormat.h>
+#endif
+
+CAAudioChannelLayout::CAAudioChannelLayout ()
+{
+ mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(0);
+}
+
+//=============================================================================
+// CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround)
+{
+ // this chooses default layouts based on the number of channels...
+ AudioChannelLayoutTag tag;
+
+ switch (inNumberChannels)
+ {
+ default:
+ // here we have a "broken" layout, in the sense that we haven't any idea how to lay this out
+ mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(inNumberChannels);
+ SetAllToUnknown(*mLayout->GetLayout(), inNumberChannels);
+ return; // don't fall into the tag case
+ case 1:
+ tag = kAudioChannelLayoutTag_Mono;
+ break;
+ case 2:
+ tag = inChooseSurround ? kAudioChannelLayoutTag_Binaural : kAudioChannelLayoutTag_Stereo;
+ break;
+ case 4:
+ tag = inChooseSurround ? kAudioChannelLayoutTag_Ambisonic_B_Format : kAudioChannelLayoutTag_AudioUnit_4;
+ break;
+ case 5:
+ tag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_5_0 : kAudioChannelLayoutTag_AudioUnit_5;
+ break;
+ case 6:
+ tag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_6_0 : kAudioChannelLayoutTag_AudioUnit_6;
+ break;
+ case 7:
+ tag = kAudioChannelLayoutTag_AudioUnit_7_0;
+ break;
+ case 8:
+ tag = kAudioChannelLayoutTag_AudioUnit_8;
+ break;
+ }
+
+ mLayout = RefCountedLayout::CreateWithLayoutTag(tag);
+}
+
+//=============================================================================
+// CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (AudioChannelLayoutTag inLayoutTag)
+ : mLayout(NULL)
+{
+ SetWithTag(inLayoutTag);
+}
+
+//=============================================================================
+// CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (const CAAudioChannelLayout &c)
+ : mLayout(NULL)
+{
+ *this = c;
+}
+
+
+//=============================================================================
+// CAAudioChannelLayout::AudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout)
+ : mLayout(NULL)
+{
+ *this = inChannelLayout;
+}
+
+//=============================================================================
+// CAAudioChannelLayout::~CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::~CAAudioChannelLayout ()
+{
+ if (mLayout) {
+ mLayout->release();
+ mLayout = NULL;
+ }
+}
+
+//=============================================================================
+// CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout& CAAudioChannelLayout::operator= (const CAAudioChannelLayout &c)
+{
+ if (mLayout != c.mLayout) {
+ if (mLayout)
+ mLayout->release();
+
+ if ((mLayout = c.mLayout) != NULL)
+ mLayout->retain();
+ }
+
+ return *this;
+}
+
+CAAudioChannelLayout& CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout)
+{
+ if (mLayout && &mLayout->Layout() == inChannelLayout)
+ return *this;
+
+ if (mLayout)
+ mLayout->release();
+
+ if (inChannelLayout == NULL)
+ {
+ mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(0);
+ }
+ else
+ {
+ mLayout = RefCountedLayout::CreateWithLayout(inChannelLayout);
+ }
+ return *this;
+}
+
+void CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag)
+{
+ if (mLayout)
+ mLayout->release();
+
+ mLayout = RefCountedLayout::CreateWithLayoutTag(inTag);
+}
+
+//=============================================================================
+// CAAudioChannelLayout::operator==
+//=============================================================================
+bool CAAudioChannelLayout::operator== (const CAAudioChannelLayout &c) const
+{
+ if (mLayout == c.mLayout)
+ return true;
+ return Layout() == c.Layout();
+}
+
+//=============================================================================
+// CAAudioChannelLayout::operator!=
+//=============================================================================
+bool CAAudioChannelLayout::operator!= (const CAAudioChannelLayout &c) const
+{
+ if (mLayout == c.mLayout)
+ return false;
+
+ return !(Layout() == c.Layout());
+}
+
+//=============================================================================
+// CAAudioChannelLayout::Print
+//=============================================================================
+void CAAudioChannelLayout::Print (FILE* file) const
+{
+ CAShowAudioChannelLayout (file, &Layout());
+}
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.cpp
new file mode 100644
index 0000000000..ce2efeae60
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.cpp
@@ -0,0 +1,424 @@
+/*
+ File: CAAudioFileFormats.cpp
+ Abstract: CAAudioFileFormats.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CAAudioFileFormats.h"
+#include <algorithm>
+#include <ctype.h>
+
+CAAudioFileFormats *CAAudioFileFormats::sInstance = NULL;
+
+CAAudioFileFormats *CAAudioFileFormats::Instance(bool loadDataFormats)
+{
+ if (sInstance == NULL)
+ sInstance = new CAAudioFileFormats(loadDataFormats);
+ return sInstance;
+}
+
+/*
+class CompareFileFormatNames {
+public:
+ bool operator() (const CAAudioFileFormats::FileFormatInfo &a, const CAAudioFileFormats::FileFormatInfo &b)
+ {
+ return CFStringCompare(a.mFileTypeName, b.mFileTypeName,
+ kCFCompareCaseInsensitive | kCFCompareLocalized) == kCFCompareLessThan;
+ }
+};*/
+
+static int CompareFileFormatNames(const void *va, const void *vb)
+{
+ CAAudioFileFormats::FileFormatInfo *a = (CAAudioFileFormats::FileFormatInfo *)va,
+ *b = (CAAudioFileFormats::FileFormatInfo *)vb;
+ return CFStringCompare(a->mFileTypeName, b->mFileTypeName,
+ kCFCompareCaseInsensitive | kCFCompareLocalized);
+}
+
+CAAudioFileFormats::CAAudioFileFormats(bool loadDataFormats) :
+ mNumFileFormats(0), mFileFormats(NULL)
+{
+ OSStatus err;
+ UInt32 size;
+ UInt32 *fileTypes = NULL;
+
+ // get all file types
+ err = AudioFileGetGlobalInfoSize(kAudioFileGlobalInfo_WritableTypes, 0, NULL, &size);
+ if (err != noErr) goto bail;
+ mNumFileFormats = size / sizeof(UInt32);
+ mFileFormats = new FileFormatInfo[mNumFileFormats];
+ fileTypes = new UInt32[mNumFileFormats];
+ err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_WritableTypes, 0, NULL, &size, fileTypes);
+ if (err != noErr) goto bail;
+
+ // get info for each file type
+ for (int i = 0; i < mNumFileFormats; ++i) {
+ FileFormatInfo *ffi = &mFileFormats[i];
+ OSType filetype = fileTypes[i];
+
+ ffi->mFileTypeID = filetype;
+
+ // file type name
+ ffi->mFileTypeName = NULL;
+ size = sizeof(CFStringRef);
+ err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_FileTypeName, sizeof(UInt32), &filetype, &size, &ffi->mFileTypeName);
+ if (err == noErr && ffi->mFileTypeName)
+ CFRetain(ffi->mFileTypeName);
+
+ // file extensions
+ size = sizeof(CFArrayRef);
+ err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_ExtensionsForType,
+ sizeof(OSType), &filetype, &size, &ffi->mExtensions);
+ if (err)
+ ffi->mExtensions = NULL;
+
+ // file data formats
+ ffi->mNumDataFormats = 0;
+ ffi->mDataFormats = NULL;
+
+ if (loadDataFormats)
+ ffi->LoadDataFormats();
+ }
+
+ // sort file formats by name
+ qsort(mFileFormats, mNumFileFormats, sizeof(FileFormatInfo), CompareFileFormatNames);
+bail:
+ delete[] fileTypes;
+}
+
+void CAAudioFileFormats::FileFormatInfo::LoadDataFormats()
+{
+ if (mDataFormats != NULL) return;
+
+ UInt32 *writableFormats = NULL, *readableFormats = NULL;
+ int nWritableFormats, nReadableFormats;
+ // get all writable formats
+ UInt32 size;
+ OSStatus err = AudioFormatGetPropertyInfo(kAudioFormatProperty_EncodeFormatIDs, 0, NULL, &size);
+ if (err != noErr) goto bail;
+ nWritableFormats = size / sizeof(UInt32);
+ writableFormats = new UInt32[nWritableFormats];
+ err = AudioFormatGetProperty(kAudioFormatProperty_EncodeFormatIDs, 0, NULL, &size, writableFormats);
+ if (err != noErr) goto bail;
+
+ // get all readable formats
+ err = AudioFormatGetPropertyInfo(kAudioFormatProperty_DecodeFormatIDs, 0, NULL, &size);
+ if (err != noErr) goto bail;
+ nReadableFormats = size / sizeof(UInt32);
+ readableFormats = new UInt32[nReadableFormats];
+ err = AudioFormatGetProperty(kAudioFormatProperty_DecodeFormatIDs, 0, NULL, &size, readableFormats);
+ if (err != noErr) goto bail;
+
+ err = AudioFileGetGlobalInfoSize(kAudioFileGlobalInfo_AvailableFormatIDs, sizeof(UInt32), &mFileTypeID, &size);
+ if (err == noErr) {
+ mNumDataFormats = size / sizeof(OSType);
+ OSType *formatIDs = new OSType[mNumDataFormats];
+ err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_AvailableFormatIDs,
+ sizeof(UInt32), &mFileTypeID, &size, formatIDs);
+ if (err == noErr) {
+ mDataFormats = new DataFormatInfo[mNumDataFormats];
+ for (int j = 0; j < mNumDataFormats; ++j) {
+ int k;
+ bool anyBigEndian = false, anyLittleEndian = false;
+ DataFormatInfo *dfi = &mDataFormats[j];
+ dfi->mFormatID = formatIDs[j];
+ dfi->mReadable = (dfi->mFormatID == kAudioFormatLinearPCM);
+ dfi->mWritable = (dfi->mFormatID == kAudioFormatLinearPCM);
+ for (k = 0; k < nReadableFormats; ++k)
+ if (readableFormats[k] == dfi->mFormatID) {
+ dfi->mReadable = true;
+ break;
+ }
+ for (k = 0; k < nWritableFormats; ++k)
+ if (writableFormats[k] == dfi->mFormatID) {
+ dfi->mWritable = true;
+ break;
+ }
+
+ dfi->mNumVariants = 0;
+ AudioFileTypeAndFormatID tf = { mFileTypeID, dfi->mFormatID };
+ err = AudioFileGetGlobalInfoSize(kAudioFileGlobalInfo_AvailableStreamDescriptionsForFormat,
+ sizeof(AudioFileTypeAndFormatID), &tf, &size);
+ if (err == noErr) {
+ dfi->mNumVariants = size / sizeof(AudioStreamBasicDescription);
+ dfi->mVariants = new AudioStreamBasicDescription[dfi->mNumVariants];
+ err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_AvailableStreamDescriptionsForFormat,
+ sizeof(AudioFileTypeAndFormatID), &tf, &size, dfi->mVariants);
+ if (err) {
+ dfi->mNumVariants = 0;
+ delete[] dfi->mVariants;
+ dfi->mVariants = NULL;
+ } else {
+ for (k = 0; k < dfi->mNumVariants; ++k) {
+ AudioStreamBasicDescription *desc = &dfi->mVariants[k];
+ if (desc->mBitsPerChannel > 8) {
+ if (desc->mFormatFlags & kAudioFormatFlagIsBigEndian)
+ anyBigEndian = true;
+ else
+ anyLittleEndian = true;
+ }
+ }
+ }
+ }
+
+ dfi->mEitherEndianPCM = (anyBigEndian && anyLittleEndian);
+ }
+ }
+ delete[] formatIDs;
+ }
+bail:
+ delete[] readableFormats;
+ delete[] writableFormats;
+}
+
+// note that the outgoing format will have zero for the sample rate, channels per frame, bytesPerPacket, bytesPerFrame
+bool CAAudioFileFormats::InferDataFormatFromFileFormat(AudioFileTypeID filetype, CAStreamBasicDescription &fmt)
+{
+ // if the file format only supports one data format
+ for (int i = 0; i < mNumFileFormats; ++i) {
+ FileFormatInfo *ffi = &mFileFormats[i];
+ ffi->LoadDataFormats();
+ if (ffi->mFileTypeID == filetype && ffi->mNumDataFormats > 0) {
+ DataFormatInfo *dfi = &ffi->mDataFormats[0];
+ if (ffi->mNumDataFormats > 1) {
+ // file can contain multiple data formats. Take PCM if it's there.
+ for (int j = 0; j < ffi->mNumDataFormats; ++j) {
+ if (ffi->mDataFormats[j].mFormatID == kAudioFormatLinearPCM) {
+ dfi = &ffi->mDataFormats[j];
+ break;
+ }
+ }
+ }
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.mFormatID = dfi->mFormatID;
+ if (dfi->mNumVariants > 0) {
+ // take the first variant as a default
+ fmt = dfi->mVariants[0];
+ if (dfi->mNumVariants > 1 && dfi->mFormatID == kAudioFormatLinearPCM) {
+ // look for a 16-bit variant as a better default
+ for (int j = 0; j < dfi->mNumVariants; ++j) {
+ AudioStreamBasicDescription *desc = &dfi->mVariants[j];
+ if (desc->mBitsPerChannel == 16) {
+ fmt = *desc;
+ break;
+ }
+ }
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CAAudioFileFormats::InferFileFormatFromFilename(CFStringRef filename, AudioFileTypeID &filetype)
+{
+ bool result = false;
+ CFRange range = CFStringFind(filename, CFSTR("."), kCFCompareBackwards);
+ if (range.location == kCFNotFound) return false;
+ range.location += 1;
+ range.length = CFStringGetLength(filename) - range.location;
+ CFStringRef ext = CFStringCreateWithSubstring(NULL, filename, range);
+ for (int i = 0; i < mNumFileFormats; ++i) {
+ FileFormatInfo *ffi = &mFileFormats[i];
+ if (ffi->MatchExtension(ext)) {
+ filetype = ffi->mFileTypeID;
+ result = true;
+ break;
+ }
+ }
+ CFRelease(ext);
+ return result;
+}
+
+bool CAAudioFileFormats::InferFileFormatFromFilename(const char *filename, AudioFileTypeID &filetype)
+{
+ if (filename == NULL) return false;
+ CFStringRef cfname = CFStringCreateWithCString(NULL, filename, kCFStringEncodingUTF8);
+ bool result = InferFileFormatFromFilename(cfname, filetype);
+ CFRelease(cfname);
+ return result;
+}
+
+bool CAAudioFileFormats::InferFileFormatFromDataFormat(const CAStreamBasicDescription &fmt,
+ AudioFileTypeID &filetype)
+{
+ // if there's exactly one file format that supports this data format
+ FileFormatInfo *theFileFormat = NULL;
+ for (int i = 0; i < mNumFileFormats; ++i) {
+ FileFormatInfo *ffi = &mFileFormats[i];
+ ffi->LoadDataFormats();
+ DataFormatInfo *dfi = ffi->mDataFormats, *dfiend = dfi + ffi->mNumDataFormats;
+ for ( ; dfi < dfiend; ++dfi)
+ if (dfi->mFormatID == fmt.mFormatID) {
+ if (theFileFormat != NULL)
+ return false; // ambiguous
+ theFileFormat = ffi; // got a candidate
+ }
+ }
+ if (theFileFormat == NULL)
+ return false;
+ filetype = theFileFormat->mFileTypeID;
+ return true;
+}
+
+bool CAAudioFileFormats::IsKnownDataFormat(OSType dataFormat)
+{
+ for (int i = 0; i < mNumFileFormats; ++i) {
+ FileFormatInfo *ffi = &mFileFormats[i];
+ ffi->LoadDataFormats();
+ DataFormatInfo *dfi = ffi->mDataFormats, *dfiend = dfi + ffi->mNumDataFormats;
+ for ( ; dfi < dfiend; ++dfi)
+ if (dfi->mFormatID == dataFormat)
+ return true;
+ }
+ return false;
+}
+
+CAAudioFileFormats::FileFormatInfo * CAAudioFileFormats::FindFileFormat(UInt32 formatID)
+{
+ for (int i = 0; i < mNumFileFormats; ++i) {
+ FileFormatInfo *ffi = &mFileFormats[i];
+ if (ffi->mFileTypeID == formatID)
+ return ffi;
+ }
+ return NULL;
+}
+
+bool CAAudioFileFormats::FileFormatInfo::AnyWritableFormats()
+{
+ LoadDataFormats();
+ DataFormatInfo *dfi = mDataFormats, *dfiend = dfi + mNumDataFormats;
+ for ( ; dfi < dfiend; ++dfi)
+ if (dfi->mWritable)
+ return true;
+ return false;
+}
+
+char *OSTypeToStr(char *buf, size_t bufsize, OSType t)
+{
+ if (bufsize > 0) {
+ char *p = buf, *pend = buf + bufsize;
+ char str[4] = {0}, *q = str;
+ *(UInt32 *)str = CFSwapInt32HostToBig(t);
+ for (int i = 0; i < 4 && p < pend; ++i) {
+ if (isprint(*q) && *q != '\\')
+ *p++ = *q++;
+ else {
+ snprintf(p, pend - p, "\\x%02x", *q++);
+ p += 4;
+ }
+ }
+ if (p >= pend) p = pend - 1;
+ *p = '\0';
+ }
+ return buf;
+}
+
+int StrToOSType(const char *str, OSType &t)
+{
+ char buf[4];
+ const char *p = str;
+ int x;
+ for (int i = 0; i < 4; ++i) {
+ if (*p != '\\') {
+ if ((buf[i] = *p++) == '\0') {
+ // special-case for 'aac ': if we only got three characters, assume the last was a space
+ if (i == 3) {
+ --p;
+ buf[i] = ' ';
+ break;
+ }
+ goto fail;
+ }
+ } else {
+ if (*++p != 'x') goto fail;
+ if (sscanf(++p, "%02X", &x) != 1) goto fail;
+ buf[i] = x;
+ p += 2;
+ }
+ }
+ t = CFSwapInt32BigToHost(*(UInt32 *)buf);
+ return static_cast<int>(p - str);
+fail:
+ return 0;
+}
+
+#if DEBUG
+
+void CAAudioFileFormats::DebugPrint()
+{
+ for (int i = 0; i < mNumFileFormats; ++i)
+ mFileFormats[i].DebugPrint();
+}
+
+void CAAudioFileFormats::FileFormatInfo::DebugPrint()
+{
+ char ftype[20];
+ char ftypename[64];
+ CFStringGetCString(mFileTypeName, ftypename, sizeof(ftypename), kCFStringEncodingUTF8);
+ printf("File type: '%s' = %s\n Extensions:", OSTypeToStr(ftype, sizeof(ftype), mFileTypeID), ftypename);
+ int i, n = NumberOfExtensions();
+ for (i = 0; i < n; ++i) {
+ GetExtension(i, ftype, sizeof(ftype));
+ printf(" .%s", ftype);
+ }
+ LoadDataFormats();
+ printf("\n Formats:\n");
+ for (i = 0; i < mNumDataFormats; ++i)
+ mDataFormats[i].DebugPrint();
+}
+
+void CAAudioFileFormats::DataFormatInfo::DebugPrint()
+{
+ char buf[20];
+ static const char *ny[] = { "not ", "" };
+ printf(" '%s': %sreadable %swritable\n", OSTypeToStr(buf, sizeof(buf), mFormatID), ny[mReadable], ny[mWritable]);
+ for (int i = 0; i < mNumVariants; ++i) {
+ CAStreamBasicDescription desc(mVariants[i]);
+ desc.PrintFormat(stdout, " ", "");
+ //printf(" %d bytes/frame\n", desc.mBytesPerFrame);
+ }
+}
+#endif
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.h
new file mode 100644
index 0000000000..3d2f90f6de
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.h
@@ -0,0 +1,149 @@
+/*
+ File: CAAudioFileFormats.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAAudioFileFormats_h__
+#define __CAAudioFileFormats_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioToolbox/AudioToolbox.h>
+#else
+ #include <AudioToolbox.h>
+#endif
+#include "CAStreamBasicDescription.h"
+
+class CAAudioFileFormats {
+public:
+ enum { noErr = 0 };
+
+ struct DataFormatInfo {
+ DataFormatInfo() : mVariants(NULL) { }
+ ~DataFormatInfo() { delete[] mVariants; }
+
+ UInt32 mFormatID;
+ int mNumVariants;
+ AudioStreamBasicDescription * mVariants;
+ bool mReadable;
+ bool mWritable;
+ bool mEitherEndianPCM;
+
+#if DEBUG
+ void DebugPrint();
+#endif
+ };
+
+ struct FileFormatInfo {
+ FileFormatInfo() : mFileTypeName(NULL), mExtensions(NULL), mDataFormats(NULL) { }
+ ~FileFormatInfo() {
+ delete[] mDataFormats;
+ if (mFileTypeName)
+ CFRelease(mFileTypeName);
+ if (mExtensions)
+ CFRelease(mExtensions);
+ }
+
+ AudioFileTypeID mFileTypeID;
+ CFStringRef mFileTypeName;
+ CFArrayRef mExtensions;
+ int mNumDataFormats;
+ DataFormatInfo * mDataFormats; // NULL until loaded!
+
+ int NumberOfExtensions() { return static_cast<int>(mExtensions ? CFArrayGetCount(mExtensions) : 0); }
+ char * GetExtension(int index, char *buf, int buflen) {
+ CFStringRef cfext = (CFStringRef)CFArrayGetValueAtIndex(mExtensions, index);
+ CFStringGetCString(cfext, buf, buflen, kCFStringEncodingUTF8);
+ return buf;
+ }
+ bool MatchExtension(CFStringRef testExt) { // testExt should not include "."
+ CFIndex n = NumberOfExtensions();
+ for (CFIndex i = 0; i < n; ++i) {
+ CFStringRef ext = (CFStringRef)CFArrayGetValueAtIndex(mExtensions, i);
+ if (CFStringCompare(ext, testExt, kCFCompareCaseInsensitive) == kCFCompareEqualTo)
+ return true;
+ }
+ return false;
+ }
+ bool AnyWritableFormats();
+ void LoadDataFormats();
+
+#if DEBUG
+ void DebugPrint();
+#endif
+ };
+
+private: // use Instance()
+ CAAudioFileFormats(bool loadDataFormats);
+ ~CAAudioFileFormats();
+public:
+
+ bool InferDataFormatFromFileFormat(AudioFileTypeID filetype, CAStreamBasicDescription &fmt);
+
+ bool InferFileFormatFromFilename(const char *filename, AudioFileTypeID &filetype);
+
+ bool InferFileFormatFromFilename(CFStringRef filename, AudioFileTypeID &filetype);
+
+ bool InferFileFormatFromDataFormat(const CAStreamBasicDescription &fmt, AudioFileTypeID &filetype);
+
+ bool IsKnownDataFormat(UInt32 dataFormat);
+
+#if DEBUG
+ void DebugPrint();
+#endif
+
+ int mNumFileFormats;
+ FileFormatInfo * mFileFormats;
+
+ FileFormatInfo * FindFileFormat(UInt32 formatID);
+
+ static CAAudioFileFormats * Instance(bool loadDataFormats=true);
+
+private:
+ static CAAudioFileFormats * sInstance;
+};
+
+char * OSTypeToStr(char *buf, size_t bufsize, UInt32 t);
+int StrToOSType(const char *str, UInt32 &t);
+
+#endif // __CAAudioFileFormats_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.cpp
new file mode 100644
index 0000000000..0200ec9b79
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.cpp
@@ -0,0 +1,135 @@
+/*
+ File: CAAudioTimeStamp.cpp
+ Abstract: CAAudioTimeStamp.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CAAudioTimeStamp.h"
+
+//=============================================================================
+// CAAudioTimeStamp
+//=============================================================================
+
+const AudioTimeStamp CAAudioTimeStamp::kZero = { 0.0, 0, 0.0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0 };
+
+bool operator<(const AudioTimeStamp& x, const AudioTimeStamp& y)
+{
+ bool isLessThan = false;
+ bool isDone = false;
+
+ // check the sample time
+ if(!isDone)
+ {
+ if((x.mFlags & kAudioTimeStampSampleTimeValid) && (y.mFlags & kAudioTimeStampSampleTimeValid))
+ {
+ isLessThan = x.mSampleTime < y.mSampleTime;
+ isDone = true;
+ }
+ }
+
+ // check the host time
+ if(!isDone)
+ {
+ if((x.mFlags & kAudioTimeStampHostTimeValid) && (y.mFlags & kAudioTimeStampHostTimeValid))
+ {
+ isLessThan = x.mHostTime < y.mHostTime;
+ isDone = true;
+ }
+ }
+
+ // check the word clock time
+ if(!isDone)
+ {
+ if((x.mFlags & kAudioTimeStampWordClockTimeValid) && (y.mFlags & kAudioTimeStampWordClockTimeValid))
+ {
+ isLessThan = x.mWordClockTime < y.mWordClockTime;
+ // commented out to prevent this from being flagged as a dead store by the static analyzer
+ //isDone = true;
+ }
+ }
+
+ return isLessThan;
+}
+
+bool operator==(const AudioTimeStamp& x, const AudioTimeStamp& y)
+{
+ bool isEqual = false;
+ bool isDone = false;
+
+ // check the sample time
+ if(!isDone)
+ {
+ if((x.mFlags & kAudioTimeStampSampleTimeValid) && (y.mFlags & kAudioTimeStampSampleTimeValid))
+ {
+ isEqual = x.mSampleTime == y.mSampleTime;
+ isDone = true;
+ }
+ }
+
+ // check the host time
+ if(!isDone)
+ {
+ if((x.mFlags & kAudioTimeStampHostTimeValid) && (y.mFlags & kAudioTimeStampHostTimeValid))
+ {
+ isEqual = x.mHostTime == y.mHostTime;
+ isDone = true;
+ }
+ }
+
+ // check the word clock time
+ if(!isDone)
+ {
+ if((x.mFlags & kAudioTimeStampWordClockTimeValid) && (y.mFlags & kAudioTimeStampWordClockTimeValid))
+ {
+ isEqual = x.mWordClockTime == y.mWordClockTime;
+ // commented out to prevent this from being flagged as a dead store by the static analyzer
+ //isDone = true;
+ }
+ }
+
+ return isEqual;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.h
new file mode 100644
index 0000000000..9b8d6abe41
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.h
@@ -0,0 +1,97 @@
+/*
+ File: CAAudioTimeStamp.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAAudioTimeStamp_h__)
+#define __CAAudioTimeStamp_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+#include <string.h>
+
+//=============================================================================
+// CAAudioTimeStamp
+//=============================================================================
+
+struct CAAudioTimeStamp
+:
+ public AudioTimeStamp
+{
+
+// Construction/Destruction
+public:
+ CAAudioTimeStamp() { memset(this, 0, sizeof(AudioTimeStamp)); }
+ CAAudioTimeStamp(const AudioTimeStamp& v) { memcpy(this, &v, sizeof(AudioTimeStamp)); }
+ CAAudioTimeStamp(Float64 inSampleTime) { memset(this, 0, sizeof(AudioTimeStamp)); mSampleTime = inSampleTime; mFlags = kAudioTimeStampSampleTimeValid; }
+ CAAudioTimeStamp(UInt64 inHostTime) { memset(this, 0, sizeof(AudioTimeStamp)); mHostTime = inHostTime; mFlags = kAudioTimeStampHostTimeValid; }
+ CAAudioTimeStamp(Float64 inSampleTime, UInt64 inHostTime) { memset(this, 0, sizeof(AudioTimeStamp)); mSampleTime = inSampleTime; mHostTime = inHostTime; mFlags = kAudioTimeStampSampleTimeValid | kAudioTimeStampHostTimeValid; }
+ CAAudioTimeStamp(Float64 inSampleTime, UInt64 inHostTime, Float64 inRateScalar) { memset(this, 0, sizeof(AudioTimeStamp)); mSampleTime = inSampleTime; mHostTime = inHostTime; mRateScalar = inRateScalar; mFlags = kAudioTimeStampSampleTimeValid | kAudioTimeStampHostTimeValid | kAudioTimeStampRateScalarValid; }
+
+// Assignment
+public:
+ CAAudioTimeStamp& operator=(const AudioTimeStamp& v) { memcpy(this, &v, sizeof(AudioTimeStamp)); return *this; }
+
+// Constants
+public:
+ static const AudioTimeStamp kZero;
+
+};
+
+bool operator<(const AudioTimeStamp& x, const AudioTimeStamp& y);
+bool operator==(const AudioTimeStamp& x, const AudioTimeStamp& y);
+inline bool operator!=(const AudioTimeStamp& x, const AudioTimeStamp& y) { return !(x == y); }
+inline bool operator<=(const AudioTimeStamp& x, const AudioTimeStamp& y) { return (x < y) || (x == y); }
+inline bool operator>=(const AudioTimeStamp& x, const AudioTimeStamp& y) { return !(x < y); }
+inline bool operator>(const AudioTimeStamp& x, const AudioTimeStamp& y) { return !((x < y) || (x == y)); }
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.cpp
new file mode 100644
index 0000000000..53da5a1cc6
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.cpp
@@ -0,0 +1,1421 @@
+/*
+ File: CAAudioUnit.cpp
+ Abstract: CAAudioUnit.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CAAudioUnit.h"
+
+#if !TARGET_OS_IPHONE
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/Components.h>
+ #include <dlfcn.h>
+#else
+ #include <Components.h>
+#endif
+#endif
+
+#include "CAXException.h"
+#include "CAReferenceCounted.h"
+#include "AUOutputBL.h" //this is for the Preroll only
+
+struct StackAUChannelInfo {
+ StackAUChannelInfo (UInt32 inSize) : mChanInfo ((AUChannelInfo*)malloc (inSize)) {}
+ ~StackAUChannelInfo() { free (mChanInfo); }
+
+ AUChannelInfo* mChanInfo;
+};
+
+// is this symbol is not defined then we use the default setting which is that fast dispatch
+// is supported on a desktop environment
+#ifndef CA_AU_USE_FAST_DISPATCH
+ #define CA_AU_USE_FAST_DISPATCH !TARGET_OS_IPHONE
+#endif
+
+#if CA_AU_USE_FAST_DISPATCH
+static void *LoadGetComponentInstanceStorage (void *inst);
+#endif
+
+
+class CAAudioUnit::AUState : public CAReferenceCounted {
+public:
+ AUState (AudioComponent inComp)
+ : mUnit(0), mNode (0)
+ {
+ OSStatus result = ::AudioComponentInstanceNew (inComp, &mUnit);
+ if (result)
+ throw result;
+ Init();
+ }
+
+ AUState (const AUNode &inNode, const AudioUnit& inUnit)
+ : mUnit (inUnit), mNode (inNode)
+ {
+ Init();
+ }
+
+ ~AUState();
+
+ AudioUnit mUnit;
+ AUNode mNode;
+
+ OSStatus GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+ Float32 &outValue) const
+ {
+#if CA_AU_USE_FAST_DISPATCH
+ if (mGetParamProc != NULL) {
+ return (mGetParamProc) (mConnInstanceStorage, inID, scope, element, &outValue);
+ }
+#endif
+ return AudioUnitGetParameter(mUnit, inID, scope, element, &outValue);
+ }
+
+ OSStatus SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+ Float32 value, UInt32 bufferOffsetFrames)
+ {
+#if CA_AU_USE_FAST_DISPATCH
+ if (mSetParamProc != NULL) {
+ return (mSetParamProc) (mConnInstanceStorage, inID, scope, element, value, bufferOffsetFrames);
+ }
+#endif
+ return AudioUnitSetParameter(mUnit, inID, scope, element, value, bufferOffsetFrames);
+ }
+
+ OSStatus Render (AudioUnitRenderActionFlags * ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inOutputBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList * ioData)
+ {
+#if CA_AU_USE_FAST_DISPATCH
+ if (mRenderProc != NULL) {
+ return (mRenderProc) (mConnInstanceStorage, ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
+ }
+#endif
+ return AudioUnitRender(mUnit, ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
+ }
+
+ OSStatus MIDIEvent (UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame)
+ {
+#if !TARGET_OS_WIN32
+#if CA_AU_USE_FAST_DISPATCH
+ if (mMIDIEventProc != NULL) {
+ return (mMIDIEventProc) (mConnInstanceStorage, inStatus, inData1, inData2, inOffsetSampleFrame);
+ }
+#endif
+ return MusicDeviceMIDIEvent (mUnit, inStatus, inData1, inData2, inOffsetSampleFrame);
+#else // ON WINDOWS _ NO MIDI EVENT dispatch
+ return paramErr;
+#endif
+ }
+
+ OSStatus StartNote (MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams * inParams)
+ {
+#if !TARGET_OS_WIN32
+#if CA_AU_USE_FAST_DISPATCH
+ if (mStartNoteProc != NULL) {
+ return (mStartNoteProc) (mConnInstanceStorage, inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams);
+ }
+#endif
+ return MusicDeviceStartNote (mUnit, inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams);
+#else
+ return paramErr;
+#endif
+ }
+ OSStatus StopNote (MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame)
+ {
+#if !TARGET_OS_WIN32
+#if CA_AU_USE_FAST_DISPATCH
+ if (mStopNoteProc != NULL) {
+ return (mStopNoteProc) (mConnInstanceStorage, inGroupID, inNoteInstanceID, inOffsetSampleFrame);
+ }
+#endif
+ return MusicDeviceStopNote (mUnit, inGroupID, inNoteInstanceID, inOffsetSampleFrame);
+#else
+ return paramErr;
+#endif
+ }
+
+private:
+ // get the fast dispatch pointers
+ void Init()
+ {
+#if CA_AU_USE_FAST_DISPATCH
+ UInt32 size = sizeof(AudioUnitRenderProc);
+ if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
+ kAudioUnitScope_Global, kAudioUnitRenderSelect,
+ &mRenderProc, &size) != noErr)
+ mRenderProc = NULL;
+
+ size = sizeof(AudioUnitGetParameterProc);
+ if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
+ kAudioUnitScope_Global, kAudioUnitGetParameterSelect,
+ &mGetParamProc, &size) != noErr)
+ mGetParamProc = NULL;
+
+ size = sizeof(AudioUnitSetParameterProc);
+ if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
+ kAudioUnitScope_Global, kAudioUnitSetParameterSelect,
+ &mSetParamProc, &size) != noErr)
+ mSetParamProc = NULL;
+
+ size = sizeof(MusicDeviceMIDIEventProc);
+ if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
+ kAudioUnitScope_Global, kMusicDeviceMIDIEventSelect,
+ &mMIDIEventProc, &size) != noErr)
+ mMIDIEventProc = NULL;
+
+ size = sizeof(MusicDeviceStartNoteProc);
+ if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
+ kAudioUnitScope_Global, kMusicDeviceStartNoteSelect,
+ &mStartNoteProc, &size) != noErr)
+ mStartNoteProc = NULL;
+
+ size = sizeof(MusicDeviceStopNoteProc);
+ if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
+ kAudioUnitScope_Global, kMusicDeviceStopNoteSelect,
+ &mStopNoteProc, &size) != noErr)
+ mStopNoteProc = NULL;
+
+ if (mRenderProc || mGetParamProc || mSetParamProc || mMIDIEventProc || mStartNoteProc || mStopNoteProc) {
+ mConnInstanceStorage = LoadGetComponentInstanceStorage ( mUnit );
+ } else
+ mConnInstanceStorage = NULL;
+#else
+ mConnInstanceStorage = NULL;
+#endif
+ }
+
+#if CA_AU_USE_FAST_DISPATCH
+ AudioUnitRenderProc mRenderProc;
+ AudioUnitGetParameterProc mGetParamProc;
+ AudioUnitSetParameterProc mSetParamProc;
+ MusicDeviceMIDIEventProc mMIDIEventProc;
+ MusicDeviceStartNoteProc mStartNoteProc;
+ MusicDeviceStopNoteProc mStopNoteProc;
+#endif
+
+ void * mConnInstanceStorage;
+
+private:
+ // get the compiler to tell us when we do a bad thing!!!
+ AUState () {}
+ AUState (const AUState&);
+ AUState& operator= (const AUState&);
+};
+
+
+CAAudioUnit::AUState::~AUState ()
+{
+ if (mUnit && (mNode == 0)) {
+ ::AudioComponentInstanceDispose (mUnit);
+ }
+ mNode = 0;
+ mUnit = 0;
+}
+
+OSStatus CAAudioUnit::Open (const CAComponent& inComp, CAAudioUnit &outUnit)
+{
+ try {
+ outUnit = inComp;
+ return noErr;
+ } catch (OSStatus res) {
+ return res;
+ } catch (...) {
+ return -1;
+ }
+}
+
+CAAudioUnit::CAAudioUnit (const AudioUnit& inUnit)
+ : mComp (inUnit), mDataPtr (new AUState (kCAAU_DoNotKnowIfAUNode, inUnit))
+{
+}
+
+CAAudioUnit::CAAudioUnit (const CAComponent& inComp)
+ : mComp (inComp), mDataPtr (new AUState (mComp.Comp()))
+{
+}
+
+CAAudioUnit::CAAudioUnit (const AUNode &inNode, const AudioUnit& inUnit)
+ : mComp (inUnit), mDataPtr(new AUState (inNode, inUnit))
+{
+}
+
+CAAudioUnit::~CAAudioUnit ()
+{
+ Close();
+}
+
+void CAAudioUnit::Close()
+{
+ if (mDataPtr) {
+ mDataPtr->release();
+ mDataPtr = NULL;
+ }
+}
+
+CAAudioUnit& CAAudioUnit::operator= (const CAAudioUnit &a)
+{
+ if (mDataPtr != a.mDataPtr) {
+ if (mDataPtr)
+ mDataPtr->release();
+
+ if ((mDataPtr = a.mDataPtr) != NULL)
+ mDataPtr->retain();
+
+ mComp = a.mComp;
+ }
+
+ return *this;
+}
+
+bool CAAudioUnit::operator== (const CAAudioUnit& y) const
+{
+ if (mDataPtr == y.mDataPtr) return true;
+ AudioUnit au1 = mDataPtr ? mDataPtr->mUnit : 0;
+ AudioUnit au2 = y.mDataPtr ? y.mDataPtr->mUnit : 0;
+ return au1 == au2;
+}
+
+bool CAAudioUnit::operator== (const AudioUnit& y) const
+{
+ if (!mDataPtr) return false;
+ return mDataPtr->mUnit == y;
+}
+
+OSStatus CAAudioUnit::RemovePropertyListener (AudioUnitPropertyID inID,
+ AudioUnitPropertyListenerProc inProc,
+ void * inProcUserData)
+{
+ // we call this first. If it fails we call the old API as the failure can
+ // mean that the AU doesn't implement that selector.
+ OSStatus result = AudioUnitRemovePropertyListenerWithUserData(AU(), inID,
+ inProc, inProcUserData);
+ #if !__LP64__ && !TARGET_OS_IPHONE
+ if (result) result = AudioUnitRemovePropertyListener (AU(), inID, inProc);
+ #endif
+ return result;
+}
+
+#pragma mark __State Management
+
+bool CAAudioUnit::IsValid () const
+{
+ return mDataPtr ? mDataPtr->mUnit != 0 : false;
+}
+
+AudioUnit CAAudioUnit::AU() const
+{
+ return mDataPtr ? mDataPtr->mUnit : 0;
+}
+
+AUNode CAAudioUnit::GetAUNode () const
+{
+ return mDataPtr ? mDataPtr->mNode : 0;
+}
+
+#pragma mark __Format Handling
+
+bool CAAudioUnit::CanDo ( int inChannelsIn,
+ int inChannelsOut) const
+{
+ // this is the default assumption of an audio effect unit
+ Boolean* isWritable = 0;
+ UInt32 dataSize = 0;
+ // lets see if the unit has any channel restrictions
+ OSStatus result = AudioUnitGetPropertyInfo (AU(),
+ kAudioUnitProperty_SupportedNumChannels,
+ kAudioUnitScope_Global, 0,
+ &dataSize, isWritable); //don't care if this is writable
+
+ // if this property is NOT implemented an FX unit
+ // is expected to deal with same channel valance in and out
+ if (result)
+ {
+ if ((Comp().Desc().IsEffect() && inChannelsIn == inChannelsOut)
+ || (Comp().Desc().IsOffline() && inChannelsIn == inChannelsOut))
+ {
+ return true;
+ }
+ else
+ {
+ // the au should either really tell us about this
+ // or we will assume the worst
+ return false;
+ }
+ }
+
+ StackAUChannelInfo info (dataSize);
+
+ result = GetProperty (kAudioUnitProperty_SupportedNumChannels,
+ kAudioUnitScope_Global, 0,
+ info.mChanInfo, &dataSize);
+ if (result) { return false; }
+
+ return ValidateChannelPair (inChannelsIn, inChannelsOut, info.mChanInfo, (dataSize / sizeof (AUChannelInfo)));
+}
+
+int CAAudioUnit::GetChannelInfo (AUChannelInfo** chaninfo, UInt32& cnt)
+{
+ // this is the default assumption of an audio effect unit
+ Boolean* isWritable = 0;
+ UInt32 dataSize = 0;
+ // lets see if the unit has any channel restrictions
+ OSStatus result = AudioUnitGetPropertyInfo (AU(),
+ kAudioUnitProperty_SupportedNumChannels,
+ kAudioUnitScope_Global, 0,
+ &dataSize, isWritable); //don't care if this is writable
+
+ // if this property is NOT implemented an FX unit
+ // is expected to deal with same channel valance in and out
+
+ if (result)
+ {
+ if (Comp().Desc().IsEffect())
+ {
+ return 1;
+ }
+ else if (Comp().Desc().IsGenerator() || Comp().Desc().IsMusicDevice()) {
+ // directly query Bus Formats
+ // Note that that these may refer to different subBusses
+ // (eg. Kick, Snare,.. on a Drummachine)
+ // eventually the Bus-Name for each configuration should be exposed
+ // for the User to select..
+
+ UInt32 elCountIn, elCountOut;
+
+ if (GetElementCount (kAudioUnitScope_Input, elCountIn)) return -1;
+ if (GetElementCount (kAudioUnitScope_Output, elCountOut)) return -1;
+
+ cnt = std::max(elCountIn, elCountOut);
+
+ *chaninfo = (AUChannelInfo*) malloc (sizeof (AUChannelInfo) * cnt);
+
+ for (unsigned int i = 0; i < elCountIn; ++i) {
+ UInt32 numChans;
+ if (NumberChannels (kAudioUnitScope_Input, i, numChans)) return -1;
+ (*chaninfo)[i].inChannels = numChans;
+ }
+ for (unsigned int i = elCountIn; i < cnt; ++i) {
+ (*chaninfo)[i].inChannels = 0;
+ }
+
+ for (unsigned int i = 0; i < elCountOut; ++i) {
+ UInt32 numChans;
+ if (NumberChannels (kAudioUnitScope_Output, i, numChans)) return -1;
+ (*chaninfo)[i].outChannels = numChans;
+ }
+ for (unsigned int i = elCountOut; i < cnt; ++i) {
+ (*chaninfo)[i].outChannels = 0;
+ }
+ return 0;
+ }
+ else
+ {
+ // the au should either really tell us about this
+ // or we will assume the worst
+ return -1;
+ }
+ }
+
+ *chaninfo = (AUChannelInfo*) malloc (dataSize);
+ cnt = dataSize / sizeof (AUChannelInfo);
+
+ result = GetProperty (kAudioUnitProperty_SupportedNumChannels,
+ kAudioUnitScope_Global, 0,
+ *chaninfo, &dataSize);
+
+ if (result) { return -1; }
+ return 0;
+}
+
+bool CAAudioUnit::ValidateChannelPair (int inChannelsIn,
+ int inChannelsOut,
+ const AUChannelInfo * info,
+ UInt32 numChanInfo) const
+{
+// we've the following cases (some combinations) to test here:
+/*
+>0 An explicit number of channels on either side
+0 that side (generally input!) has no elements
+-1 wild card:
+-1,-1 any num channels as long as same channels on in and out
+-1,-2 any num channels channels on in and out - special meaning
+-2+ indicates total num channs AU can handle
+ - elements configurable to any num channels,
+ - element count in scope must be writable
+*/
+
+ //now chan layout can contain -1 for either scope (ie. doesn't care)
+ for (unsigned int i = 0; i < numChanInfo; ++i)
+ {
+ //less than zero on both sides - check for special attributes
+ if ((info[i].inChannels < 0) && (info[i].outChannels < 0))
+ {
+ // these are our wild card matches
+ if (info[i].inChannels == -1 && info[i].outChannels == -1) {
+ if (inChannelsIn && inChannelsOut) {
+ if (inChannelsOut == inChannelsIn)
+ return true;
+ } else
+ return true; // if one of these is zero, then a -1 means any
+ }
+ else if ((info[i].inChannels == -1 && info[i].outChannels == -2)
+ || (info[i].inChannels == -2 && info[i].outChannels == -1))
+ {
+ return true;
+ }
+ // these are our total num channels matches
+ // element count MUST be writable
+ else {
+ bool outWrite = false; bool inWrite = false;
+ IsElementCountWritable (kAudioUnitScope_Output, outWrite);
+ IsElementCountWritable (kAudioUnitScope_Input, inWrite);
+ if (inWrite && outWrite) {
+ if ((inChannelsOut <= abs(info[i].outChannels))
+ && (inChannelsIn <= abs(info[i].inChannels)))
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ // special meaning on input, specific num on output
+ else if (info[i].inChannels < 0) {
+ if (info[i].outChannels == inChannelsOut)
+ {
+ // can do any in channels
+ if (info[i].inChannels == -1) {
+ return true;
+ }
+ // total chans on input
+ else {
+ bool inWrite = false;
+ IsElementCountWritable (kAudioUnitScope_Input, inWrite);
+ if (inWrite && (inChannelsIn <= abs(info[i].inChannels))) {
+ return true;
+ }
+ }
+ }
+ }
+
+ // special meaning on output, specific num on input
+ else if (info[i].outChannels < 0) {
+ if (info[i].inChannels == inChannelsIn)
+ {
+ // can do any out channels
+ if (info[i].outChannels == -1) {
+ return true;
+ }
+ // total chans on output
+ else {
+ bool outWrite = false;
+ IsElementCountWritable (kAudioUnitScope_Output, outWrite);
+ if (outWrite && (inChannelsOut <= abs(info[i].outChannels))) {
+ return true;
+ }
+ }
+ }
+ }
+
+ // both chans in struct >= 0 - thus has to explicitly match
+ else if ((info[i].inChannels == inChannelsIn) && (info[i].outChannels == inChannelsOut)) {
+ return true;
+ }
+
+ // now check to see if a wild card on the args (inChannelsIn or inChannelsOut chans is zero) is found
+ // tells us to match just one side of the scopes
+ else if (inChannelsIn == 0) {
+ if (info[i].outChannels == inChannelsOut) {
+ return true;
+ }
+ }
+ else if (inChannelsOut == 0) {
+ if (info[i].inChannels == inChannelsIn) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static
+bool CheckDynCount (SInt32 inTotalChans, const CAAUChanHelper &inHelper)
+{
+ int totalChans = 0;
+ for (unsigned int i = 0; i < inHelper.mNumEls; ++i)
+ totalChans += inHelper.mChans[i];
+ return (totalChans <= inTotalChans);
+}
+
+bool CAAudioUnit::CheckOneSide (const CAAUChanHelper &inHelper,
+ bool checkOutput,
+ const AUChannelInfo *info,
+ UInt32 numInfo) const
+{
+ // now we can use the wildcard option (see above impl) to see if this matches
+ for (unsigned int el = 0; el < inHelper.mNumEls; ++el) {
+ bool testAlready = false;
+ for (unsigned int i = 0; i < el; ++i) {
+ if (inHelper.mChans[i] == inHelper.mChans[el]) {
+ testAlready = true;
+ break;
+ }
+ }
+ if (!testAlready) {
+ if (checkOutput) {
+ if (!ValidateChannelPair (0, inHelper.mChans[el], info, numInfo)) return false;
+ } else {
+ if (!ValidateChannelPair (inHelper.mChans[el], 0, info, numInfo)) return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool CAAudioUnit::CanDo (const CAAUChanHelper &inputs,
+ const CAAUChanHelper &outputs) const
+
+{
+// first check our state
+ // huh!
+ if (inputs.mNumEls == 0 && outputs.mNumEls == 0) return false;
+
+ UInt32 elCount;
+ if (GetElementCount (kAudioUnitScope_Input, elCount)) { return false; }
+ if (elCount != inputs.mNumEls) return false;
+
+ if (GetElementCount (kAudioUnitScope_Output, elCount)) { return false; }
+ if (elCount != outputs.mNumEls) return false;
+
+// (1) special cases (effects and sources (generators and instruments) only)
+ UInt32 dataSize = 0;
+ if (GetPropertyInfo (kAudioUnitProperty_SupportedNumChannels,
+ kAudioUnitScope_Global, 0, &dataSize, NULL) != noErr)
+ {
+ if (Comp().Desc().IsEffect() || Comp().Desc().IsOffline()) {
+ UInt32 numChan = outputs.mNumEls > 0 ? outputs.mChans[0] : inputs.mChans[0];
+ for (unsigned int in = 0; in < inputs.mNumEls; ++in)
+ if (numChan != inputs.mChans[in]) return false;
+ for (unsigned int out = 0; out < outputs.mNumEls; ++out)
+ if (numChan != outputs.mChans[out]) return false;
+ return true;
+ }
+
+ // in this case, all the channels have to match the current config
+ if (Comp().Desc().IsGenerator() || Comp().Desc().IsMusicDevice()) {
+ for (unsigned int in = 0; in < inputs.mNumEls; ++in) {
+ UInt32 chan;
+ if (NumberChannels (kAudioUnitScope_Input, in, chan)) return false;
+ if (chan != UInt32(inputs.mChans[in])) return false;
+ }
+ for (unsigned int out = 0; out < outputs.mNumEls; ++out) {
+ UInt32 chan;
+ if (NumberChannels (kAudioUnitScope_Output, out, chan)) return false;
+ if (chan != UInt32(outputs.mChans[out])) return false;
+ }
+ return true;
+ }
+
+ // if we get here we can't determine anything about channel capabilities
+ return false;
+ }
+
+ StackAUChannelInfo info (dataSize);
+
+ if (GetProperty (kAudioUnitProperty_SupportedNumChannels,
+ kAudioUnitScope_Global, 0,
+ info.mChanInfo, &dataSize) != noErr)
+ {
+ return false;
+ }
+
+ int numInfo = dataSize / sizeof(AUChannelInfo);
+
+// (2) Test for dynamic capability (or no elements on that scope)
+ SInt32 dynInChans = 0;
+ if (ValidateDynamicScope (kAudioUnitScope_Input, dynInChans, info.mChanInfo, numInfo)) {
+ if (CheckDynCount (dynInChans, inputs) == false) return false;
+ }
+
+ SInt32 dynOutChans = 0;
+ if (ValidateDynamicScope (kAudioUnitScope_Output, dynOutChans, info.mChanInfo, numInfo)) {
+ if (CheckDynCount (dynOutChans, outputs) == false) return false;
+ }
+
+ if (dynOutChans && dynInChans) { return true; }
+
+// (3) Just need to test one side
+ if (dynInChans || (inputs.mNumEls == 0)) {
+ return CheckOneSide (outputs, true, info.mChanInfo, numInfo);
+ }
+
+ if (dynOutChans || (outputs.mNumEls == 0)) {
+ return CheckOneSide (inputs, false, info.mChanInfo, numInfo);
+ }
+
+// (4) - not a dynamic AU, has ins and outs, and has channel constraints so we test every possible pairing
+ for (unsigned int in = 0; in < inputs.mNumEls; ++in)
+ {
+ bool testInAlready = false;
+ for (unsigned int i = 0; i < in; ++i) {
+ if (inputs.mChans[i] == inputs.mChans[in]) {
+ testInAlready = true;
+ break;
+ }
+ }
+ if (!testInAlready) {
+ for (unsigned int out = 0; out < outputs.mNumEls; ++out) {
+ // try to save a little bit and not test the same pairing multiple times...
+ bool testOutAlready = false;
+ for (unsigned int i = 0; i < out; ++i) {
+ if (outputs.mChans[i] == outputs.mChans[out]) {
+ testOutAlready = true;
+ break;
+ }
+ }
+ if (!testOutAlready) {
+ if (!ValidateChannelPair (inputs.mChans[in], outputs.mChans[out],info.mChanInfo, numInfo)) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool CAAudioUnit::SupportsNumChannels () const
+{
+ // this is the default assumption of an audio effect unit
+ Boolean* isWritable = 0;
+ UInt32 dataSize = 0;
+ // lets see if the unit has any channel restrictions
+ OSStatus result = AudioUnitGetPropertyInfo (AU(),
+ kAudioUnitProperty_SupportedNumChannels,
+ kAudioUnitScope_Global, 0,
+ &dataSize, isWritable); //don't care if this is writable
+
+ // if this property is NOT implemented an FX unit
+ // is expected to deal with same channel valance in and out
+ if (result) {
+ if (Comp().Desc().IsEffect() || Comp().Desc().IsOffline())
+ return true;
+ }
+ return result == noErr;
+}
+
+OSStatus CAAudioUnit::GetChannelLayoutTags (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ ChannelTagVector &outChannelVector) const
+{
+ if (HasChannelLayouts (inScope, inEl) == false) return kAudioUnitErr_InvalidProperty;
+
+ UInt32 dataSize;
+ OSStatus result = AudioUnitGetPropertyInfo (AU(),
+ kAudioUnitProperty_SupportedChannelLayoutTags,
+ inScope, inEl,
+ &dataSize, NULL);
+
+ if (result) return result;
+
+ // OK lets get our channel layouts and see if the one we want is present
+ AudioChannelLayoutTag* info = (AudioChannelLayoutTag*)malloc (dataSize);
+ result = AudioUnitGetProperty (AU(),
+ kAudioUnitProperty_SupportedChannelLayoutTags,
+ inScope, inEl,
+ info, &dataSize);
+ if (result) goto home;
+
+ outChannelVector.erase (outChannelVector.begin(), outChannelVector.end());
+ for (unsigned int i = 0; i < (dataSize / sizeof (AudioChannelLayoutTag)); ++i)
+ outChannelVector.push_back (info[i]);
+
+home:
+ free (info);
+ return result;
+}
+
+bool CAAudioUnit::HasChannelLayouts (AudioUnitScope inScope,
+ AudioUnitElement inEl) const
+{
+ OSStatus result = AudioUnitGetPropertyInfo (AU(),
+ kAudioUnitProperty_SupportedChannelLayoutTags,
+ inScope, inEl,
+ NULL, NULL);
+ return !result;
+}
+
+bool CAAudioUnit::HasChannelLayout (AudioUnitScope inScope,
+ AudioUnitElement inEl) const
+{
+ Boolean writable;
+ UInt32 size;
+
+ return AudioUnitGetPropertyInfo (AU(),
+ kAudioUnitProperty_AudioChannelLayout,
+ inScope, inEl,
+ &size, &writable) == noErr;
+}
+
+OSStatus CAAudioUnit::GetChannelLayout (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ CAAudioChannelLayout &outLayout) const
+{
+ UInt32 size;
+ OSStatus result = AudioUnitGetPropertyInfo (AU(), kAudioUnitProperty_AudioChannelLayout,
+ inScope, inEl, &size, NULL);
+ if (result) return result;
+
+ AudioChannelLayout *layout = (AudioChannelLayout*)malloc (size);
+
+ ca_require_noerr (result = AudioUnitGetProperty (AU(), kAudioUnitProperty_AudioChannelLayout,
+ inScope, inEl, layout, &size), home);
+
+ outLayout = CAAudioChannelLayout (layout);
+
+home:
+ free (layout);
+ return result;
+}
+
+OSStatus CAAudioUnit::SetChannelLayout (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ const CAAudioChannelLayout &inLayout)
+{
+ OSStatus result = AudioUnitSetProperty (AU(),
+ kAudioUnitProperty_AudioChannelLayout,
+ inScope, inEl,
+ inLayout, inLayout.Size());
+ return result;
+}
+
+OSStatus CAAudioUnit::SetChannelLayout (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ const AudioChannelLayout &inLayout,
+ UInt32 inSize)
+{
+ OSStatus result = AudioUnitSetProperty (AU(),
+ kAudioUnitProperty_AudioChannelLayout,
+ inScope, inEl,
+ &inLayout, inSize);
+ return result;
+}
+
+OSStatus CAAudioUnit::ClearChannelLayout (AudioUnitScope inScope,
+ AudioUnitElement inEl)
+{
+ return AudioUnitSetProperty (AU(),
+ kAudioUnitProperty_AudioChannelLayout,
+ inScope, inEl, NULL, 0);
+}
+
+OSStatus CAAudioUnit::GetFormat (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ AudioStreamBasicDescription &outFormat) const
+{
+ UInt32 dataSize = sizeof (AudioStreamBasicDescription);
+ return AudioUnitGetProperty (AU(), kAudioUnitProperty_StreamFormat,
+ inScope, inEl,
+ &outFormat, &dataSize);
+}
+
+OSStatus CAAudioUnit::SetFormat (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ const AudioStreamBasicDescription &inFormat)
+{
+ return AudioUnitSetProperty (AU(), kAudioUnitProperty_StreamFormat,
+ inScope, inEl,
+ const_cast<AudioStreamBasicDescription*>(&inFormat),
+ sizeof (AudioStreamBasicDescription));
+}
+
+OSStatus CAAudioUnit::GetSampleRate (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ Float64 &outRate) const
+{
+ UInt32 dataSize = sizeof (Float64);
+ return AudioUnitGetProperty (AU(), kAudioUnitProperty_SampleRate,
+ inScope, inEl,
+ &outRate, &dataSize);
+}
+
+OSStatus CAAudioUnit::SetSampleRate (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ Float64 inRate)
+{
+ AudioStreamBasicDescription desc;
+ OSStatus result = GetFormat (inScope, inEl, desc);
+ if (result) return result;
+ desc.mSampleRate = inRate;
+ return SetFormat (inScope, inEl, desc);
+}
+
+OSStatus CAAudioUnit::SetSampleRate (Float64 inSampleRate)
+{
+ OSStatus result;
+
+ UInt32 elCount;
+ ca_require_noerr (result = GetElementCount(kAudioUnitScope_Input, elCount), home);
+ if (elCount) {
+ for (unsigned int i = 0; i < elCount; ++i) {
+ ca_require_noerr (result = SetSampleRate (kAudioUnitScope_Input, i, inSampleRate), home);
+ }
+ }
+
+ ca_require_noerr (result = GetElementCount(kAudioUnitScope_Output, elCount), home);
+ if (elCount) {
+ for (unsigned int i = 0; i < elCount; ++i) {
+ ca_require_noerr (result = SetSampleRate (kAudioUnitScope_Output, i, inSampleRate), home);
+ }
+ }
+
+home:
+ return result;
+}
+
+OSStatus CAAudioUnit::NumberChannels (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ UInt32 &outChans) const
+{
+ AudioStreamBasicDescription desc;
+ OSStatus result = GetFormat (inScope, inEl, desc);
+ if (!result)
+ outChans = desc.mChannelsPerFrame;
+ return result;
+}
+
+OSStatus CAAudioUnit::SetNumberChannels (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ UInt32 inChans)
+{
+ // set this as the output of the AU
+ CAStreamBasicDescription desc;
+ OSStatus result = GetFormat (inScope, inEl, desc);
+ if (result) return result;
+ desc.ChangeNumberChannels (inChans, desc.IsInterleaved());
+ result = SetFormat (inScope, inEl, desc);
+ return result;
+}
+
+OSStatus CAAudioUnit::IsElementCountWritable (AudioUnitScope inScope, bool &outWritable) const
+{
+ Boolean isWritable;
+ UInt32 outDataSize;
+ OSStatus result = GetPropertyInfo (kAudioUnitProperty_ElementCount, inScope, 0, &outDataSize, &isWritable);
+ if (result)
+ return result;
+ outWritable = isWritable ? true : false;
+ return noErr;
+}
+
+OSStatus CAAudioUnit::GetElementCount (AudioUnitScope inScope, UInt32 &outCount) const
+{
+ UInt32 propSize = sizeof(outCount);
+ return GetProperty (kAudioUnitProperty_ElementCount, inScope, 0, &outCount, &propSize);
+}
+
+OSStatus CAAudioUnit::SetElementCount (AudioUnitScope inScope, UInt32 inCount)
+{
+ return SetProperty (kAudioUnitProperty_ElementCount, inScope, 0, &inCount, sizeof(inCount));
+}
+
+bool CAAudioUnit::HasDynamicScope (AudioUnitScope inScope, SInt32 &outTotalNumChannels) const
+{
+ // ok - now we need to check the AU's capability here.
+ // this is the default assumption of an audio effect unit
+ Boolean* isWritable = 0;
+ UInt32 dataSize = 0;
+ OSStatus result = GetPropertyInfo (kAudioUnitProperty_SupportedNumChannels,
+ kAudioUnitScope_Global, 0,
+ &dataSize, isWritable); //don't care if this is writable
+
+ // AU has to explicitly tell us about this.
+ if (result) return false;
+
+ StackAUChannelInfo info (dataSize);
+
+ result = GetProperty (kAudioUnitProperty_SupportedNumChannels,
+ kAudioUnitScope_Global, 0,
+ info.mChanInfo, &dataSize);
+ if (result) return false;
+
+ return ValidateDynamicScope (inScope, outTotalNumChannels, info.mChanInfo, (dataSize / sizeof(AUChannelInfo)));
+}
+
+// as we've already checked that the element count is writable
+// the following conditions will match this..
+/*
+-1, -2 -> signifies no restrictions
+-2, -1 -> signifies no restrictions -> in this case outTotalNumChannels == -1 (any num channels)
+
+-N (where N is less than -2), signifies the total channel count on the scope side (in or out)
+*/
+bool CAAudioUnit::ValidateDynamicScope (AudioUnitScope inScope,
+ SInt32 &outTotalNumChannels,
+ const AUChannelInfo *info,
+ UInt32 numInfo) const
+{
+ bool writable = false;
+ OSStatus result = IsElementCountWritable (inScope, writable);
+ if (result || (writable == false))
+ return false;
+
+ //now chan layout can contain -1 for either scope (ie. doesn't care)
+ for (unsigned int i = 0; i < numInfo; ++i)
+ {
+ // lets test the special wild card case first...
+ // this says the AU can do any num channels on input or output - for eg. Matrix Mixer
+ if (((info[i].inChannels == -1) && (info[i].outChannels == -2))
+ || ((info[i].inChannels == -2) && (info[i].outChannels == -1)))
+ {
+ outTotalNumChannels = -1;
+ return true;
+ }
+
+ // ok lets now test our special case....
+ if (inScope == kAudioUnitScope_Input) {
+ // isn't dynamic on this side at least
+ if (info[i].inChannels >= 0)
+ continue;
+
+ if (info[i].inChannels < -2) {
+ outTotalNumChannels = abs (info[i].inChannels);
+ return true;
+ }
+ }
+
+ else if (inScope == kAudioUnitScope_Output) {
+ // isn't dynamic on this side at least
+ if (info[i].outChannels >= 0)
+ continue;
+
+ if (info[i].outChannels < -2) {
+ outTotalNumChannels = abs (info[i].outChannels);
+ return true;
+ }
+ }
+
+ else {
+ break; // wrong scope was specified
+ }
+ }
+
+ return false;
+}
+
+OSStatus CAAudioUnit::ConfigureDynamicScope (AudioUnitScope inScope,
+ UInt32 inNumElements,
+ UInt32 *inChannelsPerElement,
+ Float64 inSampleRate)
+{
+ SInt32 numChannels = 0;
+ bool isDyamic = HasDynamicScope (inScope, numChannels);
+ if (isDyamic == false)
+ return kAudioUnitErr_InvalidProperty;
+
+ //lets to a sanity check...
+ // if numChannels == -1, then it can do "any"...
+ if (numChannels > 0) {
+ SInt32 count = 0;
+ for (unsigned int i = 0; i < inNumElements; ++i)
+ count += inChannelsPerElement[i];
+ if (count > numChannels)
+ return kAudioUnitErr_InvalidPropertyValue;
+ }
+
+ OSStatus result = SetElementCount (inScope, inNumElements);
+ if (result)
+ return result;
+
+ for (unsigned int i = 0; i < inNumElements; ++i) {
+ CAStreamBasicDescription desc;
+ result = GetFormat (inScope, i, desc);
+ if (result) return result;
+ desc.ChangeNumberChannels (inChannelsPerElement[i], desc.IsInterleaved());
+ desc.mSampleRate = inSampleRate;
+ result = SetFormat (inScope, i, desc);
+ if (result)
+ return result;
+ }
+ return noErr;
+}
+
+#pragma mark __Properties
+
+bool CAAudioUnit::CanBypass () const
+{
+ Boolean outWritable;
+ OSStatus result = AudioUnitGetPropertyInfo (AU(), kAudioUnitProperty_BypassEffect,
+ kAudioUnitScope_Global, 0,
+ NULL, &outWritable);
+ return (!result && outWritable);
+}
+
+bool CAAudioUnit::GetBypass () const
+{
+ UInt32 dataSize = sizeof (UInt32);
+ UInt32 outBypass;
+ OSStatus result = AudioUnitGetProperty (AU(), kAudioUnitProperty_BypassEffect,
+ kAudioUnitScope_Global, 0,
+ &outBypass, &dataSize);
+ return (result ? false : outBypass);
+}
+
+OSStatus CAAudioUnit::SetBypass (bool inBypass) const
+{
+ UInt32 bypass = inBypass ? 1 : 0;
+ return AudioUnitSetProperty (AU(), kAudioUnitProperty_BypassEffect,
+ kAudioUnitScope_Global, 0,
+ &bypass, sizeof (UInt32));
+}
+
+OSStatus CAAudioUnit::GetMaxFramesPerSlice (UInt32& outMaxFrames) const
+{
+ UInt32 dataSize = sizeof(outMaxFrames);
+ return AudioUnitGetProperty (AU(), kAudioUnitProperty_MaximumFramesPerSlice,
+ kAudioUnitScope_Global, 0,
+ &outMaxFrames, &dataSize);
+}
+
+OSStatus CAAudioUnit::SetMaxFramesPerSlice (UInt32 inMaxFrames)
+{
+ return AudioUnitSetProperty (AU(), kAudioUnitProperty_MaximumFramesPerSlice,
+ kAudioUnitScope_Global, 0,
+ &inMaxFrames, sizeof (UInt32));
+}
+
+Float64 CAAudioUnit::Latency () const
+{
+ Float64 secs;
+ UInt32 size = sizeof(secs);
+ if (GetProperty (kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0, &secs, &size))
+ return 0;
+ return secs;
+}
+
+OSStatus CAAudioUnit::GetAUPreset (CFPropertyListRef &outData) const
+{
+ UInt32 dataSize = sizeof(outData);
+ return AudioUnitGetProperty (AU(), kAudioUnitProperty_ClassInfo,
+ kAudioUnitScope_Global, 0,
+ &outData, &dataSize);
+}
+
+OSStatus CAAudioUnit::SetAUPreset (CFPropertyListRef &inData)
+{
+ return AudioUnitSetProperty (AU(), kAudioUnitProperty_ClassInfo,
+ kAudioUnitScope_Global, 0,
+ &inData, sizeof (CFPropertyListRef));
+}
+
+#if !TARGET_OS_IPHONE
+OSStatus CAAudioUnit::SetAUPresetFromDocument (CFPropertyListRef &inData)
+{
+ return AudioUnitSetProperty (AU(), kAudioUnitProperty_ClassInfoFromDocument,
+ kAudioUnitScope_Global, 0,
+ &inData, sizeof (CFPropertyListRef));
+}
+#endif
+
+OSStatus CAAudioUnit::GetPresentPreset (AUPreset &outData) const
+{
+ UInt32 dataSize = sizeof(outData);
+ OSStatus result = AudioUnitGetProperty (AU(), kAudioUnitProperty_PresentPreset,
+ kAudioUnitScope_Global, 0,
+ &outData, &dataSize);
+#if !TARGET_OS_IPHONE
+#ifndef __LP64__
+ if (result == kAudioUnitErr_InvalidProperty) {
+ dataSize = sizeof(outData);
+ result = AudioUnitGetProperty (AU(), kAudioUnitProperty_CurrentPreset,
+ kAudioUnitScope_Global, 0,
+ &outData, &dataSize);
+ if (result == noErr) {
+ // we now retain the CFString in the preset so for the client of this API
+ // it is consistent (ie. the string should be released when done)
+ if (outData.presetName)
+ CFRetain (outData.presetName);
+ }
+ }
+#endif
+#endif
+ return result;
+}
+
+OSStatus CAAudioUnit::SetPresentPreset (AUPreset &inData)
+{
+ OSStatus result = AudioUnitSetProperty (AU(), kAudioUnitProperty_PresentPreset,
+ kAudioUnitScope_Global, 0,
+ &inData, sizeof (AUPreset));
+#if !TARGET_OS_IPHONE
+#ifndef __LP64__
+ if (result == kAudioUnitErr_InvalidProperty) {
+ result = AudioUnitSetProperty (AU(), kAudioUnitProperty_CurrentPreset,
+ kAudioUnitScope_Global, 0,
+ &inData, sizeof (AUPreset));
+ }
+#endif
+#endif
+ return result;
+}
+
+bool CAAudioUnit::HasCustomView () const
+{
+#if !TARGET_OS_IPHONE
+ UInt32 dataSize = 0;
+ OSStatus result = -4/*unimpErr*/;
+#ifndef __LP64__
+ result = GetPropertyInfo(kAudioUnitProperty_GetUIComponentList,
+ kAudioUnitScope_Global, 0,
+ &dataSize, NULL);
+#endif
+ if (result || !dataSize) {
+ dataSize = 0;
+ result = GetPropertyInfo(kAudioUnitProperty_CocoaUI,
+ kAudioUnitScope_Global, 0,
+ &dataSize, NULL);
+ if (result || !dataSize)
+ return false;
+ }
+ return true;
+#else
+ return false;
+#endif
+
+}
+
+OSStatus CAAudioUnit::GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+ Float32 &outValue) const
+{
+ return mDataPtr ? mDataPtr->GetParameter (inID, scope, element, outValue) : static_cast<OSStatus>(paramErr);
+}
+
+OSStatus CAAudioUnit::SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+ Float32 value, UInt32 bufferOffsetFrames)
+{
+ return mDataPtr ? mDataPtr->SetParameter (inID, scope, element, value, bufferOffsetFrames) : static_cast<OSStatus>(paramErr);
+}
+
+OSStatus CAAudioUnit::MIDIEvent (UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame)
+{
+ return mDataPtr ? mDataPtr->MIDIEvent (inStatus, inData1, inData2, inOffsetSampleFrame) : paramErr;
+}
+
+OSStatus CAAudioUnit::StartNote (MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams * inParams)
+{
+ return mDataPtr ? mDataPtr->StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams)
+ : paramErr;
+}
+
+OSStatus CAAudioUnit::StopNote (MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame)
+{
+ return mDataPtr ? mDataPtr->StopNote (inGroupID, inNoteInstanceID, inOffsetSampleFrame) : paramErr;
+}
+
+
+#pragma mark __Render
+
+OSStatus CAAudioUnit::Render (AudioUnitRenderActionFlags * ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inOutputBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList * ioData)
+{
+ return mDataPtr ? mDataPtr->Render (ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData) : static_cast<OSStatus>(paramErr);
+}
+
+extern "C" OSStatus
+AudioUnitProcess ( AudioUnit inUnit,
+ AudioUnitRenderActionFlags * ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inNumberFrames,
+ AudioBufferList * ioData);
+
+OSStatus CAAudioUnit::Process (AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames,
+ AudioBufferList & ioData)
+{
+#if defined(__MAC_10_7) || defined(__IPHONE_4_0)
+ return AudioUnitProcess (AU(), &ioActionFlags, &inTimeStamp, inNumberFrames, &ioData);
+#else
+ return -4/*unimpErr*/;
+#endif
+}
+
+extern "C" OSStatus
+AudioUnitProcessMultiple ( AudioUnit inUnit,
+ AudioUnitRenderActionFlags * ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inNumberFrames,
+ UInt32 inNumberInputBufferLists,
+ const AudioBufferList ** inInputBufferLists,
+ UInt32 inNumberOutputBufferLists,
+ AudioBufferList ** ioOutputBufferLists);
+
+OSStatus CAAudioUnit::ProcessMultiple (AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames,
+ UInt32 inNumberInputBufferLists,
+ const AudioBufferList ** inInputBufferLists,
+ UInt32 inNumberOutputBufferLists,
+ AudioBufferList ** ioOutputBufferLists)
+{
+#if defined(__MAC_10_7) || defined(__IPHONE_4_0)
+ return AudioUnitProcessMultiple (AU(), &ioActionFlags, &inTimeStamp, inNumberFrames,
+ inNumberInputBufferLists, inInputBufferLists, inNumberOutputBufferLists, ioOutputBufferLists);
+#else
+ return -4/*unimpErr*/;
+#endif
+}
+
+#pragma mark __CAAUChanHelper
+
+CAAUChanHelper::CAAUChanHelper(const CAAudioUnit &inAU, AudioUnitScope inScope)
+ :mChans(NULL), mNumEls(0), mDidAllocate(false)
+{
+ UInt32 elCount;
+ if (inAU.GetElementCount (inScope, elCount)) return;
+ if (elCount > kStaticElCount) {
+ mChans = new UInt32[elCount];
+ mDidAllocate = true;
+ memset (mChans, 0, sizeof(int) * elCount);
+ } else {
+ mChans = mStaticChans;
+ memset (mChans, 0, sizeof(int) * kStaticElCount);
+ }
+ for (unsigned int i = 0; i < elCount; ++i) {
+ UInt32 numChans;
+ if (inAU.NumberChannels (inScope, i, numChans)) return;
+ mChans[i] = numChans;
+ }
+ mNumEls = elCount;
+}
+
+CAAUChanHelper::CAAUChanHelper(UInt32 inMaxElems)
+ : mNumEls(inMaxElems), mDidAllocate(false)
+{
+ if (inMaxElems > kStaticElCount) {
+ mChans = new UInt32[inMaxElems];
+ mDidAllocate = true;
+ memset (mChans, 0, sizeof(int) * inMaxElems);
+ } else {
+ mChans = mStaticChans;
+ memset (mChans, 0, sizeof(int) * kStaticElCount);
+ }
+}
+
+CAAUChanHelper::~CAAUChanHelper()
+{
+ if (mDidAllocate) delete [] mChans;
+}
+
+CAAUChanHelper& CAAUChanHelper::operator= (const CAAUChanHelper &c)
+{
+ if (mDidAllocate) delete [] mChans;
+ if (c.mDidAllocate) {
+ mChans = new UInt32[c.mNumEls];
+ mDidAllocate = true;
+ } else {
+ mDidAllocate = false;
+ mChans = mStaticChans;
+ }
+ memcpy (mChans, c.mChans, c.mNumEls * sizeof(int));
+
+ return *this;
+}
+
+
+#pragma mark __Print Utilities
+
+void CAAudioUnit::Print (FILE* file) const
+{
+ fprintf (file, "AudioUnit:%p\n", AU());
+ if (IsValid()) {
+ fprintf (file, "\tnode=%ld\t", (long)GetAUNode()); Comp().Print (file);
+ }
+}
+
+#if CA_AU_USE_FAST_DISPATCH
+// Handle GetComponentInstanceStorage(ComponentInstance aComponentInstance)
+static void *LoadGetComponentInstanceStorage (void *inst)
+{
+ typedef void* (*GetComponentInstanceStorageProc)(void* aComponentInstance);
+ static GetComponentInstanceStorageProc sGetComponentInstanceStorageProc = NULL;
+
+ static int sDoCSLoad = 1;
+ if (sDoCSLoad) {
+ sDoCSLoad = 0;
+ void *theImage = dlopen("/System/Library/Frameworks/CoreServices.framework/CoreServices", RTLD_LAZY);
+ if (!theImage) return NULL;
+
+ sGetComponentInstanceStorageProc = (GetComponentInstanceStorageProc) dlsym(theImage, "GetComponentInstanceStorage");
+ }
+ if (sGetComponentInstanceStorageProc)
+ return (*sGetComponentInstanceStorageProc)(inst);
+ return NULL;
+}
+#endif
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.h
new file mode 100644
index 0000000000..07a522e912
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.h
@@ -0,0 +1,439 @@
+/*
+ File: CAAudioUnit.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAAudioUnit_h__
+#define __CAAudioUnit_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <AudioUnit/AudioUnit.h>
+ #include <AudioToolbox/AUGraph.h>
+ #include <AudioUnit/MusicDevice.h>
+#else
+ #include <ConditionalMacros.h>
+ #include <CoreAudioTypes.h>
+ #include <AudioUnit.h>
+ #include <MusicDevice.h>
+ #include <AUGraph.h>
+ #include <MusicDevice.h>
+#endif
+
+#include <vector>
+#include "CAStreamBasicDescription.h"
+#include "CAComponent.h"
+#include "CAAudioChannelLayout.h"
+
+// defined below
+class CAAUChanHelper;
+
+// These constructors will NOT throw exceptions - so "check" after creation if AU IsValid()
+// The destructor will NOT automatically close the AU down
+// This state should be managed by the Caller
+// once closed, the unit represented by this object is no longer valid
+// it is up to the user of this object to ensure its validity is in sync
+// if it is removed from a graph
+
+// methods that can significantly change the state of the AU (like its format) are
+// NOT const whereas those that don't change the externally related state of the AU are not const
+
+class CAAudioUnit {
+ enum {
+ paramErr = -50,
+ badComponentSelector = (long)0x80008002
+ };
+public:
+ typedef std::vector<AudioChannelLayoutTag> ChannelTagVector;
+ typedef ChannelTagVector::iterator ChannelTagVectorIter;
+
+public:
+ CAAudioUnit ()
+ : mDataPtr(0) {}
+
+ CAAudioUnit (const AudioUnit& inUnit);
+
+ CAAudioUnit (const AUNode &inNode, const AudioUnit& inUnit);
+
+ CAAudioUnit (const CAAudioUnit& y)
+ : mDataPtr(0) { *this = y; }
+
+ static OSStatus Open (const CAComponent& inComp, CAAudioUnit &outUnit);
+
+ ~CAAudioUnit ();
+
+ void Close ();
+
+
+ CAAudioUnit& operator= (const CAAudioUnit& y);
+
+ bool operator== (const CAAudioUnit& y) const;
+
+ bool operator== (const AudioUnit& y) const;
+
+#pragma mark __State Management
+ bool IsValid () const;
+
+ AudioUnit AU() const;
+ operator AudioUnit () const { return AU(); }
+
+ const CAComponent& Comp() const { return mComp; }
+
+ const CAComponentDescription& Desc() const { return mComp.Desc(); }
+
+ bool FromAUGraph () const { return GetAUNode() != 0 && GetAUNode() != kCAAU_DoNotKnowIfAUNode; }
+
+ AUNode GetAUNode () const;
+ operator AUNode () const { return GetAUNode(); }
+
+#pragma mark __API Wrapper
+ OSStatus Initialize() const {
+ return AudioUnitInitialize(AU());
+ }
+ OSStatus Uninitialize() const {
+ return AudioUnitUninitialize(AU());
+ }
+ OSStatus GetPropertyInfo(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element,
+ UInt32 *outDataSize, Boolean *outWritable) const
+ {
+ return AudioUnitGetPropertyInfo(AU(), propID, scope, element, outDataSize, outWritable);
+ }
+ OSStatus GetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element,
+ void *outData, UInt32 *ioDataSize) const
+ {
+ return AudioUnitGetProperty(AU(), propID, scope, element, outData, ioDataSize);
+ }
+ OSStatus SetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element,
+ const void *inData, UInt32 inDataSize)
+ {
+ return AudioUnitSetProperty(AU(), propID, scope, element, inData, inDataSize);
+ }
+ OSStatus SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+ Float32 value, UInt32 bufferOffsetFrames=0);
+
+ OSStatus GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+ Float32 &outValue) const;
+
+ OSStatus Render (AudioUnitRenderActionFlags * ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inOutputBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList * ioData);
+
+ OSStatus Process (AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames,
+ AudioBufferList & ioData);
+
+ OSStatus ProcessMultiple (AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames,
+ UInt32 inNumberInputBufferLists,
+ const AudioBufferList ** inInputBufferLists,
+ UInt32 inNumberOutputBufferLists,
+ AudioBufferList ** ioOutputBufferLists);
+
+
+ OSStatus Reset (AudioUnitScope scope, AudioUnitElement element)
+ {
+ return AudioUnitReset (AU(), scope, element);
+ }
+ OSStatus GlobalReset ()
+ {
+ return AudioUnitReset (AU(), kAudioUnitScope_Global, 0);
+ }
+
+ OSStatus AddRenderNotify (AURenderCallback inProc, void *inProcRefCon)
+ {
+ return AudioUnitAddRenderNotify (AU(), inProc, inProcRefCon);
+ }
+
+ OSStatus RemoveRenderNotify (AURenderCallback inProc, void *inProcRefCon)
+ {
+ return AudioUnitRemoveRenderNotify (AU(), inProc, inProcRefCon);
+ }
+
+ OSStatus AddPropertyListener (AudioUnitPropertyID inID,
+ AudioUnitPropertyListenerProc inProc,
+ void * inProcRefCon)
+ {
+ return AudioUnitAddPropertyListener (AU(), inID, inProc, inProcRefCon);
+ }
+
+ OSStatus RemovePropertyListener (AudioUnitPropertyID inID,
+ AudioUnitPropertyListenerProc inProc,
+ void * inProcUserData);
+
+ OSStatus MIDIEvent (UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame);
+
+ // uses the default VoiceForGroup value - this is the normal case
+ OSStatus StartNote (MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams * inParams)
+ {
+ return StartNote (kMusicNoteEvent_UseGroupInstrument,
+ inGroupID, outNoteInstanceID,
+ inOffsetSampleFrame, inParams);
+ }
+
+ OSStatus StartNote (MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams * inParams);
+
+ OSStatus StopNote (MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame);
+
+#pragma mark __Format Utilities
+ // typically you ask this about an AU
+ // These Questions are asking about Input and Output...
+
+ // These ones just say whether an AU can do a single combination of channels
+ // and is fine if the AU has a single output (and if an input, a single input)
+ bool CanDo (int inChannelsInOut) const
+ {
+ return CanDo (inChannelsInOut, inChannelsInOut);
+ }
+
+ bool CanDo ( int inChannelsIn,
+ int inChannelsOut) const;
+
+ // This version does a more thorough test for ANY AU with ANY ins/outs
+ // you pass in the channel helper (for the current element count on that scope)
+
+ bool CanDo ( const CAAUChanHelper &input,
+ const CAAUChanHelper &output) const;
+
+ bool SupportsNumChannels () const;
+
+ bool HasChannelLayouts (AudioUnitScope inScope,
+ AudioUnitElement inEl) const;
+
+ int GetChannelInfo (AUChannelInfo** chaninfo, UInt32& cnt);
+ OSStatus GetChannelLayoutTags (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ ChannelTagVector &outChannelVector) const;
+
+ bool HasChannelLayout (AudioUnitScope inScope,
+ AudioUnitElement inEl) const;
+
+ OSStatus GetChannelLayout (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ CAAudioChannelLayout &outLayout) const;
+
+ OSStatus SetChannelLayout (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ const CAAudioChannelLayout &inLayout);
+
+ OSStatus SetChannelLayout (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ const AudioChannelLayout &inLayout,
+ UInt32 inSize);
+
+ OSStatus ClearChannelLayout (AudioUnitScope inScope,
+ AudioUnitElement inEl);
+
+ OSStatus GetFormat (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ AudioStreamBasicDescription &outFormat) const;
+ // if an AudioChannelLayout is either required or set, this call can fail
+ // and the SetChannelLayout call should be used to set the format
+ OSStatus SetFormat (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ const AudioStreamBasicDescription &inFormat);
+
+ OSStatus GetSampleRate (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ Float64 &outRate) const;
+ OSStatus SetSampleRate (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ Float64 inRate);
+
+ // this sets the sample rate on all in/out buses of the AU
+ OSStatus SetSampleRate (Float64 inSampleRate);
+
+ OSStatus NumberChannels (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ UInt32 &outChans) const;
+
+ OSStatus GetNumberChannels (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ UInt32 &outChans) const
+ {
+ return NumberChannels (inScope, inEl, outChans);
+ }
+
+ OSStatus SetNumberChannels (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ UInt32 inChans);
+
+ OSStatus IsElementCountWritable (AudioUnitScope inScope, bool &outWritable) const;
+
+ OSStatus GetElementCount (AudioUnitScope inScope, UInt32 &outCount) const;
+
+ OSStatus SetElementCount (AudioUnitScope inScope, UInt32 inCount);
+
+ // value of -1 for outTotalNumChannels indicates no restriction on num channels
+ // for ex. the Matrix Mixer satisfies this (its in/out element count is writable, and can be set to
+ // any number of channels.
+ // outTotalNumChannels is only valid if method returns true...
+ bool HasDynamicInputs (SInt32 &outTotalNumChannels) const
+ {
+ return HasDynamicScope (kAudioUnitScope_Input, outTotalNumChannels);
+ }
+
+ bool HasDynamicOutputs (SInt32 &outTotalNumChannels) const
+ {
+ return HasDynamicScope (kAudioUnitScope_Output, outTotalNumChannels);
+ }
+
+ // here, if the in (or out) elements are dynamic, then you supply the number of elements
+ // you want on in (or out) scope, and the number of channels on each consecutive element
+ OSStatus ConfigureDynamicInput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate)
+ {
+ return ConfigureDynamicScope (kAudioUnitScope_Input, inNumElements, inChannelsPerElement, inSampleRate);
+ }
+
+ OSStatus ConfigureDynamicOutput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate)
+ {
+ return ConfigureDynamicScope (kAudioUnitScope_Output, inNumElements, inChannelsPerElement, inSampleRate);
+ }
+
+ bool CanBypass () const;
+
+ bool GetBypass () const;
+
+ OSStatus SetBypass (bool inBypass) const;
+
+ OSStatus GetMaxFramesPerSlice (UInt32& outMaxFrames) const;
+
+ OSStatus SetMaxFramesPerSlice (UInt32 inMaxFrames);
+
+ Float64 Latency () const;
+
+ // these calls just deal with the global preset state
+ // you could rescope them to deal with presets on the part scope
+ OSStatus GetAUPreset (CFPropertyListRef &outData) const;
+
+ OSStatus SetAUPreset (CFPropertyListRef &inData);
+
+ OSStatus SetAUPresetFromDocument (CFPropertyListRef &inData);
+
+ OSStatus GetPresentPreset (AUPreset &outData) const;
+
+ OSStatus SetPresentPreset (AUPreset &inData);
+
+ bool HasCustomView () const;
+
+#pragma mark __Print
+ void Print () const { Print (stdout); }
+ void Print (FILE* file) const;
+
+private:
+ CAComponent mComp;
+
+ class AUState;
+ AUState* mDataPtr;
+
+ // this can throw - so wrap this up in a static that returns a result code...
+ CAAudioUnit (const CAComponent& inComp);
+
+ bool HasDynamicScope (AudioUnitScope inScope, SInt32 &outTotalNumChannels) const;
+ OSStatus ConfigureDynamicScope (AudioUnitScope inScope,
+ UInt32 inNumElements,
+ UInt32 *inChannelsPerElement,
+ Float64 inSampleRate);
+ bool ValidateChannelPair (int inChannelsIn,
+ int inChannelsOut,
+ const AUChannelInfo * info,
+ UInt32 numChanInfo) const;
+
+ bool ValidateDynamicScope (AudioUnitScope inScope,
+ SInt32 &outTotalNumChannels,
+ const AUChannelInfo * info,
+ UInt32 numInfo) const;
+ bool CheckOneSide (const CAAUChanHelper &inHelper,
+ bool checkOutput,
+ const AUChannelInfo *info,
+ UInt32 numInfo) const;
+ enum {
+ kCAAU_DoNotKnowIfAUNode = -1
+ };
+};
+
+class CAAUChanHelper {
+public:
+ CAAUChanHelper()
+ : mChans(mStaticChans), mNumEls(0), mDidAllocate(false)
+ {
+ memset (mChans, 0, sizeof(UInt32) * kStaticElCount);
+ }
+ CAAUChanHelper(UInt32 inMaxElems);
+ CAAUChanHelper(const CAAudioUnit &inAU, AudioUnitScope inScope);
+ CAAUChanHelper (const CAAUChanHelper &c)
+ : mChans(mStaticChans), mNumEls(0), mDidAllocate(false)
+ { *this = c; }
+
+ ~CAAUChanHelper();
+
+ CAAUChanHelper& operator= (const CAAUChanHelper &c);
+
+ UInt32 * mChans;
+ UInt32 mNumEls;
+
+private:
+ enum {
+ kStaticElCount = 8
+ };
+ UInt32 mStaticChans[kStaticElCount];
+ bool mDidAllocate;
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnitOutputCapturer.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnitOutputCapturer.h
new file mode 100644
index 0000000000..42bebfacc3
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioUnitOutputCapturer.h
@@ -0,0 +1,143 @@
+/*
+ File: CAAudioUnitOutputCapturer.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAAudioUnitOutputCapturer_h__
+#define __CAAudioUnitOutputCapturer_h__
+
+#include <AudioToolbox/ExtendedAudioFile.h>
+
+/*
+ Class to capture output from an AudioUnit for analysis.
+
+ example:
+
+ CFURL fileurl = CFURLCreateWithFileSystemPath(NULL, CFSTR("/tmp/recording.caf"), kCFURLPOSIXPathStyle, false);
+
+ CAAudioUnitOutputCapturer captor(someAU, fileurl, 'caff', anASBD);
+
+ {
+ captor.Start();
+ ...
+ captor.Stop();
+ } // can repeat
+
+ captor.Close(); // can be omitted; happens automatically from destructor
+*/
+
+class CAAudioUnitOutputCapturer {
+public:
+ enum { noErr = 0 };
+
+ CAAudioUnitOutputCapturer(AudioUnit au, CFURLRef outputFileURL, AudioFileTypeID fileType, const AudioStreamBasicDescription &format, UInt32 busNumber = 0) :
+ mFileOpen(false),
+ mClientFormatSet(false),
+ mAudioUnit(au),
+ mExtAudioFile(NULL),
+ mBusNumber (busNumber)
+ {
+ CFShow(outputFileURL);
+ OSStatus err = ExtAudioFileCreateWithURL(outputFileURL, fileType, &format, NULL, kAudioFileFlags_EraseFile, &mExtAudioFile);
+ if (!err)
+ mFileOpen = true;
+ }
+
+ void Start() {
+ if (mFileOpen) {
+ if (!mClientFormatSet) {
+ AudioStreamBasicDescription clientFormat;
+ UInt32 size = sizeof(clientFormat);
+ AudioUnitGetProperty(mAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, mBusNumber, &clientFormat, &size);
+ ExtAudioFileSetProperty(mExtAudioFile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat);
+ mClientFormatSet = true;
+ }
+ ExtAudioFileWriteAsync(mExtAudioFile, 0, NULL); // initialize async writes
+ AudioUnitAddRenderNotify(mAudioUnit, RenderCallback, this);
+ }
+ }
+
+ void Stop() {
+ if (mFileOpen)
+ AudioUnitRemoveRenderNotify(mAudioUnit, RenderCallback, this);
+ }
+
+ void Close() {
+ if (mExtAudioFile) {
+ ExtAudioFileDispose(mExtAudioFile);
+ mExtAudioFile = NULL;
+ }
+ }
+
+ ~CAAudioUnitOutputCapturer() {
+ Close();
+ }
+
+private:
+ static OSStatus RenderCallback( void * inRefCon,
+ AudioUnitRenderActionFlags * ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList * ioData)
+ {
+ if (*ioActionFlags & kAudioUnitRenderAction_PostRender) {
+ CAAudioUnitOutputCapturer *This = (CAAudioUnitOutputCapturer *)inRefCon;
+ static int TEMP_kAudioUnitRenderAction_PostRenderError = (1 << 8);
+ if (This->mBusNumber == inBusNumber && !(*ioActionFlags & TEMP_kAudioUnitRenderAction_PostRenderError)) {
+ OSStatus result = ExtAudioFileWriteAsync(This->mExtAudioFile, inNumberFrames, ioData);
+ if (result) DebugMessageN1("ERROR WRITING FRAMES: %d\n", (int)result);
+ }
+ }
+ return noErr;
+ }
+
+ bool mFileOpen;
+ bool mClientFormatSet;
+ AudioUnit mAudioUnit;
+ ExtAudioFileRef mExtAudioFile;
+ UInt32 mBusNumber;
+};
+
+#endif // __CAAudioUnitOutputCapturer_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.cpp
new file mode 100644
index 0000000000..203e437af6
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.cpp
@@ -0,0 +1,262 @@
+/*
+ File: CAAudioValueRange.cpp
+ Abstract: CAAudioValueRange.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CAAudioValueRange.h"
+
+// Standard Library
+#include <algorithm>
+
+//==================================================================================================
+// CAAudioValueRange
+//==================================================================================================
+
+Float64 CAAudioValueRange::BoundValue(const AudioValueRange& inRange, Float64 inValue)
+{
+ if (inValue <= inRange.mMinimum)
+ {
+ return inRange.mMinimum;
+ }
+ else if (inValue >= inRange.mMaximum)
+ {
+ return inRange.mMaximum;
+ }
+ else
+ {
+ return inValue;
+ }
+}
+
+Float64 CAAudioValueRange::PickCommonSampleRate(const AudioValueRange& inRange)
+{
+ // This routine will pick a "common" sample rate from the give range of rates or the maximum
+ // if no common rates can be found. It assumes that inRange contains a continuous range of
+ // sample rates.
+ Float64 theAnswer = inRange.mMaximum;
+
+ if(ContainsValue(inRange, 44100.0))
+ {
+ theAnswer = 44100.0;
+ }
+ else if(ContainsValue(inRange, 48000.0))
+ {
+ theAnswer = 48000.0;
+ }
+ else if(ContainsValue(inRange, 96000.0))
+ {
+ theAnswer = 96000.0;
+ }
+ else if(ContainsValue(inRange, 88200.0))
+ {
+ theAnswer = 88200.0;
+ }
+ else if(ContainsValue(inRange, 64000.0))
+ {
+ theAnswer = 64000.0;
+ }
+ else if(ContainsValue(inRange, 32000.0))
+ {
+ theAnswer = 32000.0;
+ }
+ else if(ContainsValue(inRange, 24000.0))
+ {
+ theAnswer = 24000.0;
+ }
+ else if(ContainsValue(inRange, 22050.0))
+ {
+ theAnswer = 22050.0;
+ }
+ else if(ContainsValue(inRange, 16000.0))
+ {
+ theAnswer = 16000.0;
+ }
+ else if(ContainsValue(inRange, 12000.0))
+ {
+ theAnswer = 12000.0;
+ }
+ else if(ContainsValue(inRange, 11025.0))
+ {
+ theAnswer = 11025.0;
+ }
+ else if(ContainsValue(inRange, 8000.0))
+ {
+ theAnswer = 8000.0;
+ }
+
+ return theAnswer;
+}
+
+bool CAAudioValueRange::Intersection(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange)
+{
+ bool isNonEmpty;
+ if(!IsStrictlyLessThan(x, y) && !IsStrictlyGreaterThan(x, y))
+ {
+ outRange.mMinimum = std::max(x.mMinimum, y.mMinimum);
+ outRange.mMaximum = std::min(x.mMaximum, y.mMaximum);
+ isNonEmpty = true;
+ }
+ else
+ {
+ outRange.mMinimum = 0;
+ outRange.mMaximum = 0;
+ isNonEmpty = false;
+ }
+ return isNonEmpty;
+}
+
+bool CAAudioValueRange::Union(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange)
+{
+ bool isDisjoint;
+ if(!IsStrictlyLessThan(x, y) && !IsStrictlyGreaterThan(x, y))
+ {
+ outRange.mMinimum = std::min(x.mMinimum, y.mMinimum);
+ outRange.mMaximum = std::max(x.mMaximum, y.mMaximum);
+ isDisjoint = false;
+ }
+ else
+ {
+ outRange.mMinimum = 0;
+ outRange.mMaximum = 0;
+ isDisjoint = true;
+ }
+ return isDisjoint;
+}
+
+void CAAudioValueRange_ComputeUnion(const AudioValueRange& inRange, const CAAudioValueRangeList& inRangeList, CAAudioValueRangeList& outUnion)
+{
+ // this method assumes that the ranges in inRangeList are disjoint and that they are sorted from low to high and
+ outUnion.clear();
+
+ // start at the beginning of inRangeList
+ CAAudioValueRangeList::const_iterator theIterator = inRangeList.begin();
+
+ // iterate through inRangeList and add all the ranges that are strictly less than inRange
+ while((theIterator != inRangeList.end()) && CAAudioValueRange::IsStrictlyLessThan(*theIterator, inRange))
+ {
+ // put this range in the union
+ outUnion.push_back(*theIterator);
+
+ // go to the next one
+ std::advance(theIterator, 1);
+ }
+
+ if(theIterator != inRangeList.end())
+ {
+ if(!CAAudioValueRange::IsStrictlyGreaterThan(*theIterator, inRange))
+ {
+ // inRange intersects the range that theIterator points at, but might actually intersect several contiguous ranges
+
+ // initialize the starting point, noting that we can skip the current one since we already know it's in the intersection
+ CAAudioValueRangeList::const_iterator theGreaterIterator = theIterator;
+ std::advance(theGreaterIterator, 1);
+
+ // iterate until we find a range that is strictly greater than inRange
+ while((theGreaterIterator != inRangeList.end()) && !CAAudioValueRange::IsStrictlyGreaterThan(*theGreaterIterator, inRange))
+ {
+ // go to the next one
+ std::advance(theGreaterIterator, 1);
+ }
+
+ // theGreaterIterator now points at either one past the highest range in the intersection or the end of the vector
+ // Either way, we have to adjust it to point at the true highest range in the intersection
+ std::advance(theGreaterIterator, -1);
+
+ // now theIterator points at the lowest range in the intersection and theGreaterIterator points at the highest
+ // so we can compute the coagulated range
+ AudioValueRange theCoagulation;
+ theCoagulation.mMinimum = std::min(theIterator->mMinimum, inRange.mMinimum);
+ theCoagulation.mMaximum = std::max(theGreaterIterator->mMaximum, inRange.mMaximum);
+
+ // add the coagulation to the union
+ outUnion.push_back(theCoagulation);
+
+ // adjust theIterator to point at the next range for processing
+ theIterator = theGreaterIterator;
+ std::advance(theIterator, 1);
+ }
+ else
+ {
+ // the range theIterator points at is strictly greater than inRange, so insert inRange in front of it and we're done
+ outUnion.push_back(inRange);
+ }
+
+ // we need to now copy the remaining higher ranges in inRangeList into the union
+ while(theIterator != inRangeList.end())
+ {
+ // put this range in the union
+ outUnion.push_back(*theIterator);
+
+ // go to the next one
+ std::advance(theIterator, 1);
+ }
+ }
+ else
+ {
+ // inRange is larger than all of the ranges in inRangeList, so just add it onto the end of the union and we're done
+ // This is also the case if inRangeList is empty
+ outUnion.push_back(inRange);
+ }
+}
+
+void CAAudioValueRange_ComputeIntersection(UInt32 inNumberRangeList1Items, AudioValueRange inRangeList1[], const CAAudioValueRangeList& inRangeList2, CAAudioValueRangeList& outIntersections)
+{
+ outIntersections.clear();
+ for(UInt32 theRangeList1Index = 0; theRangeList1Index < inNumberRangeList1Items; ++theRangeList1Index)
+ {
+ for(CAAudioValueRangeList::const_iterator theRangeList2Iterator = inRangeList2.begin(); theRangeList2Iterator != inRangeList2.end(); std::advance(theRangeList2Iterator, 1))
+ {
+ AudioValueRange theIntersection;
+ if(CAAudioValueRange::Intersection(inRangeList1[theRangeList1Index], *theRangeList2Iterator, theIntersection))
+ {
+ outIntersections.push_back(theIntersection);
+ }
+ }
+ }
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.h b/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.h
new file mode 100644
index 0000000000..e17c4574bc
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.h
@@ -0,0 +1,121 @@
+/*
+ File: CAAudioValueRange.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAAudioValueRange_h__)
+#define __CAAudioValueRange_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+// Standard Library Includes
+#include <functional>
+#include <vector>
+
+//=============================================================================
+// CAAudioValueRange
+//=============================================================================
+
+struct CAAudioValueRange
+:
+ public AudioValueRange
+{
+
+// Construction/Destruction
+public:
+ CAAudioValueRange() { mMinimum = 0.0; mMaximum = 0.0; }
+ CAAudioValueRange(const AudioValueRange& v) { mMinimum = v.mMinimum; mMaximum = v.mMaximum; }
+ CAAudioValueRange(Float64 inMinimum, Float64 inMaximum) { mMinimum = inMinimum; mMaximum = inMaximum; }
+
+// Assignment
+public:
+ CAAudioValueRange& operator=(const AudioValueRange& v) { mMinimum = v.mMinimum; mMaximum = v.mMaximum; return *this; }
+
+// Operations
+public:
+ static bool ContainsValue(const AudioValueRange& inRange, Float64 inValue) { return (inValue >= inRange.mMinimum) && (inValue <= inRange.mMaximum); }
+ static Float64 BoundValue(const AudioValueRange& inRange, Float64 inValue);
+ static Float64 PickCommonSampleRate(const AudioValueRange& inRange);
+ static bool IsStrictlyLessThan(const AudioValueRange& x, const AudioValueRange& y) { return x.mMaximum < y.mMinimum; }
+ static bool IsStrictlyGreaterThan(const AudioValueRange& x, const AudioValueRange& y) { return x.mMinimum > y.mMaximum; }
+ static bool IsStrictlyContainedBy(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum >= y.mMinimum) && (x.mMaximum <= y.mMaximum); }
+ static bool OverlapsLow(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum < y.mMinimum) && (x.mMaximum >= y.mMinimum) && (x.mMaximum <= y.mMaximum); }
+ static bool OverlapsHigh(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum >= y.mMinimum) && (x.mMinimum <= y.mMaximum) && (x.mMaximum > y.mMaximum); }
+ static bool Intersection(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange);
+ static bool Union(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange);
+
+// STL Helpers
+public:
+ struct LessThan
+ :
+ public std::binary_function<AudioValueRange, AudioValueRange, bool>
+ {
+ bool operator()(const AudioValueRange& x, const AudioValueRange& y) const
+ {
+ return x.mMinimum < y.mMinimum;
+ }
+ };
+
+};
+
+inline bool operator<(const AudioValueRange& x, const AudioValueRange& y) { return x.mMinimum < y.mMinimum; }
+inline bool operator==(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum == y.mMinimum) && (x.mMaximum == y.mMaximum); }
+inline bool operator!=(const AudioValueRange& x, const AudioValueRange& y) { return !(x == y); }
+inline bool operator<=(const AudioValueRange& x, const AudioValueRange& y) { return (x < y) || (x == y); }
+inline bool operator>=(const AudioValueRange& x, const AudioValueRange& y) { return !(x < y); }
+inline bool operator>(const AudioValueRange& x, const AudioValueRange& y) { return !((x < y) || (x == y)); }
+
+typedef std::vector<CAAudioValueRange> CAAudioValueRangeList;
+void CAAudioValueRange_ComputeUnion(const AudioValueRange& inRange, const CAAudioValueRangeList& inRangeList, CAAudioValueRangeList& outUnion);
+void CAAudioValueRange_ComputeIntersection(UInt32 inNumberRangeList1Items, AudioValueRange inRangeList1[], const CAAudioValueRangeList& inRangeList2, CAAudioValueRangeList& outIntersections);
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAAutoDisposer.h b/libs/appleutility/CoreAudio/PublicUtility/CAAutoDisposer.h
new file mode 100644
index 0000000000..2da241506c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAAutoDisposer.h
@@ -0,0 +1,508 @@
+/*
+ File: CAAutoDisposer.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAPtr_h__)
+#define __CAPtr_h__
+
+#include <stdlib.h> // for malloc
+#include <new> // for bad_alloc
+#include <string.h> // for memset
+
+inline void* CA_malloc(size_t size)
+{
+ void* p = malloc(size);
+ if (!p && size) throw std::bad_alloc();
+ return p;
+}
+
+inline void* CA_realloc(void* old, size_t size)
+{
+#if TARGET_OS_WIN32
+ void* p = realloc(old, size);
+#else
+ void* p = reallocf(old, size); // reallocf ensures the old pointer is freed if memory is full (p is NULL).
+#endif
+ if (!p && size) throw std::bad_alloc();
+ return p;
+}
+
+#ifndef UINTPTR_MAX
+#if __LP64__
+#define UINTPTR_MAX 18446744073709551615ULL
+#else
+#define UINTPTR_MAX 4294967295U
+#endif
+#endif
+
+inline void* CA_calloc(size_t n, size_t size)
+{
+ // ensure that multiplication will not overflow
+ if (n && UINTPTR_MAX / n < size) throw std::bad_alloc();
+
+ size_t nsize = n*size;
+ void* p = malloc(nsize);
+ if (!p && nsize) throw std::bad_alloc();
+
+ memset(p, 0, nsize);
+ return p;
+}
+
+
+// helper class for automatic conversions
+template <typename T>
+struct CAPtrRef
+{
+ T* ptr_;
+
+ explicit CAPtrRef(T* ptr) : ptr_(ptr) {}
+};
+
+template <typename T>
+class CAAutoFree
+{
+private:
+ T* ptr_;
+
+public:
+
+ CAAutoFree() : ptr_(0) {}
+
+ explicit CAAutoFree(T* ptr) : ptr_(ptr) {}
+
+ template<typename U>
+ CAAutoFree(CAAutoFree<U>& that) : ptr_(that.release()) {} // take ownership
+
+ // C++ std says: a template constructor is never a copy constructor
+ CAAutoFree(CAAutoFree<T>& that) : ptr_(that.release()) {} // take ownership
+
+ CAAutoFree(size_t n, bool clear = false)
+ // this becomes an ambiguous call if n == 0
+ : ptr_(0)
+ {
+ size_t maxItems = ~size_t(0) / sizeof(T);
+ if (n > maxItems)
+ throw std::bad_alloc();
+
+ ptr_ = static_cast<T*>(clear ? CA_calloc(n, sizeof(T)) : CA_malloc(n * sizeof(T)));
+ }
+
+ ~CAAutoFree() { free(); }
+
+ void alloc(size_t numItems, bool clear = false)
+ {
+ size_t maxItems = ~size_t(0) / sizeof(T);
+ if (numItems > maxItems) throw std::bad_alloc();
+
+ free();
+ ptr_ = static_cast<T*>(clear ? CA_calloc(numItems, sizeof(T)) : CA_malloc(numItems * sizeof(T)));
+ }
+
+ void allocBytes(size_t numBytes, bool clear = false)
+ {
+ free();
+ ptr_ = static_cast<T*>(clear ? CA_calloc(1, numBytes) : CA_malloc(numBytes));
+ }
+
+ void reallocBytes(size_t numBytes)
+ {
+ ptr_ = static_cast<T*>(CA_realloc(ptr_, numBytes));
+ }
+
+ void reallocItems(size_t numItems)
+ {
+ size_t maxItems = ~size_t(0) / sizeof(T);
+ if (numItems > maxItems) throw std::bad_alloc();
+
+ ptr_ = static_cast<T*>(CA_realloc(ptr_, numItems * sizeof(T)));
+ }
+
+ template <typename U>
+ CAAutoFree& operator=(CAAutoFree<U>& that)
+ {
+ set(that.release()); // take ownership
+ return *this;
+ }
+
+ CAAutoFree& operator=(CAAutoFree& that)
+ {
+ set(that.release()); // take ownership
+ return *this;
+ }
+
+ CAAutoFree& operator=(T* ptr)
+ {
+ set(ptr);
+ return *this;
+ }
+
+ template <typename U>
+ CAAutoFree& operator=(U* ptr)
+ {
+ set(ptr);
+ return *this;
+ }
+
+ T& operator*() const { return *ptr_; }
+ T* operator->() const { return ptr_; }
+
+ T* operator()() const { return ptr_; }
+ T* get() const { return ptr_; }
+ operator T*() const { return ptr_; }
+
+ bool operator==(CAAutoFree const& that) const { return ptr_ == that.ptr_; }
+ bool operator!=(CAAutoFree const& that) const { return ptr_ != that.ptr_; }
+ bool operator==(T* ptr) const { return ptr_ == ptr; }
+ bool operator!=(T* ptr) const { return ptr_ != ptr; }
+
+ T* release()
+ {
+ // release ownership
+ T* result = ptr_;
+ ptr_ = 0;
+ return result;
+ }
+
+ void set(T* ptr)
+ {
+ if (ptr != ptr_)
+ {
+ ::free(ptr_);
+ ptr_ = ptr;
+ }
+ }
+
+ void free()
+ {
+ set(0);
+ }
+
+
+ // automatic conversions to allow assignment from results of functions.
+ // hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
+ CAAutoFree(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }
+
+ CAAutoFree& operator=(CAPtrRef<T> ref)
+ {
+ set(ref.ptr_);
+ return *this;
+ }
+
+ template<typename U>
+ operator CAPtrRef<U>()
+ { return CAPtrRef<U>(release()); }
+
+ template<typename U>
+ operator CAAutoFree<U>()
+ { return CAAutoFree<U>(release()); }
+
+};
+
+
+template <typename T>
+class CAAutoDelete
+{
+private:
+ T* ptr_;
+
+public:
+ CAAutoDelete() : ptr_(0) {}
+
+ explicit CAAutoDelete(T* ptr) : ptr_(ptr) {}
+
+ template<typename U>
+ CAAutoDelete(CAAutoDelete<U>& that) : ptr_(that.release()) {} // take ownership
+
+ // C++ std says: a template constructor is never a copy constructor
+ CAAutoDelete(CAAutoDelete<T>& that) : ptr_(that.release()) {} // take ownership
+
+ ~CAAutoDelete() { free(); }
+
+ template <typename U>
+ CAAutoDelete& operator=(CAAutoDelete<U>& that)
+ {
+ set(that.release()); // take ownership
+ return *this;
+ }
+
+ CAAutoDelete& operator=(CAAutoDelete& that)
+ {
+ set(that.release()); // take ownership
+ return *this;
+ }
+
+ CAAutoDelete& operator=(T* ptr)
+ {
+ set(ptr);
+ return *this;
+ }
+
+ template <typename U>
+ CAAutoDelete& operator=(U* ptr)
+ {
+ set(ptr);
+ return *this;
+ }
+
+ T& operator*() const { return *ptr_; }
+ T* operator->() const { return ptr_; }
+
+ T* operator()() const { return ptr_; }
+ T* get() const { return ptr_; }
+ operator T*() const { return ptr_; }
+
+ bool operator==(CAAutoDelete const& that) const { return ptr_ == that.ptr_; }
+ bool operator!=(CAAutoDelete const& that) const { return ptr_ != that.ptr_; }
+ bool operator==(T* ptr) const { return ptr_ == ptr; }
+ bool operator!=(T* ptr) const { return ptr_ != ptr; }
+
+ T* release()
+ {
+ // release ownership
+ T* result = ptr_;
+ ptr_ = 0;
+ return result;
+ }
+
+ void set(T* ptr)
+ {
+ if (ptr != ptr_)
+ {
+ delete ptr_;
+ ptr_ = ptr;
+ }
+ }
+
+ void free()
+ {
+ set(0);
+ }
+
+
+ // automatic conversions to allow assignment from results of functions.
+ // hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
+ CAAutoDelete(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }
+
+ CAAutoDelete& operator=(CAPtrRef<T> ref)
+ {
+ set(ref.ptr_);
+ return *this;
+ }
+
+ template<typename U>
+ operator CAPtrRef<U>()
+ { return CAPtrRef<U>(release()); }
+
+ template<typename U>
+ operator CAAutoFree<U>()
+ { return CAAutoFree<U>(release()); }
+
+};
+
+
+template <typename T>
+class CAAutoArrayDelete
+{
+private:
+ T* ptr_;
+
+public:
+ CAAutoArrayDelete() : ptr_(0) {}
+
+ explicit CAAutoArrayDelete(T* ptr) : ptr_(ptr) {}
+
+ template<typename U>
+ CAAutoArrayDelete(CAAutoArrayDelete<U>& that) : ptr_(that.release()) {} // take ownership
+
+ // C++ std says: a template constructor is never a copy constructor
+ CAAutoArrayDelete(CAAutoArrayDelete<T>& that) : ptr_(that.release()) {} // take ownership
+
+ // this becomes an ambiguous call if n == 0
+ CAAutoArrayDelete(size_t n) : ptr_(new T[n]) {}
+
+ ~CAAutoArrayDelete() { free(); }
+
+ void alloc(size_t numItems)
+ {
+ free();
+ ptr_ = new T [numItems];
+ }
+
+ template <typename U>
+ CAAutoArrayDelete& operator=(CAAutoArrayDelete<U>& that)
+ {
+ set(that.release()); // take ownership
+ return *this;
+ }
+
+ CAAutoArrayDelete& operator=(CAAutoArrayDelete& that)
+ {
+ set(that.release()); // take ownership
+ return *this;
+ }
+
+ CAAutoArrayDelete& operator=(T* ptr)
+ {
+ set(ptr);
+ return *this;
+ }
+
+ template <typename U>
+ CAAutoArrayDelete& operator=(U* ptr)
+ {
+ set(ptr);
+ return *this;
+ }
+
+ T& operator*() const { return *ptr_; }
+ T* operator->() const { return ptr_; }
+
+ T* operator()() const { return ptr_; }
+ T* get() const { return ptr_; }
+ operator T*() const { return ptr_; }
+
+ bool operator==(CAAutoArrayDelete const& that) const { return ptr_ == that.ptr_; }
+ bool operator!=(CAAutoArrayDelete const& that) const { return ptr_ != that.ptr_; }
+ bool operator==(T* ptr) const { return ptr_ == ptr; }
+ bool operator!=(T* ptr) const { return ptr_ != ptr; }
+
+ T* release()
+ {
+ // release ownership
+ T* result = ptr_;
+ ptr_ = 0;
+ return result;
+ }
+
+ void set(T* ptr)
+ {
+ if (ptr != ptr_)
+ {
+ delete [] ptr_;
+ ptr_ = ptr;
+ }
+ }
+
+ void free()
+ {
+ set(0);
+ }
+
+
+ // automatic conversions to allow assignment from results of functions.
+ // hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
+ CAAutoArrayDelete(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }
+
+ CAAutoArrayDelete& operator=(CAPtrRef<T> ref)
+ {
+ set(ref.ptr_);
+ return *this;
+ }
+
+ template<typename U>
+ operator CAPtrRef<U>()
+ { return CAPtrRef<U>(release()); }
+
+ template<typename U>
+ operator CAAutoArrayDelete<U>()
+ { return CAAutoFree<U>(release()); }
+
+};
+
+
+
+
+
+// convenience function
+template <typename T>
+void free(CAAutoFree<T>& p)
+{
+ p.free();
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#if 0
+// example program showing ownership transfer
+
+CAAutoFree<char> source()
+{
+ // source allocates and returns ownership to the caller.
+ const char* str = "this is a test";
+ size_t size = strlen(str) + 1;
+ CAAutoFree<char> captr(size, false);
+ strlcpy(captr(), str, size);
+ printf("source %08X %08X '%s'\n", &captr, captr(), captr());
+ return captr;
+}
+
+void user(CAAutoFree<char> const& captr)
+{
+ // passed by const reference. user can access the pointer but does not take ownership.
+ printf("user: %08X %08X '%s'\n", &captr, captr(), captr());
+}
+
+void sink(CAAutoFree<char> captr)
+{
+ // passed by value. sink takes ownership and frees the pointer on return.
+ printf("sink: %08X %08X '%s'\n", &captr, captr(), captr());
+}
+
+
+int main (int argc, char * const argv[])
+{
+
+ CAAutoFree<char> captr(source());
+ printf("main captr A %08X %08X\n", &captr, captr());
+ user(captr);
+ sink(captr);
+ printf("main captr B %08X %08X\n", &captr, captr());
+ return 0;
+}
+#endif
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABitOperations.h b/libs/appleutility/CoreAudio/PublicUtility/CABitOperations.h
new file mode 100644
index 0000000000..21cb516a60
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CABitOperations.h
@@ -0,0 +1,206 @@
+/*
+ File: CABitOperations.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef _CABitOperations_h_
+#define _CABitOperations_h_
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ //#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
+ #include <CoreFoundation/CFBase.h>
+#else
+// #include <MacTypes.h>
+ #include "CFBase.h"
+#endif
+#include <TargetConditionals.h>
+
+// return whether a number is a power of two
+inline UInt32 IsPowerOfTwo(UInt32 x)
+{
+ return (x & (x-1)) == 0;
+}
+
+// count the leading zeros in a word
+// Metrowerks Codewarrior. powerpc native count leading zeros instruction:
+// I think it's safe to remove this ...
+//#define CountLeadingZeroes(x) ((int)__cntlzw((unsigned int)x))
+
+inline UInt32 CountLeadingZeroes(UInt32 arg)
+{
+// GNUC / LLVM have a builtin
+#if defined(__GNUC__) || defined(__llvm___)
+#if (TARGET_CPU_X86 || TARGET_CPU_X86_64)
+ if (arg == 0) return 32;
+#endif // TARGET_CPU_X86 || TARGET_CPU_X86_64
+ return __builtin_clz(arg);
+#elif TARGET_OS_WIN32
+ UInt32 tmp;
+ __asm{
+ bsr eax, arg
+ mov ecx, 63
+ cmovz eax, ecx
+ xor eax, 31
+ mov tmp, eax // this moves the result in tmp to return.
+ }
+ return tmp;
+#else
+#error "Unsupported architecture"
+#endif // defined(__GNUC__)
+}
+// Alias (with different spelling)
+#define CountLeadingZeros CountLeadingZeroes
+
+inline UInt32 CountLeadingZeroesLong(UInt64 arg)
+{
+// GNUC / LLVM have a builtin
+#if defined(__GNUC__) || defined(__llvm___)
+#if (TARGET_CPU_X86 || TARGET_CPU_X86_64)
+ if (arg == 0) return 64;
+#endif // TARGET_CPU_X86 || TARGET_CPU_X86_64
+ return __builtin_clzll(arg);
+#elif TARGET_OS_WIN32
+ UInt32 x = CountLeadingZeroes((UInt32)(arg >> 32));
+ if(x < 32)
+ return x;
+ else
+ return 32+CountLeadingZeroes((UInt32)arg);
+#else
+#error "Unsupported architecture"
+#endif // defined(__GNUC__)
+}
+#define CountLeadingZerosLong CountLeadingZeroesLong
+
+// count trailing zeroes
+inline UInt32 CountTrailingZeroes(UInt32 x)
+{
+ return 32 - CountLeadingZeroes(~x & (x-1));
+}
+
+// count leading ones
+inline UInt32 CountLeadingOnes(UInt32 x)
+{
+ return CountLeadingZeroes(~x);
+}
+
+// count trailing ones
+inline UInt32 CountTrailingOnes(UInt32 x)
+{
+ return 32 - CountLeadingZeroes(x & (~x-1));
+}
+
+// number of bits required to represent x.
+inline UInt32 NumBits(UInt32 x)
+{
+ return 32 - CountLeadingZeroes(x);
+}
+
+// base 2 log of next power of two greater or equal to x
+inline UInt32 Log2Ceil(UInt32 x)
+{
+ return 32 - CountLeadingZeroes(x - 1);
+}
+
+// base 2 log of next power of two less or equal to x
+inline UInt32 Log2Floor(UInt32 x)
+{
+ return 32 - CountLeadingZeroes(x) - 1;
+}
+
+// next power of two greater or equal to x
+inline UInt32 NextPowerOfTwo(UInt32 x)
+{
+ return 1 << Log2Ceil(x);
+}
+
+// counting the one bits in a word
+inline UInt32 CountOnes(UInt32 x)
+{
+ // secret magic algorithm for counting bits in a word.
+ x = x - ((x >> 1) & 0x55555555);
+ x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+ return (((x + (x >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
+}
+
+// counting the zero bits in a word
+inline UInt32 CountZeroes(UInt32 x)
+{
+ return CountOnes(~x);
+}
+
+// return the bit position (0..31) of the least significant bit
+inline UInt32 LSBitPos(UInt32 x)
+{
+ return CountTrailingZeroes(x & -(SInt32)x);
+}
+
+// isolate the least significant bit
+inline UInt32 LSBit(UInt32 x)
+{
+ return x & -(SInt32)x;
+}
+
+// return the bit position (0..31) of the most significant bit
+inline UInt32 MSBitPos(UInt32 x)
+{
+ return 31 - CountLeadingZeroes(x);
+}
+
+// isolate the most significant bit
+inline UInt32 MSBit(UInt32 x)
+{
+ return 1 << MSBitPos(x);
+}
+
+// Division optimized for power of 2 denominators
+inline UInt32 DivInt(UInt32 numerator, UInt32 denominator)
+{
+ if(IsPowerOfTwo(denominator))
+ return numerator >> (31 - CountLeadingZeroes(denominator));
+ else
+ return numerator/denominator;
+}
+
+#endif
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABool.h b/libs/appleutility/CoreAudio/PublicUtility/CABool.h
new file mode 100644
index 0000000000..719fd74bb2
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CABool.h
@@ -0,0 +1,89 @@
+/*
+ File: CABool.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CABool_h__)
+#define __CABool_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#include "CADebugMacros.h"
+#include "CAException.h"
+
+//=============================================================================
+// CABool
+//
+// This class implements a boolean value that has a third state that marks
+// it as uninitialized. Accessing the value of an instance of this class that
+// is uninitialized will throw an exception.
+//=============================================================================
+
+class CABool
+{
+
+// Construction/Destruction
+public:
+ CABool() : mValue(-1) {}
+ CABool(bool inValue) : mValue(inValue ? 1 : 0) {}
+ CABool(const CABool& inValue) : mValue(inValue.mValue) {}
+ ~CABool() {}
+
+ CABool& operator=(bool inValue) { mValue = inValue; return *this; }
+ CABool& operator=(const CABool& inValue) { mValue = inValue.mValue; return *this; }
+
+ operator bool() const { ThrowIf(mValue == -1, CAException('nope'), "CABool: uninitialized"); return mValue != 0; }
+ bool IsInitialized() const { return mValue != -1; }
+ void Uninitialize() { mValue = -1; }
+
+private:
+ SInt32 mValue;
+
+ CABool(const void*); // prevent accidental instantiation with a pointer via bool constructor
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABufferList.cpp b/libs/appleutility/CoreAudio/PublicUtility/CABufferList.cpp
new file mode 100644
index 0000000000..3249013b59
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CABufferList.cpp
@@ -0,0 +1,259 @@
+/*
+ File: CABufferList.cpp
+ Abstract: CABufferList.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CABufferList.h"
+#include "CAByteOrder.h"
+
+void CABufferList::AllocateBuffers(UInt32 nBytes)
+{
+ if (nBytes <= GetNumBytes()) return;
+
+ if (mABL.mNumberBuffers > 1)
+ // align successive buffers for Altivec and to take alternating
+ // cache line hits by spacing them by odd multiples of 16
+ nBytes = ((nBytes + 15) & ~15) | 16;
+ UInt32 memorySize = nBytes * mABL.mNumberBuffers;
+ Byte *newMemory = new Byte[memorySize], *p = newMemory;
+ memset(newMemory, 0, memorySize); // get page faults now, not later
+
+ AudioBuffer *buf = mABL.mBuffers;
+ for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
+ if (buf->mData != NULL && buf->mDataByteSize > 0)
+ // preserve existing buffer contents
+ memcpy(p, buf->mData, buf->mDataByteSize);
+ buf->mDataByteSize = nBytes;
+ buf->mData = p;
+ p += nBytes;
+ }
+ Byte *oldMemory = mBufferMemory;
+ mBufferMemory = newMemory;
+ mBufferCapacity = nBytes;
+ delete[] oldMemory;
+}
+
+void CABufferList::AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inSrcList, CABufferList *inSetPtrList)
+{
+ if (mABL.mNumberBuffers != inSrcList->mABL.mNumberBuffers) return;
+ if (mABL.mNumberBuffers != inSetPtrList->mABL.mNumberBuffers) return;
+ if (nBytes <= GetNumBytes()) {
+ CopyAllFrom(inSrcList, inSetPtrList);
+ return;
+ }
+ inSetPtrList->VerifyNotTrashingOwnedBuffer();
+ UInt32 fromByteSize = inSrcList->GetNumBytes();
+
+ if (mABL.mNumberBuffers > 1)
+ // align successive buffers for Altivec and to take alternating
+ // cache line hits by spacing them by odd multiples of 16
+ nBytes = ((nBytes + 15) & ~15) | 16;
+ UInt32 memorySize = nBytes * mABL.mNumberBuffers;
+ Byte *newMemory = new Byte[memorySize], *p = newMemory;
+ memset(newMemory, 0, memorySize); // make buffer "hot"
+
+ AudioBuffer *buf = mABL.mBuffers;
+ AudioBuffer *ptrBuf = inSetPtrList->mABL.mBuffers;
+ AudioBuffer *srcBuf = inSrcList->mABL.mBuffers;
+ for (UInt32 i = mABL.mNumberBuffers; i--; ++buf, ++ptrBuf, ++srcBuf) {
+ if (srcBuf->mData != NULL && srcBuf->mDataByteSize > 0)
+ // preserve existing buffer contents
+ memmove(p, srcBuf->mData, srcBuf->mDataByteSize);
+ buf->mDataByteSize = nBytes;
+ buf->mData = p;
+ ptrBuf->mDataByteSize = srcBuf->mDataByteSize;
+ ptrBuf->mData = p;
+ p += nBytes;
+ }
+ Byte *oldMemory = mBufferMemory;
+ mBufferMemory = newMemory;
+ mBufferCapacity = nBytes;
+ if (inSrcList != inSetPtrList)
+ inSrcList->BytesConsumed(fromByteSize);
+ delete[] oldMemory;
+}
+
+void CABufferList::DeallocateBuffers()
+{
+ AudioBuffer *buf = mABL.mBuffers;
+ for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
+ buf->mData = NULL;
+ buf->mDataByteSize = 0;
+ }
+ if (mBufferMemory != NULL) {
+ delete[] mBufferMemory;
+ mBufferMemory = NULL;
+ mBufferCapacity = 0;
+ }
+
+}
+
+static void show(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label, const char *fmtstr=NULL)
+{
+ printf("%s %p (%d fr%s):\n", label ? label : "AudioBufferList", &abl, framesToPrint, fmtstr ? fmtstr : "");
+ const AudioBuffer *buf = abl.mBuffers;
+ for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++buf) {
+ printf(" [%2d] %5dbytes %dch @ %p", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData);
+ if (framesToPrint && buf->mData != NULL) {
+ printf(":");
+ Byte *p = (Byte *)buf->mData;
+ for (int j = framesToPrint * buf->mNumberChannels; --j >= 0; )
+ switch (wordSize) {
+ case 0: // native float
+ printf(" %6.3f", *(Float32 *)p);
+ p += sizeof(Float32);
+ break;
+ // positive: big endian
+ case 1:
+ case -1:
+ printf(" %02X", *p);
+ p += 1;
+ break;
+ case 2:
+ printf(" %04X", CFSwapInt16BigToHost(*(UInt16 *)p));
+ p += 2;
+ break;
+ case 3:
+ printf(" %06X", (p[0] << 16) | (p[1] << 8) | p[2]);
+ p += 3;
+ break;
+ case 4:
+ printf(" %08X", (unsigned int)CFSwapInt32BigToHost(*(UInt32 *)p));
+ p += 4;
+ break;
+ case 10:
+ printf(" %6.3f", CASwapFloat32BigToHost(*(Float32 *)p));
+ p += sizeof(Float32);
+ break;
+ case -2:
+ printf(" %04X", CFSwapInt16LittleToHost(*(UInt16 *)p));
+ p += 2;
+ break;
+ case -3:
+ printf(" %06X", (p[2] << 16) | (p[1] << 8) | p[0]);
+ p += 3;
+ break;
+ case -4:
+ printf(" %08X", (unsigned int)CFSwapInt32LittleToHost(*(UInt32 *)p));
+ p += 4;
+ break;
+ case -10:
+ printf(" %6.3f", CASwapFloat32LittleToHost(*(Float32 *)p));
+ p += sizeof(Float32);
+ break;
+ }
+ }
+ printf("\n");
+ }
+}
+
+void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, const AudioStreamBasicDescription &asbd, const char *label)
+{
+ CAStreamBasicDescription fmt(asbd);
+ int wordSize = 1;
+ char fmtstr[80] = { 0 };
+
+ if (fmt.mFormatID == kAudioFormatLinearPCM) {
+ if (fmt.mFormatFlags & kLinearPCMFormatFlagIsFloat) {
+ if (fmt.mBitsPerChannel == 32) {
+ if (fmt.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) {
+ wordSize = 10;
+ strlcpy(fmtstr, ", BEF", sizeof(fmtstr));
+ } else {
+ wordSize = -10;
+ strlcpy(fmtstr, ", LEF", sizeof(fmtstr));
+ }
+ }
+ } else {
+ wordSize = fmt.SampleWordSize();
+ if (wordSize > 0) {
+ int fracbits = (asbd.mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
+ if (fracbits > 0)
+ snprintf(fmtstr, sizeof(fmtstr), ", %d.%d-bit", (int)asbd.mBitsPerChannel - fracbits, fracbits);
+ else
+ snprintf(fmtstr, sizeof(fmtstr), ", %d-bit", (int)asbd.mBitsPerChannel);
+
+ if (!(fmt.mFormatFlags & kLinearPCMFormatFlagIsBigEndian)) {
+ wordSize = -wordSize;
+ strlcat(fmtstr, " LEI", sizeof(fmtstr));
+ } else {
+ strlcat(fmtstr, " BEI", sizeof(fmtstr));
+ }
+ }
+ }
+ }
+ show(abl, framesToPrint, wordSize, label, fmtstr);
+}
+
+void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label)
+{
+ show(abl, framesToPrint, wordSize, label);
+}
+
+extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize)
+{
+ show(*abl, framesToPrint, wordSize, NULL);
+}
+
+// if the return result is odd, there was a null buffer.
+extern "C" int CrashIfClientProvidedBogusAudioBufferList(const AudioBufferList *abl, bool nullok)
+{
+ const AudioBuffer *buf = abl->mBuffers, *bufend = buf + abl->mNumberBuffers;
+ int sum = 0; // defeat attempts by the compiler to optimize away the code that touches the buffers
+ int anyNull = 0;
+ for ( ; buf < bufend; ++buf) {
+ const int *p = (const int *)buf->mData;
+ if (p == NULL) {
+ anyNull = 1;
+ if (nullok) continue;
+ }
+ unsigned datasize = buf->mDataByteSize;
+ if (datasize >= sizeof(int) && p != NULL) {
+ sum += p[0];
+ sum += p[datasize / sizeof(int) - 1];
+ }
+ }
+ return anyNull | (sum & ~1);
+}
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABufferList.h b/libs/appleutility/CoreAudio/PublicUtility/CABufferList.h
new file mode 100644
index 0000000000..72c93f8626
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CABufferList.h
@@ -0,0 +1,324 @@
+/*
+ File: CABufferList.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CABufferList_h__
+#define __CABufferList_h__
+
+#include <stddef.h>
+#include "CAStreamBasicDescription.h"
+#include "CAXException.h"
+
+void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, const AudioStreamBasicDescription &fmt, const char *label=NULL);
+void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label=NULL);
+extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize);
+extern "C" int CrashIfClientProvidedBogusAudioBufferList(const AudioBufferList *abl, bool nullOK=false);
+
+/* ____________________________________________________________________________
+// CABufferList - variable length buffer list
+
+ This class is designed for use in non-simplistic cases. For AudioUnits, AUBufferList
+ is preferred.
+
+ CABufferList can be used in one of two ways:
+ - as mutable pointers into non-owned memory
+ - as an immutable array of buffers (owns its own memory).
+
+ All buffers are assumed to have the same format (number of channels, word size), so that
+ we can assume their mDataByteSizes are all the same.
+____________________________________________________________________________ */
+class CABufferList {
+public:
+ void * operator new(size_t /*size*/, int nBuffers) {
+ return ::operator new(sizeof(CABufferList) + (nBuffers-1) * sizeof(AudioBuffer));
+ }
+ static CABufferList * New(const char *name, const CAStreamBasicDescription &format)
+ {
+ UInt32 numBuffers = format.NumberChannelStreams(), channelsPerBuffer = format.NumberInterleavedChannels();
+ return new(numBuffers) CABufferList(name, numBuffers, channelsPerBuffer);
+ }
+ static CABufferList * New(const CAStreamBasicDescription &format) { return New("", format); }
+
+ static CABufferList * New(UInt32 numBuffers, UInt32 channelsPerBuffer, const char *name="") {
+ return new(numBuffers) CABufferList(name, numBuffers, channelsPerBuffer);
+ }
+
+protected:
+ CABufferList(const char *name, UInt32 numBuffers, UInt32 channelsPerBuffer) :
+ mName(name),
+ mBufferMemory(NULL),
+ mBufferCapacity(0)
+ {
+ //XAssert(numBuffers > 0 /*&& channelsPerBuffer > 0*/);
+ mABL.mNumberBuffers = numBuffers;
+ AudioBuffer *buf = mABL.mBuffers;
+ for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
+ buf->mNumberChannels = channelsPerBuffer;
+ buf->mDataByteSize = 0;
+ buf->mData = NULL;
+ }
+ }
+
+public:
+ ~CABufferList()
+ {
+ if (mBufferMemory)
+ delete[] mBufferMemory;
+ }
+
+ const char * Name() { return mName; }
+
+ const AudioBufferList & GetBufferList() const { return mABL; }
+
+ AudioBufferList & GetModifiableBufferList() { return _GetBufferList(); }
+
+ UInt32 GetNumberBuffers() const { return mABL.mNumberBuffers; }
+
+ UInt32 GetNumBytes() const
+ {
+ return mABL.mBuffers[0].mDataByteSize;
+ }
+
+ void SetBytes(UInt32 nBytes, void *data)
+ {
+ VerifyNotTrashingOwnedBuffer();
+ XAssert(mABL.mNumberBuffers == 1);
+ mABL.mBuffers[0].mDataByteSize = nBytes;
+ mABL.mBuffers[0].mData = data;
+ }
+
+ void CopyAllFrom(CABufferList *srcbl, CABufferList *ptrbl)
+ // copies bytes from srcbl
+ // make ptrbl reflect the length copied
+ // note that srcbl may be same as ptrbl!
+ {
+ // Note that this buffer *can* own memory and its pointers/lengths are not
+ // altered; only its buffer contents, which are copied from srcbl.
+ // The pointers/lengths in ptrbl are updated to reflect the addresses/lengths
+ // of the copied data, and srcbl's contents are consumed.
+ ptrbl->VerifyNotTrashingOwnedBuffer();
+ UInt32 nBytes = srcbl->GetNumBytes();
+ AudioBuffer *mybuf = mABL.mBuffers, *srcbuf = srcbl->mABL.mBuffers,
+ *ptrbuf = ptrbl->mABL.mBuffers;
+ for (UInt32 i = mABL.mNumberBuffers; i--; ++mybuf, ++srcbuf, ++ptrbuf) {
+ memmove(mybuf->mData, srcbuf->mData, srcbuf->mDataByteSize);
+ ptrbuf->mData = mybuf->mData;
+ ptrbuf->mDataByteSize = srcbuf->mDataByteSize;
+ }
+ if (srcbl != ptrbl)
+ srcbl->BytesConsumed(nBytes);
+ }
+
+ // copies data from another buffer list.
+ void CopyDataFrom(const AudioBufferList &other)
+ {
+ for (unsigned i = 0; i < other.mNumberBuffers; ++i) {
+ XAssert(mBufferCapacity == 0 || other.mBuffers[i].mDataByteSize <= mBufferCapacity);
+ memcpy(mABL.mBuffers[i].mData, other.mBuffers[i].mData,
+ mABL.mBuffers[i].mDataByteSize = other.mBuffers[i].mDataByteSize);
+ }
+ }
+
+ void AppendFrom(CABufferList *blp, UInt32 nBytes)
+ {
+ // this may mutate a buffer that owns memory.
+ AudioBuffer *mybuf = mABL.mBuffers, *srcbuf = blp->mABL.mBuffers;
+ for (UInt32 i = mABL.mNumberBuffers; i--; ++mybuf, ++srcbuf) {
+ XAssert(nBytes <= srcbuf->mDataByteSize);
+ XAssert(mBufferCapacity == 0 || mybuf->mDataByteSize + nBytes <= mBufferCapacity);
+ memcpy((Byte *)mybuf->mData + mybuf->mDataByteSize, srcbuf->mData, nBytes);
+ mybuf->mDataByteSize += nBytes;
+ }
+ blp->BytesConsumed(nBytes);
+ }
+
+ void PadWithZeroes(UInt32 desiredBufferSize)
+ // for cases where an algorithm (e.g. SRC) requires some
+ // padding to create silence following end-of-file
+ {
+ XAssert(mBufferCapacity == 0 || desiredBufferSize <= mBufferCapacity);
+ if (GetNumBytes() > desiredBufferSize) return;
+ AudioBuffer *buf = mABL.mBuffers;
+ for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
+ memset((Byte *)buf->mData + buf->mDataByteSize, 0, desiredBufferSize - buf->mDataByteSize);
+ buf->mDataByteSize = desiredBufferSize;
+ }
+ }
+
+ void SetToZeroes(UInt32 nBytes)
+ {
+ XAssert(mBufferCapacity == 0 || nBytes <= mBufferCapacity);
+ AudioBuffer *buf = mABL.mBuffers;
+ for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
+ memset((Byte *)buf->mData, 0, nBytes);
+ buf->mDataByteSize = nBytes;
+ }
+ }
+
+ void Reset()
+ {
+ DeallocateBuffers();
+ }
+
+ Boolean SameDataAs(const CABufferList* anotherBufferList)
+ {
+ // check to see if two buffer lists point to the same memory.
+ if (mABL.mNumberBuffers != anotherBufferList->mABL.mNumberBuffers) return false;
+
+ for (UInt32 i = 0; i < mABL.mNumberBuffers; ++i) {
+ if (mABL.mBuffers[i].mData != anotherBufferList->mABL.mBuffers[i].mData) return false;
+ }
+ return true;
+ }
+
+ void BytesConsumed(UInt32 nBytes)
+ // advance buffer pointers, decrease buffer sizes
+ {
+ VerifyNotTrashingOwnedBuffer();
+ AudioBuffer *buf = mABL.mBuffers;
+ for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
+ XAssert(nBytes <= buf->mDataByteSize);
+ buf->mData = (Byte *)buf->mData + nBytes;
+ buf->mDataByteSize -= nBytes;
+ }
+ }
+
+ void SetFrom(const AudioBufferList *abl)
+ {
+ VerifyNotTrashingOwnedBuffer();
+ memcpy(&_GetBufferList(), abl, (char *)&abl->mBuffers[abl->mNumberBuffers] - (char *)abl);
+ }
+
+ void SetFrom(const CABufferList *blp)
+ {
+ SetFrom(&blp->GetBufferList());
+ }
+
+ void SetFrom(const AudioBufferList *abl, UInt32 nBytes)
+ {
+ VerifyNotTrashingOwnedBuffer();
+ AudioBuffer *mybuf = mABL.mBuffers;
+ const AudioBuffer *srcbuf = abl->mBuffers;
+ for (UInt32 i = mABL.mNumberBuffers; i--; ++mybuf, ++srcbuf) {
+ mybuf->mNumberChannels = srcbuf->mNumberChannels;
+ mybuf->mDataByteSize = nBytes;
+ mybuf->mData = srcbuf->mData;
+ }
+ }
+
+ void SetFrom(const CABufferList *blp, UInt32 nBytes)
+ {
+ SetFrom(&blp->GetBufferList(), nBytes);
+ }
+
+ AudioBufferList * ToAudioBufferList(AudioBufferList *abl) const
+ {
+ memcpy(abl, &GetBufferList(), (char *)&abl->mBuffers[mABL.mNumberBuffers] - (char *)abl);
+ return abl;
+ }
+
+ void AllocateBuffers(UInt32 nBytes);
+ void AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inCopyFromList, CABufferList *inSetPtrList);
+
+ void DeallocateBuffers();
+
+ void UseExternalBuffer(Byte *ptr, UInt32 nBytes);
+
+ void AdvanceBufferPointers(UInt32 nBytes) // $$$ ReducingSize
+ // this is for bufferlists that function simply as
+ // an array of pointers into another bufferlist, being advanced,
+ // as in RenderOutput implementations
+ {
+ VerifyNotTrashingOwnedBuffer();
+ AudioBuffer *buf = mABL.mBuffers;
+ for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
+ buf->mData = (Byte *)buf->mData + nBytes;
+ buf->mDataByteSize -= nBytes;
+ }
+ }
+
+ void SetNumBytes(UInt32 nBytes)
+ {
+ XAssert(mBufferCapacity == 0 || nBytes <= mBufferCapacity);
+ AudioBuffer *buf = mABL.mBuffers;
+ for (UInt32 i = mABL.mNumberBuffers; i--; ++buf)
+ buf->mDataByteSize = nBytes;
+ }
+
+ void Print(const char *label=NULL, int nframes=0, int wordSize=0) const
+ {
+ if (label == NULL)
+ label = mName;
+ printf("%s - ", label);
+ CAShowAudioBufferList(&GetBufferList(), nframes, wordSize);
+ if (mBufferMemory)
+ printf(" owned memory @ 0x%p:\n", mBufferMemory);
+ }
+
+ UInt32 GetCapacityBytes() const { return mBufferCapacity; }
+
+ template <typename T>
+ T* GetData(UInt32 inBuffer) {
+ return static_cast<T*>(mABL.mBuffers[inBuffer].mData);
+ }
+
+protected:
+ AudioBufferList & _GetBufferList() { return mABL; } // use with care
+ // if we make this public, then we lose ability to call VerifyNotTrashingOwnedBuffer
+ void VerifyNotTrashingOwnedBuffer()
+ {
+ // This needs to be called from places where we are modifying the buffer pointers.
+ // It's an error to modify the buffer pointers or lengths if we own the buffer memory.
+ XAssert(mBufferMemory == NULL);
+ }
+
+ const char * mName; // for debugging
+ Byte * mBufferMemory;
+ UInt32 mBufferCapacity; // max mDataByteSize of each buffer
+ AudioBufferList mABL;
+ // don't add anything here
+};
+
+#endif // __CABufferList_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.cpp b/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.cpp
new file mode 100644
index 0000000000..2161be7447
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.cpp
@@ -0,0 +1,84 @@
+/*
+ File: CABundleLocker.cpp
+ Abstract: CABundleLocker.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CABundleLocker.h"
+#include <pthread.h>
+
+/*
+some bundle operations are not thread safe, notably CFCopyLocalizedStringFromTableInBundle
+*/
+
+static pthread_mutex_t sCABundleLocker = PTHREAD_MUTEX_INITIALIZER;
+
+#define RECURSIVE_LOCK 0
+
+#if RECURSIVE_LOCK
+static pthread_once_t sOnce = PTHREAD_ONCE_INIT;
+
+static void InitCABundleLocker()
+{
+ // have to do this because OS X lacks PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&sCABundleLocker, &attr);
+ pthread_mutexattr_destroy(&attr);
+}
+#endif
+
+CABundleLocker::CABundleLocker()
+{
+#if RECURSIVE_LOCK
+ pthread_once(&sOnce, InitCABundleLocker);
+#endif
+ pthread_mutex_lock(&sCABundleLocker);
+}
+
+CABundleLocker::~CABundleLocker()
+{
+ pthread_mutex_unlock(&sCABundleLocker);
+}
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.h b/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.h
new file mode 100644
index 0000000000..821ca34af0
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.h
@@ -0,0 +1,69 @@
+/*
+ File: CABundleLocker.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef _CABundleLocker_h_
+#define _CABundleLocker_h_
+
+#include <TargetConditionals.h>
+
+/*
+some bundle operations are not thread safe, notably CFCopyLocalizedStringFromTableInBundle
+*/
+
+class CABundleLocker
+{
+public:
+
+#if TARGET_OS_MAC
+ CABundleLocker();
+ ~CABundleLocker();
+#else
+ CABundleLocker() {}
+ ~CABundleLocker() {}
+#endif
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAByteOrder.h b/libs/appleutility/CoreAudio/PublicUtility/CAByteOrder.h
new file mode 100644
index 0000000000..9a56c6d858
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAByteOrder.h
@@ -0,0 +1,161 @@
+/*
+ File: CAByteOrder.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAByteOrder_h__)
+#define __CAByteOrder_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include "CoreFoundation.h"
+#endif
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+CF_INLINE Float32 CASwapFloat32 (Float32 arg) {
+ union {
+ Float32 f;
+ UInt32 i;
+ } flip;
+
+ flip.f = arg;
+ flip.i = CFSwapInt32 (flip.i);
+
+ return flip.f;
+}
+
+CF_INLINE Float64 CASwapFloat64 (Float64 arg) {
+ union {
+ Float64 f;
+ UInt64 i;
+ } flip;
+
+ flip.f = arg;
+ flip.i = CFSwapInt64 (flip.i);
+
+ return flip.f;
+}
+
+#pragma mark -Flippers
+
+CF_INLINE Float32 CASwapFloat32BigToHost(Float32 arg) {
+#if defined(__BIG_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat32(arg);
+#endif
+}
+
+CF_INLINE Float64 CASwapFloat64BigToHost(Float64 arg) {
+#if defined(__BIG_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat64(arg);
+#endif
+}
+
+CF_INLINE Float32 CASwapFloat32HostToBig(Float32 arg) {
+#if defined(__BIG_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat32(arg);
+#endif
+}
+
+CF_INLINE Float64 CASwapFloat64HostToBig(Float64 arg) {
+#if defined(__BIG_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat64(arg);
+#endif
+}
+
+CF_INLINE Float32 CASwapFloat32LittleToHost(Float32 arg) {
+#if defined(__LITTLE_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat32(arg);
+#endif
+}
+
+CF_INLINE Float64 CASwapFloat64LittleToHost(Float64 arg) {
+#if defined(__LITTLE_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat64(arg);
+#endif
+}
+
+CF_INLINE Float32 CASwapFloat32HostToLittle(Float32 arg) {
+#if defined(__LITTLE_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat32(arg);
+#endif
+}
+
+CF_INLINE Float64 CASwapFloat64HostToLittle(Float64 arg) {
+#if defined(__LITTLE_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat64(arg);
+#endif
+}
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFArray.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFArray.cpp
new file mode 100644
index 0000000000..e7c057d8da
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFArray.cpp
@@ -0,0 +1,821 @@
+/*
+ File: CACFArray.cpp
+ Abstract: CACFArray.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+// Self Include
+#include "CACFArray.h"
+
+// PublicUtility Includes
+#include "CACFDictionary.h"
+#include "CACFNumber.h"
+#include "CACFString.h"
+
+//=============================================================================
+// CACFArray
+//=============================================================================
+
+bool CACFArray::HasItem(const void* inItem) const
+{
+ bool theAnswer = false;
+ if(mCFArray != NULL)
+ {
+ CFRange theRange = { 0, CFArrayGetCount(mCFArray)};
+ theAnswer = CFArrayContainsValue(mCFArray, theRange, inItem);
+ }
+ return theAnswer;
+}
+
+bool CACFArray::GetIndexOfItem(const void* inItem, UInt32& outIndex) const
+{
+ bool theAnswer = false;
+ outIndex = 0;
+ if(mCFArray != NULL)
+ {
+ CFRange theRange = { 0, CFArrayGetCount(mCFArray)};
+ CFIndex theIndex = CFArrayGetFirstIndexOfValue(mCFArray, theRange, inItem);
+ if(theIndex != -1)
+ {
+ theAnswer = true;
+ outIndex = ToUInt32(theIndex);
+ }
+ }
+ return theAnswer;
+}
+
+bool CACFArray::GetBool(UInt32 inIndex, bool& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inIndex, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFBooleanGetTypeID()))
+ {
+ outValue = CFBooleanGetValue(static_cast<CFBooleanRef>(theValue));
+ theAnswer = true;
+ }
+ else if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ SInt32 theNumericValue = 0;
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue);
+ outValue = theNumericValue != 0;
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetSInt32(UInt32 inIndex, SInt32& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt32Type, &outItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetUInt32(UInt32 inIndex, UInt32& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt32Type, &outItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetSInt64(UInt32 inIndex, SInt64& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt64Type, &outItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetUInt64(UInt32 inIndex, UInt64& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt64Type, &outItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetFloat32(UInt32 inIndex, Float32& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberFloat32Type, &outItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetFloat64(UInt32 inIndex, Float64& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberFloat64Type, &outItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::Get4CC(UInt32 inIndex, UInt32& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inIndex, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+ theAnswer = true;
+ }
+ else if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
+ {
+ CFStringRef theString = static_cast<CFStringRef>(theValue);
+ if(CFStringGetLength(theString) == 4)
+ {
+ char theCString[5];
+ CFStringGetCString(theString, theCString, 5, kCFStringEncodingASCII);
+ outValue = CFSwapInt32BigToHost(*reinterpret_cast<UInt32*>(theCString));
+ }
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetString(UInt32 inIndex, CFStringRef& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFStringGetTypeID()))
+ {
+ outItem = static_cast<CFStringRef>(theItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetArray(UInt32 inIndex, CFArrayRef& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFArrayGetTypeID()))
+ {
+ outItem = static_cast<CFArrayRef>(theItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetDictionary(UInt32 inIndex, CFDictionaryRef& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFDictionaryGetTypeID()))
+ {
+ outItem = static_cast<CFDictionaryRef>(theItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetData(UInt32 inIndex, CFDataRef& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFDataGetTypeID()))
+ {
+ outItem = static_cast<CFDataRef>(theItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetUUID(UInt32 inIndex, CFUUIDRef& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFUUIDGetTypeID()))
+ {
+ outItem = static_cast<CFUUIDRef>(theItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetCFType(UInt32 inIndex, CFTypeRef& outItem) const
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && (inIndex < GetNumberItems()))
+ {
+ outItem = CFArrayGetValueAtIndex(mCFArray, static_cast<CFIndex>(inIndex));
+ theAnswer = outItem != NULL;
+ }
+
+ return theAnswer;
+}
+
+void CACFArray::GetCACFString(UInt32 inIndex, CACFString& outItem) const
+{
+ outItem = static_cast<CFStringRef>(NULL);
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFStringGetTypeID()))
+ {
+ outItem = static_cast<CFStringRef>(theItem);
+ }
+ }
+}
+
+void CACFArray::GetCACFArray(UInt32 inIndex, CACFArray& outItem) const
+{
+ outItem = static_cast<CFArrayRef>(NULL);
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFArrayGetTypeID()))
+ {
+ outItem = static_cast<CFArrayRef>(theItem);
+ }
+ }
+}
+
+void CACFArray::GetCACFDictionary(UInt32 inIndex, CACFDictionary& outItem) const
+{
+ outItem = static_cast<CFDictionaryRef>(NULL);
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFDictionaryGetTypeID()))
+ {
+ outItem = static_cast<CFDictionaryRef>(theItem);
+ }
+ }
+}
+
+bool CACFArray::AppendBool(bool inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFBoolean theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = AppendCFType(theItem.GetCFBoolean());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::AppendSInt32(SInt32 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = AppendCFType(theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::AppendUInt32(UInt32 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = AppendCFType(theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::AppendSInt64(SInt64 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = AppendCFType(theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::AppendUInt64(UInt64 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = AppendCFType(theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::AppendFloat32(Float32 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = AppendCFType(theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::AppendFloat64(Float64 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = AppendCFType(theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::AppendString(const CFStringRef inItem)
+{
+ return AppendCFType(inItem);
+}
+
+bool CACFArray::AppendArray(const CFArrayRef inItem)
+{
+ return AppendCFType(inItem);
+}
+
+bool CACFArray::AppendDictionary(const CFDictionaryRef inItem)
+{
+ return AppendCFType(inItem);
+}
+
+bool CACFArray::AppendData(const CFDataRef inItem)
+{
+ return AppendCFType(inItem);
+}
+
+bool CACFArray::AppendCFType(const CFTypeRef inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CFArrayAppendValue(mCFArray, inItem);
+ theAnswer = true;
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertBool(UInt32 inIndex, bool inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFBoolean theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = InsertCFType(inIndex, theItem.GetCFBoolean());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertSInt32(UInt32 inIndex, SInt32 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertUInt32(UInt32 inIndex, UInt32 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertSInt64(UInt32 inIndex, SInt64 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertUInt64(UInt32 inIndex, UInt64 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertFloat32(UInt32 inIndex, Float32 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertFloat64(UInt32 inIndex, Float64 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertString(UInt32 inIndex, const CFStringRef inItem)
+{
+ return InsertCFType(inIndex, inItem);
+}
+
+bool CACFArray::InsertArray(UInt32 inIndex, const CFArrayRef inItem)
+{
+ return InsertCFType(inIndex, inItem);
+}
+
+bool CACFArray::InsertDictionary(UInt32 inIndex, const CFDictionaryRef inItem)
+{
+ return InsertCFType(inIndex, inItem);
+}
+
+bool CACFArray::InsertData(UInt32 inIndex, const CFDataRef inItem)
+{
+ return InsertCFType(inIndex, inItem);
+}
+
+bool CACFArray::InsertCFType(UInt32 inIndex, const CFTypeRef inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ if(inIndex < GetNumberItems())
+ {
+ CFArrayInsertValueAtIndex(mCFArray, static_cast<CFIndex>(inIndex), inItem);
+ }
+ else
+ {
+ CFArrayAppendValue(mCFArray, inItem);
+ }
+ theAnswer = true;
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::SetBool(UInt32 inIndex, bool inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+ {
+ CACFBoolean theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = SetCFType(inIndex, theItem.GetCFBoolean());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::SetSInt32(UInt32 inIndex, SInt32 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::SetUInt32(UInt32 inIndex, UInt32 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::SetSInt64(UInt32 inIndex, SInt64 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::SetUInt64(UInt32 inIndex, UInt64 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::SetFloat32(UInt32 inIndex, Float32 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::SetFloat64(UInt32 inIndex, Float64 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::SetString(UInt32 inIndex, const CFStringRef inItem)
+{
+ return SetCFType(inIndex, inItem);
+}
+
+bool CACFArray::SetArray(UInt32 inIndex, const CFArrayRef inItem)
+{
+ return SetCFType(inIndex, inItem);
+}
+
+bool CACFArray::SetDictionary(UInt32 inIndex, const CFDictionaryRef inItem)
+{
+ return SetCFType(inIndex, inItem);
+}
+
+bool CACFArray::SetData(UInt32 inIndex, const CFDataRef inItem)
+{
+ return SetCFType(inIndex, inItem);
+}
+
+bool CACFArray::SetCFType(UInt32 inIndex, const CFTypeRef inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
+ {
+ CFArraySetValueAtIndex(mCFArray, static_cast<CFIndex>(inIndex), inItem);
+ theAnswer = true;
+ }
+
+ return theAnswer;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFArray.h b/libs/appleutility/CoreAudio/PublicUtility/CACFArray.h
new file mode 100644
index 0000000000..89c8c559e4
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFArray.h
@@ -0,0 +1,195 @@
+/*
+ File: CACFArray.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CACFArray_h__)
+#define __CACFArray_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include <CoreAudioTypes.h>
+ #include <CoreFoundation.h>
+#endif
+
+#include "CADebugMacros.h"
+
+//=============================================================================
+// Types
+//=============================================================================
+
+class CACFDictionary;
+class CACFString;
+
+//=============================================================================
+// CACFArray
+//=============================================================================
+
+class CACFArray
+{
+
+// Construction/Destruction
+public:
+ CACFArray() : mCFArray(CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)), mRelease(true), mMutable(true) {}
+ explicit CACFArray(bool inRelease) : mCFArray(CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)), mRelease(inRelease), mMutable(true) {}
+ CACFArray(UInt32 inMaxNumberItems, bool inRelease) : mCFArray(CFArrayCreateMutable(NULL, static_cast<CFIndex>(inMaxNumberItems), &kCFTypeArrayCallBacks)), mRelease(inRelease), mMutable(true) {}
+ CACFArray(CFArrayRef inCFArray, bool inRelease) : mCFArray(const_cast<CFMutableArrayRef>(inCFArray)), mRelease(inRelease), mMutable(false) {}
+ CACFArray(CFMutableArrayRef inCFArray, bool inRelease) : mCFArray(inCFArray), mRelease(inRelease), mMutable(true) {}
+ CACFArray(const CACFArray& inArray) : mCFArray(inArray.mCFArray), mRelease(inArray.mRelease), mMutable(inArray.mMutable) { Retain(); }
+ CACFArray& operator=(const CACFArray& inArray) { Release(); mCFArray = inArray.mCFArray; mRelease = inArray.mRelease; mMutable = inArray.mMutable; Retain(); return *this; }
+ CACFArray& operator=(CFArrayRef inCFArray) { Release(); mCFArray = const_cast<CFMutableArrayRef>(inCFArray); mMutable = false; Retain(); return *this; }
+ CACFArray& operator=(CFMutableArrayRef inCFArray) { Release(); mCFArray = inCFArray; mMutable = true; Retain(); return *this; }
+ ~CACFArray() { Release(); }
+
+private:
+ void Retain() { if(mRelease && (mCFArray != NULL)) { CFRetain(mCFArray); } }
+ void Release() { if(mRelease && (mCFArray != NULL)) { CFRelease(mCFArray); } }
+
+// Attributes
+public:
+ bool IsValid() const { return mCFArray != NULL; }
+ bool IsMutable() const { return mMutable; }
+ bool CanModify() const { return mMutable && (mCFArray != NULL); }
+
+ bool WillRelease() const { return mRelease; }
+ void ShouldRelease(bool inRelease) { mRelease = inRelease; }
+
+ CFTypeID GetTypeID() const { return CFGetTypeID(mCFArray); }
+
+ CFArrayRef GetCFArray() const { return mCFArray; }
+ CFArrayRef CopyCFArray() const { if(mCFArray != NULL) { CFRetain(mCFArray); } return mCFArray; }
+
+ CFMutableArrayRef GetCFMutableArray() const { return mCFArray; }
+ CFMutableArrayRef CopyCFMutableArray() const { if(mCFArray != NULL) { CFRetain(mCFArray); } return mCFArray; }
+ CFPropertyListRef AsPropertyList() const { return mCFArray; }
+
+ void SetCFMutableArrayFromCopy(CFArrayRef inArray, bool inRelease = true) { Release(); mCFArray = CFArrayCreateMutableCopy(NULL, 0, inArray); mMutable = true; mRelease = inRelease; }
+
+// Item Operations
+public:
+ UInt32 GetNumberItems() const { UInt32 theAnswer = 0; if(mCFArray != NULL) { theAnswer = ToUInt32(CFArrayGetCount(mCFArray)); } return theAnswer; }
+ bool HasItem(const void* inItem) const;
+ void RemoveItem(const void* inItem) { UInt32 theIndex; if(CanModify() && GetIndexOfItem(inItem, theIndex)) { RemoveItemAtIndex(theIndex); } }
+ bool GetIndexOfItem(const void* inItem, UInt32& outIndex) const;
+ void RemoveItemAtIndex(UInt32 inIndex) { if(CanModify()) { CFArrayRemoveValueAtIndex(mCFArray, static_cast<CFIndex>(inIndex)); } }
+ void Clear() { if(CanModify()) { CFArrayRemoveAllValues(mCFArray); } }
+ void Sort(CFComparatorFunction inCompareFunction) { if(CanModify()) { CFRange theRange = { 0, CFArrayGetCount(mCFArray) }; CFArraySortValues(mCFArray, theRange, inCompareFunction, NULL); } }
+ void SortNumbers() { Sort((CFComparatorFunction)CFNumberCompare); }
+ void SortStrings() { Sort((CFComparatorFunction)CFStringCompare); }
+
+ bool GetBool(UInt32 inIndex, bool& outValue) const;
+ bool GetSInt32(UInt32 inIndex, SInt32& outItem) const;
+ bool GetUInt32(UInt32 inIndex, UInt32& outItem) const;
+ bool GetSInt64(UInt32 inIndex, SInt64& outItem) const;
+ bool GetUInt64(UInt32 inIndex, UInt64& outItem) const;
+ bool GetFloat32(UInt32 inIndex, Float32& outItem) const;
+ bool GetFloat64(UInt32 inIndex, Float64& outItem) const;
+ bool Get4CC(UInt32 inIndex, UInt32& outValue) const;
+ bool GetString(UInt32 inIndex, CFStringRef& outItem) const;
+ bool GetArray(UInt32 inIndex, CFArrayRef& outItem) const;
+ bool GetDictionary(UInt32 inIndex, CFDictionaryRef& outItem) const;
+ bool GetData(UInt32 inIndex, CFDataRef& outItem) const;
+ bool GetUUID(UInt32 inIndex, CFUUIDRef& outItem) const;
+ bool GetCFType(UInt32 inIndex, CFTypeRef& outItem) const;
+
+ void GetCACFString(UInt32 inIndex, CACFString& outItem) const;
+ void GetCACFArray(UInt32 inIndex, CACFArray& outItem) const;
+ void GetCACFDictionary(UInt32 inIndex, CACFDictionary& outItem) const;
+
+ bool AppendBool(bool inItem);
+ bool AppendSInt32(SInt32 inItem);
+ bool AppendUInt32(UInt32 inItem);
+ bool AppendSInt64(SInt64 inItem);
+ bool AppendUInt64(UInt64 inItem);
+ bool AppendFloat32(Float32 inItem);
+ bool AppendFloat64(Float64 inItem);
+ bool AppendString(const CFStringRef inItem);
+ bool AppendArray(const CFArrayRef inItem);
+ bool AppendDictionary(const CFDictionaryRef inItem);
+ bool AppendData(const CFDataRef inItem);
+ bool AppendCFType(const CFTypeRef inItem);
+
+ bool InsertBool(UInt32 inIndex, bool inItem);
+ bool InsertSInt32(UInt32 inIndex, SInt32 inItem);
+ bool InsertUInt32(UInt32 inIndex, UInt32 inItem);
+ bool InsertSInt64(UInt32 inIndex, SInt64 inItem);
+ bool InsertUInt64(UInt32 inIndex, UInt64 inItem);
+ bool InsertFloat32(UInt32 inIndex, Float32 inItem);
+ bool InsertFloat64(UInt32 inIndex, Float64 inItem);
+ bool InsertString(UInt32 inIndex, const CFStringRef inItem);
+ bool InsertArray(UInt32 inIndex, const CFArrayRef inItem);
+ bool InsertDictionary(UInt32 inIndex, const CFDictionaryRef inItem);
+ bool InsertData(UInt32 inIndex, const CFDataRef inItem);
+ bool InsertCFType(UInt32 inIndex, const CFTypeRef inItem);
+
+ bool SetBool(UInt32 inIndex, bool inItem);
+ bool SetSInt32(UInt32 inIndex, SInt32 inItem);
+ bool SetUInt32(UInt32 inIndex, UInt32 inItem);
+ bool SetSInt64(UInt32 inIndex, SInt64 inItem);
+ bool SetUInt64(UInt32 inIndex, UInt64 inItem);
+ bool SetFloat32(UInt32 inIndex, Float32 inItem);
+ bool SetFloat64(UInt32 inIndex, Float64 inItem);
+ bool SetString(UInt32 inIndex, const CFStringRef inItem);
+ bool SetArray(UInt32 inIndex, const CFArrayRef inItem);
+ bool SetDictionary(UInt32 inIndex, const CFDictionaryRef inItem);
+ bool SetData(UInt32 inIndex, const CFDataRef inItem);
+ bool SetCFType(UInt32 inIndex, const CFTypeRef inItem);
+
+// Implementation
+private:
+ CFMutableArrayRef mCFArray;
+ bool mRelease;
+ bool mMutable;
+
+ CACFArray(const void*); // prevent accidental instantiation with a pointer via bool constructor
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFData.h b/libs/appleutility/CoreAudio/PublicUtility/CACFData.h
new file mode 100644
index 0000000000..7ce08dcf13
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFData.h
@@ -0,0 +1,108 @@
+/*
+ File: CACFData.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CACFData_h__)
+#define __CACFData_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <CoreFoundation/CFData.h>
+#else
+ #include <CoreAudioTypes.h>
+ #include <CFData.h>
+#endif
+
+#include "CADebugMacros.h"
+
+//=============================================================================
+// CACFData
+//=============================================================================
+
+class CACFData
+{
+
+// Construction/Destruction
+public:
+ explicit CACFData(CFDataRef inCFData) : mCFData(inCFData), mWillRelease(true) {}
+ CACFData(CFDataRef inCFData, bool inWillRelease) : mCFData(inCFData), mWillRelease(inWillRelease) {}
+ CACFData(const void* inData, UInt32 inDataSize) : mCFData(NULL), mWillRelease(true) { mCFData = CFDataCreate(NULL, static_cast<const UInt8*>(inData), static_cast<CFIndex>(inDataSize)); }
+ ~CACFData() { Release(); }
+ CACFData(const CACFData& inNumber) : mCFData(inNumber.mCFData), mWillRelease(inNumber.mWillRelease) { Retain(); }
+ CACFData& operator=(const CACFData& inNumber) { Release(); mCFData = inNumber.mCFData; mWillRelease = inNumber.mWillRelease; Retain(); return *this; }
+ CACFData& operator=(CFDataRef inCFData) { Release(); mCFData = inCFData; mWillRelease = true; return *this; }
+
+private:
+ void Retain() { if(mWillRelease && (mCFData != NULL)) { CFRetain(mCFData); } }
+ void Release() { if(mWillRelease && (mCFData != NULL)) { CFRelease(mCFData); } }
+
+ CFDataRef mCFData;
+ bool mWillRelease;
+
+// Operations
+public:
+ void AllowRelease() { mWillRelease = true; }
+ void DontAllowRelease() { mWillRelease = false; }
+ bool IsValid() { return mCFData != NULL; }
+
+// Value Access
+public:
+ CFDataRef GetCFData() const { return mCFData; }
+ CFDataRef CopyCFData() const { if(mCFData != NULL) { CFRetain(mCFData); } return mCFData; }
+
+ UInt32 GetSize() const { return ToUInt32(CFDataGetLength(mCFData)); }
+ const void* GetDataPtr() const { return CFDataGetBytePtr(mCFData); }
+ void CopyData(UInt32 inStartOffset, void* outData, UInt32 inDataSize) const { CFRange theRange = { static_cast<CFIndex>(inStartOffset), static_cast<CFIndex>(inDataSize) }; CFDataGetBytes(mCFData, theRange, static_cast<UInt8*>(outData)); }
+
+ SInt32 GetSInt32() const { SInt32 theAnswer = 0; CopyData(0, &theAnswer, SizeOf32(SInt32)); return theAnswer; }
+ Float32 GetFloat32() const { Float32 theAnswer = 0; CopyData(0, &theAnswer, SizeOf32(Float32)); return theAnswer; }
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.cpp
new file mode 100644
index 0000000000..fbac774ab5
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.cpp
@@ -0,0 +1,581 @@
+/*
+ File: CACFDictionary.cpp
+ Abstract: CACFDictionary.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+// Self Include
+#include "CACFDictionary.h"
+
+// PublicUtility Includes
+#include "CACFArray.h"
+#include "CACFNumber.h"
+#include "CACFString.h"
+
+//=============================================================================
+// CACFDictionary
+//=============================================================================
+
+bool CACFDictionary::HasKey(const CFStringRef inKey) const
+{
+ return CFDictionaryContainsKey(mCFDictionary, inKey) != 0;
+}
+
+UInt32 CACFDictionary::Size () const
+{
+ return mCFDictionary ? ToUInt32(CFDictionaryGetCount(mCFDictionary)) : 0;
+}
+
+void CACFDictionary::GetKeys (const void **keys) const
+{
+ CFDictionaryGetKeysAndValues(mCFDictionary, keys, NULL);
+}
+
+void CACFDictionary::GetKeysAndValues (const void **keys, const void **values) const
+{
+ CFDictionaryGetKeysAndValues(mCFDictionary, keys, values);
+}
+
+bool CACFDictionary::GetBool(const CFStringRef inKey, bool& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFBooleanGetTypeID()))
+ {
+ outValue = CFBooleanGetValue(static_cast<CFBooleanRef>(theValue));
+ theAnswer = true;
+ }
+ else if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ SInt32 theNumericValue = 0;
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue);
+ outValue = theNumericValue != 0;
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetSInt32(const CFStringRef inKey, SInt32& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetUInt32(const CFStringRef inKey, UInt32& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetSInt64(const CFStringRef inKey, SInt64& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetUInt64(const CFStringRef inKey, UInt64& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetFloat32FromString(const CFStringRef inKey, Float32& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
+ {
+ outValue = static_cast<Float32>(CFStringGetDoubleValue(static_cast<CFStringRef>(theValue)));
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetUInt32FromString(const CFStringRef inKey, UInt32& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
+ {
+ outValue = CFStringGetIntValue(static_cast<CFStringRef>(theValue));
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetFloat32(const CFStringRef inKey, Float32& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat32Type, &outValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetFloat64(const CFStringRef inKey, Float64& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat64Type, &outValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetFixed32(const CFStringRef inKey, Float32& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ SInt32 theFixed32 = 0;
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theFixed32);
+
+ // this is a 16.16 value so convert it to a float
+ Float32 theSign = theFixed32 < 0 ? -1.0f : 1.0f;
+ theFixed32 *= (SInt32)theSign;
+ Float32 theWholePart = (theFixed32 & 0x7FFF0000) >> 16;
+ Float32 theFractPart = theFixed32 & 0x0000FFFF;
+ theFractPart /= 65536.0f;
+ outValue = theSign * (theWholePart + theFractPart);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetFixed64(const CFStringRef inKey, Float64& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ SInt64 theFixed64 = 0;
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &theFixed64);
+ outValue = static_cast<Float64>(theFixed64 >> 32);
+ outValue += static_cast<Float64>(theFixed64 & 0x00000000FFFFFFFFLL) / static_cast<Float64>(0x0000000100000000LL);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::Get4CC(const CFStringRef inKey, UInt32& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+ theAnswer = true;
+ }
+ else if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
+ {
+ CFStringRef theString = static_cast<CFStringRef>(theValue);
+ if(CFStringGetLength(theString) == 4)
+ {
+ char theCString[5];
+ CFStringGetCString(theString, theCString, 5, kCFStringEncodingASCII);
+ outValue = CFSwapInt32BigToHost(*reinterpret_cast<UInt32*>(theCString));
+ }
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetString(const CFStringRef inKey, CFStringRef& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
+ {
+ outValue = static_cast<CFStringRef>(theValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetArray(const CFStringRef inKey, CFArrayRef& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFArrayGetTypeID()))
+ {
+ outValue = static_cast<CFArrayRef>(theValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetDictionary(const CFStringRef inKey, CFDictionaryRef& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFDictionaryGetTypeID()))
+ {
+ outValue = static_cast<CFDictionaryRef>(theValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetData(const CFStringRef inKey, CFDataRef& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFDataGetTypeID()))
+ {
+ outValue = static_cast<CFDataRef>(theValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetCFType(const CFStringRef inKey, CFTypeRef& outValue) const
+{
+ bool theAnswer = false;
+
+ if(mCFDictionary != NULL)
+ {
+ outValue = CFDictionaryGetValue(mCFDictionary, inKey);
+ theAnswer = (outValue != NULL);
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetURL(const CFStringRef inKey, CFURLRef& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFURLGetTypeID()))
+ {
+ outValue = static_cast<CFURLRef>(theValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetCFTypeWithCStringKey(const char* inKey, CFTypeRef& outValue) const
+{
+ bool theAnswer = false;
+
+ if(mCFDictionary != NULL)
+ {
+ CACFString theKey(inKey);
+ if(theKey.IsValid())
+ {
+ theAnswer = GetCFType(theKey.GetCFString(), outValue);
+ }
+ }
+
+ return theAnswer;
+}
+
+void CACFDictionary::GetCACFString(const CFStringRef inKey, CACFString& outValue) const
+{
+ outValue = static_cast<CFStringRef>(NULL);
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
+ {
+ outValue = static_cast<CFStringRef>(theValue);
+ }
+ }
+}
+
+void CACFDictionary::GetCACFArray(const CFStringRef inKey, CACFArray& outValue) const
+{
+ outValue = static_cast<CFArrayRef>(NULL);
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFArrayGetTypeID()))
+ {
+ outValue = static_cast<CFArrayRef>(theValue);
+ }
+ }
+}
+
+void CACFDictionary::GetCACFDictionary(const CFStringRef inKey, CACFDictionary& outValue) const
+{
+ outValue = static_cast<CFDictionaryRef>(NULL);
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFDictionaryGetTypeID()))
+ {
+ outValue = static_cast<CFDictionaryRef>(theValue);
+ }
+ }
+}
+
+bool CACFDictionary::AddBool(const CFStringRef inKey, bool inValue)
+{
+ CACFBoolean theValue(inValue);
+ return AddCFType(inKey, theValue.GetCFBoolean());
+}
+
+bool CACFDictionary::AddSInt32(const CFStringRef inKey, SInt32 inValue)
+{
+ CACFNumber theValue(inValue);
+ return AddCFType(inKey, theValue.GetCFNumber());
+}
+
+bool CACFDictionary::AddUInt32(const CFStringRef inKey, UInt32 inValue)
+{
+ CACFNumber theValue(inValue);
+ return AddCFType(inKey, theValue.GetCFNumber());
+}
+
+bool CACFDictionary::AddSInt64(const CFStringRef inKey, SInt64 inValue)
+{
+ CACFNumber theValue(inValue);
+ return AddCFType(inKey, theValue.GetCFNumber());
+}
+
+bool CACFDictionary::AddUInt64(const CFStringRef inKey, UInt64 inValue)
+{
+ CACFNumber theValue(inValue);
+ return AddCFType(inKey, theValue.GetCFNumber());
+}
+
+bool CACFDictionary::AddFloat32(const CFStringRef inKey, Float32 inValue)
+{
+ CACFNumber theValue(inValue);
+ return AddCFType(inKey, theValue.GetCFNumber());
+}
+
+bool CACFDictionary::AddFloat64(const CFStringRef inKey, Float64 inValue)
+{
+ CACFNumber theValue(inValue);
+ return AddCFType(inKey, theValue.GetCFNumber());
+}
+
+bool CACFDictionary::AddNumber(const CFStringRef inKey, const CFNumberRef inValue)
+{
+ return AddCFType(inKey, inValue);
+}
+
+bool CACFDictionary::AddString(const CFStringRef inKey, const CFStringRef inValue)
+{
+ return AddCFType(inKey, inValue);
+}
+
+bool CACFDictionary::AddArray(const CFStringRef inKey, const CFArrayRef inValue)
+{
+ return AddCFType(inKey, inValue);
+}
+
+bool CACFDictionary::AddDictionary(const CFStringRef inKey, const CFDictionaryRef inValue)
+{
+ return AddCFType(inKey, inValue);
+}
+
+bool CACFDictionary::AddData(const CFStringRef inKey, const CFDataRef inValue)
+{
+ return AddCFType(inKey, inValue);
+}
+
+bool CACFDictionary::AddURL(const CFStringRef inKey, const CFURLRef inValue)
+{
+ return AddCFType (inKey, inValue);
+}
+
+bool CACFDictionary::AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue)
+{
+ bool theAnswer = false;
+
+ if (inKey)
+ {
+ CACFString theKey(inKey);
+ if(theKey.IsValid())
+ {
+ theAnswer = AddCFType(theKey.GetCFString(), inValue);
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::AddCString(const CFStringRef inKey, const char* inValue)
+{
+ bool theAnswer = false;
+
+ if (inValue)
+ {
+ CACFString theValue(inValue);
+ if(theValue.IsValid())
+ {
+ theAnswer = AddCFType(inKey, theValue.GetCFString());
+ }
+ }
+ return theAnswer;
+}
+
+bool CACFDictionary::AddCFType(const CFStringRef inKey, const CFTypeRef inValue)
+{
+ bool theAnswer = false;
+
+ if(mMutable && (mCFDictionary != NULL) && inValue)
+ {
+ CFDictionarySetValue(mCFDictionary, inKey, inValue);
+ theAnswer = true;
+ }
+
+ return theAnswer;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.h b/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.h
new file mode 100644
index 0000000000..c389e50042
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.h
@@ -0,0 +1,176 @@
+/*
+ File: CACFDictionary.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CACFDictionary_h__)
+#define __CACFDictionary_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include <CoreFoundation.h>
+#endif
+
+//=============================================================================
+// Types
+//=============================================================================
+
+class CACFArray;
+class CACFString;
+
+//=============================================================================
+// CACFDictionary
+//=============================================================================
+
+class CACFDictionary
+{
+
+// Construction/Destruction
+public:
+ CACFDictionary() : mCFDictionary(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)), mRelease(true), mMutable(true) {}
+ explicit CACFDictionary(bool inRelease) : mCFDictionary(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)), mRelease(inRelease), mMutable(true) {}
+ CACFDictionary(CFDictionaryRef inCFDictionary, bool inRelease) : mCFDictionary(const_cast<CFMutableDictionaryRef>(inCFDictionary)), mRelease(inRelease), mMutable(false) {}
+ CACFDictionary(CFMutableDictionaryRef inCFDictionary, bool inRelease) : mCFDictionary(inCFDictionary), mRelease(inRelease), mMutable(true) {}
+ CACFDictionary(const CACFDictionary& inDictionary) : mCFDictionary(inDictionary.mCFDictionary), mRelease(inDictionary.mRelease), mMutable(inDictionary.mMutable) { Retain(); }
+ CACFDictionary& operator=(const CACFDictionary& inDictionary) { Release(); mCFDictionary = inDictionary.mCFDictionary; mRelease = inDictionary.mRelease; mMutable = inDictionary.mMutable; Retain(); return *this; }
+ CACFDictionary& operator=(CFDictionaryRef inDictionary) { Release(); mCFDictionary = const_cast<CFMutableDictionaryRef>(inDictionary); mMutable = false; Retain(); return *this; }
+ CACFDictionary& operator=(CFMutableDictionaryRef inDictionary) { Release(); mCFDictionary = inDictionary; mMutable = true; Retain(); return *this; }
+ ~CACFDictionary() { Release(); }
+
+private:
+ void Retain() { if(mRelease && (mCFDictionary != NULL)) { CFRetain(mCFDictionary); } }
+ void Release() { if(mRelease && (mCFDictionary != NULL)) { CFRelease(mCFDictionary); } }
+
+// Attributes
+public:
+ bool IsValid() const { return mCFDictionary != NULL; }
+ bool IsMutable() const { return mMutable;}
+ bool CanModify() const { return mMutable && (mCFDictionary != NULL); }
+
+ bool WillRelease() const { return mRelease; }
+ void ShouldRelease(bool inRelease) { mRelease = inRelease; }
+
+ CFDictionaryRef GetDict() const { return mCFDictionary; }
+ CFDictionaryRef GetCFDictionary() const { return mCFDictionary; }
+ CFDictionaryRef CopyCFDictionary() const { if(mCFDictionary != NULL) { CFRetain(mCFDictionary); } return mCFDictionary; }
+
+ CFMutableDictionaryRef GetMutableDict() { return mCFDictionary; }
+ CFMutableDictionaryRef GetCFMutableDictionary() const { return mCFDictionary; }
+ CFMutableDictionaryRef CopyCFMutableDictionary() const { if(mCFDictionary != NULL) { CFRetain(mCFDictionary); } return mCFDictionary; }
+ void SetCFMutableDictionaryFromCopy(CFDictionaryRef inDictionary, bool inRelease = true) { Release(); mCFDictionary = CFDictionaryCreateMutableCopy(NULL, 0, inDictionary); mMutable = true; mRelease = inRelease; }
+ void SetCFMutableDictionaryToEmpty(bool inRelease = true) { Release(); mCFDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); mMutable = true; mRelease = inRelease; }
+
+ CFPropertyListRef AsPropertyList() const { return mCFDictionary; }
+ OSStatus GetDictIfMutable(CFMutableDictionaryRef& outDict) const { OSStatus theAnswer = -1; if(mMutable) { outDict = mCFDictionary; theAnswer = 0; } return theAnswer; }
+
+// Item Operations
+public:
+ bool HasKey(const CFStringRef inKey) const;
+ UInt32 Size() const;
+ void GetKeys(const void** keys) const;
+ void GetKeysAndValues (const void **keys, const void **values) const;
+
+ bool GetBool(const CFStringRef inKey, bool& outValue) const;
+ bool GetSInt32(const CFStringRef inKey, SInt32& outValue) const;
+ bool GetUInt32(const CFStringRef inKey, UInt32& outValue) const;
+ bool GetUInt32FromString(const CFStringRef inKey, UInt32& outValue) const;
+ bool GetSInt64(const CFStringRef inKey, SInt64& outValue) const;
+ bool GetUInt64(const CFStringRef inKey, UInt64& outValue) const;
+ bool GetFloat32(const CFStringRef inKey, Float32& outValue) const;
+ bool GetFloat32FromString(const CFStringRef inKey, Float32& outValue) const;
+ bool GetFloat64(const CFStringRef inKey, Float64& outValue) const;
+ bool GetFixed32(const CFStringRef inKey, Float32& outValue) const;
+ bool GetFixed64(const CFStringRef inKey, Float64& outValue) const;
+ bool Get4CC(const CFStringRef inKey, UInt32& outValue) const;
+ bool GetString(const CFStringRef inKey, CFStringRef& outValue) const;
+ bool GetArray(const CFStringRef inKey, CFArrayRef& outValue) const;
+ bool GetDictionary(const CFStringRef inKey, CFDictionaryRef& outValue) const;
+ bool GetData(const CFStringRef inKey, CFDataRef& outValue) const;
+ bool GetCFType(const CFStringRef inKey, CFTypeRef& outValue) const;
+ bool GetURL(const CFStringRef inKey, CFURLRef& outValue) const;
+ bool GetCFTypeWithCStringKey(const char* inKey, CFTypeRef& outValue) const;
+
+ void GetCACFString(const CFStringRef inKey, CACFString& outItem) const;
+ void GetCACFArray(const CFStringRef inKey, CACFArray& outItem) const;
+ void GetCACFDictionary(const CFStringRef inKey, CACFDictionary& outItem) const;
+
+ bool AddBool(const CFStringRef inKey, bool inValue);
+ bool AddSInt32(const CFStringRef inKey, SInt32 inValue);
+ bool AddUInt32(const CFStringRef inKey, UInt32 inValue);
+ bool AddSInt64(const CFStringRef inKey, SInt64 inValue);
+ bool AddUInt64(const CFStringRef inKey, UInt64 inValue);
+ bool AddFloat32(const CFStringRef inKey, Float32 inValue);
+ bool AddFloat64(const CFStringRef inKey, Float64 inValue);
+ bool AddNumber(const CFStringRef inKey, const CFNumberRef inValue);
+ bool AddString(const CFStringRef inKey, const CFStringRef inValue);
+ bool AddArray(const CFStringRef inKey, const CFArrayRef inValue);
+ bool AddDictionary(const CFStringRef inKey, const CFDictionaryRef inValue);
+ bool AddData(const CFStringRef inKey, const CFDataRef inValue);
+ bool AddCFType(const CFStringRef inKey, const CFTypeRef inValue);
+ bool AddURL(const CFStringRef inKey, const CFURLRef inValue);
+
+ bool AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue);
+ bool AddCString(const CFStringRef inKey, const char* inValue);
+
+ void RemoveKey(const CFStringRef inKey) { if(CanModify()) { CFDictionaryRemoveValue(mCFDictionary, inKey); } }
+ void Clear() { if(CanModify()) { CFDictionaryRemoveAllValues(mCFDictionary); } }
+
+ void Show() { CFShow(mCFDictionary); }
+
+// Implementation
+private:
+ CFMutableDictionaryRef mCFDictionary;
+ bool mRelease;
+ bool mMutable;
+
+ CACFDictionary(const void*); // prevent accidental instantiation with a pointer via bool constructor
+};
+
+#endif //__CACFDictionary_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.cpp
new file mode 100644
index 0000000000..36c6923e2d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.cpp
@@ -0,0 +1,107 @@
+/*
+ File: CACFDistributedNotification.cpp
+ Abstract: CACFDistributedNotification.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CACFDistributedNotification.h"
+
+// PublicUtility Includes
+#include "CADebugMacros.h"
+
+//==================================================================================================
+// CACFDistributedNotification
+//==================================================================================================
+
+void CACFDistributedNotification::AddObserver(const void* inObserver, CFNotificationCallback inCallback, CFStringRef inName, CFNotificationSuspensionBehavior inSuspensionBehavior)
+{
+#if !TARGET_OS_IPHONE
+ CFNotificationCenterRef theCenter = CFNotificationCenterGetDistributedCenter();
+ CFNotificationSuspensionBehavior theSuspensionBehavior = inSuspensionBehavior;
+#else
+ #pragma unused(inSuspensionBehavior)
+ CFNotificationCenterRef theCenter = CFNotificationCenterGetDarwinNotifyCenter();
+ CFNotificationSuspensionBehavior theSuspensionBehavior = static_cast<CFNotificationSuspensionBehavior>(0);
+#endif
+
+ CFNotificationCenterAddObserver(theCenter, inObserver, inCallback, inName, NULL, theSuspensionBehavior);
+}
+
+void CACFDistributedNotification::RemoveObserver(const void* inObserver, CFStringRef inName)
+{
+#if !TARGET_OS_IPHONE
+ CFNotificationCenterRef theCenter = CFNotificationCenterGetDistributedCenter();
+#else
+ CFNotificationCenterRef theCenter = CFNotificationCenterGetDarwinNotifyCenter();
+#endif
+
+ CFNotificationCenterRemoveObserver(theCenter, inObserver, inName, NULL);
+}
+
+void CACFDistributedNotification::PostNotification(CFStringRef inName, CFDictionaryRef inUserInfo, bool inPostToAllSessions)
+{
+#if !TARGET_OS_IPHONE
+ CFNotificationCenterRef theCenter = CFNotificationCenterGetDistributedCenter();
+ CFDictionaryRef theUserInfo = inUserInfo;
+ CFOptionFlags theFlags = kCFNotificationDeliverImmediately;
+ if(inPostToAllSessions)
+ {
+ theFlags += kCFNotificationPostToAllSessions;
+ }
+#else
+ // flag unsupported features
+ Assert(inUserInfo == NULL, "CACFDistributedNotification::PostNotification: distributed notifications do not support a payload");
+ Assert(inPostToAllSessions, "CACFDistributedNotification::PostNotification: distributed notifications do not support per-session delivery");
+
+ CFNotificationCenterRef theCenter = CFNotificationCenterGetDarwinNotifyCenter();
+ CFDictionaryRef theUserInfo = NULL;
+ CFOptionFlags theFlags = 0;
+#endif
+
+ CFNotificationCenterPostNotificationWithOptions(theCenter, inName, NULL, theUserInfo, theFlags);
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.h b/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.h
new file mode 100644
index 0000000000..d75e23bd8a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.h
@@ -0,0 +1,73 @@
+/*
+ File: CACFDistributedNotification.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CACFDistributedNotification_h__)
+#define __CACFDistributedNotification_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// System Includes
+#include <CoreAudio/CoreAudioTypes.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+//==================================================================================================
+// CACFDistributedNotification
+//==================================================================================================
+
+class CACFDistributedNotification
+{
+
+// Operations
+public:
+ static void AddObserver(const void* inObserver, CFNotificationCallback inCallback, CFStringRef inName, CFNotificationSuspensionBehavior inSuspensionBehavior = CFNotificationSuspensionBehaviorCoalesce);
+ static void RemoveObserver(const void* inObserver, CFStringRef inName);
+ static void PostNotification(CFStringRef inName, CFDictionaryRef inUserInfo, bool inPostToAllSessions);
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.cpp
new file mode 100644
index 0000000000..9a33d5dae1
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.cpp
@@ -0,0 +1,168 @@
+/*
+ File: CACFMachPort.cpp
+ Abstract: CACFMachPort.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+#include "CACFMachPort.h"
+#include "CAException.h"
+#include "CADebugMacros.h"
+
+//==================================================================================================
+// CACFMachPort
+//==================================================================================================
+
+// This constructor is the short form. The CFMachPort will own the send and receive rights.
+CACFMachPort::CACFMachPort(CFMachPortCallBack inCallBack, void* inUserData)
+:
+ mMachPort(NULL),
+ mRunLoopSource(NULL),
+ mOwnsPort(true)
+{
+ CFMachPortContext theContext = { 1, inUserData, NULL, NULL, NULL };
+ mMachPort = CFMachPortCreate(NULL, inCallBack, &theContext, NULL);
+ ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort(s): couldn't create the CFMachPort");
+
+ mRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mMachPort, 0);
+ if(mRunLoopSource == NULL)
+ {
+ CFMachPortInvalidate(mMachPort);
+ CFRelease(mMachPort);
+ mMachPort = NULL;
+ DebugMessage("CACFMachPort::CACFMachPort(s): couldn't create the CFRunLoopSource");
+ throw CAException('what');
+ }
+}
+
+// This constructor is the general form:
+// - If inMachPort is MACH_PORT_NULL, the CFMachPort will allocate the port and own the send and
+// receive rights. Otherwise, the caller owns the rights and is resposible for cleaning them
+// up.
+// - If inCallBack is NULL, then received messages will just get swallowed by the CFMachPort.
+// This is useful if you are only using the CFMachPort to track port death (aka invalidation).
+// - If inInvalidationCallBack is non-NULL, then it will be installed as the invalidation
+// callback on the CFMachPort.
+CACFMachPort::CACFMachPort(mach_port_t inMachPort, CFMachPortCallBack inCallBack, CFMachPortInvalidationCallBack inInvalidationCallBack, void* inUserData)
+:
+ mMachPort(NULL),
+ mRunLoopSource(NULL),
+ mOwnsPort(false)
+{
+ CFMachPortContext theContext = { 1, inUserData, NULL, NULL, NULL };
+
+ if(inMachPort == MACH_PORT_NULL)
+ {
+ mMachPort = CFMachPortCreate(NULL, inCallBack, &theContext, NULL);
+ ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort: couldn't create the CFMachPort");
+ mOwnsPort = true;
+ }
+ else
+ {
+ mMachPort = CFMachPortCreateWithPort(NULL, inMachPort, inCallBack, &theContext, NULL);
+ ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort: couldn't create the CFMachPort with a port");
+ mOwnsPort = false;
+ }
+
+ mRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mMachPort, 0);
+ if(mRunLoopSource == NULL)
+ {
+ if(mOwnsPort)
+ {
+ CFMachPortInvalidate(mMachPort);
+ }
+ CFRelease(mMachPort);
+ mMachPort = NULL;
+ DebugMessage("CACFMachPort::CACFMachPort: couldn't create the CFRunLoopSource");
+ throw CAException('what');
+ }
+
+ if(inInvalidationCallBack != NULL)
+ {
+ CFMachPortSetInvalidationCallBack(mMachPort, inInvalidationCallBack);
+ }
+}
+
+CACFMachPort::~CACFMachPort()
+{
+ if(mRunLoopSource != NULL)
+ {
+ CFRelease(mRunLoopSource);
+ }
+
+ if(mMachPort != NULL)
+ {
+ if(mOwnsPort)
+ {
+ CFMachPortInvalidate(mMachPort);
+ }
+ CFRelease(mMachPort);
+ }
+}
+
+kern_return_t CACFMachPort::ReceiveMessage(UInt32 inMaxMessageSize, mach_msg_header_t* outMessage, mach_msg_timeout_t inTimeOut)
+{
+ // snag the port
+ mach_port_t thePort = CFMachPortGetPort(mMachPort);
+
+ // fill out the message header
+ outMessage->msgh_bits = 0;
+ outMessage->msgh_size = 0;
+ outMessage->msgh_remote_port = MACH_PORT_NULL;
+ outMessage->msgh_local_port = thePort;
+ outMessage->msgh_reserved = 0;
+ outMessage->msgh_id = 0;
+
+ // figure the options
+ mach_msg_options_t theOptions = MACH_RCV_MSG;
+ if(inTimeOut > 0)
+ {
+ theOptions |= MACH_RCV_TIMEOUT;
+ }
+
+ // receive the messsage
+ return mach_msg(outMessage, theOptions, 0, inMaxMessageSize, thePort, inTimeOut, MACH_PORT_NULL);
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.h b/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.h
new file mode 100644
index 0000000000..18b8ccc6c2
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.h
@@ -0,0 +1,95 @@
+/*
+ File: CACFMachPort.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CACFMachPort_h__)
+#define __CACFMachPort_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// System Includes
+#include <CoreFoundation/CFMachPort.h>
+#include <mach/mach.h>
+
+//==================================================================================================
+// CACFMachPort
+//
+// This class wraps a CFMachPort.
+//
+// Note that when you create a CFMachPort object, CF will attach the run loop source for the the
+// Mach Port that handles Port Death notifications (aka the Invalidation Callback) to the current
+// thread's run loop. This is something over which there is no control, so be sure to create the
+// CFMachPort on the thread on which you want to handle Port Death notificaitons on.
+//==================================================================================================
+
+class CACFMachPort
+{
+
+// Construction/Destruction
+public:
+ CACFMachPort(CFMachPortCallBack inCallBack, void* inUserData = NULL);
+ CACFMachPort(mach_port_t inMachPort, CFMachPortCallBack inCallBack, CFMachPortInvalidationCallBack inInvalidationCallBack, void* inUserData);
+ virtual ~CACFMachPort();
+
+// Attributes
+public:
+ CFMachPortRef GetMachPortRef() const { return mMachPort; }
+ mach_port_t GetMachPort() const { return CFMachPortGetPort(mMachPort); }
+ CFRunLoopSourceRef GetRunLoopSource() const { return mRunLoopSource; }
+
+// Operations
+public:
+ kern_return_t ReceiveMessage(UInt32 inMaxMessageSize, mach_msg_header_t* outMessage, mach_msg_timeout_t inTimeOut);
+
+// Implementation
+protected:
+ CFMachPortRef mMachPort;
+ CFRunLoopSourceRef mRunLoopSource;
+ bool mOwnsPort;
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.cpp
new file mode 100644
index 0000000000..97b5da1dd9
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.cpp
@@ -0,0 +1,163 @@
+/*
+ File: CACFMessagePort.cpp
+ Abstract: CACFMessagePort.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CACFMessagePort.h"
+#include "CADebugMacros.h"
+#include "CAException.h"
+
+//=============================================================================
+// CACFLocalMessagePort
+//=============================================================================
+
+CACFLocalMessagePort::CACFLocalMessagePort(CFStringRef inName, CFMessagePortCallBack inPortCallBack, CFMessagePortInvalidationCallBack inInvalidationCallBack, void* inUserData)
+:
+ mMessagePort(NULL),
+ mRunLoopSource(NULL),
+ mDispatchQueue(NULL)
+{
+ // create the CFMessagePort
+ CFMessagePortContext theContext = { 0, inUserData, NULL, NULL, NULL };
+ mMessagePort = CFMessagePortCreateLocal(NULL, inName, inPortCallBack, &theContext, NULL);
+ if(mMessagePort != NULL)
+ {
+ // add the invalidation callback, if any
+ if(inInvalidationCallBack != NULL)
+ {
+ CFMessagePortSetInvalidationCallBack(mMessagePort, inInvalidationCallBack);
+ }
+ }
+}
+
+CACFLocalMessagePort::~CACFLocalMessagePort()
+{
+ if(mRunLoopSource != NULL)
+ {
+ CFRelease(mRunLoopSource);
+ }
+ if(mMessagePort != NULL)
+ {
+ CFMessagePortInvalidate(mMessagePort);
+ CFRelease(mMessagePort);
+ }
+}
+
+CFRunLoopSourceRef CACFLocalMessagePort::GetRunLoopSource() const
+{
+ Assert(mDispatchQueue == NULL, "CACFLocalMessagePort::SetDispatchQueue: should have both a run loop source and a dispatch queue");
+ if(mRunLoopSource == NULL)
+ {
+ const_cast<CACFLocalMessagePort*>(this)->mRunLoopSource = CFMessagePortCreateRunLoopSource(NULL, mMessagePort, 0);
+ }
+ return mRunLoopSource;
+}
+
+void CACFLocalMessagePort::SetDispatchQueue(dispatch_queue_t inDispatchQueue)
+{
+ Assert(mRunLoopSource == NULL, "CACFLocalMessagePort::SetDispatchQueue: should have both a run loop source and a dispatch queue");
+ mDispatchQueue = inDispatchQueue;
+ CFMessagePortSetDispatchQueue(mMessagePort, mDispatchQueue);
+}
+
+//=============================================================================
+// CACFRemoteMessagePort
+//=============================================================================
+
+CACFRemoteMessagePort::CACFRemoteMessagePort(CFStringRef inName, CFMessagePortInvalidationCallBack inInvalidationCallBack)
+:
+ mMessagePort(NULL),
+ mRunLoopSource(NULL),
+ mDispatchQueue(NULL)
+{
+ // create the CFMessagePort
+ mMessagePort = CFMessagePortCreateRemote(NULL, inName);
+ if(mMessagePort != NULL)
+ {
+ // failure to create a remote port does not need to throw an exception
+ // because it isn't really an error since the port in question may not
+ // exist and this fact requires a more complex response than an excpeption
+ // provides for.
+
+ // add the invalidation callback, if any
+ if(inInvalidationCallBack != NULL)
+ {
+ CFMessagePortSetInvalidationCallBack(mMessagePort, inInvalidationCallBack);
+ }
+ }
+}
+
+CACFRemoteMessagePort::~CACFRemoteMessagePort()
+{
+ if(mRunLoopSource != NULL)
+ {
+ CFRelease(mRunLoopSource);
+ }
+ if(mMessagePort != NULL)
+ {
+ //CFMessagePortInvalidate(mMessagePort);
+ CFRelease(mMessagePort);
+ }
+}
+
+CFRunLoopSourceRef CACFRemoteMessagePort::GetRunLoopSource() const
+{
+ Assert(mDispatchQueue == NULL, "CACFRemoteMessagePort::SetDispatchQueue: should have both a run loop source and a dispatch queue");
+ if(mRunLoopSource == NULL)
+ {
+ const_cast<CACFRemoteMessagePort*>(this)->mRunLoopSource = CFMessagePortCreateRunLoopSource(NULL, mMessagePort, 0);
+ }
+ return mRunLoopSource;
+}
+
+void CACFRemoteMessagePort::SetDispatchQueue(dispatch_queue_t inDispatchQueue)
+{
+ Assert(mRunLoopSource == NULL, "CACFRemoteMessagePort::SetDispatchQueue: should have both a run loop source and a dispatch queue");
+ mDispatchQueue = inDispatchQueue;
+ CFMessagePortSetDispatchQueue(mMessagePort, mDispatchQueue);
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.h b/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.h
new file mode 100644
index 0000000000..c369251664
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.h
@@ -0,0 +1,119 @@
+/*
+ File: CACFMessagePort.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CACFMessagePort_h__)
+#define __CACFMessagePort_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CFMessagePort.h>
+#else
+ #include <CFMessagePort.h>
+#endif
+
+//=============================================================================
+// CACFLocalMessagePort
+//=============================================================================
+
+class CACFLocalMessagePort
+{
+
+// Construction/Destruction
+public:
+ CACFLocalMessagePort(CFStringRef inName, CFMessagePortCallBack inPortCallBack, CFMessagePortInvalidationCallBack inInvalidationCallBack, void* inUserData = NULL);
+ virtual ~CACFLocalMessagePort();
+
+// Attributes
+public:
+ bool IsValid() const { return mMessagePort != NULL; }
+ CFMessagePortRef GetMessagePortRef() const { return mMessagePort; }
+ CFRunLoopSourceRef GetRunLoopSource() const;
+ void SetDispatchQueue(dispatch_queue_t inDispatchQueue);
+
+// Implementation
+protected:
+ CFMessagePortRef mMessagePort;
+ CFRunLoopSourceRef mRunLoopSource;
+ dispatch_queue_t mDispatchQueue;
+
+};
+
+//=============================================================================
+// CACFRemoteMessagePort
+//=============================================================================
+
+class CACFRemoteMessagePort
+{
+
+// Construction/Destruction
+public:
+ CACFRemoteMessagePort(CFStringRef inName, CFMessagePortInvalidationCallBack inInvalidationCallBack);
+ virtual ~CACFRemoteMessagePort();
+
+// Attributes
+public:
+ bool IsValid() const { return mMessagePort != NULL; }
+ CFMessagePortRef GetMessagePortRef() const { return mMessagePort; }
+ CFRunLoopSourceRef GetRunLoopSource() const;
+ void SetDispatchQueue(dispatch_queue_t inDispatchQueue);
+
+// Operations
+public:
+ SInt32 SendRequest(SInt32 inMessageID, CFDataRef inData, CFTimeInterval inSendTimeout, CFTimeInterval inReceiveTimout) const { return CFMessagePortSendRequest(mMessagePort, inMessageID, inData, inSendTimeout, inReceiveTimout, NULL, NULL); }
+ SInt32 SendRequest(SInt32 inMessageID, CFDataRef inData, CFTimeInterval inSendTimeout, CFTimeInterval inReceiveTimout, CFStringRef inReplyMode, CFDataRef& outReturnData) const { return CFMessagePortSendRequest(mMessagePort, inMessageID, inData, inSendTimeout, inReceiveTimout, inReplyMode, &outReturnData); }
+
+// Implementation
+protected:
+ CFMessagePortRef mMessagePort;
+ CFRunLoopSourceRef mRunLoopSource;
+ dispatch_queue_t mDispatchQueue;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.cpp
new file mode 100644
index 0000000000..36d1c2e2e2
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.cpp
@@ -0,0 +1,83 @@
+/*
+ File: CACFNumber.cpp
+ Abstract: CACFNumber.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CACFNumber.h"
+
+//=============================================================================
+// CACFNumber
+//=============================================================================
+
+Float32 CACFNumber::GetFixed32() const
+{
+ SInt32 theFixedValue = GetSInt32();
+
+ // this is a 16.16 value so convert it to a float
+ Float32 theSign = theFixedValue < 0 ? -1.0f : 1.0f;
+ theFixedValue *= (SInt32)theSign;
+ Float32 theWholePart = (theFixedValue & 0x7FFF0000) >> 16;
+ Float32 theFractPart = theFixedValue & 0x0000FFFF;
+ theFractPart /= 65536.0f;
+
+ return theSign * (theWholePart + theFractPart);
+}
+
+Float64 CACFNumber::GetFixed64() const
+{
+ SInt64 theFixedValue = GetSInt64();
+
+ // this is a 32.32 value so convert it to a double
+ Float64 theSign = theFixedValue < 0 ? -1.0 : 1.0;
+ theFixedValue *= (SInt64)theSign;
+ Float64 theWholePart = (theFixedValue & 0x7FFFFFFF00000000LL) >> 32;
+ Float64 theFractPart = theFixedValue & 0x00000000FFFFFFFFLL;
+ theFractPart /= 4294967296.0;
+
+ return theSign * (theWholePart + theFractPart);
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.h b/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.h
new file mode 100644
index 0000000000..25887f6ca1
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFNumber.h
@@ -0,0 +1,151 @@
+/*
+ File: CACFNumber.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CACFNumber_h__)
+#define __CACFNumber_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <CoreFoundation/CFNumber.h>
+#else
+ #include <CoreAudioTypes.h>
+ #include <CFNumber.h>
+#endif
+
+//=============================================================================
+// CACFBoolean
+//=============================================================================
+
+class CACFBoolean
+{
+// Construction/Destruction
+public:
+ explicit CACFBoolean(CFBooleanRef inCFBoolean) : mCFBoolean(inCFBoolean), mWillRelease(true) {}
+ CACFBoolean(CFBooleanRef inCFBoolean, bool inWillRelease) : mCFBoolean(inCFBoolean), mWillRelease(inWillRelease) {}
+ explicit CACFBoolean(bool inValue) : mCFBoolean(inValue ? kCFBooleanTrue : kCFBooleanFalse), mWillRelease(true) { Retain(); }
+ ~CACFBoolean() { Release(); }
+ CACFBoolean(const CACFBoolean& inBoolean) : mCFBoolean(inBoolean.mCFBoolean), mWillRelease(inBoolean.mWillRelease) { Retain(); }
+ CACFBoolean& operator=(const CACFBoolean& inBoolean) { Release(); mCFBoolean = inBoolean.mCFBoolean; mWillRelease = inBoolean.mWillRelease; Retain(); return *this; }
+ CACFBoolean& operator=(CFBooleanRef inCFBoolean) { Release(); mCFBoolean = inCFBoolean; mWillRelease = true; return *this; }
+
+private:
+ void Retain() { if(mWillRelease && (mCFBoolean != NULL)) { CFRetain(mCFBoolean); } }
+ void Release() { if(mWillRelease && (mCFBoolean != NULL)) { CFRelease(mCFBoolean); } }
+
+ CFBooleanRef mCFBoolean;
+ bool mWillRelease;
+
+// Operations
+public:
+ void AllowRelease() { mWillRelease = true; }
+ void DontAllowRelease() { mWillRelease = false; }
+ bool IsValid() { return mCFBoolean != NULL; }
+
+// Value Access
+public:
+ CFBooleanRef GetCFBoolean() const { return mCFBoolean; }
+ CFBooleanRef CopyCFBoolean() const { if(mCFBoolean != NULL) { CFRetain(mCFBoolean); } return mCFBoolean; }
+
+ bool GetBoolean() const { bool theAnswer = false; if(mCFBoolean != NULL) { theAnswer = CFEqual(mCFBoolean, kCFBooleanTrue); } return theAnswer; }
+
+ CACFBoolean(const void*); // prevent accidental instantiation with a pointer via bool constructor
+};
+
+//=============================================================================
+// CACFNumber
+//=============================================================================
+
+class CACFNumber
+{
+// Construction/Destruction
+public:
+ explicit CACFNumber(CFNumberRef inCFNumber) : mCFNumber(inCFNumber), mWillRelease(true) {}
+ CACFNumber(CFNumberRef inCFNumber, bool inWillRelease) : mCFNumber(inCFNumber), mWillRelease(inWillRelease) {}
+ CACFNumber(SInt32 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt32Type, &inValue)), mWillRelease(true) {}
+ CACFNumber(UInt32 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt32Type, &inValue)), mWillRelease(true) {}
+ CACFNumber(SInt64 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt64Type, &inValue)), mWillRelease(true) {}
+ CACFNumber(UInt64 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt64Type, &inValue)), mWillRelease(true) {}
+ CACFNumber(Float32 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberFloat32Type, &inValue)), mWillRelease(true) {}
+ CACFNumber(Float64 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberFloat64Type, &inValue)), mWillRelease(true) {}
+ ~CACFNumber() { Release(); }
+ CACFNumber(const CACFNumber& inNumber) : mCFNumber(inNumber.mCFNumber), mWillRelease(inNumber.mWillRelease) { Retain(); }
+ CACFNumber& operator=(const CACFNumber& inNumber) { Release(); mCFNumber = inNumber.mCFNumber; mWillRelease = inNumber.mWillRelease; Retain(); return *this; }
+ CACFNumber& operator=(CFNumberRef inCFNumber) { Release(); mCFNumber = inCFNumber; mWillRelease = true; return *this; }
+
+private:
+ void Retain() { if(mWillRelease && (mCFNumber != NULL)) { CFRetain(mCFNumber); } }
+ void Release() { if(mWillRelease && (mCFNumber != NULL)) { CFRelease(mCFNumber); } }
+
+ CFNumberRef mCFNumber;
+ bool mWillRelease;
+
+// Operations
+public:
+ void AllowRelease() { mWillRelease = true; }
+ void DontAllowRelease() { mWillRelease = false; }
+ bool IsValid() const { return mCFNumber != NULL; }
+
+// Value Access
+public:
+ CFNumberRef GetCFNumber() const { return mCFNumber; }
+ CFNumberRef CopyCFNumber() const { if(mCFNumber != NULL) { CFRetain(mCFNumber); } return mCFNumber; }
+
+ SInt8 GetSInt8() const { SInt8 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt8Type, &theAnswer); } return theAnswer; }
+ SInt32 GetSInt32() const { SInt32 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt32Type, &theAnswer); } return theAnswer; }
+ UInt32 GetUInt32() const { UInt32 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt32Type, &theAnswer); } return theAnswer; }
+ Float32 GetFloat32() const { Float32 theAnswer = 0.0f; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberFloat32Type, &theAnswer); } return theAnswer; }
+ Float32 GetFixed32() const;
+ Float64 GetFixed64() const;
+ SInt64 GetSInt64() const { SInt64 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt64Type, &theAnswer); } return theAnswer; }
+
+ CACFNumber(const void*); // prevent accidental instantiation with a pointer via bool constructor
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFObject.h b/libs/appleutility/CoreAudio/PublicUtility/CACFObject.h
new file mode 100644
index 0000000000..748016b48f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFObject.h
@@ -0,0 +1,138 @@
+/*
+ File: CACFObject.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CACFObject_h__)
+#define __CACFObject_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include <CoreAudioTypes.h>
+ #include <CoreFoundation.h>
+#endif
+
+//=============================================================================
+// Wrappers for CFRetain and CFRelease that check for NULL
+//=============================================================================
+
+template <typename CFObjectType>
+CFObjectType CACFRetain(CFObjectType inObject)
+{
+ CFObjectType theAnswer = inObject;
+ if(inObject != NULL)
+ {
+ theAnswer = reinterpret_cast<CFObjectType>(CFRetain(inObject));
+ }
+ return theAnswer;
+}
+
+inline void CACFRelease(CFTypeRef inObject)
+{
+ if(inObject != NULL)
+ {
+ CFRelease(inObject);
+ }
+}
+
+//=============================================================================
+// CACFObject
+//
+// Notes
+// - Using the AssignWithoutRetain() method will fool the static analyzer into thinking that the
+// CFObject being assigned will be leaked. This is because the static analyzer is not smart
+// enough to understand that the destructor will release the object.
+//=============================================================================
+
+template <class CFObjectType>
+class CACFObject
+{
+
+// Construction/Destruction
+public:
+ CACFObject() : mCFObject(NULL), mWillRelease(true) {}
+ explicit CACFObject(CFObjectType inCFObject) : mCFObject(inCFObject), mWillRelease(true) {}
+ CACFObject(CFObjectType inCFObject, bool inWillRelease) : mCFObject(inCFObject), mWillRelease(inWillRelease) {}
+ ~CACFObject() { Release(); }
+ CACFObject(const CACFObject& inObject) : mCFObject(inObject.mCFObject), mWillRelease(inObject.mWillRelease) { Retain(); }
+ CACFObject& operator=(const CACFObject& inObject) { Release(); mCFObject = inObject.mCFObject; mWillRelease = inObject.mWillRelease; Retain(); return *this; }
+ CACFObject& operator=(CFObjectType inCFObject) { Release(); mCFObject = inCFObject; mWillRelease = true; Retain(); return *this; }
+ void AssignWithoutRetain(CFObjectType inObject) { if (inObject != mCFObject) { Release(); mCFObject = inObject; } mWillRelease = true; }
+
+private:
+ void Retain() { if(mWillRelease && (mCFObject != NULL)) { CFRetain(mCFObject); } }
+ void Release() { if(mWillRelease && (mCFObject != NULL)) { CFRelease(mCFObject); mCFObject = NULL; } }
+
+ CFObjectType mCFObject;
+ bool mWillRelease;
+
+// Operations
+public:
+ void AllowRelease() { mWillRelease = true; }
+ void DontAllowRelease() { mWillRelease = false; }
+ bool IsValid() const { return mCFObject != NULL; }
+ CFTypeID GetTypeID() const { return CFGetTypeID(mCFObject); }
+ bool IsEqual(CFObjectType inCFObject) const { return CFEqual(inCFObject, mCFObject) != 0; }
+
+// Value Access
+public:
+ CFObjectType GetCFObject() const { return mCFObject; }
+ CFObjectType CopyCFObject() const { if(mCFObject != NULL) { CFRetain(mCFObject); } return mCFObject; }
+ const CFObjectType* GetPointerToStorage() const { return &mCFObject; }
+
+};
+
+typedef CACFObject<CFBundleRef> CACFBundle;
+typedef CACFObject<CFPropertyListRef> CACFPropertyList;
+typedef CACFObject<CFTypeRef> CACFType;
+typedef CACFObject<CFUUIDRef> CACFUUID;
+typedef CACFObject<CFURLRef> CACFURL;
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFPlugIn.h b/libs/appleutility/CoreAudio/PublicUtility/CACFPlugIn.h
new file mode 100644
index 0000000000..babde13b90
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFPlugIn.h
@@ -0,0 +1,101 @@
+/*
+ File: CACFPlugIn.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CACFPlugIn_h__)
+#define __CACFPlugIn_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// System Includes
+#include <CoreAudio/CoreAudioTypes.h>
+#include <CoreFoundation/CFPlugIn.h>
+
+//==================================================================================================
+// CACFPlugIn
+//==================================================================================================
+
+class CACFPlugIn
+{
+
+// Construction/Destruction
+public:
+ CACFPlugIn() : mCFPlugIn(NULL), mWillRelease(true) {}
+ CACFPlugIn(CFPlugInRef inCFPlugIn, bool inWillRelease = true) : mCFPlugIn(inCFPlugIn), mWillRelease(inWillRelease) {}
+ CACFPlugIn(CFURLRef inURL, bool inWillRelease = true) : mCFPlugIn(CFPlugInCreate(NULL, inURL)), mWillRelease(inWillRelease) {}
+ ~CACFPlugIn() { Release(); }
+ CACFPlugIn(const CACFPlugIn& inObject) : mCFPlugIn(inObject.mCFPlugIn), mWillRelease(inObject.mWillRelease) { Retain(); }
+ CACFPlugIn& operator=(const CACFPlugIn& inObject) { Release(); mCFPlugIn = inObject.mCFPlugIn; mWillRelease = inObject.mWillRelease; Retain(); return *this; }
+ CACFPlugIn& operator=(CFPlugInRef inCFPlugIn) { Release(); mCFPlugIn = inCFPlugIn; mWillRelease = true; return *this; }
+
+private:
+ void Retain() { if(mWillRelease && (mCFPlugIn != NULL)) { CFRetain(mCFPlugIn); } }
+ void Release() { if(mWillRelease && (mCFPlugIn != NULL)) { CFRelease(mCFPlugIn); mCFPlugIn = NULL; } }
+
+ CFPlugInRef mCFPlugIn;
+ bool mWillRelease;
+
+// Operations
+public:
+ void AllowRelease() { mWillRelease = true; }
+ void DontAllowRelease() { mWillRelease = false; }
+ bool IsValid() const { return mCFPlugIn != NULL; }
+
+ CFBundleRef GetBundle() const { CFBundleRef theAnswer = NULL; if(IsValid()) { theAnswer = CFPlugInGetBundle(mCFPlugIn); } return theAnswer; }
+ CFStringRef CopyBundleID() const { CFStringRef theAnswer = NULL; CFBundleRef theBundle = GetBundle(); if(IsValid() && (theBundle != NULL)) { theAnswer = CFBundleGetIdentifier(theBundle); if(theAnswer != NULL) { CFRetain(theAnswer); } } return theAnswer; }
+ UInt32 GetBundleVersion() const { UInt32 theAnswer = 0; CFBundleRef theBundle = GetBundle(); if(IsValid() && (theBundle != NULL)) { theAnswer = CFBundleGetVersionNumber(theBundle); } return theAnswer; }
+ CFDictionaryRef CopyBundleInfo() const { CFDictionaryRef theAnswer = NULL; CFBundleRef theBundle = GetBundle(); if(IsValid() && (theBundle != NULL)) { theAnswer = CFBundleGetInfoDictionary(theBundle); if(theAnswer != NULL) { CFRetain(theAnswer); } } return theAnswer; }
+ CFArrayRef FindFactoriesForType(CFUUIDRef inTypeUUID) const { CFArrayRef theAnswer = NULL; if(IsValid()) { theAnswer = CFPlugInFindFactoriesForPlugInTypeInPlugIn(inTypeUUID, mCFPlugIn); } return theAnswer; }
+
+// Value Access
+public:
+ CFPlugInRef GetCFPlugIn() const { return mCFPlugIn; }
+ CFPlugInRef CopyCFPlugIn() const { if(mCFPlugIn != NULL) { CFRetain(mCFPlugIn); } return mCFPlugIn; }
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.cpp
new file mode 100644
index 0000000000..cb2e86c34d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.cpp
@@ -0,0 +1,287 @@
+/*
+ File: CACFPreferences.cpp
+ Abstract: CACFPreferences.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CACFPreferences.h"
+
+// PublicUtility Includes
+#include "CACFDistributedNotification.h"
+#include "CADebugMacros.h"
+
+//==================================================================================================
+// CACFPreferences
+//==================================================================================================
+
+CFPropertyListRef CACFPreferences::CopyValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost)
+{
+ // synchronize to make sure that what's in memory matches what's on disk
+ Synchronize(inCurrentUser, inCurrentHost, false);
+
+ CFPropertyListRef theAnswer = NULL;
+ CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
+ CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost;
+
+ theAnswer = CFPreferencesCopyValue(inKey, kCFPreferencesAnyApplication, theUser, theHost);
+
+ return theAnswer;
+}
+
+CFStringRef CACFPreferences::CopyStringValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost)
+{
+ CFStringRef theAnswer = NULL;
+
+ // get the raw value
+ CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost);
+
+ if(theRawValue != NULL)
+ {
+ // get it's type ID and make sure it's a CFString
+ CFTypeID theTypeID = CFGetTypeID(theRawValue);
+ if(theTypeID == CFStringGetTypeID())
+ {
+ // cast the value
+ theAnswer = static_cast<CFStringRef>(theRawValue);
+ }
+ else
+ {
+ CFRelease(theRawValue);
+ DebugMessage("CACFPreferences::CopyStringValue: not a CFString");
+ }
+ }
+
+ return theAnswer;
+}
+
+CFNumberRef CACFPreferences::CopyNumberValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost)
+{
+ CFNumberRef theAnswer = NULL;
+
+ // get the raw value
+ CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost);
+
+ if(theRawValue != NULL)
+ {
+ // get it's type ID and make sure it's a CFNumber
+ CFTypeID theTypeID = CFGetTypeID(theRawValue);
+ if(theTypeID == CFNumberGetTypeID())
+ {
+ // cast the value
+ theAnswer = static_cast<CFNumberRef>(theRawValue);
+ }
+ else
+ {
+ CFRelease(theRawValue);
+ DebugMessage("CACFPreferences::CopyNumberValue: not a CFNumber");
+ }
+ }
+
+ return theAnswer;
+}
+
+CFArrayRef CACFPreferences::CopyArrayValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost)
+{
+ CFArrayRef theAnswer = NULL;
+
+ // get the raw value
+ CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost);
+
+ if(theRawValue != NULL)
+ {
+ // get it's type ID and make sure it's a CFArray
+ CFTypeID theTypeID = CFGetTypeID(theRawValue);
+ if(theTypeID == CFArrayGetTypeID())
+ {
+ // cast the value
+ theAnswer = static_cast<CFArrayRef>(theRawValue);
+ }
+ else
+ {
+ CFRelease(theRawValue);
+ DebugMessage("CACFPreferences::CopyArrayValue: not a CFArray");
+ }
+ }
+
+ return theAnswer;
+}
+
+CFDictionaryRef CACFPreferences::CopyDictionaryValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost)
+{
+ CFDictionaryRef theAnswer = NULL;
+
+ // get the raw value
+ CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost);
+
+ if(theRawValue != NULL)
+ {
+ // get it's type ID and make sure it's a CFDictionary
+ CFTypeID theTypeID = CFGetTypeID(theRawValue);
+ if(theTypeID == CFDictionaryGetTypeID())
+ {
+ // cast the value
+ theAnswer = static_cast<CFDictionaryRef>(theRawValue);
+ }
+ else
+ {
+ CFRelease(theRawValue);
+ DebugMessage("CACFPreferences::CopyDictionaryValue: not a CFDictionary");
+ }
+ }
+
+ return theAnswer;
+}
+
+void CACFPreferences::SetValue(CFStringRef inKey, CFPropertyListRef inValue, bool inCurrentUser, bool inCurrentHost, bool inSynchronize)
+{
+ CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
+ CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost;
+ CFPreferencesSetValue(inKey, inValue, kCFPreferencesAnyApplication, theUser, theHost);
+
+ if(inSynchronize)
+ {
+ Synchronize(inCurrentUser, inCurrentHost, true);
+ }
+}
+
+void CACFPreferences::DeleteValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost, bool inSynchronize)
+{
+ CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
+ CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost;
+ CFPreferencesSetValue(inKey, NULL, kCFPreferencesAnyApplication, theUser, theHost);
+
+ if(inSynchronize)
+ {
+ Synchronize(theUser, inCurrentHost, true);
+ }
+}
+
+void CACFPreferences::Synchronize(bool inCurrentUser, bool inCurrentHost, bool inForce)
+{
+ if(inForce || ArePrefsOutOfDate(inCurrentUser, inCurrentHost))
+ {
+ CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
+ CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost;
+ CFPreferencesSynchronize(kCFPreferencesAnyApplication, theUser, theHost);
+ MarkPrefsClean(inCurrentUser, inCurrentHost);
+ }
+}
+
+void CACFPreferences::MarkPrefsOutOfDate(bool inCurrentUser, bool inCurrentHost)
+{
+ if(!inCurrentUser && !inCurrentHost)
+ {
+ sAnyUserAnyHostPrefsOutOfDate = true;
+ }
+ else if(!inCurrentUser && inCurrentHost)
+ {
+ sAnyUserCurrentHostPrefsOutOfDate = true;
+ }
+ else if(inCurrentUser && !inCurrentHost)
+ {
+ sCurrentUserAnyHostPrefsOutOfDate = true;
+ }
+ else if(inCurrentUser && inCurrentHost)
+ {
+ sCurrentUserCurrentHostPrefsOutOfDate = true;
+ }
+}
+
+void CACFPreferences::MarkPrefsClean(bool inCurrentUser, bool inCurrentHost)
+{
+ if(!inCurrentUser && !inCurrentHost)
+ {
+ sAnyUserAnyHostPrefsOutOfDate = false;
+ }
+ else if(!inCurrentUser && inCurrentHost)
+ {
+ sAnyUserCurrentHostPrefsOutOfDate = false;
+ }
+ else if(inCurrentUser && !inCurrentHost)
+ {
+ sCurrentUserAnyHostPrefsOutOfDate = false;
+ }
+ else if(inCurrentUser && inCurrentHost)
+ {
+ sCurrentUserCurrentHostPrefsOutOfDate = false;
+ }
+}
+
+void CACFPreferences::SendNotification(CFStringRef inName)
+{
+ CACFDistributedNotification::PostNotification(inName, NULL, true);
+}
+
+bool CACFPreferences::ArePrefsOutOfDate(bool inCurrentUser, bool inCurrentHost)
+{
+ bool theAnswer = false;
+
+ if(!inCurrentUser && !inCurrentHost)
+ {
+ theAnswer = sAnyUserAnyHostPrefsOutOfDate;
+ }
+ else if(!inCurrentUser && inCurrentHost)
+ {
+ theAnswer = sAnyUserCurrentHostPrefsOutOfDate;
+ }
+ else if(inCurrentUser && !inCurrentHost)
+ {
+ theAnswer = sCurrentUserAnyHostPrefsOutOfDate;
+ }
+ else if(inCurrentUser && inCurrentHost)
+ {
+ theAnswer = sCurrentUserCurrentHostPrefsOutOfDate;
+ }
+
+ return theAnswer;
+}
+
+bool CACFPreferences::sAnyUserAnyHostPrefsOutOfDate = false;
+bool CACFPreferences::sAnyUserCurrentHostPrefsOutOfDate = false;
+bool CACFPreferences::sCurrentUserAnyHostPrefsOutOfDate = false;
+bool CACFPreferences::sCurrentUserCurrentHostPrefsOutOfDate = false;
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.h b/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.h
new file mode 100644
index 0000000000..040490f74e
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.h
@@ -0,0 +1,92 @@
+/*
+ File: CACFPreferences.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CACFPreferences_h__)
+#define __CACFPreferences_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include <CoreFoundation.h>
+#endif
+
+//==================================================================================================
+// CACFPreferences
+//==================================================================================================
+
+class CACFPreferences
+{
+
+// Operations
+public:
+ static CFPropertyListRef CopyValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost);
+ static CFStringRef CopyStringValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost);
+ static CFNumberRef CopyNumberValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost);
+ static CFArrayRef CopyArrayValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost);
+ static CFDictionaryRef CopyDictionaryValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost);
+ static void SetValue(CFStringRef inKey, CFPropertyListRef inValue, bool inCurrentUser, bool inCurrentHost, bool inSynchronize);
+ static void DeleteValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost, bool inSynchronize);
+ static void Synchronize(bool inCurrentUser, bool inCurrentHost, bool inForce);
+ static void MarkPrefsOutOfDate(bool inCurrentUser, bool inCurrentHost);
+ static void MarkPrefsClean(bool inCurrentUser, bool inCurrentHost);
+ static void SendNotification(CFStringRef inName);
+
+private:
+ static bool ArePrefsOutOfDate(bool inCurrentUser, bool inCurrentHost);
+
+ static bool sAnyUserAnyHostPrefsOutOfDate;
+ static bool sAnyUserCurrentHostPrefsOutOfDate;
+ static bool sCurrentUserAnyHostPrefsOutOfDate;
+ static bool sCurrentUserCurrentHostPrefsOutOfDate;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFString.cpp b/libs/appleutility/CoreAudio/PublicUtility/CACFString.cpp
new file mode 100644
index 0000000000..3ce81a56f4
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFString.cpp
@@ -0,0 +1,110 @@
+/*
+ File: CACFString.cpp
+ Abstract: CACFString.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CACFString.h"
+
+//=============================================================================
+// CACFString
+//=============================================================================
+
+UInt32 CACFString::GetStringByteLength(CFStringRef inCFString, CFStringEncoding inEncoding)
+{
+ CFIndex theAnswer = 0;
+
+ if(inCFString != NULL)
+ {
+ CFRange theRange = { 0, CFStringGetLength(inCFString) };
+ CFStringGetBytes(inCFString, theRange, inEncoding, 0, false, NULL, 0x7FFFFFFF, &theAnswer);
+ }
+
+ return UInt32(theAnswer);
+}
+
+void CACFString::GetCString(CFStringRef inCFString, char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding)
+{
+ if(ioStringSize > 0)
+ {
+ if(inCFString != NULL)
+ {
+ CFIndex theLength = 0;
+ CFRange theRange = { 0, CFStringGetLength(inCFString) };
+ CFStringGetBytes(inCFString, theRange, inEncoding, 0, false, (UInt8*)outString, static_cast<CFIndex>(ioStringSize - 1), &theLength);
+ outString[theLength] = 0;
+ ioStringSize = ToUInt32(theLength) + 1;
+ }
+ else
+ {
+ outString[0] = 0;
+ ioStringSize = 1;
+ }
+ }
+}
+
+void CACFString::GetUnicodeString(CFStringRef inCFString, UInt16* outString, UInt32& ioStringSize)
+{
+ if(ioStringSize > 0)
+ {
+ if(inCFString != NULL)
+ {
+ CFRange theStringRange = { 0, CFStringGetLength(inCFString) };
+ if(static_cast<UInt32>(theStringRange.length) > ioStringSize)
+ {
+ theStringRange.length = static_cast<CFIndex>(ioStringSize);
+ }
+ CFStringGetCharacters(inCFString, theStringRange, outString);
+ ioStringSize = ToUInt32(theStringRange.length);
+ }
+ else
+ {
+ outString[0] = 0;
+ ioStringSize = 0;
+ }
+ }
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CACFString.h b/libs/appleutility/CoreAudio/PublicUtility/CACFString.h
new file mode 100644
index 0000000000..3abce514bf
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CACFString.h
@@ -0,0 +1,196 @@
+/*
+ File: CACFString.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CACFString_h__)
+#define __CACFString_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CADebugMacros.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <CoreFoundation/CFString.h>
+#else
+ #include <CoreAudioTypes.h>
+ #include <CFString.h>
+#endif
+
+//=============================================================================
+// CACFString
+//
+// Notes
+// - Using the AssignWithoutRetain() method will fool the static analyzer into thinking that the
+// CFString being assigned will be leaked. This is because the static analyzer is not smart
+// enough to understand that the destructor will release the object.
+//=============================================================================
+
+class CACFString
+{
+// Construction/Destruction
+public:
+ CACFString() : mCFString(NULL), mWillRelease(true) {}
+ explicit CACFString(CFStringRef inCFString) : mCFString(inCFString), mWillRelease(true) {}
+ CACFString(const char* inCString) : mCFString(CFStringCreateWithCString(NULL, inCString, kCFStringEncodingASCII)), mWillRelease(true) {}
+ CACFString(CFStringRef inCFString, bool inWillRelease) : mCFString(inCFString), mWillRelease(inWillRelease) {}
+ CACFString(const char* inCString, bool inWillRelease) : mCFString(CFStringCreateWithCString(NULL, inCString, kCFStringEncodingASCII)), mWillRelease(inWillRelease) {}
+ CACFString(const char* inCString, CFStringEncoding inCStringEncoding, bool inWillRelease = true) : mCFString(CFStringCreateWithCString(NULL, inCString, inCStringEncoding)), mWillRelease(inWillRelease) {}
+ ~CACFString() { Release(); }
+ CACFString(const CACFString& inString) : mCFString(inString.mCFString), mWillRelease(inString.mWillRelease) { Retain(); }
+ CACFString& operator=(const CACFString& inString) { if (inString.mCFString != mCFString) { Release(); mCFString = inString.mCFString; mWillRelease = inString.mWillRelease; Retain(); } return *this; }
+ CACFString& operator=(CFStringRef inCFString) { if (inCFString != mCFString) { Release(); mCFString = inCFString; } mWillRelease = true; Retain(); return *this; }
+ void AssignWithoutRetain(CFStringRef inCFString) { if (inCFString != mCFString) { Release(); mCFString = inCFString; } mWillRelease = true; }
+
+private:
+ void Retain() { if(mWillRelease && (mCFString != NULL)) { CFRetain(mCFString); } }
+ void Release() { if(mWillRelease && (mCFString != NULL)) { CFRelease(mCFString); } }
+
+ CFStringRef mCFString;
+ bool mWillRelease;
+
+// Operations
+public:
+ void AllowRelease() { mWillRelease = true; }
+ void DontAllowRelease() { mWillRelease = false; }
+ bool IsValid() const { return mCFString != NULL; }
+ bool IsEqualTo(CFStringRef inString) const { bool theAnswer = false; if(mCFString != NULL) { theAnswer = CFStringCompare(inString, mCFString, 0) == kCFCompareEqualTo; } return theAnswer; }
+ bool StartsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFString != NULL) { theAnswer = CFStringHasPrefix(mCFString, inString); } return theAnswer; }
+ bool EndsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFString != NULL) { theAnswer = CFStringHasSuffix(mCFString, inString); } return theAnswer; }
+
+// Value Access
+public:
+ CFStringRef GetCFString() const { return mCFString; }
+ CFStringRef CopyCFString() const { if(mCFString != NULL) { CFRetain(mCFString); } return mCFString; }
+ const CFStringRef* GetPointerToStorage() const { return &mCFString; }
+ CFStringRef& GetStorage() { Release(); mWillRelease = true; return mCFString; }
+ UInt32 GetLength() const { UInt32 theAnswer = 0; if(mCFString != NULL) { theAnswer = ToUInt32(CFStringGetLength(mCFString)); } return theAnswer; }
+ UInt32 GetByteLength(CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { UInt32 theAnswer = 0; if(mCFString != NULL) { theAnswer = GetStringByteLength(mCFString, inEncoding); } return theAnswer; }
+ void GetCString(char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { GetCString(mCFString, outString, ioStringSize, inEncoding); }
+ void GetUnicodeString(UInt16* outString, UInt32& ioStringSize) const { GetUnicodeString(mCFString, outString, ioStringSize); }
+ SInt32 GetAsInteger() { return GetAsInteger(mCFString); }
+ Float64 GetAsFloat64() { return GetAsFloat64(mCFString); }
+
+ static UInt32 GetStringLength(CFStringRef inCFString) { UInt32 theAnswer = 0; if(inCFString != NULL) { theAnswer = ToUInt32(CFStringGetLength(inCFString)); } return theAnswer; }
+ static UInt32 GetStringByteLength(CFStringRef inCFString, CFStringEncoding inEncoding = kCFStringEncodingUTF8);
+ static void GetCString(CFStringRef inCFString, char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8);
+ static void GetUnicodeString(CFStringRef inCFString, UInt16* outString, UInt32& ioStringSize);
+ static SInt32 GetAsInteger(CFStringRef inCFString) { SInt32 theAnswer = 0; if(inCFString != NULL){ theAnswer = CFStringGetIntValue(inCFString); } return theAnswer; }
+ static Float64 GetAsFloat64(CFStringRef inCFString) { Float64 theAnswer = 0; if(inCFString != NULL){ theAnswer = CFStringGetDoubleValue(inCFString); } return theAnswer; }
+
+};
+
+inline bool operator<(const CACFString& x, const CACFString& y) { return CFStringCompare(x.GetCFString(), y.GetCFString(), 0) == kCFCompareLessThan; }
+inline bool operator==(const CACFString& x, const CACFString& y) { return CFStringCompare(x.GetCFString(), y.GetCFString(), 0) == kCFCompareEqualTo; }
+inline bool operator!=(const CACFString& x, const CACFString& y) { return !(x == y); }
+inline bool operator<=(const CACFString& x, const CACFString& y) { return (x < y) || (x == y); }
+inline bool operator>=(const CACFString& x, const CACFString& y) { return !(x < y); }
+inline bool operator>(const CACFString& x, const CACFString& y) { return !((x < y) || (x == y)); }
+
+inline bool operator<(const CACFString& x, CFStringRef y) { return CFStringCompare(x.GetCFString(), y, 0) == kCFCompareLessThan; }
+inline bool operator==(const CACFString& x, CFStringRef y) { return CFStringCompare(x.GetCFString(), y, 0) == kCFCompareEqualTo; }
+inline bool operator!=(const CACFString& x, CFStringRef y) { return !(x == y); }
+inline bool operator<=(const CACFString& x, CFStringRef y) { return (x < y) || (x == y); }
+inline bool operator>=(const CACFString& x, CFStringRef y) { return !(x < y); }
+inline bool operator>(const CACFString& x, CFStringRef y) { return !((x < y) || (x == y)); }
+
+inline bool operator<(CFStringRef x, const CACFString& y) { return CFStringCompare(x, y.GetCFString(), 0) == kCFCompareLessThan; }
+inline bool operator==(CFStringRef x, const CACFString& y) { return CFStringCompare(x, y.GetCFString(), 0) == kCFCompareEqualTo; }
+inline bool operator!=(CFStringRef x, const CACFString& y) { return !(x == y); }
+inline bool operator<=(CFStringRef x, const CACFString& y) { return (x < y) || (x == y); }
+inline bool operator>=(CFStringRef x, const CACFString& y) { return !(x < y); }
+inline bool operator>(CFStringRef x, const CACFString& y) { return !((x < y) || (x == y)); }
+
+//=============================================================================
+// CACFMutableString
+//=============================================================================
+
+class CACFMutableString
+{
+// Construction/Destruction
+public:
+ CACFMutableString() : mCFMutableString(NULL), mWillRelease(true) {}
+ CACFMutableString(CFMutableStringRef inCFMutableString, bool inWillRelease = true) : mCFMutableString(inCFMutableString), mWillRelease(inWillRelease) {}
+ CACFMutableString(CFStringRef inStringToCopy, bool /*inMakeCopy*/, bool inWillRelease = true) : mCFMutableString(CFStringCreateMutableCopy(NULL, 0, inStringToCopy)), mWillRelease(inWillRelease) {}
+ CACFMutableString(const char* inCString, bool inWillRelease = true) : mCFMutableString(NULL), mWillRelease(inWillRelease) { CACFString theString(inCString); mCFMutableString = CFStringCreateMutableCopy(NULL, 0, theString.GetCFString()); }
+ CACFMutableString(const char* inCString, CFStringEncoding inCStringEncoding, bool inWillRelease = true) : mCFMutableString(NULL), mWillRelease(inWillRelease) { CACFString theString(inCString, inCStringEncoding); mCFMutableString = CFStringCreateMutableCopy(NULL, 0, theString.GetCFString()); }
+ ~CACFMutableString() { Release(); }
+ CACFMutableString(const CACFMutableString& inString) : mCFMutableString(inString.mCFMutableString), mWillRelease(inString.mWillRelease) { Retain(); }
+ CACFMutableString& operator=(const CACFMutableString& inString) { Release(); mCFMutableString = inString.mCFMutableString; mWillRelease = inString.mWillRelease; Retain(); return *this; }
+ CACFMutableString& operator=(CFMutableStringRef inCFMutableString) { Release(); mCFMutableString = inCFMutableString; mWillRelease = true; return *this; }
+
+private:
+ void Retain() { if(mWillRelease && (mCFMutableString != NULL)) { CFRetain(mCFMutableString); } }
+ void Release() { if(mWillRelease && (mCFMutableString != NULL)) { CFRelease(mCFMutableString); } }
+
+ CFMutableStringRef mCFMutableString;
+ bool mWillRelease;
+
+// Operations
+public:
+ void AllowRelease() { mWillRelease = true; }
+ void DontAllowRelease() { mWillRelease = false; }
+ bool IsValid() { return mCFMutableString != NULL; }
+ bool IsEqualTo(CFStringRef inString) const { bool theAnswer = false; if(mCFMutableString != NULL) { theAnswer = CFStringCompare(inString, mCFMutableString, 0) == kCFCompareEqualTo; } return theAnswer; }
+ bool StartsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFMutableString != NULL) { theAnswer = CFStringHasPrefix(mCFMutableString, inString); } return theAnswer; }
+ bool EndsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFMutableString != NULL) { theAnswer = CFStringHasSuffix(mCFMutableString, inString); } return theAnswer; }
+ void Append(CFStringRef inString) { if(mCFMutableString != NULL) { CFStringAppend(mCFMutableString, inString); } }
+
+// Value Access
+public:
+ CFMutableStringRef GetCFMutableString() const { return mCFMutableString; }
+ CFMutableStringRef CopyCFMutableString() const { if(mCFMutableString != NULL) { CFRetain(mCFMutableString); } return mCFMutableString; }
+ UInt32 GetLength() const { UInt32 theAnswer = 0; if(mCFMutableString != NULL) { theAnswer = ToUInt32(CFStringGetLength(mCFMutableString)); } return theAnswer; }
+ UInt32 GetByteLength(CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { UInt32 theAnswer = 0; if(mCFMutableString != NULL) { theAnswer = CACFString::GetStringByteLength(mCFMutableString, inEncoding); } return theAnswer; }
+ void GetCString(char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { CACFString::GetCString(mCFMutableString, outString, ioStringSize, inEncoding); }
+ void GetUnicodeString(UInt16* outString, UInt32& ioStringSize) const { CACFString::GetUnicodeString(mCFMutableString, outString, ioStringSize); }
+ SInt32 GetAsInteger() { return CACFString::GetAsInteger(mCFMutableString); }
+ Float64 GetAsFloat64() { return CACFString::GetAsFloat64(mCFMutableString); }
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAComponent.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAComponent.cpp
new file mode 100644
index 0000000000..04eae545cf
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAComponent.cpp
@@ -0,0 +1,182 @@
+/*
+ File: CAComponent.cpp
+ Abstract: CAComponent.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CAComponent.h"
+#include "CAComponentDescription.h"
+#include "CACFDictionary.h"
+#include <stdlib.h>
+#include "CAAutoDisposer.h"
+
+CAComponent::CAComponent (const AudioComponentDescription& inDesc, CAComponent* next)
+ : mManuName(0), mAUName(0), mCompName(0)
+{
+ mComp = AudioComponentFindNext ((next ? next->Comp() : NULL), &inDesc);
+ if (mComp)
+ AudioComponentGetDescription(Comp(), &mDesc);
+ else
+ memcpy (&mDesc, &inDesc, sizeof(AudioComponentDescription));
+}
+
+CAComponent::CAComponent (const AudioComponent& comp)
+ : mComp (comp),
+ mManuName(0),
+ mAUName(0),
+ mCompName(0)
+{
+ AudioComponentGetDescription (Comp(), &mDesc);
+}
+
+CAComponent::CAComponent (const AudioComponentInstance& compInst)
+ : mComp (NULL),
+ mManuName(0),
+ mAUName(0),
+ mCompName(0)
+{
+ mComp = AudioComponentInstanceGetComponent (compInst);
+ AudioComponentGetDescription (Comp(), &mDesc);
+}
+
+CAComponent::CAComponent (OSType inType, OSType inSubtype, OSType inManu)
+ : mDesc (inType, inSubtype, inManu),
+ mManuName(0), mAUName(0), mCompName(0)
+{
+ mComp = AudioComponentFindNext (NULL, &mDesc);
+ AudioComponentGetDescription (Comp(), &mDesc);
+}
+
+CAComponent::~CAComponent ()
+{
+ Clear();
+}
+
+OSStatus CAComponent::GetVersion (UInt32 &outVersion) const
+{
+ return AudioComponentGetVersion (mComp, &outVersion);
+}
+
+void CAComponent::Clear ()
+{
+ if (mManuName) { CFRelease (mManuName); mManuName = 0; }
+ if (mAUName) { CFRelease (mAUName); mAUName = 0; }
+ if (mCompName) { CFRelease (mCompName); mCompName = 0; }
+}
+
+CAComponent& CAComponent::operator= (const CAComponent& y)
+{
+ Clear();
+
+ mComp = y.mComp;
+ mDesc = y.mDesc;
+
+ if (y.mManuName) { mManuName = y.mManuName; CFRetain (mManuName); }
+ if (y.mAUName) { mAUName = y.mAUName; CFRetain (mAUName); }
+ if (y.mCompName) { mCompName = y.mCompName; CFRetain (mCompName); }
+
+ return *this;
+}
+
+void CAComponent::SetCompNames () const
+{
+ if (!mCompName) {
+
+ CFStringRef compName;
+ OSStatus result = AudioComponentCopyName (Comp(), &compName);
+ if (result) return;
+
+ const_cast<CAComponent*>(this)->mCompName = compName;
+ if (compName)
+ {
+ CFArrayRef splitStrArray = CFStringCreateArrayBySeparatingStrings(NULL, compName, CFSTR(":"));
+
+ // we need to retain these values so the strings are not lost when the array is released
+ const_cast<CAComponent*>(this)->mManuName = (CFStringRef)CFArrayGetValueAtIndex(splitStrArray, 0);
+ CFRetain(this->mManuName);
+ if (CFArrayGetCount(splitStrArray) > 1)
+ {
+ CFStringRef str = (CFStringRef)CFArrayGetValueAtIndex(splitStrArray, 1);
+
+ CFMutableStringRef mstr = CFStringCreateMutableCopy (NULL, CFStringGetLength(str), str);
+
+ // this needs to trim out white space:
+
+ CFStringTrimWhitespace (mstr);
+
+ const_cast<CAComponent*>(this)->mAUName = mstr;
+ } else
+ const_cast<CAComponent*>(this)->mAUName = NULL;
+
+ CFRelease(splitStrArray);
+ }
+ }
+}
+
+static void _ShowCF (FILE* file, CFStringRef str)
+{
+ if (CFGetTypeID(str) != CFStringGetTypeID()) {
+ CFShow(str);
+ return;
+ }
+
+ CFIndex len = CFStringGetLength(str);
+ char* chars = (char*)CA_malloc (len * 2); // give us plenty of room for unichar chars
+ if (CFStringGetCString (str, chars, len * 2, kCFStringEncodingUTF8))
+ fprintf (file, "%s", chars);
+ else
+ CFShow (str);
+
+ free (chars);
+}
+
+void CAComponent::Print(FILE* file) const
+{
+ fprintf (file, "CAComponent: %p", Comp());
+ if (mManuName) {
+ fprintf (file, ", Manu:"); _ShowCF (file, mManuName);
+ if (mAUName) fprintf (file, ", Name:"); _ShowCF (file, mAUName);
+ }
+ fprintf (file, ", ");
+ Desc ().Print(file);
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAComponent.h b/libs/appleutility/CoreAudio/PublicUtility/CAComponent.h
new file mode 100644
index 0000000000..5ff24ee01a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAComponent.h
@@ -0,0 +1,121 @@
+/*
+ File: CAComponent.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAComponent_h__
+#define __CAComponent_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+#else
+ #include <ConditionalMacros.h>
+#endif
+
+#include "CAComponentDescription.h"
+
+class CAComponent
+{
+public:
+ CAComponent ()
+ : mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0) {}
+
+ // if next is specifed that is used to find the next component after that one
+ CAComponent (const AudioComponentDescription& inDesc, CAComponent* next = 0);
+
+ CAComponent (const CAComponent& y)
+ : mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0) { *this = y; }
+
+ CAComponent (const AudioComponent& comp);
+
+ CAComponent (const AudioComponentInstance& compInst);
+
+ CAComponent (OSType inType, OSType inSubtype = 0, OSType inManu = 0);
+
+ ~CAComponent ();
+
+ CAComponent& operator= (const CAComponent& y);
+
+ // returns true if this object references a valid component
+ bool IsValid () const { return Comp() != 0; }
+
+ bool HasAUStrings() const { SetCompNames (); return mManuName != 0; }
+
+ // CFStringRef should be retained by caller if needed beyond lifetime of this object
+
+ // Can return NULL if component doesn't follow AU naming conventions
+ CFStringRef GetAUManu () const { SetCompNames (); return mManuName; }
+ CFStringRef GetAUName () const { SetCompNames (); return mAUName ? mAUName : mCompName; }
+
+ // Return value of NULL indicates a problem getting that information from the component
+ CFStringRef GetCompName () const { SetCompNames(); return mCompName; }
+
+ const CAComponentDescription& Desc () const { return mDesc; }
+
+ OSStatus Open (AudioComponentInstance& outInst) const
+ {
+ return AudioComponentInstanceNew (Comp(), &outInst);
+ }
+
+ OSStatus GetVersion (UInt32 &outVersion) const;
+
+ const AudioComponent& Comp() const { return mComp; }
+
+ void Print(FILE* file = stdout) const;
+
+ OSStatus Save (CFPropertyListRef *outData) const;
+
+ OSStatus Restore (CFPropertyListRef &inData);
+
+private:
+ AudioComponent mComp;
+ CAComponentDescription mDesc;
+
+ CFStringRef mManuName, mAUName, mCompName;
+
+ void SetCompNames () const;
+ void SetCompInfo () const;
+ void Clear ();
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.cpp
new file mode 100644
index 0000000000..a3c877b6fe
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.cpp
@@ -0,0 +1,110 @@
+/*
+ File: CAComponentDescription.cpp
+ Abstract: CAComponentDescription.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CAComponentDescription.h"
+#include "CAStreamBasicDescription.h"
+#include <ctype.h>
+
+void CAShowComponentDescription(const AudioComponentDescription *desc)
+{
+ CAComponentDescription::_CAShowComponentDescription (desc, stdout);
+}
+
+void CAComponentDescription::_CAShowComponentDescription(const AudioComponentDescription *desc, FILE* file)
+{
+ if (desc)
+ {
+ char str[24];
+ fprintf (file, "AudioComponentDescription: %s - ", CAStringForOSType(desc->componentType, str, sizeof(str)));
+ fprintf (file, "%s - ", CAStringForOSType(desc->componentSubType, str, sizeof(str)));
+ fprintf (file, "%s", CAStringForOSType(desc->componentManufacturer, str, sizeof(str)));
+ fprintf (file, ", 0x%X, 0x%X\n", (int)desc->componentFlags, (int)desc->componentFlagsMask);
+ }
+}
+
+CAComponentDescription::CAComponentDescription (OSType inType, OSType inSubtype, OSType inManu)
+{
+ componentType = inType;
+ componentSubType = inSubtype;
+ componentManufacturer = inManu;
+ componentFlags = 0;
+ componentFlagsMask = 0;
+}
+
+bool CAComponentDescription::IsAU () const
+{
+ bool flag = IsEffect() || IsMusicDevice() || IsOffline();
+ if (flag) return true;
+
+ switch (componentType) {
+ case kAudioUnitType_Output:
+ case kAudioUnitType_FormatConverter:
+ case kAudioUnitType_Mixer:
+ return true;
+ }
+ return false;
+}
+
+inline bool _MatchTest (const OSType &inTypeA, const OSType &inTypeB)
+{
+ return ((inTypeA == inTypeB) || (!inTypeA && !inTypeB) || (inTypeA && !inTypeB) || (!inTypeA && inTypeB));
+}
+
+bool CAComponentDescription::Matches (const AudioComponentDescription &desc) const
+{
+ bool matches = false;
+
+ // see if the type matches
+ matches = _MatchTest (componentType, desc.componentType);
+
+ if (matches)
+ matches = _MatchTest (componentSubType, desc.componentSubType);
+
+ if (matches)
+ matches = _MatchTest (componentManufacturer, desc.componentManufacturer);
+
+ return matches;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.h b/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.h
new file mode 100644
index 0000000000..5c756eaebf
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.h
@@ -0,0 +1,145 @@
+/*
+ File: CAComponentDescription.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAComponentDescription_h__
+#define __CAComponentDescription_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnit.h>
+#else
+ #include <ConditionalMacros.h>
+ #include <AudioUnit.h>
+#endif
+
+#include "CACFDictionary.h"
+#include <stdio.h>
+#include <string.h>
+
+void CAShowComponentDescription(const AudioComponentDescription *desc);
+
+// ____________________________________________________________________________
+//
+// CAComponentDescription
+class CAComponentDescription : public AudioComponentDescription {
+public:
+ CAComponentDescription() { memset (this, 0, sizeof (AudioComponentDescription)); }
+
+ CAComponentDescription (OSType inType, OSType inSubtype = 0, OSType inManu = 0);
+
+ CAComponentDescription(const AudioComponentDescription& desc) { memcpy (this, &desc, sizeof (AudioComponentDescription)); }
+
+ // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ //
+ // interrogation
+
+ bool IsAU () const;
+
+ bool IsAUFX() const { return componentType == kAudioUnitType_Effect; }
+ bool IsAUFM() const { return componentType == kAudioUnitType_MusicEffect; }
+
+ bool IsAUMI() const { return componentType == 'aumi' /*kAudioUnitType_MIDIProcessor*/; }
+
+ bool IsAUAX () const { return componentType == 'auax' /*kAudioUnitType_Auxiliary*/; }
+
+ bool IsEffect () const { return IsAUFX() || IsAUFM() || IsPanner(); }
+
+ bool IsOffline () const { return componentType == 'auol' /*kAudioUnitType_Offline*/; }
+
+ bool IsFConv () const { return componentType == kAudioUnitType_FormatConverter; }
+
+ bool IsPanner () const { return componentType == kAudioUnitType_Panner; }
+
+ bool IsMusicDevice () const { return componentType == kAudioUnitType_MusicDevice; }
+
+#ifndef MAC_OS_X_VERSION_10_4
+ bool IsGenerator () const { return componentType =='augn'; }
+#else
+ bool IsGenerator () const { return componentType ==kAudioUnitType_Generator; }
+#endif
+
+ bool IsOutput () const { return componentType == kAudioUnitType_Output; }
+
+ bool IsSource () const { return IsMusicDevice() || IsGenerator(); }
+
+ OSType Type () const { return componentType; }
+ OSType SubType () const { return componentSubType; }
+ OSType Manu () const { return componentManufacturer; }
+
+ int Count() const { return AudioComponentCount(const_cast<CAComponentDescription*>(this)); }
+
+ // does a semantic match where "wild card" values for type, subtype, manu will match
+ bool Matches (const AudioComponentDescription &desc) const;
+
+ // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ //
+ // other
+
+ void Print(FILE* file = stdout) const { _CAShowComponentDescription (this, file); }
+
+ OSStatus Save (CFPropertyListRef *outData) const;
+ OSStatus Restore (CFPropertyListRef &inData);
+
+private:
+ static void _CAShowComponentDescription (const AudioComponentDescription *desc, FILE* file);
+ friend void CAShowComponentDescription (const AudioComponentDescription *desc);
+};
+
+inline bool operator< (const AudioComponentDescription& x, const AudioComponentDescription& y)
+{
+ return memcmp (&x, &y, offsetof (AudioComponentDescription, componentFlags)) < 0;
+}
+
+inline bool operator== (const AudioComponentDescription& x, const AudioComponentDescription& y)
+{
+ return !memcmp (&x, &y, offsetof (AudioComponentDescription, componentFlags));
+}
+
+inline bool operator!= (const AudioComponentDescription& x, const AudioComponentDescription& y)
+{
+ return !(x == y);
+}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.cpp b/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.cpp
new file mode 100644
index 0000000000..9739e3753c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.cpp
@@ -0,0 +1,90 @@
+/*
+ File: CADebugMacros.cpp
+ Abstract: CADebugMacros.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CADebugMacros.h"
+#include <stdio.h>
+#include <stdarg.h>
+#if TARGET_API_MAC_OSX
+ #include <syslog.h>
+#endif
+
+#if DEBUG
+#include <stdio.h>
+
+void DebugPrint(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+}
+#endif // DEBUG
+
+void LogError(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+#if DEBUG
+ vprintf(fmt, args);
+#endif
+#if TARGET_API_MAC_OSX
+ vsyslog(LOG_ERR, fmt, args);
+#endif
+ va_end(args);
+}
+
+void LogWarning(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+#if DEBUG
+ vprintf(fmt, args);
+#endif
+#if TARGET_API_MAC_OSX
+ vsyslog(LOG_WARNING, fmt, args);
+#endif
+ va_end(args);
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.h b/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.h
new file mode 100644
index 0000000000..15af91909f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.h
@@ -0,0 +1,581 @@
+/*
+ File: CADebugMacros.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CADebugMacros_h__)
+#define __CADebugMacros_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include "CoreAudioTypes.h"
+#endif
+
+//=============================================================================
+// CADebugMacros
+//=============================================================================
+
+//#define CoreAudio_StopOnFailure 1
+//#define CoreAudio_TimeStampMessages 1
+//#define CoreAudio_ThreadStampMessages 1
+//#define CoreAudio_FlushDebugMessages 1
+
+#if TARGET_RT_BIG_ENDIAN
+ #define CA4CCToCString(the4CC) { ((char*)&the4CC)[0], ((char*)&the4CC)[1], ((char*)&the4CC)[2], ((char*)&the4CC)[3], 0 }
+ #define CACopy4CCToCString(theCString, the4CC) { theCString[0] = ((char*)&the4CC)[0]; theCString[1] = ((char*)&the4CC)[1]; theCString[2] = ((char*)&the4CC)[2]; theCString[3] = ((char*)&the4CC)[3]; theCString[4] = 0; }
+#else
+ #define CA4CCToCString(the4CC) { ((char*)&the4CC)[3], ((char*)&the4CC)[2], ((char*)&the4CC)[1], ((char*)&the4CC)[0], 0 }
+ #define CACopy4CCToCString(theCString, the4CC) { theCString[0] = ((char*)&the4CC)[3]; theCString[1] = ((char*)&the4CC)[2]; theCString[2] = ((char*)&the4CC)[1]; theCString[3] = ((char*)&the4CC)[0]; theCString[4] = 0; }
+#endif
+
+// This is a macro that does a sizeof and casts the result to a UInt32. This is useful for all the
+// places where -wshorten64-32 catches assigning a sizeof expression to a UInt32.
+// For want of a better place to park this, we'll park it here.
+#define SizeOf32(X) ((UInt32)sizeof(X))
+
+// This is a macro that does a offsetof and casts the result to a UInt32. This is useful for all the
+// places where -wshorten64-32 catches assigning an offsetof expression to a UInt32.
+// For want of a better place to park this, we'll park it here.
+#define OffsetOf32(X, Y) ((UInt32)offsetof(X, Y))
+
+// This macro casts the expression to a UInt32. It is called out specially to allow us to track casts
+// that have been added purely to avert -wshorten64-32 warnings on 64 bit platforms.
+// For want of a better place to park this, we'll park it here.
+#define ToUInt32(X) ((UInt32)(X))
+#define ToSInt32(X) ((SInt32)(X))
+
+#pragma mark Basic Definitions
+
+#if DEBUG || CoreAudio_Debug
+ // can be used to break into debugger immediately, also see CADebugger
+ #define BusError() { long* p=NULL; *p=0; }
+
+ // basic debugging print routines
+ #if TARGET_OS_MAC && !TARGET_API_MAC_CARBON
+ extern void DebugStr(const unsigned char* debuggerMsg);
+ #define DebugMessage(msg) DebugStr("\p"msg)
+ #define DebugMessageN1(msg, N1)
+ #define DebugMessageN2(msg, N1, N2)
+ #define DebugMessageN3(msg, N1, N2, N3)
+ #else
+ #include "CADebugPrintf.h"
+
+ #if (CoreAudio_FlushDebugMessages && !CoreAudio_UseSysLog) || defined(CoreAudio_UseSideFile)
+ #define FlushRtn ,fflush(DebugPrintfFile)
+ #else
+ #define FlushRtn
+ #endif
+
+ #if CoreAudio_ThreadStampMessages
+ #include <pthread.h>
+ #include "CAHostTimeBase.h"
+ #if TARGET_RT_64_BIT
+ #define DebugPrintfThreadIDFormat "%16p"
+ #else
+ #define DebugPrintfThreadIDFormat "%8p"
+ #endif
+ #define DebugMsg(inFormat, ...) DebugPrintf("%17qd: " DebugPrintfThreadIDFormat " " inFormat, CAHostTimeBase::GetCurrentTimeInNanos(), pthread_self(), ## __VA_ARGS__) FlushRtn
+ #elif CoreAudio_TimeStampMessages
+ #include "CAHostTimeBase.h"
+ #define DebugMsg(inFormat, ...) DebugPrintf("%17qd: " inFormat, CAHostTimeBase::GetCurrentTimeInNanos(), ## __VA_ARGS__) FlushRtn
+ #else
+ #define DebugMsg(inFormat, ...) DebugPrintf(inFormat, ## __VA_ARGS__) FlushRtn
+ #endif
+ #endif
+ void DebugPrint(const char *fmt, ...); // can be used like printf
+ #ifndef DEBUGPRINT
+ #define DEBUGPRINT(msg) DebugPrint msg // have to double-parenthesize arglist (see Debugging.h)
+ #endif
+ #if VERBOSE
+ #define vprint(msg) DEBUGPRINT(msg)
+ #else
+ #define vprint(msg)
+ #endif
+
+ // Original macro keeps its function of turning on and off use of CADebuggerStop() for both asserts and throws.
+ // For backwards compat, it overrides any setting of the two sub-macros.
+ #if CoreAudio_StopOnFailure
+ #include "CADebugger.h"
+ #undef CoreAudio_StopOnAssert
+ #define CoreAudio_StopOnAssert 1
+ #undef CoreAudio_StopOnThrow
+ #define CoreAudio_StopOnThrow 1
+ #define STOP CADebuggerStop()
+ #else
+ #define STOP
+ #endif
+
+ #if CoreAudio_StopOnAssert
+ #if !CoreAudio_StopOnFailure
+ #include "CADebugger.h"
+ #define STOP
+ #endif
+ #define __ASSERT_STOP CADebuggerStop()
+ #else
+ #define __ASSERT_STOP
+ #endif
+
+ #if CoreAudio_StopOnThrow
+ #if !CoreAudio_StopOnFailure
+ #include "CADebugger.h"
+ #define STOP
+ #endif
+ #define __THROW_STOP CADebuggerStop()
+ #else
+ #define __THROW_STOP
+ #endif
+
+#else
+ #define DebugMsg(inFormat, ...)
+ #ifndef DEBUGPRINT
+ #define DEBUGPRINT(msg)
+ #endif
+ #define vprint(msg)
+ #define STOP
+ #define __ASSERT_STOP
+ #define __THROW_STOP
+#endif
+
+// Old-style numbered DebugMessage calls are implemented in terms of DebugMsg() now
+#define DebugMessage(msg) DebugMsg(msg)
+#define DebugMessageN1(msg, N1) DebugMsg(msg, N1)
+#define DebugMessageN2(msg, N1, N2) DebugMsg(msg, N1, N2)
+#define DebugMessageN3(msg, N1, N2, N3) DebugMsg(msg, N1, N2, N3)
+#define DebugMessageN4(msg, N1, N2, N3, N4) DebugMsg(msg, N1, N2, N3, N4)
+#define DebugMessageN5(msg, N1, N2, N3, N4, N5) DebugMsg(msg, N1, N2, N3, N4, N5)
+#define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) DebugMsg(msg, N1, N2, N3, N4, N5, N6)
+#define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) DebugMsg(msg, N1, N2, N3, N4, N5, N6, N7)
+#define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) DebugMsg(msg, N1, N2, N3, N4, N5, N6, N7, N8)
+#define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugMsg(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9)
+
+void LogError(const char *fmt, ...); // writes to syslog (and stderr if debugging)
+void LogWarning(const char *fmt, ...); // writes to syslog (and stderr if debugging)
+
+#define NO_ACTION (void)0
+
+#if DEBUG || CoreAudio_Debug
+
+#pragma mark Debug Macros
+
+#define Assert(inCondition, inMessage) \
+ if(!(inCondition)) \
+ { \
+ DebugMessage(inMessage); \
+ __ASSERT_STOP; \
+ }
+
+#define AssertFileLine(inCondition, inMessage) \
+ if(!(inCondition)) \
+ { \
+ DebugMessageN3("%s, line %d: %s", __FILE__, __LINE__, inMessage); \
+ __ASSERT_STOP; \
+ }
+
+#define AssertNoError(inError, inMessage) \
+ { \
+ SInt32 __Err = (inError); \
+ if(__Err != 0) \
+ { \
+ char __4CC[5] = CA4CCToCString(__Err); \
+ DebugMessageN2(inMessage ", Error: %d (%s)", (int)__Err, __4CC); \
+ __ASSERT_STOP; \
+ } \
+ }
+
+#define AssertNoKernelError(inError, inMessage) \
+ { \
+ unsigned int __Err = (unsigned int)(inError); \
+ if(__Err != 0) \
+ { \
+ DebugMessageN1(inMessage ", Error: 0x%X", __Err); \
+ __ASSERT_STOP; \
+ } \
+ }
+
+#define AssertNotNULL(inPtr, inMessage) \
+ { \
+ if((inPtr) == NULL) \
+ { \
+ DebugMessage(inMessage); \
+ __ASSERT_STOP; \
+ } \
+ }
+
+#define FailIf(inCondition, inHandler, inMessage) \
+ if(inCondition) \
+ { \
+ DebugMessage(inMessage); \
+ STOP; \
+ goto inHandler; \
+ }
+
+#define FailWithAction(inCondition, inAction, inHandler, inMessage) \
+ if(inCondition) \
+ { \
+ DebugMessage(inMessage); \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ }
+
+#define FailIfNULL(inPointer, inAction, inHandler, inMessage) \
+ if((inPointer) == NULL) \
+ { \
+ DebugMessage(inMessage); \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ }
+
+#define FailIfKernelError(inKernelError, inAction, inHandler, inMessage) \
+ { \
+ unsigned int __Err = (inKernelError); \
+ if(__Err != 0) \
+ { \
+ DebugMessageN1(inMessage ", Error: 0x%X", __Err); \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ } \
+ }
+
+#define FailIfError(inError, inAction, inHandler, inMessage) \
+ { \
+ SInt32 __Err = (inError); \
+ if(__Err != 0) \
+ { \
+ char __4CC[5] = CA4CCToCString(__Err); \
+ DebugMessageN2(inMessage ", Error: %ld (%s)", (long int)__Err, __4CC); \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ } \
+ }
+
+#define FailIfNoMessage(inCondition, inHandler, inMessage) \
+ if(inCondition) \
+ { \
+ STOP; \
+ goto inHandler; \
+ }
+
+#define FailWithActionNoMessage(inCondition, inAction, inHandler, inMessage) \
+ if(inCondition) \
+ { \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ }
+
+#define FailIfNULLNoMessage(inPointer, inAction, inHandler, inMessage) \
+ if((inPointer) == NULL) \
+ { \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ }
+
+#define FailIfKernelErrorNoMessage(inKernelError, inAction, inHandler, inMessage) \
+ { \
+ unsigned int __Err = (inKernelError); \
+ if(__Err != 0) \
+ { \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ } \
+ }
+
+#define FailIfErrorNoMessage(inError, inAction, inHandler, inMessage) \
+ { \
+ SInt32 __Err = (inError); \
+ if(__Err != 0) \
+ { \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ } \
+ }
+
+#if defined(__cplusplus)
+
+#define Throw(inException) __THROW_STOP; throw (inException)
+
+#define ThrowIf(inCondition, inException, inMessage) \
+ if(inCondition) \
+ { \
+ DebugMessage(inMessage); \
+ Throw(inException); \
+ }
+
+#define ThrowIfNULL(inPointer, inException, inMessage) \
+ if((inPointer) == NULL) \
+ { \
+ DebugMessage(inMessage); \
+ Throw(inException); \
+ }
+
+#define ThrowIfKernelError(inKernelError, inException, inMessage) \
+ { \
+ int __Err = (inKernelError); \
+ if(__Err != 0) \
+ { \
+ DebugMessageN1(inMessage ", Error: 0x%X", __Err); \
+ Throw(inException); \
+ } \
+ }
+
+#define ThrowIfError(inError, inException, inMessage) \
+ { \
+ SInt32 __Err = (inError); \
+ if(__Err != 0) \
+ { \
+ char __4CC[5] = CA4CCToCString(__Err); \
+ DebugMessageN2(inMessage ", Error: %d (%s)", (int)__Err, __4CC); \
+ Throw(inException); \
+ } \
+ }
+
+#if TARGET_OS_WIN32
+#define ThrowIfWinError(inError, inException, inMessage) \
+ { \
+ HRESULT __Err = (inError); \
+ if(FAILED(__Err)) \
+ { \
+ DebugMessageN2(inMessage ", Code: %d, Facility: 0x%X", HRESULT_CODE(__Err), HRESULT_FACILITY(__Err)); \
+ Throw(inException); \
+ } \
+ }
+#endif
+
+#define SubclassResponsibility(inMethodName, inException) \
+ { \
+ DebugMessage(inMethodName": Subclasses must implement this method"); \
+ Throw(inException); \
+ }
+
+#endif // defined(__cplusplus)
+
+#else
+
+#pragma mark Release Macros
+
+#define Assert(inCondition, inMessage) \
+ if(!(inCondition)) \
+ { \
+ __ASSERT_STOP; \
+ }
+
+#define AssertFileLine(inCondition, inMessage) Assert(inCondition, inMessage)
+
+#define AssertNoError(inError, inMessage) \
+ { \
+ SInt32 __Err = (inError); \
+ if(__Err != 0) \
+ { \
+ __ASSERT_STOP; \
+ } \
+ }
+
+#define AssertNoKernelError(inError, inMessage) \
+ { \
+ unsigned int __Err = (unsigned int)(inError); \
+ if(__Err != 0) \
+ { \
+ __ASSERT_STOP; \
+ } \
+ }
+
+#define AssertNotNULL(inPtr, inMessage) \
+ { \
+ if((inPtr) == NULL) \
+ { \
+ __ASSERT_STOP; \
+ } \
+ }
+
+#define FailIf(inCondition, inHandler, inMessage) \
+ if(inCondition) \
+ { \
+ STOP; \
+ goto inHandler; \
+ }
+
+#define FailWithAction(inCondition, inAction, inHandler, inMessage) \
+ if(inCondition) \
+ { \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ }
+
+#define FailIfNULL(inPointer, inAction, inHandler, inMessage) \
+ if((inPointer) == NULL) \
+ { \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ }
+
+#define FailIfKernelError(inKernelError, inAction, inHandler, inMessage) \
+ if((inKernelError) != 0) \
+ { \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ }
+
+#define FailIfError(inError, inAction, inHandler, inMessage) \
+ if((inError) != 0) \
+ { \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ }
+
+#define FailIfNoMessage(inCondition, inHandler, inMessage) \
+ if(inCondition) \
+ { \
+ STOP; \
+ goto inHandler; \
+ }
+
+#define FailWithActionNoMessage(inCondition, inAction, inHandler, inMessage) \
+ if(inCondition) \
+ { \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ }
+
+#define FailIfNULLNoMessage(inPointer, inAction, inHandler, inMessage) \
+ if((inPointer) == NULL) \
+ { \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ }
+
+#define FailIfKernelErrorNoMessage(inKernelError, inAction, inHandler, inMessage) \
+ { \
+ unsigned int __Err = (inKernelError); \
+ if(__Err != 0) \
+ { \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ } \
+ }
+
+#define FailIfErrorNoMessage(inError, inAction, inHandler, inMessage) \
+ { \
+ SInt32 __Err = (inError); \
+ if(__Err != 0) \
+ { \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ } \
+ }
+
+#if defined(__cplusplus)
+
+#define Throw(inException) __THROW_STOP; throw (inException)
+
+#define ThrowIf(inCondition, inException, inMessage) \
+ if(inCondition) \
+ { \
+ Throw(inException); \
+ }
+
+#define ThrowIfNULL(inPointer, inException, inMessage) \
+ if((inPointer) == NULL) \
+ { \
+ Throw(inException); \
+ }
+
+#define ThrowIfKernelError(inKernelError, inException, inMessage) \
+ { \
+ int __Err = (inKernelError); \
+ if(__Err != 0) \
+ { \
+ Throw(inException); \
+ } \
+ }
+
+#define ThrowIfError(inError, inException, inMessage) \
+ { \
+ SInt32 __Err = (inError); \
+ if(__Err != 0) \
+ { \
+ Throw(inException); \
+ } \
+ }
+
+#if TARGET_OS_WIN32
+#define ThrowIfWinError(inError, inException, inMessage) \
+ { \
+ HRESULT __Err = (inError); \
+ if(FAILED(__Err)) \
+ { \
+ Throw(inException); \
+ } \
+ }
+#endif
+
+#define SubclassResponsibility(inMethodName, inException) \
+ { \
+ Throw(inException); \
+ }
+
+#endif // defined(__cplusplus)
+
+#endif // DEBUG || CoreAudio_Debug
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.cpp b/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.cpp
new file mode 100644
index 0000000000..d691de3cd5
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.cpp
@@ -0,0 +1,89 @@
+/*
+ File: CADebugPrintf.cpp
+ Abstract: CADebugPrintf.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CADebugPrintf.h"
+
+#if DEBUG || CoreAudio_Debug
+
+ #if TARGET_OS_WIN32
+ #include <stdarg.h>
+ #include <stdio.h>
+ #include <Windows.h>
+ extern "C"
+ int CAWin32DebugPrintf(char* inFormat, ...)
+ {
+ char theMessage[1024];
+ va_list theArguments;
+ va_start(theArguments, inFormat);
+ _vsnprintf(theMessage, 1024, inFormat, theArguments);
+ va_end(theArguments);
+ OutputDebugString(theMessage);
+ return 0;
+ }
+ #endif
+
+ #if defined(CoreAudio_UseSideFile)
+ #include <unistd.h>
+ FILE* sDebugPrintfSideFile = NULL;
+ extern "C"
+ void OpenDebugPrintfSideFile()
+ {
+ if(sDebugPrintfSideFile == NULL)
+ {
+ char theFileName[1024];
+ snprintf(theFileName, sizeof(theFileName), CoreAudio_UseSideFile, getpid());
+ sDebugPrintfSideFile = fopen(theFileName, "a+");
+ DebugPrintfRtn(DebugPrintfFileComma "\n------------------------------\n");
+ }
+ }
+ #endif
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.h b/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.h
new file mode 100644
index 0000000000..79aa15dafa
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.h
@@ -0,0 +1,115 @@
+/*
+ File: CADebugPrintf.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CADebugPrintf_h__)
+#define __CADebugPrintf_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include "CoreAudioTypes.h"
+#endif
+
+//=============================================================================
+// Macros to redirect debugging output to various logging services
+//=============================================================================
+
+//#define CoreAudio_UseSysLog 1
+//#define CoreAudio_UseSideFile "/CoreAudio-%d.txt"
+
+#if DEBUG || CoreAudio_Debug
+
+ #if TARGET_OS_WIN32
+ #if defined(__cplusplus)
+ extern "C"
+ #endif
+ extern int CAWin32DebugPrintf(char* inFormat, ...);
+ #define DebugPrintfRtn CAWin32DebugPrintf
+ #define DebugPrintfFile
+ #define DebugPrintfLineEnding "\n"
+ #define DebugPrintfFileComma
+ #else
+ #if CoreAudio_UseSysLog
+ #include <sys/syslog.h>
+ #define DebugPrintfRtn syslog
+ #define DebugPrintfFile LOG_NOTICE
+ #define DebugPrintfLineEnding ""
+ #define DebugPrintfFileComma DebugPrintfFile,
+ #elif defined(CoreAudio_UseSideFile)
+ #include <stdio.h>
+ #if defined(__cplusplus)
+ extern "C"
+ #endif
+ void OpenDebugPrintfSideFile();
+ extern FILE* sDebugPrintfSideFile;
+ #define DebugPrintfRtn fprintf
+ #define DebugPrintfFile ((sDebugPrintfSideFile != NULL) ? sDebugPrintfSideFile : stderr)
+ #define DebugPrintfLineEnding "\n"
+ #define DebugPrintfFileComma DebugPrintfFile,
+ #else
+ #include <stdio.h>
+ #define DebugPrintfRtn fprintf
+ #define DebugPrintfFile stderr
+ #define DebugPrintfLineEnding "\n"
+ #define DebugPrintfFileComma DebugPrintfFile,
+ #endif
+ #endif
+
+ #define DebugPrintf(inFormat, ...) DebugPrintfRtn(DebugPrintfFileComma inFormat DebugPrintfLineEnding, ## __VA_ARGS__)
+#else
+ #define DebugPrintfRtn
+ #define DebugPrintfFile
+ #define DebugPrintfLineEnding
+ #define DebugPrintfFileComma
+ #define DebugPrintf(inFormat, ...)
+#endif
+
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugger.cpp b/libs/appleutility/CoreAudio/PublicUtility/CADebugger.cpp
new file mode 100644
index 0000000000..7f0141d206
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugger.cpp
@@ -0,0 +1,103 @@
+/*
+ File: CADebugger.cpp
+ Abstract: CADebugger.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CADebugger.h"
+
+//=============================================================================
+// CADebugger
+//=============================================================================
+
+#if TARGET_API_MAC_OSX
+
+#include <sys/sysctl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+bool CAIsDebuggerAttached(void)
+{
+ int mib[4];
+ struct kinfo_proc info;
+ size_t size;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = getpid();
+ size = sizeof(info);
+ info.kp_proc.p_flag = 0;
+
+ sysctl(mib, 4, &info, &size, NULL, 0);
+
+ return (info.kp_proc.p_flag & P_TRACED) == P_TRACED;
+}
+
+#endif
+
+void CADebuggerStop(void)
+{
+ #if CoreAudio_Debug
+ #if TARGET_API_MAC_OSX
+ if(CAIsDebuggerAttached())
+ {
+ #if defined(__i386__) || defined(__x86_64__)
+ asm("int3");
+ #else
+ __builtin_trap();
+ #endif
+ }
+ else
+ {
+ abort();
+ }
+ #else
+ __debugbreak();
+ #endif
+ #endif
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CADebugger.h b/libs/appleutility/CoreAudio/PublicUtility/CADebugger.h
new file mode 100644
index 0000000000..9391f011a2
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CADebugger.h
@@ -0,0 +1,69 @@
+/*
+ File: CADebugger.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CADebugger_h__)
+#define __CADebugger_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+//=============================================================================
+// CADebugger
+//=============================================================================
+
+#if TARGET_API_MAC_OSX
+ extern bool CAIsDebuggerAttached(void);
+#endif
+extern void CADebuggerStop(void);
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAException.h b/libs/appleutility/CoreAudio/PublicUtility/CAException.h
new file mode 100644
index 0000000000..7217001d78
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAException.h
@@ -0,0 +1,83 @@
+/*
+ File: CAException.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAException_h__)
+#define __CAException_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include "CoreAudioTypes.h"
+#endif
+
+//=============================================================================
+// CAException
+//=============================================================================
+
+class CAException
+{
+
+public:
+ CAException(OSStatus inError) : mError(inError) {}
+ CAException(const CAException& inException) : mError(inException.mError) {}
+ CAException& operator=(const CAException& inException) { mError = inException.mError; return *this; }
+ ~CAException() {}
+
+ OSStatus GetError() const { return mError; }
+
+protected:
+ OSStatus mError;
+};
+
+#define CATry try{
+#define CACatch } catch(...) {}
+#define CASwallowException(inExpression) try { inExpression; } catch(...) {}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h b/libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h
new file mode 100644
index 0000000000..f1aa56fb5e
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h
@@ -0,0 +1,300 @@
+/*
+ File: CAExtAudioFile.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAExtAudioFile_h__
+#define __CAExtAudioFile_h__
+
+#include <TargetConditionals.h>
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioToolbox/ExtendedAudioFile.h>
+ #include <AudioToolbox/AudioConverter.h>
+#else
+ #include "ExtendedAudioFile.h"
+ #include "AudioConverter.h"
+#endif
+#include "CAXException.h"
+//#include "CAAutoDisposer.h"
+#include "CAStreamBasicDescription.h"
+#include "CAAudioChannelLayout.h"
+#include "CACFObject.h"
+
+// A C++ wrapper for ExtAudioFile
+// Error returns throw CAXExceptions.
+class CAExtAudioFile {
+public:
+ // instances are not automatically associated with open files.
+ CAExtAudioFile() :
+ mExtAudioFile(NULL) { }
+
+ virtual ~CAExtAudioFile()
+ {
+ Close();
+ }
+
+ bool IsValid() const { return mExtAudioFile != NULL; }
+
+ void Open(const char* filename)
+ {
+ Close();
+ CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)filename, strlen(filename), false);
+ XThrowIf(!url, -1, "couldn't convert path to CFURLRef");
+ OSStatus res = ExtAudioFileOpenURL(url, &mExtAudioFile);
+ if (res)
+ CFRelease(url);
+ Check(res, "ExtAudioFileOpenURL");
+ CFRelease (url);
+ }
+
+ // this group of methods maps directly to the API other than OSStatus results translating into exceptions.
+ // you must explicitly open, wrap or create a file.
+ void OpenURL(CFURLRef url)
+ {
+ Close();
+ Check(ExtAudioFileOpenURL(url, &mExtAudioFile), "ExtAudioFileOpenURL");
+ }
+
+ void WrapAudioFileID(AudioFileID inFileID, Boolean forWriting)
+ {
+ Close();
+ Check(ExtAudioFileWrapAudioFileID(inFileID, forWriting, &mExtAudioFile), "ExtAudioFileWrapAudioFileID");
+ }
+
+ void Create(const char *filePath, AudioFileTypeID filetype, const AudioStreamBasicDescription &streamDesc, const AudioChannelLayout *channelLayout, UInt32 flags)
+ {
+ CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8 *)filePath, strlen(filePath), false);
+ XThrowIf(!url, -1, "couldn't convert path to CFURLRef");
+ Close();
+ OSStatus res = ExtAudioFileCreateWithURL(url, filetype, &streamDesc, channelLayout, flags, &mExtAudioFile);
+ if (res)
+ CFRelease(url);
+ Check(res, "ExtAudioFileCreateWithURL");
+ CFRelease(url);
+ }
+
+ void CreateWithURL(CFURLRef url, AudioFileTypeID filetype, const AudioStreamBasicDescription &streamDesc, const AudioChannelLayout *channelLayout, UInt32 flags)
+ {
+ Close();
+ Check(ExtAudioFileCreateWithURL(url, filetype, &streamDesc, channelLayout, flags, &mExtAudioFile), "ExtAudioFileCreateWithURL");
+ }
+
+ // you may explicitly close a file, or have it closed automatically by the destructor.
+ void Close()
+ {
+ if (mExtAudioFile != NULL) {
+ Check(ExtAudioFileDispose(mExtAudioFile), "ExtAudioFileClose");
+ mExtAudioFile = NULL;
+ }
+ }
+
+ void Read(UInt32 &ioNumberFrames, AudioBufferList *ioData)
+ {
+ Check(ExtAudioFileRead(mExtAudioFile, &ioNumberFrames, ioData), "ExtAudioFileRead");
+ }
+
+ OSStatus Write(UInt32 inNumberFrames, const AudioBufferList *ioData)
+ {
+ OSStatus err = ExtAudioFileWrite(mExtAudioFile, inNumberFrames, ioData);
+ switch (err) {
+ // noErr and certain special errors are returned without an exception
+ case noErr:
+ break;
+ #if TARGET_OS_IPHONE
+ case kExtAudioFileError_CodecUnavailableInputConsumed:
+ case kExtAudioFileError_CodecUnavailableInputNotConsumed:
+ break;
+ #endif
+ default:
+ // throw an exception
+ Check(err, "ExtAudioFileWrite");
+ break;
+ }
+ return err;
+ }
+
+ void WriteAsync(UInt32 inNumberFrames, const AudioBufferList *ioData)
+ {
+ Check(ExtAudioFileWriteAsync(mExtAudioFile, inNumberFrames, ioData), "ExtAudioFileWriteAsync");
+ }
+
+ void Seek(SInt64 inFrameOffset)
+ {
+ Check(ExtAudioFileSeek(mExtAudioFile, inFrameOffset), "ExtAudioFileSeek");
+ }
+
+ SInt64 Tell() const
+ {
+ SInt64 pos;
+ Check(ExtAudioFileTell(mExtAudioFile, &pos), "ExtAudioFileTell");
+ return pos;
+ }
+
+ UInt32 GetPropertyInfo(ExtAudioFilePropertyID propid, Boolean *outWritable) const
+ {
+ UInt32 size;
+ CheckProperty(ExtAudioFileGetPropertyInfo(mExtAudioFile, propid, &size, outWritable), "ExtAudioFileGetPropertyInfo", propid);
+ return size;
+ }
+
+ void GetProperty(ExtAudioFilePropertyID propid, UInt32 &ioSize, void *outData) const
+ {
+ CheckProperty(ExtAudioFileGetProperty(mExtAudioFile, propid, &ioSize, outData), "ExtAudioFileGetProperty", propid);
+ }
+
+ void SetProperty(ExtAudioFilePropertyID propid, UInt32 size, const void *inData)
+ {
+ CheckProperty(ExtAudioFileSetProperty(mExtAudioFile, propid, size, inData), "ExtAudioFileSetProperty", propid);
+ }
+
+ const CAAudioChannelLayout &GetFileChannelLayout()
+ {
+ return FetchChannelLayout(mFileChannelLayout, kExtAudioFileProperty_FileChannelLayout);
+ }
+
+ void SetFileChannelLayout(const CAAudioChannelLayout &layout) {
+ SetProperty(kExtAudioFileProperty_FileChannelLayout, layout.Size(), &layout.Layout());
+ }
+
+ const CAStreamBasicDescription &GetFileDataFormat()
+ {
+ UInt32 size = sizeof(mFileDataFormat);
+ GetProperty(kExtAudioFileProperty_FileDataFormat, size, &mFileDataFormat);
+ return mFileDataFormat;
+ }
+
+ const CAStreamBasicDescription &GetClientDataFormat() {
+ UInt32 size = sizeof(mClientDataFormat);
+ GetProperty(kExtAudioFileProperty_ClientDataFormat, size, &mClientDataFormat);
+ return mClientDataFormat;
+ }
+
+
+ void SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout=NULL, UInt32 codecManuf=0) {
+ if (codecManuf != 0)
+ SetProperty('cman' /*kExtAudioFileProperty_CodecManufacturer*/, sizeof(codecManuf), &codecManuf);
+ SetProperty(kExtAudioFileProperty_ClientDataFormat, sizeof(dataFormat), &dataFormat);
+ if (layout)
+ SetClientChannelLayout(*layout);
+ }
+
+ void SetClientChannelLayout(const CAAudioChannelLayout &layout) {
+ SetProperty(kExtAudioFileProperty_ClientChannelLayout, layout.Size(), &layout.Layout());
+ }
+
+ AudioConverterRef GetConverter() const {
+ UInt32 size = sizeof(AudioConverterRef);
+ AudioConverterRef converter = NULL;
+ GetProperty(kExtAudioFileProperty_AudioConverter, size, &converter);
+ return converter;
+ }
+
+ bool HasConverter() const { return GetConverter() != NULL; }
+
+ OSStatus SetConverterProperty(AudioConverterPropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData, bool inCanFail=false)
+ {
+ OSStatus err = AudioConverterSetProperty(GetConverter(), inPropertyID, inPropertyDataSize, inPropertyData);
+ if (!inCanFail)
+ XThrowIfError(err, "Couldn't set audio converter property");
+ if (!err) {
+ // must tell the file that we have changed the converter; a NULL converter config is sufficient
+ CFPropertyListRef config = NULL;
+ SetProperty(kExtAudioFileProperty_ConverterConfig, sizeof(CFPropertyListRef), &config);
+ }
+ return err;
+ }
+
+ SInt64 GetNumberFrames() {
+ SInt64 length;
+ UInt32 size = sizeof(SInt64);
+ GetProperty(kExtAudioFileProperty_FileLengthFrames, size, &length);
+ return length;
+ }
+
+
+protected:
+ virtual void Check(OSStatus err, const char *func) const
+ {
+ if (err) {
+ char txt[128];
+ snprintf(txt, sizeof(txt), "%s failed", func);
+ throw CAXException(txt, err);
+ }
+ }
+
+ virtual void CheckProperty(OSStatus err, const char *func, UInt32 propid) const
+ {
+ if (err) {
+ char txt[128];
+ char propstr[] = CA4CCToCString(propid);
+ snprintf(txt, sizeof(txt), "%s ('%s') failed", func, propstr);
+ throw CAXException(txt, err);
+ }
+ }
+
+ const CAAudioChannelLayout & FetchChannelLayout(CAAudioChannelLayout &layoutObj, ExtAudioFilePropertyID propID) {
+ UInt32 size = GetPropertyInfo(propID, NULL);
+ CAAutoFree<AudioChannelLayout> layout;
+ layout.allocBytes(size);
+ GetProperty(propID, size, layout);
+ layoutObj = layout;
+ return layoutObj;
+ }
+
+private:
+ CAExtAudioFile(const CAExtAudioFile &) { } // prohibit
+ CAExtAudioFile & operator = (const CAExtAudioFile &) { return *this; } // prohibit
+
+private:
+ ExtAudioFileRef mExtAudioFile;
+
+ // for convenience to the client, it helps if we hold onto some storage for these
+ CAStreamBasicDescription mFileDataFormat;
+ CAAudioChannelLayout mFileChannelLayout;
+ CAStreamBasicDescription mClientDataFormat;
+};
+
+
+#endif // __CAExtAudioFile_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.cpp
new file mode 100644
index 0000000000..124cb21433
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.cpp
@@ -0,0 +1,188 @@
+/*
+ File: CAFilePathUtils.cpp
+ Abstract: CAFilePathUtils.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CAFilePathUtils.h"
+#include <string.h>
+
+#if !CA_NO_CORE_SERVICES
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreServices/CoreServices.h> // FSRef
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreServices.h>
+ #include <CoreAudioTypes.h>
+#endif
+
+OSStatus PosixPathToParentFSRefAndName(const char *path, FSRef &outParentDir, CFStringRef &outFileName)
+{
+ // convert C string to CFString
+#if !TARGET_OS_WIN32
+ CFStringRef cfFullPath = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8);
+#else
+ CFStringRef cfFullPath = CFStringCreateWithCString(NULL, path, kCFStringEncodingWindowsLatin1);
+#endif
+ // convert CF string to URL
+ CFURLRef fullurl = CFURLCreateWithFileSystemPath(NULL, cfFullPath, TARGET_OS_WIN32 ? kCFURLWindowsPathStyle : kCFURLPOSIXPathStyle, false);
+ CFRelease(cfFullPath);
+ // get the directory portion of the URL
+ CFURLRef dirurl = CFURLCreateCopyDeletingLastPathComponent(NULL, fullurl);
+ // get the directory's FSRef
+ OSStatus err = CFURLGetFSRef(dirurl, &outParentDir) ? OSStatus(noErr) : OSStatus(kAudio_FileNotFoundError);
+ CFRelease(dirurl);
+
+ CFStringRef lastPathComponent = CFURLCopyLastPathComponent(fullurl);
+ CFRelease(fullurl);
+ CFMutableStringRef filename = CFStringCreateMutableCopy(NULL, 0, lastPathComponent);
+ CFRelease(lastPathComponent);
+ // convert colons (legal in POSIX paths, illegal in File Manager) to slashes
+ CFStringFindAndReplace(filename, CFSTR(":"), CFSTR("/"), CFRangeMake(0, CFStringGetLength(filename)), 0);
+
+ outFileName = filename;
+
+ return err;
+}
+#endif // !CA_NO_CORE_SERVICES
+
+
+#if TARGET_OS_WIN32
+
+char* dirname(const char* inPath)
+{
+ static char sAnswer[1024];
+
+ char* theAnswer = NULL;
+ SInt32 thePathLength = strlen(inPath);
+ if(thePathLength < 1023)
+ {
+ // make a working copy
+ strlcpy(sAnswer, inPath, sizeof(sAnswer));
+
+ // start at the end of the string
+ SInt32 theIndex = thePathLength - 1;
+
+ // walk back over the '\' characters
+ while((theIndex > 0) && (sAnswer[theIndex] == '\\'))
+ {
+ --theIndex;
+ }
+
+ // now keep walking back until we get to a '\'
+ while((theIndex > 0) && (sAnswer[theIndex] != '\\'))
+ {
+ --theIndex;
+ }
+
+ // where we are now is either the first character of the path or the '\' that marks the end of the directory name
+ if(theIndex > 0)
+ {
+ // we have a name so put a '\0' in place of the '\'
+ sAnswer[theIndex] = 0;
+ }
+ else
+ {
+ // no name, so the answer is "."
+ sAnswer[0] = '.';
+ sAnswer[1] = 0;
+ }
+
+ // set the return value
+ theAnswer = sAnswer;
+ }
+
+ return theAnswer;
+}
+
+char* basename(const char* inPath)
+{
+ static char sAnswer[1024];
+
+ char* theAnswer = NULL;
+ SInt32 thePathLength = strlen(inPath);
+ if(thePathLength < 1023)
+ {
+ // make a working copy
+ strlcpy(sAnswer, inPath, sizeof(sAnswer));
+
+ // start at the end of the string
+ SInt32 theLastIndex = thePathLength - 1;
+
+ // walk back over the '\' characters
+ while((theLastIndex > 0) && (sAnswer[theLastIndex] == '\\'))
+ {
+ --theLastIndex;
+ }
+
+ // check to see if we're at the beginning now
+ if(theLastIndex > 0)
+ {
+ // there's a name in there now, so start where we are and go back to the next '\'
+ UInt32 theFirstIndex = theLastIndex;
+ while((theFirstIndex > 0) && (sAnswer[theFirstIndex] != '\\'))
+ {
+ --theFirstIndex;
+ }
+
+ // we now have a string, so put a '\0' after the last character
+ sAnswer[theLastIndex + 1] = 0;
+
+ // and set the return value
+ theAnswer = &sAnswer[theFirstIndex];
+ }
+ else
+ {
+ // the path was entirely '\' characters, so the return value is "\"
+ sAnswer[0] = '\\';
+ sAnswer[1] = 0;
+
+ // set the return value
+ theAnswer = sAnswer;
+ }
+ }
+
+ return theAnswer;
+}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.h b/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.h
new file mode 100644
index 0000000000..41f1ee00af
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.h
@@ -0,0 +1,70 @@
+/*
+ File: CAFilePathUtils.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAFilePathUtils_h__
+#define __CAFilePathUtils_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CoreFoundation.h>
+ #include <CoreAudio/CoreAudio.h>
+#else
+ #include <TargetConditionals.h>
+ #include <CoreFoundation.h>
+ #include <CoreAudio.h>
+#endif
+
+struct FSRef;
+
+OSStatus PosixPathToParentFSRefAndName(const char *path, FSRef &outParentDir, CFStringRef &outFileName);
+
+#if !TARGET_OS_WIN32
+ #include <libgen.h>
+#else
+ char* dirname(const char* inPath);
+ char* basename(const char* inPath);
+#endif
+
+#endif // __CAFilePathUtils_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAGuard.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAGuard.cpp
new file mode 100644
index 0000000000..a1c83be9dd
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAGuard.cpp
@@ -0,0 +1,343 @@
+/*
+ File: CAGuard.cpp
+ Abstract: CAGuard.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CAGuard.h"
+
+#if TARGET_OS_MAC
+ #include <errno.h>
+#endif
+
+// PublicUtility Inludes
+#include "CADebugMacros.h"
+#include "CAException.h"
+#include "CAHostTimeBase.h"
+
+//==================================================================================================
+// Logging
+//==================================================================================================
+
+#if CoreAudio_Debug
+// #define Log_Ownership 1
+// #define Log_WaitOwnership 1
+// #define Log_TimedWaits 1
+// #define Log_Latency 1
+// #define Log_Errors 1
+#endif
+
+//#warning Need a try-based Locker too
+//==================================================================================================
+// CAGuard
+//==================================================================================================
+
+CAGuard::CAGuard(const char* inName)
+:
+ CAMutex(inName)
+#if Log_Average_Latency
+ ,mAverageLatencyAccumulator(0.0),
+ mAverageLatencyCount(0)
+#endif
+{
+#if TARGET_OS_MAC
+ OSStatus theError = pthread_cond_init(&mCondVar, NULL);
+ ThrowIf(theError != 0, CAException(theError), "CAGuard::CAGuard: Could not init the cond var");
+#elif TARGET_OS_WIN32
+ mEvent = CreateEvent(NULL, true, false, NULL);
+ ThrowIfNULL(mEvent, CAException(GetLastError()), "CAGuard::CAGuard: Could not create the event");
+#endif
+}
+
+CAGuard::~CAGuard()
+{
+#if TARGET_OS_MAC
+ pthread_cond_destroy(&mCondVar);
+#elif TARGET_OS_WIN32
+ if(mEvent != NULL)
+ {
+ CloseHandle(mEvent);
+ }
+#endif
+}
+
+void CAGuard::Wait()
+{
+#if TARGET_OS_MAC
+ ThrowIf(!pthread_equal(pthread_self(), mOwner), CAException(1), "CAGuard::Wait: A thread has to have locked a guard before it can wait");
+
+ mOwner = 0;
+
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::Wait: thread %p is waiting on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+
+ OSStatus theError = pthread_cond_wait(&mCondVar, &mMutex);
+ ThrowIf(theError != 0, CAException(theError), "CAGuard::Wait: Could not wait for a signal");
+ mOwner = pthread_self();
+
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::Wait: thread %p waited on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+#elif TARGET_OS_WIN32
+ ThrowIf(GetCurrentThreadId() != mOwner, CAException(1), "CAGuard::Wait: A thread has to have locked a guard before it can wait");
+
+ mOwner = 0;
+
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::Wait: thread %lu is waiting on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+
+ ReleaseMutex(mMutex);
+ HANDLE theHandles[] = { mMutex, mEvent };
+ OSStatus theError = WaitForMultipleObjects(2, theHandles, true, INFINITE);
+ ThrowIfError(theError, CAException(GetLastError()), "CAGuard::Wait: Could not wait for the signal");
+ mOwner = GetCurrentThreadId();
+ ResetEvent(mEvent);
+
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::Wait: thread %lu waited on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+#endif
+}
+
+bool CAGuard::WaitFor(UInt64 inNanos)
+{
+ bool theAnswer = false;
+
+#if TARGET_OS_MAC
+ ThrowIf(!pthread_equal(pthread_self(), mOwner), CAException(1), "CAGuard::WaitFor: A thread has to have locked a guard be for it can wait");
+
+ #if Log_TimedWaits
+ DebugMessageN1("CAGuard::WaitFor: waiting %.0f", (Float64)inNanos);
+ #endif
+
+ struct timespec theTimeSpec;
+ static const UInt64 kNanosPerSecond = 1000000000ULL;
+ if(inNanos >= kNanosPerSecond)
+ {
+ theTimeSpec.tv_sec = static_cast<long>(inNanos / kNanosPerSecond);
+ theTimeSpec.tv_nsec = static_cast<long>(inNanos % kNanosPerSecond);
+ }
+ else
+ {
+ theTimeSpec.tv_sec = 0;
+ theTimeSpec.tv_nsec = static_cast<long>(inNanos);
+ }
+
+ #if Log_TimedWaits || Log_Latency || Log_Average_Latency
+ UInt64 theStartNanos = CAHostTimeBase::GetCurrentTimeInNanos();
+ #endif
+
+ mOwner = 0;
+
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::WaitFor: thread %p is waiting on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+
+ OSStatus theError = pthread_cond_timedwait_relative_np(&mCondVar, &mMutex, &theTimeSpec);
+ ThrowIf((theError != 0) && (theError != ETIMEDOUT), CAException(theError), "CAGuard::WaitFor: Wait got an error");
+ mOwner = pthread_self();
+
+ #if Log_TimedWaits || Log_Latency || Log_Average_Latency
+ UInt64 theEndNanos = CAHostTimeBase::GetCurrentTimeInNanos();
+ #endif
+
+ #if Log_TimedWaits
+ DebugMessageN1("CAGuard::WaitFor: waited %.0f", (Float64)(theEndNanos - theStartNanos));
+ #endif
+
+ #if Log_Latency
+ DebugMessageN1("CAGuard::WaitFor: latency %.0f", (Float64)((theEndNanos - theStartNanos) - inNanos));
+ #endif
+
+ #if Log_Average_Latency
+ ++mAverageLatencyCount;
+ mAverageLatencyAccumulator += (theEndNanos - theStartNanos) - inNanos;
+ if(mAverageLatencyCount >= 50)
+ {
+ DebugMessageN2("CAGuard::WaitFor: average latency %.3f ns over %ld waits", mAverageLatencyAccumulator / mAverageLatencyCount, mAverageLatencyCount);
+ mAverageLatencyCount = 0;
+ mAverageLatencyAccumulator = 0.0;
+ }
+ #endif
+
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::WaitFor: thread %p waited on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+
+ theAnswer = theError == ETIMEDOUT;
+#elif TARGET_OS_WIN32
+ ThrowIf(GetCurrentThreadId() != mOwner, CAException(1), "CAGuard::WaitFor: A thread has to have locked a guard be for it can wait");
+
+ #if Log_TimedWaits
+ DebugMessageN1("CAGuard::WaitFor: waiting %.0f", (Float64)inNanos);
+ #endif
+
+ // the time out is specified in milliseconds(!)
+ UInt32 theWaitTime = static_cast<UInt32>(inNanos / 1000000ULL);
+
+ #if Log_TimedWaits || Log_Latency || Log_Average_Latency
+ UInt64 theStartNanos = CAHostTimeBase::GetCurrentTimeInNanos();
+ #endif
+
+ mOwner = 0;
+
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::WaitFor: thread %lu is waiting on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+
+ ReleaseMutex(mMutex);
+ HANDLE theHandles[] = { mMutex, mEvent };
+ OSStatus theError = WaitForMultipleObjects(2, theHandles, true, theWaitTime);
+ ThrowIf((theError != WAIT_OBJECT_0) && (theError != WAIT_TIMEOUT), CAException(GetLastError()), "CAGuard::WaitFor: Wait got an error");
+ mOwner = GetCurrentThreadId();
+ ResetEvent(mEvent);
+ // This mutex should be locked again when time out happens.rdar://12270555
+ if(theError == WAIT_TIMEOUT) {
+ DWORD dwError = WaitForSingleObject(mMutex, INFINITE);
+ ThrowIf((dwError != WAIT_OBJECT_0), CAException(GetLastError()), "CAGuard::WaitFor: failed to acquire the mutex back when timeout happened\n");
+ }
+ #if Log_TimedWaits || Log_Latency || Log_Average_Latency
+ UInt64 theEndNanos = CAHostTimeBase::GetCurrentTimeInNanos();
+ #endif
+
+ #if Log_TimedWaits
+ DebugMessageN1("CAGuard::WaitFor: waited %.0f", (Float64)(theEndNanos - theStartNanos));
+ #endif
+
+ #if Log_Latency
+ DebugMessageN1("CAGuard::WaitFor: latency %.0f", (Float64)((theEndNanos - theStartNanos) - inNanos));
+ #endif
+
+ #if Log_Average_Latency
+ ++mAverageLatencyCount;
+ mAverageLatencyAccumulator += (theEndNanos - theStartNanos) - inNanos;
+ if(mAverageLatencyCount >= 50)
+ {
+ DebugMessageN2("CAGuard::WaitFor: average latency %.3f ns over %ld waits", mAverageLatencyAccumulator / mAverageLatencyCount, mAverageLatencyCount);
+ mAverageLatencyCount = 0;
+ mAverageLatencyAccumulator = 0.0;
+ }
+ #endif
+
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::WaitFor: thread %lu waited on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+
+ theAnswer = theError == WAIT_TIMEOUT;
+#endif
+
+ return theAnswer;
+}
+
+bool CAGuard::WaitUntil(UInt64 inNanos)
+{
+ bool theAnswer = false;
+ UInt64 theCurrentNanos = CAHostTimeBase::GetCurrentTimeInNanos();
+
+#if Log_TimedWaits
+ DebugMessageN2("CAGuard::WaitUntil: now: %.0f, requested: %.0f", (double)theCurrentNanos, (double)inNanos);
+#endif
+
+ if(inNanos > theCurrentNanos)
+ {
+#if Log_Errors
+ if((inNanos - theCurrentNanos) > 1000000000ULL)
+ {
+ DebugMessage("CAGuard::WaitUntil: about to wait for more than a second");
+ }
+#endif
+ theAnswer = WaitFor(inNanos - theCurrentNanos);
+ }
+ else
+ {
+#if Log_Errors
+ DebugMessageN2("CAGuard::WaitUntil: Time has expired before waiting, now: %.0f, requested: %.0f", (double)theCurrentNanos, (double)inNanos);
+#endif
+ theAnswer = true;
+ }
+
+ return theAnswer;
+}
+
+void CAGuard::Notify()
+{
+#if TARGET_OS_MAC
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::Notify: thread %p is notifying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+
+ OSStatus theError = pthread_cond_signal(&mCondVar);
+ ThrowIf(theError != 0, CAException(theError), "CAGuard::Notify: failed");
+#elif TARGET_OS_WIN32
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::Notify: thread %lu is notifying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+
+ SetEvent(mEvent);
+#endif
+}
+
+void CAGuard::NotifyAll()
+{
+#if TARGET_OS_MAC
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::NotifyAll: thread %p is notifying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+
+ OSStatus theError = pthread_cond_broadcast(&mCondVar);
+ ThrowIf(theError != 0, CAException(theError), "CAGuard::NotifyAll: failed");
+#elif TARGET_OS_WIN32
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::NotifyAll: thread %lu is notifying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+
+ SetEvent(mEvent);
+#endif
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAGuard.h b/libs/appleutility/CoreAudio/PublicUtility/CAGuard.h
new file mode 100644
index 0000000000..ffcb59da8d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAGuard.h
@@ -0,0 +1,133 @@
+/*
+ File: CAGuard.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAGuard_h__)
+#define __CAGuard_h__
+
+//==================================================================================================
+// Includes
+//=============================================================================
+
+// Super Class Includes
+#include "CAMutex.h"
+
+#if CoreAudio_Debug
+// #define Log_Average_Latency 1
+#endif
+
+//==================================================================================================
+// CAGuard
+//
+// This is your typical mutex with signalling implemented via pthreads.
+// Lock() will return true if and only if the guard is locked on that call.
+// A thread that already has the guard will receive 'false' if it locks it
+// again. Use of the stack-based CAGuard::Locker class is highly recommended
+// to properly manage the recursive nesting. The Wait calls with timeouts
+// will return true if and only if the timeout period expired. They will
+// return false if they receive notification any other way.
+//==================================================================================================
+
+class CAGuard : public CAMutex
+{
+
+// Construction/Destruction
+public:
+ CAGuard(const char* inName);
+ virtual ~CAGuard();
+
+// Actions
+public:
+ virtual void Wait();
+ virtual bool WaitFor(UInt64 inNanos);
+ virtual bool WaitUntil(UInt64 inNanos);
+
+ virtual void Notify();
+ virtual void NotifyAll();
+
+// Implementation
+protected:
+#if TARGET_OS_MAC
+ pthread_cond_t mCondVar;
+#else
+ HANDLE mEvent;
+#endif
+#if Log_Average_Latency
+ Float64 mAverageLatencyAccumulator;
+ UInt32 mAverageLatencyCount;
+#endif
+
+// Helper class to manage taking and releasing recursively
+public:
+ class Locker
+ {
+
+ // Construction/Destruction
+ public:
+ Locker(CAGuard& inGuard) : mGuard(inGuard), mNeedsRelease(false) { mNeedsRelease = mGuard.Lock(); }
+ ~Locker() { if(mNeedsRelease) { mGuard.Unlock(); } }
+
+ private:
+ Locker(const Locker&);
+ Locker& operator=(const Locker&);
+
+ // Actions
+ public:
+ void Wait() { mGuard.Wait(); }
+ bool WaitFor(UInt64 inNanos) { return mGuard.WaitFor(inNanos); }
+ bool WaitUntil(UInt64 inNanos) { return mGuard.WaitUntil(inNanos); }
+
+ void Notify() { mGuard.Notify(); }
+ void NotifyAll() { mGuard.NotifyAll(); }
+
+ // Implementation
+ private:
+ CAGuard& mGuard;
+ bool mNeedsRelease;
+ };
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.cpp
new file mode 100644
index 0000000000..9bce34626a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.cpp
@@ -0,0 +1,1156 @@
+/*
+ File: CAHALAudioDevice.cpp
+ Abstract: CAHALAudioDevice.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CAHALAudioDevice.h"
+
+// PublicUtility Includes
+#include "CAAutoDisposer.h"
+#include "CAHALAudioStream.h"
+#include "CAHALAudioSystemObject.h"
+#include "CAPropertyAddress.h"
+
+//==================================================================================================
+// CAHALAudioDevice
+//==================================================================================================
+
+CAHALAudioDevice::CAHALAudioDevice(AudioObjectID inAudioDevice)
+:
+ CAHALAudioObject(inAudioDevice)
+{
+}
+
+CAHALAudioDevice::CAHALAudioDevice(CFStringRef inUID)
+:
+ CAHALAudioObject(CAHALAudioSystemObject().GetAudioDeviceForUID(inUID))
+{
+}
+
+CAHALAudioDevice::~CAHALAudioDevice()
+{
+}
+
+CFStringRef CAHALAudioDevice::CopyDeviceUID() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDeviceUID);
+ return GetPropertyData_CFString(theAddress, 0, NULL);
+}
+
+bool CAHALAudioDevice::HasModelUID() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyModelUID);
+ return HasProperty(theAddress);
+}
+
+CFStringRef CAHALAudioDevice::CopyModelUID() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyModelUID);
+ return GetPropertyData_CFString(theAddress, 0, NULL);
+}
+
+CFStringRef CAHALAudioDevice::CopyConfigurationApplicationBundleID() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyConfigurationApplication);
+ return GetPropertyData_CFString(theAddress, 0, NULL);
+}
+
+CFURLRef CAHALAudioDevice::CopyIconLocation() const
+{
+ CFURLRef theAnswer = NULL;
+ CAPropertyAddress theAddress(kAudioDevicePropertyIcon);
+ UInt32 theSize = sizeof(CFURLRef);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ return theAnswer;
+}
+
+UInt32 CAHALAudioDevice::GetTransportType() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyTransportType);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+bool CAHALAudioDevice::CanBeDefaultDevice(bool inIsInput, bool inIsSystem) const
+{
+ CAPropertyAddress theAddress(inIsSystem ? kAudioDevicePropertyDeviceCanBeDefaultSystemDevice : kAudioDevicePropertyDeviceCanBeDefaultDevice, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ return GetPropertyData_UInt32(theAddress, 0, NULL) != 0;
+}
+
+bool CAHALAudioDevice::HasDevicePlugInStatus() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPlugIn);
+ return HasProperty(theAddress);
+}
+
+OSStatus CAHALAudioDevice::GetDevicePlugInStatus() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPlugIn);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+bool CAHALAudioDevice::IsAlive() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDeviceIsAlive);
+ return GetPropertyData_UInt32(theAddress, 0, NULL) != 0;
+}
+
+bool CAHALAudioDevice::IsHidden() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyIsHidden);
+ return GetPropertyData_UInt32(theAddress, 0, NULL) != 0;
+}
+
+pid_t CAHALAudioDevice::GetHogModeOwner() const
+{
+ pid_t theAnswer = -1;
+ CAPropertyAddress theAddress(kAudioDevicePropertyHogMode);
+ if(HasProperty(theAddress))
+ {
+ UInt32 theSize = sizeof(pid_t);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ }
+ return theAnswer;
+}
+
+bool CAHALAudioDevice::IsHogModeSettable() const
+{
+ bool theAnswer = false;
+ CAPropertyAddress theAddress(kAudioDevicePropertyHogMode);
+ if(HasProperty(theAddress))
+ {
+ theAnswer = IsPropertySettable(theAddress);
+ }
+ return theAnswer;
+}
+
+bool CAHALAudioDevice::TakeHogMode()
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyHogMode);
+ pid_t thePID = getpid();
+ if(HasProperty(theAddress))
+ {
+ SetPropertyData(theAddress, 0, NULL, sizeof(pid_t), &thePID);
+ }
+ return thePID == getpid();
+}
+
+void CAHALAudioDevice::ReleaseHogMode()
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyHogMode);
+ if(HasProperty(theAddress))
+ {
+ pid_t thePID = -1;
+ SetPropertyData(theAddress, 0, NULL, sizeof(pid_t), &thePID);
+ }
+}
+
+bool CAHALAudioDevice::HasPreferredStereoChannels(bool inIsInput) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelsForStereo, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ return HasProperty(theAddress);
+}
+
+void CAHALAudioDevice::GetPreferredStereoChannels(bool inIsInput, UInt32& outLeft, UInt32& outRight) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelsForStereo, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ UInt32 theStereoPair[2] = { 0, 0 };
+ UInt32 theSize = 2 * sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, theStereoPair);
+ outLeft = theStereoPair[0];
+ outRight = theStereoPair[1];
+}
+
+void CAHALAudioDevice::SetPreferredStereoChannels(bool inIsInput, UInt32 inLeft, UInt32 inRight)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelsForStereo, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ UInt32 theStereoPair[2] = { inLeft, inRight };
+ SetPropertyData(theAddress, 0, NULL, 2 * sizeof(UInt32), theStereoPair);
+}
+
+bool CAHALAudioDevice::HasPreferredChannelLayout(bool inIsInput) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelLayout, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ return HasProperty(theAddress);
+}
+
+void CAHALAudioDevice::GetPreferredChannelLayout(bool inIsInput, AudioChannelLayout& outChannelLayout) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelLayout, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ UInt32 theSize = (SizeOf32(AudioChannelLayout) - SizeOf32(AudioChannelDescription)) + GetTotalNumberChannels(inIsInput) * SizeOf32(AudioChannelDescription);
+ GetPropertyData(theAddress, 0, NULL, theSize, &outChannelLayout);
+}
+
+void CAHALAudioDevice::SetPreferredStereoChannels(bool inIsInput, AudioChannelLayout& inChannelLayout)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPreferredChannelLayout, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ UInt32 theSize = (SizeOf32(AudioChannelLayout) - SizeOf32(AudioChannelDescription)) + GetTotalNumberChannels(inIsInput) * SizeOf32(AudioChannelDescription);
+ SetPropertyData(theAddress, 0, NULL, theSize, &inChannelLayout);
+}
+
+UInt32 CAHALAudioDevice::GetNumberRelatedAudioDevices() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyRelatedDevices);
+ UInt32 theAnswer = 0;
+ if(HasProperty(theAddress))
+ {
+ theAnswer = GetPropertyDataSize(theAddress, 0, NULL);
+ theAnswer /= SizeOf32(AudioObjectID);
+ }
+ return theAnswer;
+}
+
+void CAHALAudioDevice::GetRelatedAudioDevices(UInt32& ioNumberRelatedDevices, AudioObjectID* outRelatedDevices) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyRelatedDevices);
+ if(HasProperty(theAddress))
+ {
+ UInt32 theSize = ioNumberRelatedDevices * SizeOf32(AudioObjectID);
+ GetPropertyData(theAddress, 0, NULL, theSize, outRelatedDevices);
+ ioNumberRelatedDevices = theSize / SizeOf32(AudioObjectID);
+ }
+ else
+ {
+ UInt32 theSize = ioNumberRelatedDevices * SizeOf32(AudioObjectID);
+ memset(outRelatedDevices, 0, theSize);
+ ioNumberRelatedDevices = 0;
+ }
+}
+
+AudioObjectID CAHALAudioDevice::GetRelatedAudioDeviceByIndex(UInt32 inIndex) const
+{
+ AudioObjectID theAnswer = kAudioObjectUnknown;
+ UInt32 theNumberRelatedDevices = GetNumberRelatedAudioDevices();
+ if((theNumberRelatedDevices > 0) && (inIndex < theNumberRelatedDevices))
+ {
+ CAAutoArrayDelete<AudioObjectID> theRelatedDeviceList(theNumberRelatedDevices);
+ GetRelatedAudioDevices(theNumberRelatedDevices, theRelatedDeviceList);
+ if((theNumberRelatedDevices > 0) && (inIndex < theNumberRelatedDevices))
+ {
+ theAnswer = theRelatedDeviceList[inIndex];
+ }
+ }
+ return theAnswer;
+}
+
+UInt32 CAHALAudioDevice::GetNumberStreams(bool inIsInput) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyStreams, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ UInt32 theAnswer = GetPropertyDataSize(theAddress, 0, NULL);
+ theAnswer /= SizeOf32(AudioObjectID);
+ return theAnswer;
+}
+
+void CAHALAudioDevice::GetStreams(bool inIsInput, UInt32& ioNumberStreams, AudioObjectID* outStreamList) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyStreams, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ UInt32 theSize = ioNumberStreams * SizeOf32(AudioObjectID);
+ GetPropertyData(theAddress, 0, NULL, theSize, outStreamList);
+ ioNumberStreams = theSize / SizeOf32(AudioObjectID);
+}
+
+AudioObjectID CAHALAudioDevice::GetStreamByIndex(bool inIsInput, UInt32 inIndex) const
+{
+ AudioObjectID theAnswer = kAudioObjectUnknown;
+ UInt32 theNumberStreams = GetNumberStreams(inIsInput);
+ if((theNumberStreams > 0) && (inIndex < theNumberStreams))
+ {
+ CAAutoArrayDelete<AudioObjectID> theStreamList(theNumberStreams);
+ GetStreams(inIsInput, theNumberStreams, theStreamList);
+ if((theNumberStreams > 0) && (inIndex < theNumberStreams))
+ {
+ theAnswer = theStreamList[inIndex];
+ }
+ }
+ return theAnswer;
+}
+
+UInt32 CAHALAudioDevice::GetTotalNumberChannels(bool inIsInput) const
+{
+ UInt32 theAnswer = 0;
+ CAPropertyAddress theAddress(kAudioDevicePropertyStreamConfiguration, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL);
+ CAAutoFree<AudioBufferList> theBufferList(theSize);
+ GetPropertyData(theAddress, 0, NULL, theSize, theBufferList);
+ for(UInt32 theIndex = 0; theIndex < theBufferList->mNumberBuffers; ++theIndex)
+ {
+ theAnswer += theBufferList->mBuffers[theIndex].mNumberChannels;
+ }
+ return theAnswer;
+}
+
+void CAHALAudioDevice::GetCurrentVirtualFormats(bool inIsInput, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const
+{
+ ioNumberStreams = std::min(ioNumberStreams, GetNumberStreams(inIsInput));
+ for(UInt32 theIndex = 0; theIndex < ioNumberStreams; ++theIndex)
+ {
+ CAHALAudioStream theStream(GetStreamByIndex(inIsInput, theIndex));
+ theStream.GetCurrentVirtualFormat(outFormats[theIndex]);
+ }
+}
+
+void CAHALAudioDevice::GetCurrentPhysicalFormats(bool inIsInput, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const
+{
+ ioNumberStreams = std::min(ioNumberStreams, GetNumberStreams(inIsInput));
+ for(UInt32 theIndex = 0; theIndex < ioNumberStreams; ++theIndex)
+ {
+ CAHALAudioStream theStream(GetStreamByIndex(inIsInput, theIndex));
+ theStream.GetCurrentPhysicalFormat(outFormats[theIndex]);
+ }
+}
+
+bool CAHALAudioDevice::IsRunning() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDeviceIsRunning);
+ UInt32 theAnswer = GetPropertyData_UInt32(theAddress, 0, NULL);
+ return theAnswer != 0;
+}
+
+bool CAHALAudioDevice::IsRunningSomewhere() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDeviceIsRunningSomewhere);
+ UInt32 theAnswer = 0;
+ if(HasProperty(theAddress))
+ {
+ theAnswer = GetPropertyData_UInt32(theAddress, 0, NULL);
+ }
+ return theAnswer != 0;
+}
+
+UInt32 CAHALAudioDevice::GetLatency(bool inIsInput) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyLatency, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+UInt32 CAHALAudioDevice::GetSafetyOffset(bool inIsInput) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySafetyOffset, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+bool CAHALAudioDevice::HasClockDomain() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockDomain);
+ return HasProperty(theAddress);
+}
+
+UInt32 CAHALAudioDevice::GetClockDomain() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockDomain);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+Float64 CAHALAudioDevice::GetActualSampleRate() const
+{
+ Float64 theAnswer = 0;
+ CAPropertyAddress theAddress(kAudioDevicePropertyActualSampleRate);
+ if(HasProperty(theAddress))
+ {
+ UInt32 theSize = sizeof(Float64);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ }
+ else
+ {
+ theAnswer = GetNominalSampleRate();
+ }
+ return theAnswer;
+}
+
+Float64 CAHALAudioDevice::GetNominalSampleRate() const
+{
+ Float64 theAnswer = 0;
+ CAPropertyAddress theAddress(kAudioDevicePropertyNominalSampleRate);
+ UInt32 theSize = sizeof(Float64);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ return theAnswer;
+}
+
+void CAHALAudioDevice::SetNominalSampleRate(Float64 inSampleRate)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyNominalSampleRate);
+ SetPropertyData(theAddress, 0, NULL, sizeof(Float64), &inSampleRate);
+}
+
+UInt32 CAHALAudioDevice::GetNumberAvailableNominalSampleRateRanges() const
+{
+ UInt32 theAnswer = 0;
+ CAPropertyAddress theAddress(kAudioDevicePropertyAvailableNominalSampleRates);
+ if(HasProperty(theAddress))
+ {
+ UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL);
+ theAnswer = theSize / SizeOf32(AudioValueRange);
+ }
+ return theAnswer;
+}
+
+void CAHALAudioDevice::GetAvailableNominalSampleRateRanges(UInt32& ioNumberRanges, AudioValueRange* outRanges) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyAvailableNominalSampleRates);
+ if(HasProperty(theAddress))
+ {
+ UInt32 theSize = ioNumberRanges * SizeOf32(AudioValueRange);
+ GetPropertyData(theAddress, 0, NULL, theSize, outRanges);
+ ioNumberRanges = theSize / SizeOf32(AudioValueRange);
+ }
+ else
+ {
+ ioNumberRanges = 0;
+ }
+}
+
+void CAHALAudioDevice::GetAvailableNominalSampleRateRangeByIndex(UInt32 inIndex, Float64& outMinimum, Float64& outMaximum) const
+{
+ UInt32 theNumberRanges = GetNumberAvailableNominalSampleRateRanges();
+ ThrowIf(inIndex >= theNumberRanges, CAException(kAudioHardwareIllegalOperationError), "CAHALAudioDevice::GetAvailableNominalSampleRateRangeByIndex: index out of range");
+ CAAutoArrayDelete<AudioValueRange> theRanges(theNumberRanges);
+ GetAvailableNominalSampleRateRanges(theNumberRanges, theRanges);
+ outMinimum = theRanges[inIndex].mMinimum;
+ outMaximum = theRanges[inIndex].mMaximum;
+}
+
+bool CAHALAudioDevice::IsValidNominalSampleRate(Float64 inSampleRate) const
+{
+ bool theAnswer = false;
+ UInt32 theNumberRanges = GetNumberAvailableNominalSampleRateRanges();
+ CAAutoArrayDelete<AudioValueRange> theRanges(theNumberRanges);
+ GetAvailableNominalSampleRateRanges(theNumberRanges, theRanges);
+ for(UInt32 theIndex = 0; !theAnswer && (theIndex < theNumberRanges); ++theIndex)
+ {
+ theAnswer = (inSampleRate >= theRanges[theIndex].mMinimum) && (inSampleRate <= theRanges[theIndex].mMinimum);
+ }
+ return theAnswer;
+}
+
+bool CAHALAudioDevice::IsIOBufferSizeSettable() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSize);
+ return IsPropertySettable(theAddress);
+}
+
+UInt32 CAHALAudioDevice::GetIOBufferSize() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSize);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+void CAHALAudioDevice::SetIOBufferSize(UInt32 inBufferSize)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSize);
+ SetPropertyData(theAddress, 0, NULL, sizeof(UInt32), &inBufferSize);
+}
+
+bool CAHALAudioDevice::UsesVariableIOBufferSizes() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyUsesVariableBufferFrameSizes);
+ return HasProperty(theAddress);
+}
+
+UInt32 CAHALAudioDevice::GetMaximumVariableIOBufferSize() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyUsesVariableBufferFrameSizes);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+bool CAHALAudioDevice::HasIOBufferSizeRange() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSizeRange);
+ return HasProperty(theAddress);
+}
+
+void CAHALAudioDevice::GetIOBufferSizeRange(UInt32& outMinimum, UInt32& outMaximum) const
+{
+ AudioValueRange theAnswer = { 0, 0 };
+ CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSizeRange);
+ UInt32 theSize = sizeof(AudioValueRange);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ outMinimum = static_cast<UInt32>(theAnswer.mMinimum);
+ outMaximum = static_cast<UInt32>(theAnswer.mMaximum);
+}
+
+AudioDeviceIOProcID CAHALAudioDevice::CreateIOProcID(AudioDeviceIOProc inIOProc, void* inClientData)
+{
+ AudioDeviceIOProcID theAnswer = NULL;
+ OSStatus theError = AudioDeviceCreateIOProcID(mObjectID, inIOProc, inClientData, &theAnswer);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::CreateIOProcID: got an error creating the IOProc ID");
+ return theAnswer;
+}
+
+void CAHALAudioDevice::DestroyIOProcID(AudioDeviceIOProcID inIOProcID)
+{
+ OSStatus theError = AudioDeviceDestroyIOProcID(mObjectID, inIOProcID);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::DestroyIOProcID: got an error destroying the IOProc ID");
+}
+
+void CAHALAudioDevice::StartIOProc(AudioDeviceIOProcID inIOProcID)
+{
+ OSStatus theError = AudioDeviceStart(mObjectID, inIOProcID);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::StartIOProc: got an error starting an IOProc");
+}
+
+void CAHALAudioDevice::StartIOProcAtTime(AudioDeviceIOProcID inIOProcID, AudioTimeStamp& ioStartTime, bool inIsInput, bool inIgnoreHardware)
+{
+ UInt32 theFlags = 0;
+ if(inIsInput)
+ {
+ theFlags |= kAudioDeviceStartTimeIsInputFlag;
+ }
+ if(inIgnoreHardware)
+ {
+ theFlags |= kAudioDeviceStartTimeDontConsultDeviceFlag;
+ }
+
+ OSStatus theError = AudioDeviceStartAtTime(mObjectID, inIOProcID, &ioStartTime, theFlags);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::StartIOProcAtTime: got an error starting an IOProc");
+}
+
+void CAHALAudioDevice::StopIOProc(AudioDeviceIOProcID inIOProcID)
+{
+ OSStatus theError = AudioDeviceStop(mObjectID, inIOProcID);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::StopIOProc: got an error stopping an IOProc");
+}
+
+void CAHALAudioDevice::GetIOProcStreamUsage(AudioDeviceIOProcID inIOProcID, bool inIsInput, bool* outStreamUsage) const
+{
+ // make an AudioHardwareIOProcStreamUsage the right size
+ UInt32 theNumberStreams = GetNumberStreams(inIsInput);
+ UInt32 theSize = SizeOf32(void*) + SizeOf32(UInt32) + (theNumberStreams * SizeOf32(UInt32));
+ CAAutoFree<AudioHardwareIOProcStreamUsage> theStreamUsage(theSize);
+
+ // set it up
+ theStreamUsage->mIOProc = reinterpret_cast<void*>(inIOProcID);
+ theStreamUsage->mNumberStreams = theNumberStreams;
+
+ // get the property
+ CAPropertyAddress theAddress(kAudioDevicePropertyIOProcStreamUsage, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ GetPropertyData(theAddress, 0, NULL, theSize, theStreamUsage);
+
+ // fill out the return value
+ for(UInt32 theIndex = 0; theIndex < theNumberStreams; ++theIndex)
+ {
+ outStreamUsage[theIndex] = (theStreamUsage->mStreamIsOn[theIndex] != 0);
+ }
+}
+
+void CAHALAudioDevice::SetIOProcStreamUsage(AudioDeviceIOProcID inIOProcID, bool inIsInput, const bool* inStreamUsage)
+{
+ // make an AudioHardwareIOProcStreamUsage the right size
+ UInt32 theNumberStreams = GetNumberStreams(inIsInput);
+ UInt32 theSize = SizeOf32(void*) + SizeOf32(UInt32) + (theNumberStreams * SizeOf32(UInt32));
+ CAAutoFree<AudioHardwareIOProcStreamUsage> theStreamUsage(theSize);
+
+ // set it up
+ theStreamUsage->mIOProc = reinterpret_cast<void*>(inIOProcID);
+ theStreamUsage->mNumberStreams = theNumberStreams;
+ for(UInt32 theIndex = 0; theIndex < theNumberStreams; ++theIndex)
+ {
+ theStreamUsage->mStreamIsOn[theIndex] = (inStreamUsage[theIndex] ? 1 : 0);
+ }
+
+ // set the property
+ CAPropertyAddress theAddress(kAudioDevicePropertyIOProcStreamUsage, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ SetPropertyData(theAddress, 0, NULL, theSize, theStreamUsage);
+}
+
+Float32 CAHALAudioDevice::GetIOCycleUsage() const
+{
+ Float32 theAnswer = 0;
+ CAPropertyAddress theAddress(kAudioDevicePropertyIOCycleUsage);
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ return theAnswer;
+}
+
+void CAHALAudioDevice::SetIOCycleUsage(Float32 inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyIOCycleUsage);
+ SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue);
+}
+
+void CAHALAudioDevice::GetCurrentTime(AudioTimeStamp& outTime)
+{
+ OSStatus theError = AudioDeviceGetCurrentTime(mObjectID, &outTime);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::GetCurrentTime: got an error getting the current time");
+}
+
+void CAHALAudioDevice::TranslateTime(const AudioTimeStamp& inTime, AudioTimeStamp& outTime)
+{
+ OSStatus theError = AudioDeviceTranslateTime(mObjectID, &inTime, &outTime);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::TranslateTime: got an error translating time");
+}
+
+void CAHALAudioDevice::GetNearestStartTime(AudioTimeStamp& ioTime, bool inIsInput, bool inIgnoreHardware)
+{
+ UInt32 theFlags = 0;
+ if(inIsInput)
+ {
+ theFlags |= kAudioDeviceStartTimeIsInputFlag;
+ }
+ if(inIgnoreHardware)
+ {
+ theFlags |= kAudioDeviceStartTimeDontConsultDeviceFlag;
+ }
+
+ OSStatus theError = AudioDeviceGetNearestStartTime(mObjectID, &ioTime, theFlags);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::GetNearestStartTime: got an error getting the start time");
+}
+
+bool CAHALAudioDevice::HasVolumeControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::VolumeControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel);
+ return IsPropertySettable(theAddress);
+}
+
+Float32 CAHALAudioDevice::GetVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel);
+ Float32 theValue = 0.0f;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+Float32 CAHALAudioDevice::GetVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeDecibels, inScope, inChannel);
+ Float32 theValue = 0.0f;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+void CAHALAudioDevice::SetVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel);
+ SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue);
+}
+
+void CAHALAudioDevice::SetVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeDecibels, inScope, inChannel);
+ SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue);
+}
+
+Float32 CAHALAudioDevice::GetVolumeControlScalarForDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeDecibelsToScalar, inScope, inChannel);
+ Float32 theValue = inValue;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+Float32 CAHALAudioDevice::GetVolumeControlDecibelForScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalarToDecibels, inScope, inChannel);
+ Float32 theValue = inValue;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+bool CAHALAudioDevice::HasSubVolumeControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::SubVolumeControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel);
+ return IsPropertySettable(theAddress);
+}
+
+Float32 CAHALAudioDevice::GetSubVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel);
+ Float32 theValue = 0.0f;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+Float32 CAHALAudioDevice::GetSubVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeDecibels, inScope, inChannel);
+ Float32 theValue = 0.0f;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+void CAHALAudioDevice::SetSubVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel);
+ SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue);
+}
+
+void CAHALAudioDevice::SetSubVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeDecibels, inScope, inChannel);
+ SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue);
+}
+
+Float32 CAHALAudioDevice::GetSubVolumeControlScalarForDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeDecibelsToScalar, inScope, inChannel);
+ Float32 theValue = inValue;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+Float32 CAHALAudioDevice::GetSubVolumeControlDecibelForScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalarToDecibels, inScope, inChannel);
+ Float32 theValue = inValue;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+bool CAHALAudioDevice::HasMuteControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::MuteControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel);
+ return IsPropertySettable(theAddress);
+}
+
+bool CAHALAudioDevice::GetMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel);
+ UInt32 theValue = 0;
+ UInt32 theSize = sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue != 0;
+}
+
+void CAHALAudioDevice::SetMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel);
+ UInt32 theValue = (inValue ? 1 : 0);
+ UInt32 theSize = sizeof(UInt32);
+ SetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+}
+
+bool CAHALAudioDevice::HasSoloControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::SoloControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel);
+ return IsPropertySettable(theAddress);
+}
+
+bool CAHALAudioDevice::GetSoloControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel);
+ UInt32 theValue = 0;
+ UInt32 theSize = sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue != 0;
+}
+
+void CAHALAudioDevice::SetSoloControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel);
+ UInt32 theValue = (inValue ? 1 : 0);
+ UInt32 theSize = sizeof(UInt32);
+ SetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+}
+
+bool CAHALAudioDevice::HasStereoPanControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::StereoPanControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel);
+ return IsPropertySettable(theAddress);
+}
+
+Float32 CAHALAudioDevice::GetStereoPanControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel);
+ Float32 theValue = 0.0f;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+void CAHALAudioDevice::SetStereoPanControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel);
+ UInt32 theSize = sizeof(Float32);
+ SetPropertyData(theAddress, 0, NULL, theSize, &inValue);
+}
+
+void CAHALAudioDevice::GetStereoPanControlChannels(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& outLeftChannel, UInt32& outRightChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyStereoPanChannels, inScope, inChannel);
+ UInt32 theValue[2] = { 0, 0 };
+ UInt32 theSize = 2 * sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, theValue);
+ outLeftChannel = theValue[0];
+ outRightChannel = theValue[1];
+}
+
+bool CAHALAudioDevice::HasJackControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyJackIsConnected, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::GetJackControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyJackIsConnected, inScope, inChannel);
+ UInt32 theValue = 0;
+ UInt32 theSize = sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue != 0;
+}
+
+bool CAHALAudioDevice::HasSubMuteControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubMute, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::SubMuteControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubMute, inScope, inChannel);
+ return IsPropertySettable(theAddress);
+}
+
+bool CAHALAudioDevice::GetSubMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubMute, inScope, inChannel);
+ UInt32 theValue = 0;
+ UInt32 theSize = sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue != 0;
+}
+
+void CAHALAudioDevice::SetSubMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubMute, inScope, inChannel);
+ UInt32 theValue = (inValue ? 1 : 0);
+ UInt32 theSize = sizeof(UInt32);
+ SetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+}
+
+bool CAHALAudioDevice::HasiSubOwnerControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDriverShouldOwniSub, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::iSubOwnerControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDriverShouldOwniSub, inScope, inChannel);
+ return IsPropertySettable(theAddress);
+}
+
+bool CAHALAudioDevice::GetiSubOwnerControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDriverShouldOwniSub, inScope, inChannel);
+ UInt32 theValue = 0;
+ UInt32 theSize = sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue != 0;
+}
+
+void CAHALAudioDevice::SetiSubOwnerControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDriverShouldOwniSub, inScope, inChannel);
+ UInt32 theValue = (inValue ? 1 : 0);
+ UInt32 theSize = sizeof(UInt32);
+ SetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+}
+
+bool CAHALAudioDevice::HasDataSourceControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDataSource, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::DataSourceControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDataSource, inScope, inChannel);
+ return IsPropertySettable(theAddress);
+}
+
+UInt32 CAHALAudioDevice::GetCurrentDataSourceID(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDataSource, inScope, inChannel);
+ UInt32 theAnswer = 0;
+ UInt32 theSize = sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ return theAnswer;
+}
+
+void CAHALAudioDevice::SetCurrentDataSourceByID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDataSource, inScope, inChannel);
+ UInt32 theSize = sizeof(UInt32);
+ SetPropertyData(theAddress, 0, NULL, theSize, &inID);
+}
+
+UInt32 CAHALAudioDevice::GetNumberAvailableDataSources(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDataSources, inScope, inChannel);
+ UInt32 theAnswer = 0;
+ if(HasProperty(theAddress))
+ {
+ UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL);
+ theAnswer = theSize / SizeOf32(UInt32);
+ }
+ return theAnswer;
+}
+
+void CAHALAudioDevice::GetAvailableDataSources(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& ioNumberSources, UInt32* outSources) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDataSources, inScope, inChannel);
+ UInt32 theNumberSources = std::min(GetNumberAvailableDataSources(inScope, inChannel), ioNumberSources);
+ UInt32 theSize = theNumberSources * SizeOf32(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, outSources);
+ ioNumberSources = theSize / SizeOf32(UInt32);
+}
+
+UInt32 CAHALAudioDevice::GetAvailableDataSourceByIndex(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inIndex) const
+{
+ AudioStreamID theAnswer = 0;
+ UInt32 theNumberSources = GetNumberAvailableDataSources(inScope, inChannel);
+ if((theNumberSources > 0) && (inIndex < theNumberSources))
+ {
+ CAAutoArrayDelete<UInt32> theSourceList(theNumberSources);
+ GetAvailableDataSources(inScope, inChannel, theNumberSources, theSourceList);
+ theAnswer = theSourceList[inIndex];
+ }
+ return theAnswer;
+}
+
+CFStringRef CAHALAudioDevice::CopyDataSourceNameForID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDataSourceNameForIDCFString, inScope, inChannel);
+ CFStringRef theAnswer = NULL;
+ AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(CFStringRef) };
+ UInt32 theSize = sizeof(AudioValueTranslation);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theTranslation);
+ return theAnswer;
+}
+
+bool CAHALAudioDevice::HasDataDestinationControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::DataDestinationControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel);
+ return IsPropertySettable(theAddress);
+}
+
+UInt32 CAHALAudioDevice::GetCurrentDataDestinationID(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel);
+ UInt32 theAnswer = 0;
+ UInt32 theSize = sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ return theAnswer;
+}
+
+void CAHALAudioDevice::SetCurrentDataDestinationByID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel);
+ UInt32 theSize = sizeof(UInt32);
+ SetPropertyData(theAddress, 0, NULL, theSize, &inID);
+}
+
+UInt32 CAHALAudioDevice::GetNumberAvailableDataDestinations(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestinations, inScope, inChannel);
+ UInt32 theAnswer = 0;
+ if(HasProperty(theAddress))
+ {
+ UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL);
+ theAnswer = theSize / SizeOf32(UInt32);
+ }
+ return theAnswer;
+}
+
+void CAHALAudioDevice::GetAvailableDataDestinations(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& ioNumberDestinations, UInt32* outDestinations) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestinations, inScope, inChannel);
+ UInt32 theNumberDestinations = std::min(GetNumberAvailableDataDestinations(inScope, inChannel), ioNumberDestinations);
+ UInt32 theSize = theNumberDestinations * SizeOf32(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, outDestinations);
+ ioNumberDestinations = theSize / SizeOf32(UInt32);
+}
+
+UInt32 CAHALAudioDevice::GetAvailableDataDestinationByIndex(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inIndex) const
+{
+ AudioStreamID theAnswer = 0;
+ UInt32 theNumberDestinations = GetNumberAvailableDataDestinations(inScope, inChannel);
+ if((theNumberDestinations > 0) && (inIndex < theNumberDestinations))
+ {
+ CAAutoArrayDelete<UInt32> theDestinationList(theNumberDestinations);
+ GetAvailableDataDestinations(inScope, inChannel, theNumberDestinations, theDestinationList);
+ theAnswer = theDestinationList[inIndex];
+ }
+ return theAnswer;
+}
+
+CFStringRef CAHALAudioDevice::CopyDataDestinationNameForID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestinationNameForIDCFString, inScope, inChannel);
+ CFStringRef theAnswer = NULL;
+ AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(CFStringRef) };
+ UInt32 theSize = sizeof(AudioValueTranslation);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theTranslation);
+ return theAnswer;
+}
+
+bool CAHALAudioDevice::HasClockSourceControl() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSource);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::ClockSourceControlIsSettable() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSource);
+ return IsPropertySettable(theAddress);
+}
+
+UInt32 CAHALAudioDevice::GetCurrentClockSourceID() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSource);
+ UInt32 theAnswer = 0;
+ UInt32 theSize = sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ return theAnswer;
+}
+
+void CAHALAudioDevice::SetCurrentClockSourceByID(UInt32 inID)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSource);
+ UInt32 theSize = sizeof(UInt32);
+ SetPropertyData(theAddress, 0, NULL, theSize, &inID);
+}
+
+UInt32 CAHALAudioDevice::GetNumberAvailableClockSources() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSources);
+ UInt32 theAnswer = 0;
+ if(HasProperty(theAddress))
+ {
+ UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL);
+ theAnswer = theSize / SizeOf32(UInt32);
+ }
+ return theAnswer;
+}
+
+void CAHALAudioDevice::GetAvailableClockSources(UInt32& ioNumberSources, UInt32* outSources) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSources);
+ UInt32 theNumberSources = std::min(GetNumberAvailableClockSources(), ioNumberSources);
+ UInt32 theSize = theNumberSources * SizeOf32(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, outSources);
+ ioNumberSources = theSize / SizeOf32(UInt32);
+}
+
+UInt32 CAHALAudioDevice::GetAvailableClockSourceByIndex(UInt32 inIndex) const
+{
+ AudioStreamID theAnswer = 0;
+ UInt32 theNumberSources = GetNumberAvailableClockSources();
+ if((theNumberSources > 0) && (inIndex < theNumberSources))
+ {
+ CAAutoArrayDelete<UInt32> theSourceList(theNumberSources);
+ GetAvailableClockSources(theNumberSources, theSourceList);
+ theAnswer = theSourceList[inIndex];
+ }
+ return theAnswer;
+}
+
+CFStringRef CAHALAudioDevice::CopyClockSourceNameForID(UInt32 inID) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSourceNameForIDCFString);
+ CFStringRef theAnswer = NULL;
+ AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(CFStringRef) };
+ UInt32 theSize = sizeof(AudioValueTranslation);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theTranslation);
+ return theAnswer;
+}
+
+UInt32 CAHALAudioDevice::GetClockSourceKindForID(UInt32 inID) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSourceKindForID);
+ UInt32 theAnswer = 0;
+ AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(UInt32) };
+ UInt32 theSize = sizeof(AudioValueTranslation);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theTranslation);
+ return theAnswer;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.h b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.h
new file mode 100644
index 0000000000..8cfb466886
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.h
@@ -0,0 +1,238 @@
+/*
+ File: CAHALAudioDevice.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAHALAudioDevice_h__)
+#define __CAHALAudioDevice_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Super Class Includes
+#include "CAHALAudioObject.h"
+
+// PublicUtility Includes
+#include "CADebugMacros.h"
+#include "CAException.h"
+
+//==================================================================================================
+// CAHALAudioDevice
+//==================================================================================================
+
+class CAHALAudioDevice
+:
+ public CAHALAudioObject
+{
+
+// Construction/Destruction
+public:
+ CAHALAudioDevice(AudioObjectID inAudioDevice);
+ CAHALAudioDevice(CFStringRef inUID);
+ virtual ~CAHALAudioDevice();
+
+// General Stuff
+public:
+ CFStringRef CopyDeviceUID() const;
+ bool HasModelUID() const;
+ CFStringRef CopyModelUID() const;
+ CFStringRef CopyConfigurationApplicationBundleID() const;
+ CFURLRef CopyIconLocation() const;
+ UInt32 GetTransportType() const;
+ bool CanBeDefaultDevice(bool inIsInput, bool inIsSystem) const;
+ bool HasDevicePlugInStatus() const;
+ OSStatus GetDevicePlugInStatus() const;
+ bool IsAlive() const;
+ bool IsHidden() const;
+ pid_t GetHogModeOwner() const;
+ bool IsHogModeSettable() const;
+ bool TakeHogMode();
+ void ReleaseHogMode();
+ bool HasPreferredStereoChannels(bool inIsInput) const;
+ void GetPreferredStereoChannels(bool inIsInput, UInt32& outLeft, UInt32& outRight) const;
+ void SetPreferredStereoChannels(bool inIsInput, UInt32 inLeft, UInt32 inRight);
+ bool HasPreferredChannelLayout(bool inIsInput) const;
+ void GetPreferredChannelLayout(bool inIsInput, AudioChannelLayout& outChannelLayout) const;
+ void SetPreferredStereoChannels(bool inIsInput, AudioChannelLayout& inChannelLayout);
+ UInt32 GetNumberRelatedAudioDevices() const;
+ void GetRelatedAudioDevices(UInt32& ioNumberRelatedDevices, AudioObjectID* outRelatedDevices) const;
+ AudioObjectID GetRelatedAudioDeviceByIndex(UInt32 inIndex) const;
+
+// Stream Stuff
+public:
+ UInt32 GetNumberStreams(bool inIsInput) const;
+ void GetStreams(bool inIsInput, UInt32& ioNumberStreams, AudioObjectID* outStreamList) const;
+ AudioObjectID GetStreamByIndex(bool inIsInput, UInt32 inIndex) const;
+ UInt32 GetTotalNumberChannels(bool inIsInput) const;
+ void GetCurrentVirtualFormats(bool inIsInput, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const;
+ void GetCurrentPhysicalFormats(bool inIsInput, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const;
+
+// IO Stuff
+public:
+ bool IsRunning() const;
+ bool IsRunningSomewhere() const;
+ UInt32 GetLatency(bool inIsInput) const;
+ UInt32 GetSafetyOffset(bool inIsInput) const;
+ bool HasClockDomain() const;
+ UInt32 GetClockDomain() const;
+ Float64 GetActualSampleRate() const;
+ Float64 GetNominalSampleRate() const;
+ void SetNominalSampleRate(Float64 inSampleRate);
+ UInt32 GetNumberAvailableNominalSampleRateRanges() const;
+ void GetAvailableNominalSampleRateRanges(UInt32& ioNumberRanges, AudioValueRange* outRanges) const;
+ void GetAvailableNominalSampleRateRangeByIndex(UInt32 inIndex, Float64& outMinimum, Float64& outMaximum) const;
+ bool IsValidNominalSampleRate(Float64 inSampleRate) const;
+ bool IsIOBufferSizeSettable() const;
+ UInt32 GetIOBufferSize() const;
+ void SetIOBufferSize(UInt32 inBufferSize);
+ bool UsesVariableIOBufferSizes() const;
+ UInt32 GetMaximumVariableIOBufferSize() const;
+ bool HasIOBufferSizeRange() const;
+ void GetIOBufferSizeRange(UInt32& outMinimum, UInt32& outMaximum) const;
+ AudioDeviceIOProcID CreateIOProcID(AudioDeviceIOProc inIOProc, void* inClientData);
+ AudioDeviceIOProcID CreateIOProcIDWithBlock(dispatch_queue_t inDispatchQueue, AudioDeviceIOBlock inIOBlock);
+ void DestroyIOProcID(AudioDeviceIOProcID inIOProcID);
+ void StartIOProc(AudioDeviceIOProcID inIOProcID);
+ void StartIOProcAtTime(AudioDeviceIOProcID inIOProcID, AudioTimeStamp& ioStartTime, bool inIsInput, bool inIgnoreHardware);
+ void StopIOProc(AudioDeviceIOProcID inIOProcID);
+ void GetIOProcStreamUsage(AudioDeviceIOProcID inIOProcID, bool inIsInput, bool* outStreamUsage) const;
+ void SetIOProcStreamUsage(AudioDeviceIOProcID inIOProcID, bool inIsInput, const bool* inStreamUsage);
+ Float32 GetIOCycleUsage() const;
+ void SetIOCycleUsage(Float32 inValue);
+
+// Time Operations
+public:
+ void GetCurrentTime(AudioTimeStamp& outTime);
+ void TranslateTime(const AudioTimeStamp& inTime, AudioTimeStamp& outTime);
+ void GetNearestStartTime(AudioTimeStamp& ioTime, bool inIsInput, bool inIgnoreHardware);
+
+// Controls
+public:
+ bool HasVolumeControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ bool VolumeControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ Float32 GetVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ Float32 GetVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ void SetVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue);
+ void SetVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue);
+ Float32 GetVolumeControlScalarForDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const;
+ Float32 GetVolumeControlDecibelForScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const;
+
+ bool HasSubVolumeControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ bool SubVolumeControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ Float32 GetSubVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ Float32 GetSubVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ void SetSubVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue);
+ void SetSubVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue);
+ Float32 GetSubVolumeControlScalarForDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const;
+ Float32 GetSubVolumeControlDecibelForScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const;
+
+ bool HasMuteControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ bool MuteControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ bool GetMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ void SetMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue);
+
+ bool HasSoloControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ bool SoloControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ bool GetSoloControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ void SetSoloControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue);
+
+ bool HasStereoPanControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ bool StereoPanControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ Float32 GetStereoPanControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ void SetStereoPanControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue);
+ void GetStereoPanControlChannels(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& outLeftChannel, UInt32& outRightChannel) const;
+
+ bool HasJackControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ bool GetJackControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+
+ bool HasSubMuteControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ bool SubMuteControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ bool GetSubMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ void SetSubMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue);
+
+ bool HasiSubOwnerControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ bool iSubOwnerControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ bool GetiSubOwnerControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ void SetiSubOwnerControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue);
+
+ bool HasDataSourceControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ bool DataSourceControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ UInt32 GetCurrentDataSourceID(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ void SetCurrentDataSourceByID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID);
+ UInt32 GetNumberAvailableDataSources(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ void GetAvailableDataSources(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& ioNumberSources, UInt32* outSources) const;
+ UInt32 GetAvailableDataSourceByIndex(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inIndex) const;
+ CFStringRef CopyDataSourceNameForID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) const;
+
+ bool HasDataDestinationControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ bool DataDestinationControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ UInt32 GetCurrentDataDestinationID(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ void SetCurrentDataDestinationByID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID);
+ UInt32 GetNumberAvailableDataDestinations(AudioObjectPropertyScope inScope, UInt32 inChannel) const;
+ void GetAvailableDataDestinations(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& ioNumberDestinations, UInt32* outDestinations) const;
+ UInt32 GetAvailableDataDestinationByIndex(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inIndex) const;
+ CFStringRef CopyDataDestinationNameForID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) const;
+
+ bool HasClockSourceControl() const;
+ bool ClockSourceControlIsSettable() const;
+ UInt32 GetCurrentClockSourceID() const;
+ void SetCurrentClockSourceByID(UInt32 inID);
+ UInt32 GetNumberAvailableClockSources() const;
+ void GetAvailableClockSources(UInt32& ioNumberSources, UInt32* outSources) const;
+ UInt32 GetAvailableClockSourceByIndex(UInt32 inIndex) const;
+ CFStringRef CopyClockSourceNameForID(UInt32 inID) const;
+ UInt32 GetClockSourceKindForID(UInt32 inID) const;
+
+};
+
+inline AudioDeviceIOProcID CAHALAudioDevice::CreateIOProcIDWithBlock(dispatch_queue_t inDispatchQueue, AudioDeviceIOBlock inIOBlock)
+{
+ AudioDeviceIOProcID theAnswer = NULL;
+ OSStatus theError = AudioDeviceCreateIOProcIDWithBlock(&theAnswer, mObjectID, inDispatchQueue, inIOBlock);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::CreateIOProcIDWithBlock: got an error creating the IOProc ID");
+ return theAnswer;
+}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.cpp
new file mode 100644
index 0000000000..c8f16b4fb3
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.cpp
@@ -0,0 +1,370 @@
+/*
+ File: CAHALAudioObject.cpp
+ Abstract: CAHALAudioObject.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CAHALAudioObject.h"
+
+// PublicUtility Includes
+#include "CAAutoDisposer.h"
+#include "CADebugMacros.h"
+#include "CAException.h"
+#include "CAPropertyAddress.h"
+
+//==================================================================================================
+// CAHALAudioObject
+//==================================================================================================
+
+CAHALAudioObject::CAHALAudioObject(AudioObjectID inObjectID)
+:
+ mObjectID(inObjectID)
+{
+}
+
+CAHALAudioObject::~CAHALAudioObject()
+{
+}
+
+AudioObjectID CAHALAudioObject::GetObjectID() const
+{
+ return mObjectID;
+}
+
+void CAHALAudioObject::SetObjectID(AudioObjectID inObjectID)
+{
+ mObjectID = inObjectID;
+}
+
+AudioClassID CAHALAudioObject::GetClassID() const
+{
+ // set up the return value
+ AudioClassID theAnswer = 0;
+
+ // set up the property address
+ CAPropertyAddress theAddress(kAudioObjectPropertyClass);
+
+ // make sure the property exists
+ if(HasProperty(theAddress))
+ {
+ UInt32 theSize = sizeof(AudioClassID);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ }
+
+ return theAnswer;
+}
+
+AudioObjectID CAHALAudioObject::GetOwnerObjectID() const
+{
+ // set up the return value
+ AudioObjectID theAnswer = 0;
+
+ // set up the property address
+ CAPropertyAddress theAddress(kAudioObjectPropertyOwner);
+
+ // make sure the property exists
+ if(HasProperty(theAddress))
+ {
+ // get the property data
+ UInt32 theSize = sizeof(AudioObjectID);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ }
+
+ return theAnswer;
+}
+
+CFStringRef CAHALAudioObject::CopyOwningPlugInBundleID() const
+{
+ // set up the return value
+ CFStringRef theAnswer = NULL;
+
+ // set up the property address
+ CAPropertyAddress theAddress(kAudioObjectPropertyCreator);
+
+ // make sure the property exists
+ if(HasProperty(theAddress))
+ {
+ // get the property data
+ UInt32 theSize = sizeof(CFStringRef);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ }
+
+ return theAnswer;
+}
+
+CFStringRef CAHALAudioObject::CopyName() const
+{
+ // set up the return value
+ CFStringRef theAnswer = NULL;
+
+ // set up the property address
+ CAPropertyAddress theAddress(kAudioObjectPropertyName);
+
+ // make sure the property exists
+ if(HasProperty(theAddress))
+ {
+ // get the property data
+ UInt32 theSize = sizeof(CFStringRef);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ }
+
+ return theAnswer;
+}
+
+CFStringRef CAHALAudioObject::CopyManufacturer() const
+{
+ // set up the return value
+ CFStringRef theAnswer = NULL;
+
+ // set up the property address
+ CAPropertyAddress theAddress(kAudioObjectPropertyManufacturer);
+
+ // make sure the property exists
+ if(HasProperty(theAddress))
+ {
+ // get the property data
+ UInt32 theSize = sizeof(CFStringRef);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ }
+
+ return theAnswer;
+}
+
+CFStringRef CAHALAudioObject::CopyNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const
+{
+ // set up the return value
+ CFStringRef theAnswer = NULL;
+
+ // set up the property address
+ CAPropertyAddress theAddress(kAudioObjectPropertyElementName, inScope, inElement);
+
+ // make sure the property exists
+ if(HasProperty(theAddress))
+ {
+ // get the property data
+ UInt32 theSize = sizeof(CFStringRef);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ }
+
+ return theAnswer;
+}
+
+CFStringRef CAHALAudioObject::CopyCategoryNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const
+{
+ // set up the return value
+ CFStringRef theAnswer = NULL;
+
+ // set up the property address
+ CAPropertyAddress theAddress(kAudioObjectPropertyElementCategoryName, inScope, inElement);
+
+ // make sure the property exists
+ if(HasProperty(theAddress))
+ {
+ // get the property data
+ UInt32 theSize = sizeof(CFStringRef);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ }
+
+ return theAnswer;
+}
+
+CFStringRef CAHALAudioObject::CopyNumberNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const
+{
+ // set up the return value
+ CFStringRef theAnswer = NULL;
+
+ // set up the property address
+ CAPropertyAddress theAddress(kAudioObjectPropertyElementNumberName, inScope, inElement);
+
+ // make sure the property exists
+ if(HasProperty(theAddress))
+ {
+ // get the property data
+ UInt32 theSize = sizeof(CFStringRef);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ }
+
+ return theAnswer;
+}
+
+bool CAHALAudioObject::ObjectExists(AudioObjectID inObjectID)
+{
+ Boolean isSettable;
+ CAPropertyAddress theAddress(kAudioObjectPropertyClass);
+ return (inObjectID == 0) || (AudioObjectIsPropertySettable(inObjectID, &theAddress, &isSettable) != 0);
+}
+
+UInt32 CAHALAudioObject::GetNumberOwnedObjects(AudioClassID inClass) const
+{
+ // set up the return value
+ UInt32 theAnswer = 0;
+
+ // set up the property address
+ CAPropertyAddress theAddress(kAudioObjectPropertyOwnedObjects);
+
+ // figure out the qualifier
+ UInt32 theQualifierSize = 0;
+ void* theQualifierData = NULL;
+ if(inClass != 0)
+ {
+ theQualifierSize = sizeof(AudioObjectID);
+ theQualifierData = &inClass;
+ }
+
+ // get the property data size
+ theAnswer = GetPropertyDataSize(theAddress, theQualifierSize, theQualifierData);
+
+ // calculate the number of object IDs
+ theAnswer /= SizeOf32(AudioObjectID);
+
+ return theAnswer;
+}
+
+void CAHALAudioObject::GetAllOwnedObjects(AudioClassID inClass, UInt32& ioNumberObjects, AudioObjectID* ioObjectIDs) const
+{
+ // set up the property address
+ CAPropertyAddress theAddress(kAudioObjectPropertyOwnedObjects);
+
+ // figure out the qualifier
+ UInt32 theQualifierSize = 0;
+ void* theQualifierData = NULL;
+ if(inClass != 0)
+ {
+ theQualifierSize = sizeof(AudioObjectID);
+ theQualifierData = &inClass;
+ }
+
+ // get the property data
+ UInt32 theDataSize = ioNumberObjects * SizeOf32(AudioClassID);
+ GetPropertyData(theAddress, theQualifierSize, theQualifierData, theDataSize, ioObjectIDs);
+
+ // set the number of object IDs being returned
+ ioNumberObjects = theDataSize / SizeOf32(AudioObjectID);
+}
+
+AudioObjectID CAHALAudioObject::GetOwnedObjectByIndex(AudioClassID inClass, UInt32 inIndex)
+{
+ // set up the property address
+ CAPropertyAddress theAddress(kAudioObjectPropertyOwnedObjects);
+
+ // figure out the qualifier
+ UInt32 theQualifierSize = 0;
+ void* theQualifierData = NULL;
+ if(inClass != 0)
+ {
+ theQualifierSize = sizeof(AudioObjectID);
+ theQualifierData = &inClass;
+ }
+
+ // figure out how much space to allocate
+ UInt32 theDataSize = GetPropertyDataSize(theAddress, theQualifierSize, theQualifierData);
+ UInt32 theNumberObjectIDs = theDataSize / SizeOf32(AudioObjectID);
+
+ // set up the return value
+ AudioObjectID theAnswer = 0;
+
+ // maker sure the index is in range
+ if(inIndex < theNumberObjectIDs)
+ {
+ // allocate it
+ CAAutoArrayDelete<AudioObjectID> theObjectList(theDataSize / sizeof(AudioObjectID));
+
+ // get the property data
+ GetPropertyData(theAddress, theQualifierSize, theQualifierData, theDataSize, theObjectList);
+
+ // get the return value
+ theAnswer = theObjectList[inIndex];
+ }
+
+ return theAnswer;
+}
+
+bool CAHALAudioObject::HasProperty(const AudioObjectPropertyAddress& inAddress) const
+{
+ return AudioObjectHasProperty(mObjectID, &inAddress);
+}
+
+bool CAHALAudioObject::IsPropertySettable(const AudioObjectPropertyAddress& inAddress) const
+{
+ Boolean isSettable = false;
+ OSStatus theError = AudioObjectIsPropertySettable(mObjectID, &inAddress, &isSettable);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioObject::IsPropertySettable: got an error getting info about a property");
+ return isSettable != 0;
+}
+
+UInt32 CAHALAudioObject::GetPropertyDataSize(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData) const
+{
+ UInt32 theDataSize = 0;
+ OSStatus theError = AudioObjectGetPropertyDataSize(mObjectID, &inAddress, inQualifierDataSize, inQualifierData, &theDataSize);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioObject::GetPropertyDataSize: got an error getting the property data size");
+ return theDataSize;
+}
+
+void CAHALAudioObject::GetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32& ioDataSize, void* outData) const
+{
+ OSStatus theError = AudioObjectGetPropertyData(mObjectID, &inAddress, inQualifierDataSize, inQualifierData, &ioDataSize, outData);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioObject::GetPropertyData: got an error getting the property data");
+}
+
+void CAHALAudioObject::SetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32 inDataSize, const void* inData)
+{
+ OSStatus theError = AudioObjectSetPropertyData(mObjectID, &inAddress, inQualifierDataSize, inQualifierData, inDataSize, inData);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioObject::SetPropertyData: got an error setting the property data");
+}
+
+void CAHALAudioObject::AddPropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData)
+{
+ OSStatus theError = AudioObjectAddPropertyListener(mObjectID, &inAddress, inListenerProc, inClientData);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioObject::AddPropertyListener: got an error adding a property listener");
+}
+
+void CAHALAudioObject::RemovePropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData)
+{
+ OSStatus theError = AudioObjectRemovePropertyListener(mObjectID, &inAddress, inListenerProc, inClientData);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioObject::RemovePropertyListener: got an error removing a property listener");
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.h b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.h
new file mode 100644
index 0000000000..d99ab0d59a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.h
@@ -0,0 +1,155 @@
+/*
+ File: CAHALAudioObject.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAHALAudioObject_h__)
+#define __CAHALAudioObject_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// PublicUtility Includes
+#include "CADebugMacros.h"
+#include "CAException.h"
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudio.h>
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include <CoreAudio.h>
+ #include <CoreFoundation.h>
+#endif
+
+//==================================================================================================
+// CAHALAudioObject
+//==================================================================================================
+
+class CAHALAudioObject
+{
+
+// Construction/Destruction
+public:
+ CAHALAudioObject(AudioObjectID inObjectID);
+ virtual ~CAHALAudioObject();
+
+// Attributes
+public:
+ AudioObjectID GetObjectID() const;
+ void SetObjectID(AudioObjectID inObjectID);
+ AudioClassID GetClassID() const;
+ AudioObjectID GetOwnerObjectID() const;
+ CFStringRef CopyOwningPlugInBundleID() const;
+ CFStringRef CopyName() const;
+ CFStringRef CopyManufacturer() const;
+ CFStringRef CopyNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const;
+ CFStringRef CopyCategoryNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const;
+ CFStringRef CopyNumberNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const;
+
+ static bool ObjectExists(AudioObjectID inObjectID);
+
+// Owned Objects
+public:
+ UInt32 GetNumberOwnedObjects(AudioClassID inClass) const;
+ void GetAllOwnedObjects(AudioClassID inClass, UInt32& ioNumberObjects, AudioObjectID* ioObjectIDs) const;
+ AudioObjectID GetOwnedObjectByIndex(AudioClassID inClass, UInt32 inIndex);
+
+// Property Operations
+public:
+ bool HasProperty(const AudioObjectPropertyAddress& inAddress) const;
+ bool IsPropertySettable(const AudioObjectPropertyAddress& inAddress) const;
+ UInt32 GetPropertyDataSize(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData) const;
+
+ void GetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32& ioDataSize, void* outData) const;
+ void SetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32 inDataSize, const void* inData);
+
+ UInt32 GetPropertyData_UInt32(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { UInt32 theAnswer = 0; UInt32 theDataSize = SizeOf32(UInt32); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &theAnswer); return theAnswer; }
+ void SetPropertyData_UInt32(const AudioObjectPropertyAddress& inAddress, UInt32 inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(UInt32), &inValue); }
+
+ Float32 GetPropertyData_Float32(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { Float32 theAnswer = 0; UInt32 theDataSize = SizeOf32(Float32); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &theAnswer); return theAnswer; }
+ void SetPropertyData_Float32(const AudioObjectPropertyAddress& inAddress, Float32 inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(Float32), &inValue); }
+
+ Float64 GetPropertyData_Float64(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { Float64 theAnswer = 0; UInt32 theDataSize = SizeOf32(Float64); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &theAnswer); return theAnswer; }
+ void SetPropertyData_Float64(const AudioObjectPropertyAddress& inAddress, Float64 inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(Float64), &inValue); }
+
+ CFTypeRef GetPropertyData_CFType(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { CFTypeRef theAnswer = NULL; UInt32 theDataSize = SizeOf32(CFTypeRef); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &theAnswer); return theAnswer; }
+ void SetPropertyData_CFType(const AudioObjectPropertyAddress& inAddress, CFTypeRef inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(CFTypeRef), &inValue); }
+
+ CFStringRef GetPropertyData_CFString(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { CFStringRef theAnswer = NULL; UInt32 theDataSize = SizeOf32(CFStringRef); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &theAnswer); return theAnswer; }
+ void SetPropertyData_CFString(const AudioObjectPropertyAddress& inAddress, CFStringRef inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(CFStringRef), &inValue); }
+
+ template <class T> void GetPropertyData_Struct(const AudioObjectPropertyAddress& inAddress, T& outStruct, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { UInt32 theDataSize = SizeOf32(T); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &outStruct); }
+ template <class T> void SetPropertyData_Struct(const AudioObjectPropertyAddress& inAddress, T& inStruct, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(T), &inStruct); }
+
+ template <class T> UInt32 GetPropertyData_ArraySize(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { return GetPropertyDataSize(inAddress, inQualifierDataSize, inQualifierData) / SizeOf32(T); }
+ template <class T> void GetPropertyData_Array(const AudioObjectPropertyAddress& inAddress, UInt32& ioNumberItems, T* outArray, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { UInt32 theDataSize = ioNumberItems * SizeOf32(T); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, outArray); ioNumberItems = theDataSize / SizeOf32(T); }
+ template <class T> void SetPropertyData_Array(const AudioObjectPropertyAddress& inAddress, UInt32 inNumberItems, T* inArray, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, inNumberItems * SizeOf32(T), inArray); }
+
+ void AddPropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData);
+ void RemovePropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData);
+
+ void AddPropertyListenerBlock(const AudioObjectPropertyAddress& inAddress, dispatch_queue_t inDispatchQueue, AudioObjectPropertyListenerBlock inListenerBlock);
+ void RemovePropertyListenerBlock(const AudioObjectPropertyAddress& inAddress, dispatch_queue_t inDispatchQueue, AudioObjectPropertyListenerBlock inListenerBlock);
+
+// Implementation
+protected:
+ AudioObjectID mObjectID;
+
+};
+
+inline void CAHALAudioObject::AddPropertyListenerBlock(const AudioObjectPropertyAddress& inAddress, dispatch_queue_t inDispatchQueue, AudioObjectPropertyListenerBlock inListenerBlock)
+{
+ OSStatus theError = AudioObjectAddPropertyListenerBlock(mObjectID, &inAddress, inDispatchQueue, inListenerBlock);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioObject::AddPropertyListenerBlock: got an error adding a property listener");
+}
+
+inline void CAHALAudioObject::RemovePropertyListenerBlock(const AudioObjectPropertyAddress& inAddress, dispatch_queue_t inDispatchQueue, AudioObjectPropertyListenerBlock inListenerBlock)
+{
+ OSStatus theError = AudioObjectRemovePropertyListenerBlock(mObjectID, &inAddress, inDispatchQueue, inListenerBlock);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioObject::RemovePropertyListener: got an error removing a property listener");
+}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.cpp
new file mode 100644
index 0000000000..62b9b3c566
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.cpp
@@ -0,0 +1,182 @@
+/*
+ File: CAHALAudioStream.cpp
+ Abstract: CAHALAudioStream.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CAHALAudioStream.h"
+
+// PublicUtility Includes
+#include "CAAutoDisposer.h"
+#include "CADebugMacros.h"
+#include "CAException.h"
+#include "CAPropertyAddress.h"
+
+//==================================================================================================
+// CAHALAudioStream
+//==================================================================================================
+
+CAHALAudioStream::CAHALAudioStream(AudioObjectID inAudioStream)
+:
+ CAHALAudioObject(inAudioStream)
+{
+}
+
+CAHALAudioStream::~CAHALAudioStream()
+{
+}
+
+UInt32 CAHALAudioStream::GetDirection() const
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyDirection);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+UInt32 CAHALAudioStream::GetTerminalType() const
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyTerminalType);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+UInt32 CAHALAudioStream::GetStartingChannel() const
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyStartingChannel);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+UInt32 CAHALAudioStream::GetLatency() const
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyLatency);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+void CAHALAudioStream::GetCurrentVirtualFormat(AudioStreamBasicDescription& outFormat) const
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyVirtualFormat);
+ UInt32 theSize = sizeof(AudioStreamBasicDescription);
+ GetPropertyData(theAddress, 0, NULL, theSize, &outFormat);
+}
+
+void CAHALAudioStream::SetCurrentVirtualFormat(const AudioStreamBasicDescription& inFormat)
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyVirtualFormat);
+ SetPropertyData(theAddress, 0, NULL, sizeof(AudioStreamBasicDescription), &inFormat);
+}
+
+UInt32 CAHALAudioStream::GetNumberAvailableVirtualFormats() const
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyAvailableVirtualFormats);
+ UInt32 theAnswer = GetPropertyDataSize(theAddress, 0, NULL);
+ theAnswer /= SizeOf32(AudioStreamRangedDescription);
+ return theAnswer;
+}
+
+void CAHALAudioStream::GetAvailableVirtualFormats(UInt32& ioNumberFormats, AudioStreamRangedDescription* outFormats) const
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyAvailableVirtualFormats);
+ UInt32 theSize = ioNumberFormats * SizeOf32(AudioStreamRangedDescription);
+ GetPropertyData(theAddress, 0, NULL, theSize, outFormats);
+ ioNumberFormats = theSize / SizeOf32(AudioStreamRangedDescription);
+}
+
+void CAHALAudioStream::GetAvailableVirtualFormatByIndex(UInt32 inIndex, AudioStreamRangedDescription& outFormat) const
+{
+ UInt32 theNumberFormats = GetNumberAvailableVirtualFormats();
+ if((theNumberFormats > 0) && (inIndex < theNumberFormats))
+ {
+ CAAutoArrayDelete<AudioStreamRangedDescription> theFormats(theNumberFormats);
+ GetAvailableVirtualFormats(theNumberFormats, theFormats);
+ if((theNumberFormats > 0) && (inIndex < theNumberFormats))
+ {
+ outFormat = theFormats[inIndex];
+ }
+ }
+}
+
+void CAHALAudioStream::GetCurrentPhysicalFormat(AudioStreamBasicDescription& outFormat) const
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyPhysicalFormat);
+ UInt32 theSize = sizeof(AudioStreamBasicDescription);
+ GetPropertyData(theAddress, 0, NULL, theSize, &outFormat);
+}
+
+void CAHALAudioStream::SetCurrentPhysicalFormat(const AudioStreamBasicDescription& inFormat)
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyPhysicalFormat);
+ SetPropertyData(theAddress, 0, NULL, sizeof(AudioStreamBasicDescription), &inFormat);
+}
+
+UInt32 CAHALAudioStream::GetNumberAvailablePhysicalFormats() const
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyAvailablePhysicalFormats);
+ UInt32 theAnswer = GetPropertyDataSize(theAddress, 0, NULL);
+ theAnswer /= SizeOf32(AudioStreamRangedDescription);
+ return theAnswer;
+}
+
+void CAHALAudioStream::GetAvailablePhysicalFormats(UInt32& ioNumberFormats, AudioStreamRangedDescription* outFormats) const
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyAvailablePhysicalFormats);
+ UInt32 theSize = ioNumberFormats * SizeOf32(AudioStreamRangedDescription);
+ GetPropertyData(theAddress, 0, NULL, theSize, outFormats);
+ ioNumberFormats = theSize / SizeOf32(AudioStreamRangedDescription);
+}
+
+void CAHALAudioStream::GetAvailablePhysicalFormatByIndex(UInt32 inIndex, AudioStreamRangedDescription& outFormat) const
+{
+ UInt32 theNumberFormats = GetNumberAvailablePhysicalFormats();
+ if((theNumberFormats > 0) && (inIndex < theNumberFormats))
+ {
+ CAAutoArrayDelete<AudioStreamRangedDescription> theFormats(theNumberFormats);
+ GetAvailablePhysicalFormats(theNumberFormats, theFormats);
+ if((theNumberFormats > 0) && (inIndex < theNumberFormats))
+ {
+ outFormat = theFormats[inIndex];
+ }
+ }
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.h b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.h
new file mode 100644
index 0000000000..0c6cb55a85
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.h
@@ -0,0 +1,94 @@
+/*
+ File: CAHALAudioStream.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAHALAudioStream_h__)
+#define __CAHALAudioStream_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Super Class Includes
+#include "CAHALAudioObject.h"
+
+//==================================================================================================
+// CAHALAudioStream
+//==================================================================================================
+
+class CAHALAudioStream
+:
+ public CAHALAudioObject
+{
+
+// Construction/Destruction
+public:
+ CAHALAudioStream(AudioObjectID inAudioStream);
+ virtual ~CAHALAudioStream();
+
+// Attributes
+public:
+ UInt32 GetDirection() const;
+ UInt32 GetTerminalType() const;
+ UInt32 GetStartingChannel() const;
+ UInt32 GetLatency() const;
+
+// Format Info
+public:
+ void GetCurrentVirtualFormat(AudioStreamBasicDescription& outFormat) const;
+ void SetCurrentVirtualFormat(const AudioStreamBasicDescription& inFormat);
+ UInt32 GetNumberAvailableVirtualFormats() const;
+ void GetAvailableVirtualFormats(UInt32& ioNumberFormats, AudioStreamRangedDescription* outFormats) const;
+ void GetAvailableVirtualFormatByIndex(UInt32 inIndex, AudioStreamRangedDescription& outFormat) const;
+
+ void GetCurrentPhysicalFormat(AudioStreamBasicDescription& outFormat) const;
+ void SetCurrentPhysicalFormat(const AudioStreamBasicDescription& inFormat);
+ UInt32 GetNumberAvailablePhysicalFormats() const;
+ void GetAvailablePhysicalFormats(UInt32& ioNumberFormats, AudioStreamRangedDescription* outFormats) const;
+ void GetAvailablePhysicalFormatByIndex(UInt32 inIndex, AudioStreamRangedDescription& outFormat) const;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.cpp
new file mode 100644
index 0000000000..404dd98498
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.cpp
@@ -0,0 +1,181 @@
+/*
+ File: CAHALAudioSystemObject.cpp
+ Abstract: CAHALAudioSystemObject.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CAHALAudioSystemObject.h"
+
+// PublicUtility Includes
+#include "CAAutoDisposer.h"
+#include "CACFString.h"
+#include "CAHALAudioDevice.h"
+#include "CAPropertyAddress.h"
+
+//==================================================================================================
+// CAHALAudioSystemObject
+//==================================================================================================
+
+CAHALAudioSystemObject::CAHALAudioSystemObject()
+:
+ CAHALAudioObject(kAudioObjectSystemObject)
+{
+}
+
+CAHALAudioSystemObject::~CAHALAudioSystemObject()
+{
+}
+
+UInt32 CAHALAudioSystemObject::GetNumberAudioDevices() const
+{
+ CAPropertyAddress theAddress(kAudioHardwarePropertyDevices);
+ UInt32 theAnswer = GetPropertyDataSize(theAddress, 0, NULL);
+ theAnswer /= SizeOf32(AudioObjectID);
+ return theAnswer;
+}
+
+void CAHALAudioSystemObject::GetAudioDevices(UInt32& ioNumberAudioDevices, AudioObjectID* outAudioDevices) const
+{
+ CAPropertyAddress theAddress(kAudioHardwarePropertyDevices);
+ UInt32 theSize = ioNumberAudioDevices * SizeOf32(AudioObjectID);
+ GetPropertyData(theAddress, 0, NULL, theSize, outAudioDevices);
+ ioNumberAudioDevices = theSize / SizeOf32(AudioObjectID);
+}
+
+AudioObjectID CAHALAudioSystemObject::GetAudioDeviceAtIndex(UInt32 inIndex) const
+{
+ AudioObjectID theAnswer = kAudioObjectUnknown;
+ UInt32 theNumberDevices = GetNumberAudioDevices();
+ if((theNumberDevices > 0) && (inIndex < theNumberDevices))
+ {
+ CAAutoArrayDelete<AudioObjectID> theDeviceList(theNumberDevices);
+ GetAudioDevices(theNumberDevices, theDeviceList);
+ if((theNumberDevices > 0) && (inIndex < theNumberDevices))
+ {
+ theAnswer = theDeviceList[inIndex];
+ }
+ }
+ return theAnswer;
+}
+
+AudioObjectID CAHALAudioSystemObject::GetAudioDeviceForUID(CFStringRef inUID) const
+{
+ AudioObjectID theAnswer = kAudioObjectUnknown;
+ AudioValueTranslation theValue = { &inUID, sizeof(CFStringRef), &theAnswer, sizeof(AudioObjectID) };
+ CAPropertyAddress theAddress(kAudioHardwarePropertyDeviceForUID);
+ UInt32 theSize = sizeof(AudioValueTranslation);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theAnswer;
+}
+
+void CAHALAudioSystemObject::LogBasicDeviceInfo()
+{
+ UInt32 theNumberDevices = GetNumberAudioDevices();
+ CAAutoArrayDelete<AudioObjectID> theDeviceList(theNumberDevices);
+ GetAudioDevices(theNumberDevices, theDeviceList);
+ DebugMessageN1("CAHALAudioSystemObject::LogBasicDeviceInfo: %d devices", (int)theNumberDevices);
+ for(UInt32 theDeviceIndex = 0; theDeviceIndex < theNumberDevices; ++theDeviceIndex)
+ {
+ char theCString[256];
+ UInt32 theCStringSize = sizeof(theCString);
+ DebugMessageN1("CAHALAudioSystemObject::LogBasicDeviceInfo: Device %d", (int)theDeviceIndex);
+
+ CAHALAudioDevice theDevice(theDeviceList[theDeviceIndex]);
+ DebugMessageN1("CAHALAudioSystemObject::LogBasicDeviceInfo: Object ID: %d", (int)theDeviceList[theDeviceIndex]);
+
+ CACFString theDeviceName(theDevice.CopyName());
+ theCStringSize = sizeof(theCString);
+ theDeviceName.GetCString(theCString, theCStringSize);
+ DebugMessageN1("CAHALAudioSystemObject::LogBasicDeviceInfo: Name: %s", theCString);
+
+ CACFString theDeviceUID(theDevice.CopyDeviceUID());
+ theCStringSize = sizeof(theCString);
+ theDeviceUID.GetCString(theCString, theCStringSize);
+ DebugMessageN1("CAHALAudioSystemObject::LogBasicDeviceInfo: UID: %s", theCString);
+ }
+}
+
+static inline AudioObjectPropertySelector CAHALAudioSystemObject_CalculateDefaultDeviceProperySelector(bool inIsInput, bool inIsSystem)
+{
+ AudioObjectPropertySelector theAnswer = kAudioHardwarePropertyDefaultOutputDevice;
+ if(inIsInput)
+ {
+ theAnswer = kAudioHardwarePropertyDefaultInputDevice;
+ }
+ else if(inIsSystem)
+ {
+ theAnswer = kAudioHardwarePropertyDefaultSystemOutputDevice;
+ }
+ return theAnswer;
+}
+
+AudioObjectID CAHALAudioSystemObject::GetDefaultAudioDevice(bool inIsInput, bool inIsSystem) const
+{
+ AudioObjectID theAnswer = kAudioObjectUnknown;
+ CAPropertyAddress theAddress(CAHALAudioSystemObject_CalculateDefaultDeviceProperySelector(inIsInput, inIsSystem));
+ UInt32 theSize = sizeof(AudioObjectID);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ return theAnswer;
+}
+
+void CAHALAudioSystemObject::SetDefaultAudioDevice(bool inIsInput, bool inIsSystem, AudioObjectID inNewDefaultDevice)
+{
+ CAPropertyAddress theAddress(CAHALAudioSystemObject_CalculateDefaultDeviceProperySelector(inIsInput, inIsSystem));
+ UInt32 theSize = sizeof(AudioObjectID);
+ SetPropertyData(theAddress, 0, NULL, theSize, &inNewDefaultDevice);
+}
+
+AudioObjectID CAHALAudioSystemObject::GetAudioPlugInForBundleID(CFStringRef inUID) const
+{
+ AudioObjectID theAnswer = kAudioObjectUnknown;
+ AudioValueTranslation theValue = { &inUID, sizeof(CFStringRef), &theAnswer, sizeof(AudioObjectID) };
+ CAPropertyAddress theAddress(kAudioHardwarePropertyPlugInForBundleID);
+ UInt32 theSize = sizeof(AudioValueTranslation);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theAnswer;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.h b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.h
new file mode 100644
index 0000000000..0ade7a5098
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.h
@@ -0,0 +1,90 @@
+/*
+ File: CAHALAudioSystemObject.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAHALAudioSystemObject_h__)
+#define __CAHALAudioSystemObject_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Super Class Includes
+#include "CAHALAudioObject.h"
+
+//==================================================================================================
+// CAHALAudioSystemObject
+//==================================================================================================
+
+class CAHALAudioSystemObject
+:
+ public CAHALAudioObject
+{
+
+// Construction/Destruction
+public:
+ CAHALAudioSystemObject();
+ virtual ~CAHALAudioSystemObject();
+
+// Audio Device List Management
+public:
+ UInt32 GetNumberAudioDevices() const;
+ void GetAudioDevices(UInt32& ioNumberAudioDevices, AudioObjectID* outAudioDevices) const;
+ AudioObjectID GetAudioDeviceAtIndex(UInt32 inIndex) const;
+ AudioObjectID GetAudioDeviceForUID(CFStringRef inUID) const;
+ void LogBasicDeviceInfo();
+
+// Default Device Management
+public:
+ AudioObjectID GetDefaultAudioDevice(bool inIsInput, bool inIsSystem) const;
+ void SetDefaultAudioDevice(bool inIsInput, bool inIsSystem, AudioObjectID inNewDefaultDevice);
+
+// PlugIns
+public:
+ AudioObjectID GetAudioPlugInForBundleID(CFStringRef inBundleID) const;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.cpp
new file mode 100644
index 0000000000..db78a4afee
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.cpp
@@ -0,0 +1,99 @@
+/*
+ File: CAHostTimeBase.cpp
+ Abstract: CAHostTimeBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CAHostTimeBase.h"
+
+Float64 CAHostTimeBase::sFrequency = 0;
+Float64 CAHostTimeBase::sInverseFrequency = 0;
+UInt32 CAHostTimeBase::sMinDelta = 0;
+UInt32 CAHostTimeBase::sToNanosNumerator = 0;
+UInt32 CAHostTimeBase::sToNanosDenominator = 0;
+pthread_once_t CAHostTimeBase::sIsInited = PTHREAD_ONCE_INIT;
+#if Track_Host_TimeBase
+UInt64 CAHostTimeBase::sLastTime = 0;
+#endif
+
+//=============================================================================
+// CAHostTimeBase
+//
+// This class provides platform independent access to the host's time base.
+//=============================================================================
+
+void CAHostTimeBase::Initialize()
+{
+ // get the info about Absolute time
+ #if TARGET_OS_MAC
+ struct mach_timebase_info theTimeBaseInfo;
+ mach_timebase_info(&theTimeBaseInfo);
+ sMinDelta = 1;
+ sToNanosNumerator = theTimeBaseInfo.numer;
+ sToNanosDenominator = theTimeBaseInfo.denom;
+
+ // the frequency of that clock is: (sToNanosDenominator / sToNanosNumerator) * 10^9
+ sFrequency = static_cast<Float64>(sToNanosDenominator) / static_cast<Float64>(sToNanosNumerator);
+ sFrequency *= 1000000000.0;
+ #elif TARGET_OS_WIN32
+ LARGE_INTEGER theFrequency;
+ QueryPerformanceFrequency(&theFrequency);
+ sMinDelta = 1;
+ sToNanosNumerator = 1000000000ULL;
+ sToNanosDenominator = *((UInt64*)&theFrequency);
+ sFrequency = static_cast<Float64>(*((UInt64*)&theFrequency));
+ #endif
+ sInverseFrequency = 1.0 / sFrequency;
+
+ #if Log_Host_Time_Base_Parameters
+ DebugPrintf("Host Time Base Parameters");
+ DebugPrintf(" Minimum Delta: %lu", (unsigned long)sMinDelta);
+ DebugPrintf(" Frequency: %f", sFrequency);
+ DebugPrintf(" To Nanos Numerator: %lu", (unsigned long)sToNanosNumerator);
+ DebugPrintf(" To Nanos Denominator: %lu", (unsigned long)sToNanosDenominator);
+ #endif
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.h b/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.h
new file mode 100644
index 0000000000..50e3507648
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.h
@@ -0,0 +1,234 @@
+/*
+ File: CAHostTimeBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAHostTimeBase_h__)
+#define __CAHostTimeBase_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+#if TARGET_OS_MAC
+ #include <mach/mach_time.h>
+ #include <pthread.h>
+#elif TARGET_OS_WIN32
+ #include <windows.h>
+ #include "WinPThreadDefs.h"
+#else
+ #error Unsupported operating system
+#endif
+
+#include "CADebugPrintf.h"
+
+//=============================================================================
+// CAHostTimeBase
+//
+// This class provides platform independent access to the host's time base.
+//=============================================================================
+
+#if CoreAudio_Debug
+// #define Log_Host_Time_Base_Parameters 1
+// #define Track_Host_TimeBase 1
+#endif
+
+class CAHostTimeBase
+{
+
+public:
+ static UInt64 ConvertToNanos(UInt64 inHostTime);
+ static UInt64 ConvertFromNanos(UInt64 inNanos);
+
+ static UInt64 GetTheCurrentTime();
+#if TARGET_OS_MAC
+ static UInt64 GetCurrentTime() { return GetTheCurrentTime(); }
+#endif
+ static UInt64 GetCurrentTimeInNanos();
+
+ static Float64 GetFrequency() { pthread_once(&sIsInited, Initialize); return sFrequency; }
+ static Float64 GetInverseFrequency() { pthread_once(&sIsInited, Initialize); return sInverseFrequency; }
+ static UInt32 GetMinimumDelta() { pthread_once(&sIsInited, Initialize); return sMinDelta; }
+
+ static UInt64 AbsoluteHostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime);
+ static SInt64 HostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime);
+
+ static UInt64 MultiplyByRatio(UInt64 inMuliplicand, UInt32 inNumerator, UInt32 inDenominator);
+
+private:
+ static void Initialize();
+
+ static pthread_once_t sIsInited;
+
+ static Float64 sFrequency;
+ static Float64 sInverseFrequency;
+ static UInt32 sMinDelta;
+ static UInt32 sToNanosNumerator;
+ static UInt32 sToNanosDenominator;
+#if Track_Host_TimeBase
+ static UInt64 sLastTime;
+#endif
+};
+
+inline UInt64 CAHostTimeBase::GetTheCurrentTime()
+{
+ UInt64 theTime = 0;
+
+ #if TARGET_OS_MAC
+ theTime = mach_absolute_time();
+ #elif TARGET_OS_WIN32
+ LARGE_INTEGER theValue;
+ QueryPerformanceCounter(&theValue);
+ theTime = *((UInt64*)&theValue);
+ #endif
+
+ #if Track_Host_TimeBase
+ if(sLastTime != 0)
+ {
+ if(theTime <= sLastTime)
+ {
+ DebugPrintf("CAHostTimeBase::GetTheCurrentTime: the current time is earlier than the last time, now: %qd, then: %qd", theTime, sLastTime);
+ }
+ sLastTime = theTime;
+ }
+ else
+ {
+ sLastTime = theTime;
+ }
+ #endif
+
+ return theTime;
+}
+
+inline UInt64 CAHostTimeBase::ConvertToNanos(UInt64 inHostTime)
+{
+ pthread_once(&sIsInited, Initialize);
+
+ UInt64 theAnswer = MultiplyByRatio(inHostTime, sToNanosNumerator, sToNanosDenominator);
+ #if CoreAudio_Debug
+ if(((sToNanosNumerator > sToNanosDenominator) && (theAnswer < inHostTime)) || ((sToNanosDenominator > sToNanosNumerator) && (theAnswer > inHostTime)))
+ {
+ DebugPrintf("CAHostTimeBase::ConvertToNanos: The conversion wrapped");
+ }
+ #endif
+
+ return theAnswer;
+}
+
+inline UInt64 CAHostTimeBase::ConvertFromNanos(UInt64 inNanos)
+{
+ pthread_once(&sIsInited, Initialize);
+
+ UInt64 theAnswer = MultiplyByRatio(inNanos, sToNanosDenominator, sToNanosNumerator);
+ #if CoreAudio_Debug
+ if(((sToNanosDenominator > sToNanosNumerator) && (theAnswer < inNanos)) || ((sToNanosNumerator > sToNanosDenominator) && (theAnswer > inNanos)))
+ {
+ DebugPrintf("CAHostTimeBase::ConvertFromNanos: The conversion wrapped");
+ }
+ #endif
+
+ return theAnswer;
+}
+
+inline UInt64 CAHostTimeBase::GetCurrentTimeInNanos()
+{
+ return ConvertToNanos(GetTheCurrentTime());
+}
+
+inline UInt64 CAHostTimeBase::AbsoluteHostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime)
+{
+ UInt64 theAnswer;
+
+ if(inStartTime <= inEndTime)
+ {
+ theAnswer = inEndTime - inStartTime;
+ }
+ else
+ {
+ theAnswer = inStartTime - inEndTime;
+ }
+
+ return ConvertToNanos(theAnswer);
+}
+
+inline SInt64 CAHostTimeBase::HostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime)
+{
+ SInt64 theAnswer;
+ SInt64 theSign = 1;
+
+ if(inStartTime <= inEndTime)
+ {
+ theAnswer = static_cast<SInt64>(inEndTime - inStartTime);
+ }
+ else
+ {
+ theAnswer = static_cast<SInt64>(inStartTime - inEndTime);
+ theSign = -1;
+ }
+
+ return theSign * static_cast<SInt64>(ConvertToNanos(static_cast<UInt64>(theAnswer)));
+}
+
+inline UInt64 CAHostTimeBase::MultiplyByRatio(UInt64 inMuliplicand, UInt32 inNumerator, UInt32 inDenominator)
+{
+#if TARGET_OS_MAC && TARGET_RT_64_BIT
+ __uint128_t theAnswer = inMuliplicand;
+#else
+ long double theAnswer = inMuliplicand;
+#endif
+ if(inNumerator != inDenominator)
+ {
+ theAnswer *= inNumerator;
+ theAnswer /= inDenominator;
+ }
+ return static_cast<UInt64>(theAnswer);
+}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CALogMacros.h b/libs/appleutility/CoreAudio/PublicUtility/CALogMacros.h
new file mode 100644
index 0000000000..7fd4ac4c21
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CALogMacros.h
@@ -0,0 +1,140 @@
+/*
+ File: CALogMacros.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CALogMacros_h__)
+#define __CALogMacros_h__
+
+//=============================================================================
+// Log Macros
+//=============================================================================
+
+#if CoreAudio_Debug
+
+ #include "CADebugMacros.h"
+ #include "CADebugPrintf.h"
+ #include <stdio.h>
+ #include <string.h>
+
+ #define PrintLine(msg) DebugPrintfRtn(DebugPrintfFileComma "%s\n", (msg))
+
+ #define PrintBool(msg, b) DebugPrintfRtn(DebugPrintfFileComma "%s%s\n", (msg), (b) ? "true" : "false")
+ #define PrintIndexedBool(msg, i, b) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %s\n", (msg), (long)(i), (b) ? "true" : "false")
+
+ #define PrintToggle(msg, b) DebugPrintfRtn(DebugPrintfFileComma "%s%s\n", (msg), (b) ? "on" : "off")
+ #define PrintIndexedToggle(msg, i, b) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %s\n", (msg), (long)(i), (b) ? "on" : "off")
+
+ #define PrintInt(msg, n) DebugPrintfRtn(DebugPrintfFileComma "%s%ld\n", (msg), (long)(n))
+ #define PrintIndexedInt(msg, i, n) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %ld\n", (msg), (long)(i), (long)(n))
+
+ #define PrintHex(msg, n) DebugPrintfRtn(DebugPrintfFileComma "%s0x%lX\n", (msg), (unsigned long)(n))
+ #define PrintIndexedHex(msg, i, n) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: 0x%lX\n", (msg), (long)(i), (unsigned long)(n))
+
+ #define PrintFloat(msg, f) DebugPrintfRtn(DebugPrintfFileComma "%s%.6f\n", (msg), (f))
+ #define PrintIndexedFloat(msg, i, f) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %.6f\n", (msg), (long)(i), (f))
+ #define PrintFloatIndexedFloat(msg, i, f) DebugPrintfRtn(DebugPrintfFileComma " %s %.6f: %.6f\n", (msg), (i), (f))
+
+ #define PrintString(msg, s) DebugPrintfRtn(DebugPrintfFileComma "%s%s\n", (msg), (s))
+ #define PrintIndexedString(msg, i, s) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %s\n", (msg), (long)(i), (s))
+
+ #define PrintPointer(msg, p) DebugPrintfRtn(DebugPrintfFileComma "%s%p\n", (msg), (p))
+ #define PrintIndexedPointer(msg, i, p) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %p\n", (msg), (long)(i), (p))
+
+ #define Print4CharCode(msg, c) { \
+ UInt32 __4CC_number = (c); \
+ char __4CC_string[5] = CA4CCToCString(__4CC_number); \
+ DebugPrintfRtn(DebugPrintfFileComma "%s'%s'\n", (msg), __4CC_string); \
+ }
+ #define PrintIndexed4CharCode(msg, i, c) { \
+ UInt32 __4CC_number = (c); \
+ char __4CC_string[5] = CA4CCToCString(__4CC_number); \
+ DebugPrintfRtn(DebugPrintfFileComma " %s %ld: '%s'\n", (msg), (long)(i), __4CC_string); \
+ }
+
+ #define ErrorLine(s) DebugPrintfRtn(DebugPrintfFileComma "%s\n", (s))
+ #define OSErrorLine(s, e) { \
+ OSStatus __err_number = (e); \
+ char __err_string[5] = CA4CCToCString(__err_number); \
+ DebugPrintfRtn(DebugPrintfFileComma "%s, OSStatus code: %s\n", (s), __err_string); \
+ }
+
+ #define MessageIfOSError(e, s) if((e) != 0) { OSErrorLine(s, e); }
+ #define MessageIfNULL(p, s) if((p) == 0) { ErrorLine(s); }
+
+#else
+
+ #define PrintLine(msg)
+
+ #define PrintBool(msg, b) (b)
+ #define PrintIndexedBool(msg, i, b) (b)
+
+ #define PrintInt(msg, n) (n)
+ #define PrintIndexedInt(msg, i, n) (n)
+
+ #define PrintHex(msg, n) (n)
+ #define PrintIndexedHex(msg, i, n) (n)
+
+ #define PrintFloat(msg, f) (f)
+ #define PrintIndexedFloat(msg, i, f) (f)
+ #define PrintFloatIndexedFloat(msg, i, f) (f)
+
+ #define PrintString(msg, s) (s)
+ #define PrintIndexedString(msg, i, s) (s)
+
+ #define PrintPointer(msg, p) (p)
+ #define PrintIndexedPointer(msg, i, p) (p)
+
+ #define Print4CharCode(msg, c) (c)
+ #define PrintIndexed4CharCode(msg, i, c) (c)
+
+ #define ErrorLine(s) (s)
+ #define OSErrorLine(s, e) (e)
+
+ #define MessageIfOSError(e, s) (e)
+ #define MessageIfNULL(p, s) (p)
+
+#endif // CoreAudio_Debug
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAMath.h b/libs/appleutility/CoreAudio/PublicUtility/CAMath.h
new file mode 100644
index 0000000000..eb81f26e95
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAMath.h
@@ -0,0 +1,68 @@
+/*
+ File: CAMath.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAMath_h__
+#define __CAMath_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+inline bool fiszero(Float64 f) { return (f == 0.); }
+inline bool fiszero(Float32 f) { return (f == 0.f); }
+
+inline bool fnonzero(Float64 f) { return !fiszero(f); }
+inline bool fnonzero(Float32 f) { return !fiszero(f); }
+
+inline bool fequal(const Float64 &a, const Float64 &b) { return a == b; }
+inline bool fequal(const Float32 &a, const Float32 &b) { return a == b; }
+
+inline bool fnotequal(const Float64 &a, const Float64 &b) { return !fequal(a, b); }
+inline bool fnotequal(const Float32 &a, const Float32 &b) { return !fequal(a, b); }
+
+#endif // __CAMath_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAMixMap.h b/libs/appleutility/CoreAudio/PublicUtility/CAMixMap.h
new file mode 100644
index 0000000000..62e95d4aa5
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAMixMap.h
@@ -0,0 +1,157 @@
+/*
+ File: CAMixMap.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAMixMap_h__
+#define __CAMixMap_h__
+
+ // manages the setting of mix map volumes
+
+class CAMixMap {
+public:
+ CAMixMap ()
+ : mIns(0), mOuts (0), mMixMap(NULL)
+ {}
+
+ CAMixMap (const CAMixMap &mm)
+ : mIns(0), mOuts (0), mMixMap(NULL)
+ { *this = mm; }
+
+ CAMixMap (UInt32 numIns, UInt32 numOuts)
+ : mIns(numIns), mOuts (numOuts), mMixMap(NULL)
+ {
+ mMixMap = new Float32[numIns * numOuts];
+ memset (mMixMap, 0, ByteSize());
+ }
+
+ ~CAMixMap () { delete [] mMixMap; }
+
+ CAMixMap& operator=(const CAMixMap& mm)
+ {
+ if (mMixMap) { delete [] mMixMap; mMixMap = NULL; }
+ mIns = mm.mIns; mOuts = mm.mOuts;
+ if (NumIns() && NumOuts()) {
+ mMixMap = new Float32 [ NumIns() * NumOuts() ];
+ memcpy (mMixMap, mm.mMixMap, ByteSize());
+ }
+ return *this;
+ }
+
+ UInt32 NumIns () const { return mIns; }
+ UInt32 NumOuts () const { return mOuts; }
+
+ void SetCrossPoint (UInt32 inputChan, UInt32 outputChan, Float32 val)
+ {
+ if (inputChan < NumIns() && outputChan < NumOuts())
+ mMixMap[inputChan * NumOuts() + outputChan] = val;
+ }
+ Float32 GetCrossPoint (UInt32 inputChan, UInt32 outputChan) const
+ {
+ return (inputChan < NumIns() && outputChan < NumOuts())
+ ? mMixMap[inputChan * NumOuts() + outputChan]
+ : 0;
+ }
+
+ void SetDiagonal (Float32 val)
+ {
+ for (UInt32 i = 0; i < NumIns() && i < NumOuts(); ++i) {
+ mMixMap[i * NumOuts() + i] = val;
+ }
+ }
+
+ void Clear () { memset (mMixMap, 0, ByteSize()); }
+
+
+ Float32* MM() { return mMixMap; }
+ const Float32* MM() const { return mMixMap; }
+ UInt32 ByteSize () const { return NumIns() * NumOuts() * sizeof(Float32); }
+
+ UInt32 CountActiveInputs(UInt32 inOutputChannel)
+ {
+ UInt32 sum = 0;
+ for (UInt32 i = 0, k = inOutputChannel; i < mIns; ++i, k+=mOuts) {
+ if (mMixMap[k] != 0.f) sum++;
+ }
+ return sum;
+ }
+
+ void Normalize()
+ {
+ // ensure that no output channel will sum over unity.
+ Float32* mixmap = mMixMap;
+ Float32 maxsum = 0.f;
+ for (UInt32 j = 0; j < mOuts; ++j) {
+ Float32 sum = 0.f;
+ for (UInt32 i = 0, k = j; i < mIns; ++i, k+=mOuts) {
+ sum += mixmap[k];
+ }
+ if (sum > maxsum) maxsum = sum;
+ }
+
+ if (maxsum == 0.f) return;
+ Float32 scale = 1.f / maxsum;
+ for (UInt32 i = 0; i < mIns * mOuts; ++i) {
+ mixmap[i] *= scale;
+ }
+ }
+
+ void Print ()
+ {
+ printf ("Num Ins: %d, Num Outs: %d\n", (int)mIns, (int)mOuts);
+ for (unsigned int ins = 0; ins < mIns; ++ins) {
+ printf ("\t%d: ", ins);
+ for (unsigned int outs = 0; outs < mOuts; ++outs)
+ printf ("(%.3f) ", mMixMap[ins * NumOuts() + outs]);
+ printf("\n");
+ }
+ }
+
+private:
+ UInt32 mIns;
+ UInt32 mOuts;
+ Float32 *mMixMap;
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAMutex.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAMutex.cpp
new file mode 100644
index 0000000000..88cf9b0b02
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAMutex.cpp
@@ -0,0 +1,345 @@
+/*
+ File: CAMutex.cpp
+ Abstract: CAMutex.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CAMutex.h"
+
+#if TARGET_OS_MAC
+ #include <errno.h>
+#endif
+
+// PublicUtility Includes
+#include "CADebugMacros.h"
+#include "CAException.h"
+#include "CAHostTimeBase.h"
+
+//==================================================================================================
+// Logging
+//==================================================================================================
+
+#if CoreAudio_Debug
+// #define Log_Ownership 1
+// #define Log_Errors 1
+// #define Log_LongLatencies 1
+// #define LongLatencyThreshholdNS 1000000ULL // nanoseconds
+#endif
+
+//==================================================================================================
+// CAMutex
+//==================================================================================================
+
+CAMutex::CAMutex(const char* inName)
+:
+ mName(inName),
+ mOwner(0)
+{
+#if TARGET_OS_MAC
+ OSStatus theError = pthread_mutex_init(&mMutex, NULL);
+ ThrowIf(theError != 0, CAException(theError), "CAMutex::CAMutex: Could not init the mutex");
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::CAMutex: creating %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
+ #endif
+#elif TARGET_OS_WIN32
+ mMutex = CreateMutex(NULL, false, NULL);
+ ThrowIfNULL(mMutex, CAException(GetLastError()), "CAMutex::CAMutex: could not create the mutex.");
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::CAMutex: creating %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
+ #endif
+#endif
+}
+
+CAMutex::~CAMutex()
+{
+#if TARGET_OS_MAC
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::~CAMutex: destroying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
+ #endif
+ pthread_mutex_destroy(&mMutex);
+#elif TARGET_OS_WIN32
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::~CAMutex: destroying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
+ #endif
+ if(mMutex != NULL)
+ {
+ CloseHandle(mMutex);
+ }
+#endif
+}
+
+bool CAMutex::Lock()
+{
+ bool theAnswer = false;
+
+#if TARGET_OS_MAC
+ pthread_t theCurrentThread = pthread_self();
+ if(!pthread_equal(theCurrentThread, mOwner))
+ {
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Lock: thread %p is locking %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
+ #endif
+
+ #if Log_LongLatencies
+ UInt64 lockTryTime = CAHostTimeBase::GetCurrentTimeInNanos();
+ #endif
+
+ OSStatus theError = pthread_mutex_lock(&mMutex);
+ ThrowIf(theError != 0, CAException(theError), "CAMutex::Lock: Could not lock the mutex");
+ mOwner = theCurrentThread;
+ theAnswer = true;
+
+ #if Log_LongLatencies
+ UInt64 lockAcquireTime = CAHostTimeBase::GetCurrentTimeInNanos();
+ if (lockAcquireTime - lockTryTime >= LongLatencyThresholdNS)
+ DebugPrintfRtn(DebugPrintfFileComma "Thread %p took %.6fs to acquire the lock %s\n", theCurrentThread, (lockAcquireTime - lockTryTime) * 1.0e-9 /* nanos to seconds */, mName);
+ #endif
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Lock: thread %p has locked %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+ }
+#elif TARGET_OS_WIN32
+ if(mOwner != GetCurrentThreadId())
+ {
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Lock: thread %lu is locking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+
+ OSStatus theError = WaitForSingleObject(mMutex, INFINITE);
+ ThrowIfError(theError, CAException(theError), "CAMutex::Lock: could not lock the mutex");
+ mOwner = GetCurrentThreadId();
+ theAnswer = true;
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Lock: thread %lu has locked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+ }
+#endif
+
+ return theAnswer;
+}
+
+void CAMutex::Unlock()
+{
+#if TARGET_OS_MAC
+ if(pthread_equal(pthread_self(), mOwner))
+ {
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Unlock: thread %p is unlocking %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+
+ mOwner = 0;
+ OSStatus theError = pthread_mutex_unlock(&mMutex);
+ ThrowIf(theError != 0, CAException(theError), "CAMutex::Unlock: Could not unlock the mutex");
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Unlock: thread %p has unlocked %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+ }
+ else
+ {
+ DebugMessage("CAMutex::Unlock: A thread is attempting to unlock a Mutex it doesn't own");
+ }
+#elif TARGET_OS_WIN32
+ if(mOwner == GetCurrentThreadId())
+ {
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Unlock: thread %lu is unlocking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+
+ mOwner = 0;
+ bool wasReleased = ReleaseMutex(mMutex);
+ ThrowIf(!wasReleased, CAException(GetLastError()), "CAMutex::Unlock: Could not unlock the mutex");
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Unlock: thread %lu has unlocked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+ }
+ else
+ {
+ DebugMessage("CAMutex::Unlock: A thread is attempting to unlock a Mutex it doesn't own");
+ }
+#endif
+}
+
+bool CAMutex::Try(bool& outWasLocked)
+{
+ bool theAnswer = false;
+ outWasLocked = false;
+
+#if TARGET_OS_MAC
+ pthread_t theCurrentThread = pthread_self();
+ if(!pthread_equal(theCurrentThread, mOwner))
+ {
+ // this means the current thread doesn't already own the lock
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p is try-locking %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
+ #endif
+
+ // go ahead and call trylock to see if we can lock it.
+ int theError = pthread_mutex_trylock(&mMutex);
+ if(theError == 0)
+ {
+ // return value of 0 means we successfully locked the lock
+ mOwner = theCurrentThread;
+ theAnswer = true;
+ outWasLocked = true;
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p has locked %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
+ #endif
+ }
+ else if(theError == EBUSY)
+ {
+ // return value of EBUSY means that the lock was already locked by another thread
+ theAnswer = false;
+ outWasLocked = false;
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p failed to lock %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
+ #endif
+ }
+ else
+ {
+ // any other return value means something really bad happenned
+ ThrowIfError(theError, CAException(theError), "CAMutex::Try: call to pthread_mutex_trylock failed");
+ }
+ }
+ else
+ {
+ // this means the current thread already owns the lock
+ theAnswer = true;
+ outWasLocked = false;
+ }
+#elif TARGET_OS_WIN32
+ if(mOwner != GetCurrentThreadId())
+ {
+ // this means the current thread doesn't own the lock
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu is try-locking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+
+ // try to acquire the mutex
+ OSStatus theError = WaitForSingleObject(mMutex, 0);
+ if(theError == WAIT_OBJECT_0)
+ {
+ // this means we successfully locked the lock
+ mOwner = GetCurrentThreadId();
+ theAnswer = true;
+ outWasLocked = true;
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu has locked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+ }
+ else if(theError == WAIT_TIMEOUT)
+ {
+ // this means that the lock was already locked by another thread
+ theAnswer = false;
+ outWasLocked = false;
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu failed to lock %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+ }
+ else
+ {
+ // any other return value means something really bad happenned
+ ThrowIfError(theError, CAException(GetLastError()), "CAMutex::Try: call to lock the mutex failed");
+ }
+ }
+ else
+ {
+ // this means the current thread already owns the lock
+ theAnswer = true;
+ outWasLocked = false;
+ }
+#endif
+
+ return theAnswer;
+}
+
+bool CAMutex::IsFree() const
+{
+ return mOwner == 0;
+}
+
+bool CAMutex::IsOwnedByCurrentThread() const
+{
+ bool theAnswer = true;
+
+#if TARGET_OS_MAC
+ theAnswer = pthread_equal(pthread_self(), mOwner);
+#elif TARGET_OS_WIN32
+ theAnswer = (mOwner == GetCurrentThreadId());
+#endif
+
+ return theAnswer;
+}
+
+
+CAMutex::Unlocker::Unlocker(CAMutex& inMutex)
+: mMutex(inMutex),
+ mNeedsLock(false)
+{
+ Assert(mMutex.IsOwnedByCurrentThread(), "Major problem: Unlocker attempted to unlock a mutex not owned by the current thread!");
+
+ mMutex.Unlock();
+ mNeedsLock = true;
+}
+
+CAMutex::Unlocker::~Unlocker()
+{
+ if(mNeedsLock)
+ {
+ mMutex.Lock();
+ }
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAMutex.h b/libs/appleutility/CoreAudio/PublicUtility/CAMutex.h
new file mode 100644
index 0000000000..093066b400
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAMutex.h
@@ -0,0 +1,163 @@
+/*
+ File: CAMutex.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAMutex_h__
+#define __CAMutex_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+#if TARGET_OS_MAC
+ #include <pthread.h>
+#elif TARGET_OS_WIN32
+ #include <windows.h>
+#else
+ #error Unsupported operating system
+#endif
+
+//==================================================================================================
+// A recursive mutex.
+//==================================================================================================
+
+class CAMutex
+{
+// Construction/Destruction
+public:
+ CAMutex(const char* inName);
+ virtual ~CAMutex();
+
+// Actions
+public:
+ virtual bool Lock();
+ virtual void Unlock();
+ virtual bool Try(bool& outWasLocked); // returns true if lock is free, false if not
+
+ virtual bool IsFree() const;
+ virtual bool IsOwnedByCurrentThread() const;
+
+// Implementation
+protected:
+ const char* mName;
+#if TARGET_OS_MAC
+ pthread_t mOwner;
+ pthread_mutex_t mMutex;
+#elif TARGET_OS_WIN32
+ UInt32 mOwner;
+ HANDLE mMutex;
+#endif
+
+// Helper class to manage taking and releasing recursively
+public:
+ class Locker
+ {
+
+ // Construction/Destruction
+ public:
+ Locker(CAMutex& inMutex) : mMutex(&inMutex), mNeedsRelease(false) { mNeedsRelease = mMutex->Lock(); }
+ Locker(CAMutex* inMutex) : mMutex(inMutex), mNeedsRelease(false) { mNeedsRelease = (mMutex != NULL && mMutex->Lock()); }
+ // in this case the mutex can be null
+ ~Locker() { if(mNeedsRelease) { mMutex->Unlock(); } }
+
+
+ private:
+ Locker(const Locker&);
+ Locker& operator=(const Locker&);
+
+ // Implementation
+ private:
+ CAMutex* mMutex;
+ bool mNeedsRelease;
+
+ };
+
+// Unlocker
+ class Unlocker
+ {
+ public:
+ Unlocker(CAMutex& inMutex);
+ ~Unlocker();
+
+ private:
+ CAMutex& mMutex;
+ bool mNeedsLock;
+
+ // Hidden definitions of copy ctor, assignment operator
+ Unlocker(const Unlocker& copy); // Not implemented
+ Unlocker& operator=(const Unlocker& copy); // Not implemented
+ };
+
+// you can use this with Try - if you take the lock in try, pass in the outWasLocked var
+ class Tryer {
+
+ // Construction/Destruction
+ public:
+ Tryer (CAMutex &mutex) : mMutex(mutex), mNeedsRelease(false), mHasLock(false) { mHasLock = mMutex.Try (mNeedsRelease); }
+ ~Tryer () { if (mNeedsRelease) mMutex.Unlock(); }
+
+ bool HasLock () const { return mHasLock; }
+
+ private:
+ Tryer(const Tryer&);
+ Tryer& operator=(const Tryer&);
+
+ // Implementation
+ private:
+ CAMutex & mMutex;
+ bool mNeedsRelease;
+ bool mHasLock;
+ };
+};
+
+
+#endif // __CAMutex_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAPThread.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAPThread.cpp
new file mode 100644
index 0000000000..3da1058de7
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAPThread.cpp
@@ -0,0 +1,450 @@
+/*
+ File: CAPThread.cpp
+ Abstract: CAPThread.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+// Self Include
+#include "CAPThread.h"
+
+// PublicUtility Includes
+#include "CADebugMacros.h"
+#include "CAException.h"
+
+// System Includes
+#if TARGET_OS_MAC
+ #include <mach/mach.h>
+#endif
+
+// Standard Library Includes
+#include <stdio.h>
+
+//==================================================================================================
+// CAPThread
+//==================================================================================================
+
+// returns the thread's priority as it was last set by the API
+#define CAPTHREAD_SET_PRIORITY 0
+// returns the thread's priority as it was last scheduled by the Kernel
+#define CAPTHREAD_SCHEDULED_PRIORITY 1
+
+//#define Log_SetPriority 1
+
+CAPThread::CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPriority, bool inFixedPriority, bool inAutoDelete, const char* inThreadName)
+:
+#if TARGET_OS_MAC
+ mPThread(0),
+ mSpawningThreadPriority(getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY)),
+#elif TARGET_OS_WIN32
+ mThreadHandle(NULL),
+ mThreadID(0),
+#endif
+ mThreadRoutine(inThreadRoutine),
+ mThreadParameter(inParameter),
+ mPriority(inPriority),
+ mPeriod(0),
+ mComputation(0),
+ mConstraint(0),
+ mIsPreemptible(true),
+ mTimeConstraintSet(false),
+ mFixedPriority(inFixedPriority),
+ mAutoDelete(inAutoDelete)
+{
+ if(inThreadName != NULL)
+ {
+ strlcpy(mThreadName, inThreadName, kMaxThreadNameLength);
+ }
+ else
+ {
+ memset(mThreadName, 0, kMaxThreadNameLength);
+ }
+}
+
+CAPThread::CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible, bool inAutoDelete, const char* inThreadName)
+:
+#if TARGET_OS_MAC
+ mPThread(0),
+ mSpawningThreadPriority(getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY)),
+#elif TARGET_OS_WIN32
+ mThreadHandle(NULL),
+ mThreadID(0),
+#endif
+ mThreadRoutine(inThreadRoutine),
+ mThreadParameter(inParameter),
+ mPriority(kDefaultThreadPriority),
+ mPeriod(inPeriod),
+ mComputation(inComputation),
+ mConstraint(inConstraint),
+ mIsPreemptible(inIsPreemptible),
+ mTimeConstraintSet(true),
+ mFixedPriority(false),
+ mAutoDelete(inAutoDelete)
+{
+ if(inThreadName != NULL)
+ {
+ strlcpy(mThreadName, inThreadName, kMaxThreadNameLength);
+ }
+ else
+ {
+ memset(mThreadName, 0, kMaxThreadNameLength);
+ }
+}
+
+CAPThread::~CAPThread()
+{
+}
+
+UInt32 CAPThread::GetScheduledPriority()
+{
+#if TARGET_OS_MAC
+ return CAPThread::getScheduledPriority( mPThread, CAPTHREAD_SCHEDULED_PRIORITY );
+#elif TARGET_OS_WIN32
+ UInt32 theAnswer = 0;
+ if(mThreadHandle != NULL)
+ {
+ theAnswer = GetThreadPriority(mThreadHandle);
+ }
+ return theAnswer;
+#endif
+}
+
+UInt32 CAPThread::GetScheduledPriority(NativeThread thread)
+{
+#if TARGET_OS_MAC
+ return getScheduledPriority( thread, CAPTHREAD_SCHEDULED_PRIORITY );
+#elif TARGET_OS_WIN32
+ return 0; // ???
+#endif
+}
+
+void CAPThread::SetPriority(UInt32 inPriority, bool inFixedPriority)
+{
+ mPriority = inPriority;
+ mTimeConstraintSet = false;
+ mFixedPriority = inFixedPriority;
+#if TARGET_OS_MAC
+ if(mPThread != 0)
+ {
+ SetPriority(mPThread, mPriority, mFixedPriority);
+ }
+#elif TARGET_OS_WIN32
+ if(mThreadID != NULL)
+ {
+ SetPriority(mThreadID, mPriority, mFixedPriority);
+ }
+#endif
+}
+
+void CAPThread::SetPriority(NativeThread inThread, UInt32 inPriority, bool inFixedPriority)
+{
+#if TARGET_OS_MAC
+ if(inThread != 0)
+ {
+ kern_return_t theError = 0;
+
+ // set whether or not this is a fixed priority thread
+ if (inFixedPriority)
+ {
+ thread_extended_policy_data_t theFixedPolicy = { false };
+ theError = thread_policy_set(pthread_mach_thread_np(inThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
+ AssertNoKernelError(theError, "CAPThread::SetPriority: failed to set the fixed-priority policy");
+ }
+
+ // set the thread's absolute priority which is relative to the priority on which thread_policy_set() is called
+ UInt32 theCurrentThreadPriority = getScheduledPriority(pthread_self(), CAPTHREAD_SET_PRIORITY);
+ thread_precedence_policy_data_t thePrecedencePolicy = { static_cast<integer_t>(inPriority - theCurrentThreadPriority) };
+ theError = thread_policy_set(pthread_mach_thread_np(inThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT);
+ AssertNoKernelError(theError, "CAPThread::SetPriority: failed to set the precedence policy");
+
+ #if Log_SetPriority
+ DebugMessageN4("CAPThread::SetPriority: requsted: %lu spawning: %lu current: %lu assigned: %d", mPriority, mSpawningThreadPriority, theCurrentThreadPriority, thePrecedencePolicy.importance);
+ #endif
+ }
+#elif TARGET_OS_WIN32
+ if(inThread != NULL)
+ {
+ HANDLE hThread = OpenThread(NULL, FALSE, inThread);
+ if(hThread != NULL) {
+ SetThreadPriority(hThread, inPriority);
+ CloseHandle(hThread);
+ }
+ }
+#endif
+}
+
+void CAPThread::SetTimeConstraints(UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible)
+{
+ mPeriod = inPeriod;
+ mComputation = inComputation;
+ mConstraint = inConstraint;
+ mIsPreemptible = inIsPreemptible;
+ mTimeConstraintSet = true;
+#if TARGET_OS_MAC
+ if(mPThread != 0)
+ {
+ thread_time_constraint_policy_data_t thePolicy;
+ thePolicy.period = mPeriod;
+ thePolicy.computation = mComputation;
+ thePolicy.constraint = mConstraint;
+ thePolicy.preemptible = mIsPreemptible;
+ AssertNoError(thread_policy_set(pthread_mach_thread_np(mPThread), THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&thePolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT), "CAPThread::SetTimeConstraints: thread_policy_set failed");
+ }
+#elif TARGET_OS_WIN32
+ if(mThreadHandle != NULL)
+ {
+ SetThreadPriority(mThreadHandle, THREAD_PRIORITY_TIME_CRITICAL);
+ }
+#endif
+}
+
+void CAPThread::Start()
+{
+#if TARGET_OS_MAC
+ Assert(mPThread == 0, "CAPThread::Start: can't start because the thread is already running");
+ if(mPThread == 0)
+ {
+ OSStatus theResult;
+ pthread_attr_t theThreadAttributes;
+
+ theResult = pthread_attr_init(&theThreadAttributes);
+ ThrowIf(theResult != 0, CAException(theResult), "CAPThread::Start: Thread attributes could not be created.");
+
+ theResult = pthread_attr_setdetachstate(&theThreadAttributes, PTHREAD_CREATE_DETACHED);
+ ThrowIf(theResult != 0, CAException(theResult), "CAPThread::Start: A thread could not be created in the detached state.");
+
+ theResult = pthread_create(&mPThread, &theThreadAttributes, (ThreadRoutine)CAPThread::Entry, this);
+ ThrowIf(theResult != 0 || !mPThread, CAException(theResult), "CAPThread::Start: Could not create a thread.");
+
+ pthread_attr_destroy(&theThreadAttributes);
+
+ }
+#elif TARGET_OS_WIN32
+ Assert(mThreadID == 0, "CAPThread::Start: can't start because the thread is already running");
+ if(mThreadID == 0)
+ {
+ // clean up the existing thread handle
+ if(mThreadHandle != NULL)
+ {
+ CloseHandle(mThreadHandle);
+ mThreadHandle = NULL;
+ }
+
+ // create a new thread
+ mThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Entry, this, 0, &mThreadID);
+ ThrowIf(mThreadHandle == NULL, CAException(GetLastError()), "CAPThread::Start: Could not create a thread.");
+ }
+#endif
+}
+
+#if TARGET_OS_MAC
+
+void* CAPThread::Entry(CAPThread* inCAPThread)
+{
+ void* theAnswer = NULL;
+
+#if TARGET_OS_MAC
+ inCAPThread->mPThread = pthread_self();
+#elif TARGET_OS_WIN32
+ // do we need to do something here?
+#endif
+
+#if !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
+ if(inCAPThread->mThreadName[0] != 0)
+ {
+ pthread_setname_np(inCAPThread->mThreadName);
+ }
+#endif
+
+ try
+ {
+ if(inCAPThread->mTimeConstraintSet)
+ {
+ inCAPThread->SetTimeConstraints(inCAPThread->mPeriod, inCAPThread->mComputation, inCAPThread->mConstraint, inCAPThread->mIsPreemptible);
+ }
+ else
+ {
+ inCAPThread->SetPriority(inCAPThread->mPriority, inCAPThread->mFixedPriority);
+ }
+
+ if(inCAPThread->mThreadRoutine != NULL)
+ {
+ theAnswer = inCAPThread->mThreadRoutine(inCAPThread->mThreadParameter);
+ }
+ }
+ catch (...)
+ {
+ // what should be done here?
+ }
+ inCAPThread->mPThread = 0;
+ if (inCAPThread->mAutoDelete)
+ delete inCAPThread;
+ return theAnswer;
+}
+
+UInt32 CAPThread::getScheduledPriority(pthread_t inThread, int inPriorityKind)
+{
+ thread_basic_info_data_t threadInfo;
+ policy_info_data_t thePolicyInfo;
+ unsigned int count;
+
+ if (inThread == NULL)
+ return 0;
+
+ // get basic info
+ count = THREAD_BASIC_INFO_COUNT;
+ thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (thread_info_t)&threadInfo, &count);
+
+ switch (threadInfo.policy) {
+ case POLICY_TIMESHARE:
+ count = POLICY_TIMESHARE_INFO_COUNT;
+ thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&(thePolicyInfo.ts), &count);
+ if (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) {
+ return static_cast<UInt32>(thePolicyInfo.ts.cur_priority);
+ }
+ return static_cast<UInt32>(thePolicyInfo.ts.base_priority);
+ break;
+
+ case POLICY_FIFO:
+ count = POLICY_FIFO_INFO_COUNT;
+ thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (thread_info_t)&(thePolicyInfo.fifo), &count);
+ if ( (thePolicyInfo.fifo.depressed) && (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) ) {
+ return static_cast<UInt32>(thePolicyInfo.fifo.depress_priority);
+ }
+ return static_cast<UInt32>(thePolicyInfo.fifo.base_priority);
+ break;
+
+ case POLICY_RR:
+ count = POLICY_RR_INFO_COUNT;
+ thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (thread_info_t)&(thePolicyInfo.rr), &count);
+ if ( (thePolicyInfo.rr.depressed) && (inPriorityKind == CAPTHREAD_SCHEDULED_PRIORITY) ) {
+ return static_cast<UInt32>(thePolicyInfo.rr.depress_priority);
+ }
+ return static_cast<UInt32>(thePolicyInfo.rr.base_priority);
+ break;
+ }
+
+ return 0;
+}
+
+#elif TARGET_OS_WIN32
+
+UInt32 WINAPI CAPThread::Entry(CAPThread* inCAPThread)
+{
+ UInt32 theAnswer = 0;
+
+ try
+ {
+ if(inCAPThread->mTimeConstraintSet)
+ {
+ inCAPThread->SetTimeConstraints(inCAPThread->mPeriod, inCAPThread->mComputation, inCAPThread->mConstraint, inCAPThread->mIsPreemptible);
+ }
+ else
+ {
+ inCAPThread->SetPriority(inCAPThread->mPriority, inCAPThread->mFixedPriority);
+ }
+
+ if(inCAPThread->mThreadRoutine != NULL)
+ {
+ theAnswer = reinterpret_cast<UInt32>(inCAPThread->mThreadRoutine(inCAPThread->mThreadParameter));
+ }
+ inCAPThread->mThreadID = 0;
+ }
+ catch (...)
+ {
+ // what should be done here?
+ }
+ CloseHandle(inCAPThread->mThreadHandle);
+ inCAPThread->mThreadHandle = NULL;
+ if (inCAPThread->mAutoDelete)
+ delete inCAPThread;
+ return theAnswer;
+}
+
+extern "C"
+Boolean CompareAndSwap(UInt32 inOldValue, UInt32 inNewValue, UInt32* inOldValuePtr)
+{
+ return InterlockedCompareExchange((volatile LONG*)inOldValuePtr, inNewValue, inOldValue) == inOldValue;
+}
+
+#endif
+
+void CAPThread::SetName(const char* inThreadName)
+{
+ if(inThreadName != NULL)
+ {
+ strlcpy(mThreadName, inThreadName, kMaxThreadNameLength);
+ }
+ else
+ {
+ memset(mThreadName, 0, kMaxThreadNameLength);
+ }
+}
+
+#if CoreAudio_Debug
+void CAPThread::DebugPriority(const char *label)
+{
+#if !TARGET_OS_WIN32
+ if (mTimeConstraintSet)
+ printf("CAPThread::%s %p: pri=<time constraint>, spawning pri=%d, scheduled pri=%d\n", label, this,
+ (int)mSpawningThreadPriority, (mPThread != NULL) ? (int)GetScheduledPriority() : -1);
+ else
+ printf("CAPThread::%s %p: pri=%d%s, spawning pri=%d, scheduled pri=%d\n", label, this, (int)mPriority, mFixedPriority ? " fixed" : "",
+ (int)mSpawningThreadPriority, (mPThread != NULL) ? (int)GetScheduledPriority() : -1);
+#else
+ if (mTimeConstraintSet)
+ {
+ printf("CAPThread::%s %p: pri=<time constraint>, spawning pri=%d, scheduled pri=%d\n", label, this,
+ (int)mPriority, (mThreadHandle != NULL) ? (int)GetScheduledPriority() : -1);
+ }
+ else
+ {
+ printf("CAPThread::%s %p: pri=%d%s, spawning pri=%d, scheduled pri=%d\n", label, this, (int)mPriority, mFixedPriority ? " fixed" : "",
+ (int)mPriority, (mThreadHandle != NULL) ? (int)GetScheduledPriority() : -1);
+ }
+#endif
+}
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAPThread.h b/libs/appleutility/CoreAudio/PublicUtility/CAPThread.h
new file mode 100644
index 0000000000..41451252f8
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAPThread.h
@@ -0,0 +1,191 @@
+/*
+ File: CAPThread.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAPThread_h__)
+#define __CAPThread_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CFBase.h>
+#else
+ #include <CFBase.h>
+#endif
+
+#if TARGET_OS_MAC
+ #include <pthread.h>
+ #include <unistd.h>
+#elif TARGET_OS_WIN32
+ #include <windows.h>
+#else
+ #error Unsupported operating system
+#endif
+
+//==================================================================================================
+// CAPThread
+//
+// This class wraps a pthread and a Win32 thread.
+// caution: long-running fixed priority threads can make the system unresponsive
+//==================================================================================================
+
+class CAPThread
+{
+
+// Types
+public:
+ typedef void* (*ThreadRoutine)(void* inParameter);
+
+// Constants
+public:
+ enum
+ {
+#if TARGET_OS_MAC
+ kMinThreadPriority = 1,
+ kMaxThreadPriority = 63,
+ kDefaultThreadPriority = 31,
+ kMaxThreadNameLength = 64
+#elif TARGET_OS_WIN32
+ kMinThreadPriority = 1,
+ kMaxThreadPriority = 31,
+ kDefaultThreadPriority = THREAD_PRIORITY_NORMAL,
+ kMaxThreadNameLength = 256
+#endif
+ };
+
+// Construction/Destruction
+public:
+ CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPriority = kDefaultThreadPriority, bool inFixedPriority=false, bool inAutoDelete=false, const char* inThreadName = NULL);
+ CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible, bool inAutoDelete=false, const char* inThreadName = NULL);
+ virtual ~CAPThread();
+
+// Properties
+public:
+#if TARGET_OS_MAC
+ typedef pthread_t NativeThread;
+
+ NativeThread GetNativeThread() { return mPThread; }
+ static NativeThread GetCurrentThread() { return pthread_self(); }
+ static bool IsNativeThreadsEqual(NativeThread a, NativeThread b) { return (a==b); }
+
+ bool operator==(NativeThread b) { return pthread_equal(mPThread,b); }
+
+ pthread_t GetPThread() const { return mPThread; }
+ bool IsCurrentThread() const { return (0 != mPThread) && (pthread_self() == mPThread); }
+ bool IsRunning() const { return 0 != mPThread; }
+ static UInt32 getScheduledPriority(pthread_t inThread, int inPriorityKind);
+#elif TARGET_OS_WIN32
+ typedef unsigned long NativeThread;
+
+ NativeThread GetNativeThread() { return mThreadID; }
+ static NativeThread GetCurrentThread() { return GetCurrentThreadId(); }
+ static bool IsNativeThreadsEqual(NativeThread a, NativeThread b) { return (a==b); }
+
+ bool operator ==(NativeThread b) { return (mThreadID==b); }
+
+ HANDLE GetThreadHandle() const { return mThreadHandle; }
+ UInt32 GetThreadID() const { return mThreadID; }
+ bool IsCurrentThread() const { return (0 != mThreadID) && (GetCurrentThreadId() == mThreadID); }
+ bool IsRunning() const { return 0 != mThreadID; }
+#endif
+
+ bool IsTimeShareThread() const { return !mTimeConstraintSet; }
+ bool IsTimeConstraintThread() const { return mTimeConstraintSet; }
+
+ UInt32 GetPriority() const { return mPriority; }
+ UInt32 GetScheduledPriority();
+ static UInt32 GetScheduledPriority(NativeThread thread);
+ void SetPriority(UInt32 inPriority, bool inFixedPriority=false);
+ static void SetPriority(NativeThread inThread, UInt32 inPriority, bool inFixedPriority = false);
+
+ void GetTimeConstraints(UInt32& outPeriod, UInt32& outComputation, UInt32& outConstraint, bool& outIsPreemptible) const { outPeriod = mPeriod; outComputation = mComputation; outConstraint = mConstraint; outIsPreemptible = mIsPreemptible; }
+ void SetTimeConstraints(UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible);
+ void ClearTimeConstraints() { SetPriority(mPriority); }
+
+ bool WillAutoDelete() const { return mAutoDelete; }
+ void SetAutoDelete(bool b) { mAutoDelete = b; }
+
+ void SetName(const char* inThreadName);
+
+#if CoreAudio_Debug
+ void DebugPriority(const char *label);
+#endif
+
+// Actions
+public:
+ virtual void Start();
+
+// Implementation
+protected:
+#if TARGET_OS_MAC
+ static void* Entry(CAPThread* inCAPThread);
+#elif TARGET_OS_WIN32
+ static UInt32 WINAPI Entry(CAPThread* inCAPThread);
+#endif
+
+#if TARGET_OS_MAC
+ pthread_t mPThread;
+ UInt32 mSpawningThreadPriority;
+#elif TARGET_OS_WIN32
+ HANDLE mThreadHandle;
+ unsigned long mThreadID;
+#endif
+ ThreadRoutine mThreadRoutine;
+ void* mThreadParameter;
+ char mThreadName[kMaxThreadNameLength];
+ UInt32 mPriority;
+ UInt32 mPeriod;
+ UInt32 mComputation;
+ UInt32 mConstraint;
+ bool mIsPreemptible;
+ bool mTimeConstraintSet;
+ bool mFixedPriority;
+ bool mAutoDelete; // delete self when thread terminates
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAPersistence.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAPersistence.cpp
new file mode 100644
index 0000000000..d3fe008eeb
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAPersistence.cpp
@@ -0,0 +1,468 @@
+/*
+ File: CAPersistence.cpp
+ Abstract: CAPersistence.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CACFArray.h"
+#include "CACFDictionary.h"
+
+#include "CAAudioUnit.h"
+#include "CACFString.h"
+#include "CAAudioChannelLayout.h"
+#include "CAAUParameter.h"
+#include "CAAUMIDIMap.h"
+
+#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
+
+#pragma mark __CAStreamBasicDescription
+
+static const CFStringRef kSampleRate = CFSTR("sample rate");
+static const CFStringRef kFormat = CFSTR("format");
+static const CFStringRef kFormatFlags = CFSTR("format flags");
+static const CFStringRef kPacketBytes = CFSTR("packet bytes");
+static const CFStringRef kFramePackets = CFSTR("frame packets");
+static const CFStringRef kFrameBytes = CFSTR("frame bytes");
+static const CFStringRef kFrameChannels = CFSTR("frame channels");
+static const CFStringRef kChannelBits = CFSTR("channel bits");
+
+ // This will return a value that should be used as the key for this struct
+ // and a CFData object that contains the current state of this object
+OSStatus CAStreamBasicDescription::Save (CFPropertyListRef *outData) const
+{
+ CACFDictionary dict(false);
+
+ if (!dict.AddFloat64 (kSampleRate, mSampleRate)) goto error;
+ if (!dict.AddUInt32 (kFormat, mFormatID)) goto error;
+ if (!dict.AddUInt32 (kFormatFlags, mFormatFlags)) goto error;
+ if (!dict.AddUInt32 (kPacketBytes, mBytesPerPacket)) goto error;
+ if (!dict.AddUInt32 (kFramePackets, mFramesPerPacket)) goto error;
+ if (!dict.AddUInt32 (kFrameBytes, mBytesPerFrame)) goto error;
+ if (!dict.AddUInt32 (kFrameChannels, mChannelsPerFrame)) goto error;
+ if (!dict.AddUInt32 (kChannelBits, mBitsPerChannel)) goto error;
+
+ *outData = dict.GetDict();
+
+ return noErr;
+
+error:
+ dict.ShouldRelease (true);
+ return paramErr;
+}
+
+
+ // Given a CFData object generated by the save command, this will re-establish
+ // the CAStreamBasicDescription
+OSStatus CAStreamBasicDescription::Restore (CFPropertyListRef& inData)
+{
+ if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
+ CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
+
+ if (!dict.GetFloat64 (kSampleRate, mSampleRate)) return paramErr;
+ if (!dict.GetUInt32 (kFormat, mFormatID)) return paramErr;
+ if (!dict.GetUInt32 (kFormatFlags, mFormatFlags)) return paramErr;
+ if (!dict.GetUInt32 (kPacketBytes, mBytesPerPacket)) return paramErr;
+ if (!dict.GetUInt32 (kFramePackets, mFramesPerPacket)) return paramErr;
+ if (!dict.GetUInt32 (kFrameBytes, mBytesPerFrame)) return paramErr;
+ if (!dict.GetUInt32 (kFrameChannels, mChannelsPerFrame)) return paramErr;
+ if (!dict.GetUInt32 (kChannelBits, mBitsPerChannel)) return paramErr;
+
+ return noErr;
+}
+
+#pragma mark __CAComponentDescription
+
+static const CFStringRef kType = CFSTR("type");
+static const CFStringRef kSubType = CFSTR("subtype");
+static const CFStringRef kManu = CFSTR("manufacturer");
+
+OSStatus CAComponentDescription::Save (CFPropertyListRef *outData) const
+{
+ CACFDictionary dict(false);
+ if (!dict.AddUInt32 (kType, componentType)) goto error;
+ if (!dict.AddUInt32 (kSubType, componentSubType)) goto error;
+ if (!dict.AddUInt32 (kManu, componentManufacturer)) goto error;
+
+ *outData = dict.GetDict();
+
+ return 0;
+error:
+ dict.ShouldRelease (true);
+ return paramErr;
+}
+
+OSStatus CAComponentDescription::Restore (CFPropertyListRef &inData)
+{
+ if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
+ CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
+
+ if (!dict.GetUInt32 (kType, componentType)) return paramErr;
+ if (!dict.GetUInt32 (kSubType, componentSubType)) return paramErr;
+ if (!dict.GetUInt32 (kManu, componentManufacturer)) return paramErr;
+
+ componentFlags = 0;
+ componentFlagsMask = 0;
+
+ return 0;
+}
+
+#pragma mark __CAComponent
+
+OSStatus CAComponent::Save (CFPropertyListRef *outData) const
+{
+ OSStatus result = mDesc.Save (outData);
+ if (result) return result;
+
+ //add the name string of the component for a human readable name...
+ // this name string is *not* restored when restoring the component
+ CFStringRef name = GetCompName ();
+ if (name && *outData)
+ CFDictionarySetValue ((CFMutableDictionaryRef)(*outData), CFSTR("name"), name);
+
+ return noErr;
+}
+
+OSStatus CAComponent::Restore (CFPropertyListRef &inData)
+{
+ if (mDesc.Restore (inData)) return paramErr;
+
+ Clear();
+
+ mComp = AudioComponentFindNext (NULL, &mDesc);
+ // this will restore the current flags...
+ if (mComp)
+ AudioComponentGetDescription (Comp(), &mDesc);
+
+ return noErr;
+}
+
+
+#pragma mark __CAAudioChannelLayout
+
+static const CFStringRef kACLTagKey = CFSTR("acl tag");
+static const CFStringRef kACLBitmapKey = CFSTR("chan bitmap");
+static const CFStringRef kACLLabelKey = CFSTR("label");
+static const CFStringRef kACLFlagsKey = CFSTR("flags");
+static const CFStringRef kACLCoords0Key = CFSTR("coords 0");
+static const CFStringRef kACLCoords1Key = CFSTR("coords 1");
+static const CFStringRef kACLCoords2Key = CFSTR("coords 2");
+static const CFStringRef kACLDescsKey = CFSTR("descriptions");
+
+OSStatus CAAudioChannelLayout::Save (CFPropertyListRef *outData) const
+{
+ const AudioChannelLayout& layout = Layout();
+
+ CACFDictionary dict (false);
+ if (!dict.AddUInt32 (kACLTagKey, layout.mChannelLayoutTag))
+ goto badadd;
+ if (layout.mChannelBitmap && !dict.AddUInt32 (kACLBitmapKey, layout.mChannelBitmap))
+ goto badadd;
+
+ if (layout.mNumberChannelDescriptions)
+ {
+ CFMutableArrayRef descs = CFArrayCreateMutable (NULL, layout.mNumberChannelDescriptions, &kCFTypeArrayCallBacks);
+
+ const AudioChannelDescription *desc = layout.mChannelDescriptions;
+ for (unsigned int i = 0; i < layout.mNumberChannelDescriptions; ++i, ++desc)
+ {
+ CACFDictionary descDict (true);
+ if (!descDict.AddUInt32 (kACLLabelKey, desc->mChannelLabel))
+ { CFRelease (descs); goto badadd; }
+ if (!descDict.AddUInt32 (kACLFlagsKey, desc->mChannelFlags))
+ { CFRelease (descs); goto badadd; }
+ if (!descDict.AddFloat32 (kACLCoords0Key, desc->mCoordinates[0]))
+ { CFRelease (descs); goto badadd; }
+ if (!descDict.AddFloat32 (kACLCoords1Key, desc->mCoordinates[1]))
+ { CFRelease (descs); goto badadd; }
+ if (!descDict.AddFloat32 (kACLCoords2Key, desc->mCoordinates[2]))
+ { CFRelease (descs); goto badadd; }
+
+ CFArrayAppendValue (descs, descDict.AsPropertyList());
+ }
+ dict.AddArray (kACLDescsKey, descs);
+
+ CFRelease (descs);
+ }
+
+ *outData = dict.GetDict();
+
+ return noErr;
+
+badadd:
+ dict.ShouldRelease(true);
+ return paramErr;
+}
+
+OSStatus CAAudioChannelLayout::Restore (CFPropertyListRef &inData)
+{
+ if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
+ CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
+
+ RefCountedLayout *temp = NULL;
+ AudioChannelLayout* layout;
+
+ CFArrayRef descs = NULL;
+ UInt32 numDescs = 0;
+
+ if (dict.GetArray (kACLDescsKey, descs)) {
+ numDescs = static_cast<OSStatus>(CFArrayGetCount (descs));
+ }
+
+ temp = RefCountedLayout::CreateWithNumberChannelDescriptions(numDescs);
+ layout = temp->GetLayout();
+
+ if (!dict.GetUInt32 (kACLTagKey, layout->mChannelLayoutTag))
+ goto badget;
+ if (dict.HasKey (kACLBitmapKey)) {
+ if (!dict.GetUInt32 (kACLBitmapKey, layout->mChannelBitmap))
+ goto badget;
+ } else
+ layout->mChannelBitmap = 0;
+
+ layout->mNumberChannelDescriptions = numDescs;
+
+ if (numDescs)
+ {
+ AudioChannelDescription *desc = layout->mChannelDescriptions;
+ for (unsigned int i = 0; i < numDescs; ++i, ++desc)
+ {
+ CFDictionaryRef descDict = (CFDictionaryRef)CFArrayGetValueAtIndex (descs, i);
+ CACFDictionary theDesc (descDict, false);
+
+ if (!theDesc.GetUInt32 (kACLLabelKey, desc->mChannelLabel))
+ goto badget;
+ if (!theDesc.GetUInt32 (kACLFlagsKey, desc->mChannelFlags))
+ goto badget;
+ if (!theDesc.GetFloat32 (kACLCoords0Key, desc->mCoordinates[0]))
+ goto badget;
+ if (!theDesc.GetFloat32 (kACLCoords1Key, desc->mCoordinates[1]))
+ goto badget;
+ if (!theDesc.GetFloat32 (kACLCoords2Key, desc->mCoordinates[2]))
+ goto badget;
+ }
+ }
+ if (mLayout)
+ mLayout->release();
+
+ mLayout = temp;
+
+ return noErr;
+
+badget:
+ delete temp;
+ return paramErr;
+}
+
+#pragma mark __AudioUnitParameter
+
+static const CFStringRef kAUScopeStr = CFSTR("scope");
+static const CFStringRef kAUElementIDStr = CFSTR("element ID");
+static const CFStringRef kAUParameterIDStr = CFSTR("paramID");
+
+void CAAUParameter::Save (CFPropertyListRef &outData) const
+{
+ return CAAUParameter::Save (*this, outData);
+}
+
+// static functions to save/restore AudioUnitParameter
+void CAAUParameter::Save (const AudioUnitParameter &inParam, CFPropertyListRef &outData)
+{
+ CACFDictionary dict(false);
+ dict.AddUInt32 (kAUScopeStr, inParam.mScope);
+ dict.AddUInt32 (kAUElementIDStr, inParam.mElement);
+ dict.AddUInt32 (kAUParameterIDStr, inParam.mParameterID);
+
+ outData = dict.AsPropertyList();
+}
+
+OSStatus CAAUParameter::Restore (const CFPropertyListRef inData, AudioUnitParameter &outParam)
+{
+ if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
+ CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
+
+ if (!dict.GetUInt32 (kAUScopeStr, outParam.mScope)) return paramErr;
+ if (!dict.GetUInt32 (kAUElementIDStr, outParam.mElement)) return paramErr;
+ if (!dict.GetUInt32 (kAUParameterIDStr, outParam.mParameterID)) return paramErr;
+ return noErr;
+}
+
+
+#pragma mark __MIDIMap
+
+const CFStringRef kParamMIDIStr = CFSTR("param maps");
+
+const CFStringRef kMIDIFlagsStr = CFSTR("flags");
+const CFStringRef kMIDISubMinStr = CFSTR("sub min");
+const CFStringRef kMIDISubMaxStr = CFSTR("sub max");
+const CFStringRef kMIDIStatusStr = CFSTR("midi status byte");
+const CFStringRef kMIDIDataByteStr = CFSTR("midi data1 byte");
+const CFStringRef kAUStr = CFSTR("unit");
+
+static const CFStringRef kLocalElementIDStr = CFSTR("element ID");
+static const CFStringRef kLocalScopeStr = CFSTR("scope");
+static const CFStringRef kLocalParameterIDStr = CFSTR("paramID");
+
+void CAAUMIDIMap::Save(CFPropertyListRef &outData) const
+{
+ CACFDictionary paramDict(false);
+
+ paramDict.AddUInt32 (kLocalScopeStr, mScope);
+ paramDict.AddUInt32 (kLocalElementIDStr, mElement);
+ paramDict.AddUInt32 (kLocalParameterIDStr, mParameterID);
+ paramDict.AddUInt32 (kMIDIFlagsStr, mFlags);
+ paramDict.AddFloat32 (kMIDISubMinStr, mSubRangeMin);
+ paramDict.AddFloat32 (kMIDISubMaxStr, mSubRangeMax);
+
+ UInt32 data = mStatus;
+ paramDict.AddUInt32 (kMIDIStatusStr, data);
+
+ data = mData1;
+ paramDict.AddUInt32 (kMIDIDataByteStr, data);
+
+ outData = paramDict.GetCFDictionary();
+}
+
+void CAAUMIDIMap::Restore(CFDictionaryRef inData)
+{
+ CACFDictionary paramDict (inData, false);
+
+ if (!paramDict.GetUInt32 (kLocalScopeStr, mScope)) return;
+ if (!paramDict.GetUInt32 (kLocalElementIDStr, mElement)) return;
+ if (!paramDict.GetUInt32 (kLocalParameterIDStr, mParameterID)) return;
+ if (!paramDict.GetUInt32 (kMIDIFlagsStr, mFlags)) return;
+ if (!paramDict.GetFloat32 (kMIDISubMinStr, mSubRangeMin)) return;
+ if (!paramDict.GetFloat32 (kMIDISubMaxStr, mSubRangeMax)) return;
+ UInt32 data;
+ if (!paramDict.GetUInt32 (kMIDIStatusStr, data)) return;
+ mStatus = data;
+ if (!paramDict.GetUInt32 (kMIDIDataByteStr, data)) return;
+ mData1 = data;
+}
+
+void CAAUMIDIMap::SaveAsMapPList (AudioUnit inUnit, const AUParameterMIDIMapping* inMappings, UInt32 inNumMappings, CFPropertyListRef &outData, CFStringRef inName)
+{
+
+ CACFDictionary mappingDict (false);
+ CACFArray maps (true);
+
+ for (UInt32 i = 0; i< inNumMappings; ++i)
+ {
+ CFPropertyListRef data;
+ CAAUMIDIMap paramMap(inMappings[i]);
+ paramMap.Save (data);
+ if (data)
+ {
+ maps.AppendCFType (data);
+ CFRelease(data);
+ }
+ }
+
+ if (maps.GetNumberItems()) {
+ mappingDict.AddCFType (kParamMIDIStr, maps.GetCFArray());
+
+ // Add the AU info here - where this map came from
+ CAAudioUnit au (inUnit);
+ CFPropertyListRef data;
+ au.Comp().Save (&data);
+
+ mappingDict.AddCFType (kAUStr, data);
+ CFRelease(data);
+
+ if (!inName) inName = CFSTR("Untitled");
+ mappingDict.AddString (CFSTR("name"), inName);
+
+ mappingDict.AddUInt32 (CFSTR("version"), 1);
+
+ outData = mappingDict.AsPropertyList();
+ } else {
+ mappingDict.ShouldRelease(true);
+ outData = NULL;
+ }
+}
+
+UInt32 CAAUMIDIMap::NumberOfMaps (const CFDictionaryRef inData)
+{
+ CACFDictionary dict (inData, false);
+
+ if (dict.HasKey (kParamMIDIStr))
+ {
+ CFArrayRef cfArray;
+ dict.GetArray (kParamMIDIStr, cfArray);
+
+ CACFArray array (cfArray, false);
+
+ return array.GetNumberItems();
+ }
+ return 0;
+}
+
+void CAAUMIDIMap::RestoreFromMapPList (const CFDictionaryRef inData, AUParameterMIDIMapping* outMappings, UInt32 inNumMappings)
+{
+
+ CACFDictionary dict (inData, false);
+
+ if (dict.HasKey (kParamMIDIStr))
+ {
+ CFArrayRef cfArray;
+ dict.GetArray (kParamMIDIStr, cfArray);
+
+ CACFArray array (cfArray, false);
+
+ UInt32 count = array.GetNumberItems();
+ if (count > inNumMappings)
+ count = inNumMappings;
+
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ CFDictionaryRef paramsDictRef;
+ if (!array.GetDictionary(i, paramsDictRef))
+ return;
+
+ CAAUMIDIMap parameterMap;
+ parameterMap.Restore(paramsDictRef);
+ outMappings[i] = parameterMap;
+ }
+ }
+}
+
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAProcess.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAProcess.cpp
new file mode 100644
index 0000000000..23ad2c0282
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAProcess.cpp
@@ -0,0 +1,92 @@
+/*
+ File: CAProcess.cpp
+ Abstract: CAProcess.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CAProcess.h"
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+
+//=============================================================================
+// CAProcess
+//=============================================================================
+
+bool CAProcess::ProcessExists(pid_t inPID)
+{
+ // pids <= 0 are reserved for special purposes and -1 is
+ // used as a sentinel value by the HAL.
+ bool theAnswer = inPID > 0;
+
+ if(theAnswer)
+ {
+ // according to kill(2), the process exists if kill(pid, 0) returns 0
+ int wasKilled = kill(inPID, 0);
+ if(wasKilled != 0)
+ {
+ // The kill call failed for some reason, but there is only one error code that
+ // that indicates that the process doesn't exist.
+ theAnswer = errno != ESRCH;
+ }
+ }
+
+
+ return theAnswer;
+}
+
+pid_t CAProcess::GetPID()
+{
+ if(sPID == -1)
+ {
+ sPID = getpid();
+ }
+
+ return sPID;
+}
+
+pid_t CAProcess::sPID = -1;
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAProcess.h b/libs/appleutility/CoreAudio/PublicUtility/CAProcess.h
new file mode 100644
index 0000000000..e512d911be
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAProcess.h
@@ -0,0 +1,75 @@
+/*
+ File: CAProcess.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAProcess_h__)
+#define __CAProcess_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include <sys/types.h>
+
+//=============================================================================
+// CAProcess
+//
+// Wrapper for utilities for dealing with Unix Processes.
+//=============================================================================
+
+class CAProcess
+{
+
+// operations
+public:
+ static bool ProcessExists(pid_t inPID);
+ static pid_t GetPID();
+
+private:
+ static pid_t sPID;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAPropertyAddress.h b/libs/appleutility/CoreAudio/PublicUtility/CAPropertyAddress.h
new file mode 100644
index 0000000000..6df444b0b4
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAPropertyAddress.h
@@ -0,0 +1,312 @@
+/*
+ File: CAPropertyAddress.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAPropertyAddress_h__)
+#define __CAPropertyAddress_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// PublicUtility Includes
+#include "CADebugMacros.h"
+
+// System Includes
+#include <CoreAudio/AudioHardware.h>
+
+// Standard Library Includes
+#include <algorithm>
+#include <functional>
+#include <vector>
+
+//==================================================================================================
+// CAPropertyAddress
+//
+// CAPropertyAddress extends the AudioObjectPropertyAddress structure to C++ including constructors
+// and other utility operations. Note that there is no defined operator< or operator== because the
+// presence of wildcards for the fields make comparisons ambiguous without specifying whether or
+// not to take the wildcards into account. Consequently, if you want to use this struct in an STL
+// data structure, you'll need to specify the approriate function object explicitly in the template
+// declaration.
+//==================================================================================================
+
+struct CAPropertyAddress
+:
+ public AudioObjectPropertyAddress
+{
+
+// Construction/Destruction
+public:
+ CAPropertyAddress() : AudioObjectPropertyAddress() { mSelector = 0; mScope = kAudioObjectPropertyScopeGlobal; mElement = kAudioObjectPropertyElementMaster; }
+ CAPropertyAddress(AudioObjectPropertySelector inSelector) : AudioObjectPropertyAddress() { mSelector = inSelector; mScope = kAudioObjectPropertyScopeGlobal; mElement = kAudioObjectPropertyElementMaster; }
+ CAPropertyAddress(AudioObjectPropertySelector inSelector, AudioObjectPropertyScope inScope) : AudioObjectPropertyAddress() { mSelector = inSelector; mScope = inScope; mElement = kAudioObjectPropertyElementMaster; }
+ CAPropertyAddress(AudioObjectPropertySelector inSelector, AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) : AudioObjectPropertyAddress() { mSelector = inSelector; mScope = inScope; mElement = inElement; }
+ CAPropertyAddress(const AudioObjectPropertyAddress& inAddress) : AudioObjectPropertyAddress(inAddress){}
+ CAPropertyAddress(const CAPropertyAddress& inAddress) : AudioObjectPropertyAddress(inAddress){}
+ CAPropertyAddress& operator=(const AudioObjectPropertyAddress& inAddress) { AudioObjectPropertyAddress::operator=(inAddress); return *this; }
+ CAPropertyAddress& operator=(const CAPropertyAddress& inAddress) { AudioObjectPropertyAddress::operator=(inAddress); return *this; }
+
+// Operations
+public:
+ static bool IsSameAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) { return (inAddress1.mScope == inAddress2.mScope) && (inAddress1.mSelector == inAddress2.mSelector) && (inAddress1.mElement == inAddress2.mElement); }
+ static bool IsLessThanAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) { bool theAnswer = false; if(inAddress1.mScope != inAddress2.mScope) { theAnswer = inAddress1.mScope < inAddress2.mScope; } else if(inAddress1.mSelector != inAddress2.mSelector) { theAnswer = inAddress1.mSelector < inAddress2.mSelector; } else { theAnswer = inAddress1.mElement < inAddress2.mElement; } return theAnswer; }
+ static bool IsCongruentSelector(AudioObjectPropertySelector inSelector1, AudioObjectPropertySelector inSelector2) { return (inSelector1 == inSelector2) || (inSelector1 == kAudioObjectPropertySelectorWildcard) || (inSelector2 == kAudioObjectPropertySelectorWildcard); }
+ static bool IsCongruentScope(AudioObjectPropertyScope inScope1, AudioObjectPropertyScope inScope2) { return (inScope1 == inScope2) || (inScope1 == kAudioObjectPropertyScopeWildcard) || (inScope2 == kAudioObjectPropertyScopeWildcard); }
+ static bool IsCongruentElement(AudioObjectPropertyElement inElement1, AudioObjectPropertyElement inElement2) { return (inElement1 == inElement2) || (inElement1 == kAudioObjectPropertyElementWildcard) || (inElement2 == kAudioObjectPropertyElementWildcard); }
+ static bool IsCongruentAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) { return IsCongruentScope(inAddress1.mScope, inAddress2.mScope) && IsCongruentSelector(inAddress1.mSelector, inAddress2.mSelector) && IsCongruentElement(inAddress1.mElement, inAddress2.mElement); }
+ static bool IsCongruentLessThanAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) { bool theAnswer = false; if(!IsCongruentScope(inAddress1.mScope, inAddress2.mScope)) { theAnswer = inAddress1.mScope < inAddress2.mScope; } else if(!IsCongruentSelector(inAddress1.mSelector, inAddress2.mSelector)) { theAnswer = inAddress1.mSelector < inAddress2.mSelector; } else if(!IsCongruentElement(inAddress1.mElement, inAddress2.mElement)) { theAnswer = inAddress1.mElement < inAddress2.mElement; } return theAnswer; }
+
+// STL Helpers
+public:
+ struct EqualTo : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
+ {
+ bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { return IsSameAddress(inAddress1, inAddress2); }
+ };
+
+ struct LessThan : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
+ {
+ bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { return IsLessThanAddress(inAddress1, inAddress2); }
+ };
+
+ struct CongruentEqualTo : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
+ {
+ bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { return IsCongruentAddress(inAddress1, inAddress2); }
+ };
+
+ struct CongruentLessThan : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
+ {
+ bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { return IsCongruentLessThanAddress(inAddress1, inAddress2); }
+ };
+
+};
+
+//==================================================================================================
+// CAPropertyAddressList
+//
+// An auto-resizing array of CAPropertyAddress structures.
+//==================================================================================================
+
+class CAPropertyAddressList
+{
+
+// Construction/Destruction
+public:
+ CAPropertyAddressList() : mAddressList(), mToken(NULL) {}
+ explicit CAPropertyAddressList(void* inToken) : mAddressList(), mToken(inToken) {}
+ explicit CAPropertyAddressList(uintptr_t inToken) : mAddressList(), mToken(reinterpret_cast<void*>(inToken)) {}
+ CAPropertyAddressList(const CAPropertyAddressList& inAddressList) : mAddressList(inAddressList.mAddressList), mToken(inAddressList.mToken) {}
+ CAPropertyAddressList& operator=(const CAPropertyAddressList& inAddressList) { mAddressList = inAddressList.mAddressList; mToken = inAddressList.mToken; return *this; }
+ ~CAPropertyAddressList() {}
+
+// Operations
+public:
+ void* GetToken() const { return mToken; }
+ void SetToken(void* inToken) { mToken = inToken; }
+
+ uintptr_t GetIntToken() const { return reinterpret_cast<uintptr_t>(mToken); }
+ void SetIntToken(uintptr_t inToken) { mToken = reinterpret_cast<void*>(inToken); }
+
+ AudioObjectID GetAudioObjectIDToken() const { return static_cast<AudioObjectID>(reinterpret_cast<uintptr_t>(mToken)); }
+
+ bool IsEmpty() const { return mAddressList.empty(); }
+ UInt32 GetNumberItems() const { return ToUInt32(mAddressList.size()); }
+ void GetItemByIndex(UInt32 inIndex, AudioObjectPropertyAddress& outAddress) const { if(inIndex < mAddressList.size()) { outAddress = mAddressList.at(inIndex); } }
+ const AudioObjectPropertyAddress* GetItems() const { return &(*mAddressList.begin()); }
+ AudioObjectPropertyAddress* GetItems() { return &(*mAddressList.begin()); }
+
+ bool HasItem(const AudioObjectPropertyAddress& inAddress) const { AddressList::const_iterator theIterator = std::find_if(mAddressList.begin(), mAddressList.end(), std::bind1st(CAPropertyAddress::CongruentEqualTo(), inAddress)); return theIterator != mAddressList.end(); }
+ bool HasExactItem(const AudioObjectPropertyAddress& inAddress) const { AddressList::const_iterator theIterator = std::find_if(mAddressList.begin(), mAddressList.end(), std::bind1st(CAPropertyAddress::EqualTo(), inAddress)); return theIterator != mAddressList.end(); }
+
+ void AppendItem(const AudioObjectPropertyAddress& inAddress) { mAddressList.push_back(inAddress); }
+ void AppendUniqueItem(const AudioObjectPropertyAddress& inAddress) { if(!HasItem(inAddress)) { mAddressList.push_back(inAddress); } }
+ void AppendUniqueExactItem(const AudioObjectPropertyAddress& inAddress) { if(!HasExactItem(inAddress)) { mAddressList.push_back(inAddress); } }
+ void InsertItemAtIndex(UInt32 inIndex, const AudioObjectPropertyAddress& inAddress) { if(inIndex < mAddressList.size()) { AddressList::iterator theIterator = mAddressList.begin(); std::advance(theIterator, static_cast<int>(inIndex)); mAddressList.insert(theIterator, inAddress); } else { mAddressList.push_back(inAddress); } }
+ void EraseExactItem(const AudioObjectPropertyAddress& inAddress) { AddressList::iterator theIterator = std::find_if(mAddressList.begin(), mAddressList.end(), std::bind1st(CAPropertyAddress::EqualTo(), inAddress)); if(theIterator != mAddressList.end()) { mAddressList.erase(theIterator); } }
+ void EraseItemAtIndex(UInt32 inIndex) { if(inIndex < mAddressList.size()) { AddressList::iterator theIterator = mAddressList.begin(); std::advance(theIterator, static_cast<int>(inIndex)); mAddressList.erase(theIterator); } }
+ void EraseAllItems() { mAddressList.clear(); }
+
+// Implementation
+private:
+ typedef std::vector<CAPropertyAddress> AddressList;
+
+ AddressList mAddressList;
+ void* mToken;
+
+};
+
+//==================================================================================================
+// CAPropertyAddressListVector
+//
+// An auto-resizing array of CAPropertyAddressList objects.
+//==================================================================================================
+
+class CAPropertyAddressListVector
+{
+
+// Construction/Destruction
+public:
+ CAPropertyAddressListVector() : mAddressListVector() {}
+ CAPropertyAddressListVector(const CAPropertyAddressListVector& inAddressListVector) : mAddressListVector(inAddressListVector.mAddressListVector) {}
+ CAPropertyAddressListVector& operator=(const CAPropertyAddressListVector& inAddressListVector) { mAddressListVector = inAddressListVector.mAddressListVector; return *this; }
+ ~CAPropertyAddressListVector() {}
+
+// Operations
+public:
+ bool IsEmpty() const { return mAddressListVector.empty(); }
+ bool HasAnyNonEmptyItems() const;
+ bool HasAnyItemsWithAddress(const AudioObjectPropertyAddress& inAddress) const;
+ bool HasAnyItemsWithExactAddress(const AudioObjectPropertyAddress& inAddress) const;
+
+ UInt32 GetNumberItems() const { return ToUInt32(mAddressListVector.size()); }
+ const CAPropertyAddressList& GetItemByIndex(UInt32 inIndex) const { return mAddressListVector.at(inIndex); }
+ CAPropertyAddressList& GetItemByIndex(UInt32 inIndex) { return mAddressListVector.at(inIndex); }
+ const CAPropertyAddressList* GetItemByToken(void* inToken) const;
+ CAPropertyAddressList* GetItemByToken(void* inToken);
+ const CAPropertyAddressList* GetItemByIntToken(uintptr_t inToken) const;
+ CAPropertyAddressList* GetItemByIntToken(uintptr_t inToken);
+
+ void AppendItem(const CAPropertyAddressList& inAddressList) { mAddressListVector.push_back(inAddressList); }
+ void EraseAllItems() { mAddressListVector.clear(); }
+
+// Implementation
+private:
+ typedef std::vector<CAPropertyAddressList> AddressListVector;
+
+ AddressListVector mAddressListVector;
+
+};
+
+inline bool CAPropertyAddressListVector::HasAnyNonEmptyItems() const
+{
+ bool theAnswer = false;
+ for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !theAnswer && (theIterator != mAddressListVector.end()); ++theIterator)
+ {
+ theAnswer = !theIterator->IsEmpty();
+ }
+ return theAnswer;
+}
+
+inline bool CAPropertyAddressListVector::HasAnyItemsWithAddress(const AudioObjectPropertyAddress& inAddress) const
+{
+ bool theAnswer = false;
+ for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !theAnswer && (theIterator != mAddressListVector.end()); ++theIterator)
+ {
+ theAnswer = theIterator->HasItem(inAddress);
+ }
+ return theAnswer;
+}
+
+inline bool CAPropertyAddressListVector::HasAnyItemsWithExactAddress(const AudioObjectPropertyAddress& inAddress) const
+{
+ bool theAnswer = false;
+ for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !theAnswer && (theIterator != mAddressListVector.end()); ++theIterator)
+ {
+ theAnswer = theIterator->HasExactItem(inAddress);
+ }
+ return theAnswer;
+}
+
+inline const CAPropertyAddressList* CAPropertyAddressListVector::GetItemByToken(void* inToken) const
+{
+ const CAPropertyAddressList* theAnswer = NULL;
+ bool wasFound = false;
+ for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator)
+ {
+ if(theIterator->GetToken() == inToken)
+ {
+ wasFound = true;
+ theAnswer = &(*theIterator);
+ }
+ }
+ return theAnswer;
+}
+
+inline CAPropertyAddressList* CAPropertyAddressListVector::GetItemByToken(void* inToken)
+{
+ CAPropertyAddressList* theAnswer = NULL;
+ bool wasFound = false;
+ for(AddressListVector::iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator)
+ {
+ if(theIterator->GetToken() == inToken)
+ {
+ wasFound = true;
+ theAnswer = &(*theIterator);
+ }
+ }
+ return theAnswer;
+}
+
+inline const CAPropertyAddressList* CAPropertyAddressListVector::GetItemByIntToken(uintptr_t inToken) const
+{
+ const CAPropertyAddressList* theAnswer = NULL;
+ bool wasFound = false;
+ for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator)
+ {
+ if(theIterator->GetIntToken() == inToken)
+ {
+ wasFound = true;
+ theAnswer = &(*theIterator);
+ }
+ }
+ return theAnswer;
+}
+
+inline CAPropertyAddressList* CAPropertyAddressListVector::GetItemByIntToken(uintptr_t inToken)
+{
+ CAPropertyAddressList* theAnswer = NULL;
+ bool wasFound = false;
+ for(AddressListVector::iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator)
+ {
+ if(theIterator->GetIntToken() == inToken)
+ {
+ wasFound = true;
+ theAnswer = &(*theIterator);
+ }
+ }
+ return theAnswer;
+}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAReferenceCounted.h b/libs/appleutility/CoreAudio/PublicUtility/CAReferenceCounted.h
new file mode 100644
index 0000000000..f00fc61675
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAReferenceCounted.h
@@ -0,0 +1,97 @@
+/*
+ File: CAReferenceCounted.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAReferenceCounted_h__
+#define __CAReferenceCounted_h__
+
+#include "CAAtomic.h"
+
+// base class for reference-counted objects
+class CAReferenceCounted {
+public:
+ CAReferenceCounted() : mRefCount(1) {}
+
+ void retain() { CAAtomicIncrement32(&mRefCount); }
+
+ void release()
+ {
+ SInt32 rc = CAAtomicDecrement32(&mRefCount);
+ if (rc == 0) {
+ releaseObject();
+ }
+ }
+
+
+ class Retainer {
+ public:
+ Retainer(CAReferenceCounted *obj) : mObject(obj) { mObject->retain(); }
+ ~Retainer() { mObject->release(); }
+
+ private:
+ CAReferenceCounted * mObject;
+ };
+
+protected:
+ virtual ~CAReferenceCounted() { }
+
+ virtual void releaseObject ()
+ {
+ delete this;
+ }
+
+#if DEBUG
+public:
+#endif
+ SInt32 GetReferenceCount() const { return mRefCount; }
+private:
+ SInt32 mRefCount;
+
+ CAReferenceCounted(const CAReferenceCounted &a);
+ CAReferenceCounted &operator=(const CAReferenceCounted &a);
+};
+
+
+#endif // __CAReferenceCounted_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.cpp b/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.cpp
new file mode 100644
index 0000000000..c78acd2c2d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.cpp
@@ -0,0 +1,319 @@
+/*
+ File: CARingBuffer.cpp
+ Abstract: CARingBuffer.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CARingBuffer.h"
+#include "CABitOperations.h"
+#include "CAAutoDisposer.h"
+#include "CAAtomic.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <libkern/OSAtomic.h>
+
+CARingBuffer::CARingBuffer() :
+ mBuffers(NULL), mNumberChannels(0), mCapacityFrames(0), mCapacityBytes(0)
+{
+
+}
+
+CARingBuffer::~CARingBuffer()
+{
+ Deallocate();
+}
+
+
+void CARingBuffer::Allocate(int nChannels, UInt32 bytesPerFrame, UInt32 capacityFrames)
+{
+ Deallocate();
+
+ capacityFrames = NextPowerOfTwo(capacityFrames);
+
+ mNumberChannels = nChannels;
+ mBytesPerFrame = bytesPerFrame;
+ mCapacityFrames = capacityFrames;
+ mCapacityFramesMask = capacityFrames - 1;
+ mCapacityBytes = bytesPerFrame * capacityFrames;
+
+ // put everything in one memory allocation, first the pointers, then the deinterleaved channels
+ UInt32 allocSize = (mCapacityBytes + sizeof(Byte *)) * nChannels;
+ Byte *p = (Byte *)CA_malloc(allocSize);
+ memset(p, 0, allocSize);
+ mBuffers = (Byte **)p;
+ p += nChannels * sizeof(Byte *);
+ for (int i = 0; i < nChannels; ++i) {
+ mBuffers[i] = p;
+ p += mCapacityBytes;
+ }
+
+ for (UInt32 i = 0; i<kGeneralRingTimeBoundsQueueSize; ++i)
+ {
+ mTimeBoundsQueue[i].mStartTime = 0;
+ mTimeBoundsQueue[i].mEndTime = 0;
+ mTimeBoundsQueue[i].mUpdateCounter = 0;
+ }
+ mTimeBoundsQueuePtr = 0;
+}
+
+void CARingBuffer::Deallocate()
+{
+ if (mBuffers) {
+ free(mBuffers);
+ mBuffers = NULL;
+ }
+ mNumberChannels = 0;
+ mCapacityBytes = 0;
+ mCapacityFrames = 0;
+}
+
+inline void ZeroRange(Byte **buffers, int nchannels, int offset, int nbytes)
+{
+ while (--nchannels >= 0) {
+ memset(*buffers + offset, 0, nbytes);
+ ++buffers;
+ }
+}
+
+inline void StoreABL(Byte **buffers, int destOffset, const AudioBufferList *abl, int srcOffset, int nbytes)
+{
+ int nchannels = abl->mNumberBuffers;
+ const AudioBuffer *src = abl->mBuffers;
+ while (--nchannels >= 0) {
+ if (srcOffset > (int)src->mDataByteSize) continue;
+ memcpy(*buffers + destOffset, (Byte *)src->mData + srcOffset, std::min(nbytes, (int)src->mDataByteSize - srcOffset));
+ ++buffers;
+ ++src;
+ }
+}
+
+inline void FetchABL(AudioBufferList *abl, int destOffset, Byte **buffers, int srcOffset, int nbytes)
+{
+ int nchannels = abl->mNumberBuffers;
+ AudioBuffer *dest = abl->mBuffers;
+ while (--nchannels >= 0) {
+ if (destOffset > (int)dest->mDataByteSize) continue;
+ memcpy((Byte *)dest->mData + destOffset, *buffers + srcOffset, std::min(nbytes, (int)dest->mDataByteSize - destOffset));
+ ++buffers;
+ ++dest;
+ }
+}
+
+inline void ZeroABL(AudioBufferList *abl, int destOffset, int nbytes)
+{
+ int nBuffers = abl->mNumberBuffers;
+ AudioBuffer *dest = abl->mBuffers;
+ while (--nBuffers >= 0) {
+ if (destOffset > (int)dest->mDataByteSize) continue;
+ memset((Byte *)dest->mData + destOffset, 0, std::min(nbytes, (int)dest->mDataByteSize - destOffset));
+ ++dest;
+ }
+}
+
+
+CARingBufferError CARingBuffer::Store(const AudioBufferList *abl, UInt32 framesToWrite, SampleTime startWrite)
+{
+ if (framesToWrite == 0)
+ return kCARingBufferError_OK;
+
+ if (framesToWrite > mCapacityFrames)
+ return kCARingBufferError_TooMuch; // too big!
+
+ SampleTime endWrite = startWrite + framesToWrite;
+
+ if (startWrite < EndTime()) {
+ // going backwards, throw everything out
+ SetTimeBounds(startWrite, startWrite);
+ } else if (endWrite - StartTime() <= mCapacityFrames) {
+ // the buffer has not yet wrapped and will not need to
+ } else {
+ // advance the start time past the region we are about to overwrite
+ SampleTime newStart = endWrite - mCapacityFrames; // one buffer of time behind where we're writing
+ SampleTime newEnd = std::max(newStart, EndTime());
+ SetTimeBounds(newStart, newEnd);
+ }
+
+ // write the new frames
+ Byte **buffers = mBuffers;
+ int nchannels = mNumberChannels;
+ int offset0, offset1, nbytes;
+ SampleTime curEnd = EndTime();
+
+ if (startWrite > curEnd) {
+ // we are skipping some samples, so zero the range we are skipping
+ offset0 = FrameOffset(curEnd);
+ offset1 = FrameOffset(startWrite);
+ if (offset0 < offset1)
+ ZeroRange(buffers, nchannels, offset0, offset1 - offset0);
+ else {
+ ZeroRange(buffers, nchannels, offset0, mCapacityBytes - offset0);
+ ZeroRange(buffers, nchannels, 0, offset1);
+ }
+ offset0 = offset1;
+ } else {
+ offset0 = FrameOffset(startWrite);
+ }
+
+ offset1 = FrameOffset(endWrite);
+ if (offset0 < offset1)
+ StoreABL(buffers, offset0, abl, 0, offset1 - offset0);
+ else {
+ nbytes = mCapacityBytes - offset0;
+ StoreABL(buffers, offset0, abl, 0, nbytes);
+ StoreABL(buffers, 0, abl, nbytes, offset1);
+ }
+
+ // now update the end time
+ SetTimeBounds(StartTime(), endWrite);
+
+ return kCARingBufferError_OK; // success
+}
+
+void CARingBuffer::SetTimeBounds(SampleTime startTime, SampleTime endTime)
+{
+ UInt32 nextPtr = mTimeBoundsQueuePtr + 1;
+ UInt32 index = nextPtr & kGeneralRingTimeBoundsQueueMask;
+
+ mTimeBoundsQueue[index].mStartTime = startTime;
+ mTimeBoundsQueue[index].mEndTime = endTime;
+ mTimeBoundsQueue[index].mUpdateCounter = nextPtr;
+ CAAtomicCompareAndSwap32Barrier(mTimeBoundsQueuePtr, mTimeBoundsQueuePtr + 1, (SInt32*)&mTimeBoundsQueuePtr);
+}
+
+CARingBufferError CARingBuffer::GetTimeBounds(SampleTime &startTime, SampleTime &endTime)
+{
+ for (int i=0; i<8; ++i) // fail after a few tries.
+ {
+ UInt32 curPtr = mTimeBoundsQueuePtr;
+ UInt32 index = curPtr & kGeneralRingTimeBoundsQueueMask;
+ CARingBuffer::TimeBounds* bounds = mTimeBoundsQueue + index;
+
+ startTime = bounds->mStartTime;
+ endTime = bounds->mEndTime;
+ UInt32 newPtr = bounds->mUpdateCounter;
+
+ if (newPtr == curPtr)
+ return kCARingBufferError_OK;
+ }
+ return kCARingBufferError_CPUOverload;
+}
+
+CARingBufferError CARingBuffer::ClipTimeBounds(SampleTime& startRead, SampleTime& endRead)
+{
+ SampleTime startTime, endTime;
+
+ CARingBufferError err = GetTimeBounds(startTime, endTime);
+ if (err) return err;
+
+ if (startRead > endTime || endRead < startTime) {
+ endRead = startRead;
+ return kCARingBufferError_OK;
+ }
+
+ startRead = std::max(startRead, startTime);
+ endRead = std::min(endRead, endTime);
+ endRead = std::max(endRead, startRead);
+
+ return kCARingBufferError_OK; // success
+}
+
+CARingBufferError CARingBuffer::Fetch(AudioBufferList *abl, UInt32 nFrames, SampleTime startRead)
+{
+ if (nFrames == 0)
+ return kCARingBufferError_OK;
+
+ startRead = std::max(0LL, startRead);
+
+ SampleTime endRead = startRead + nFrames;
+
+ SampleTime startRead0 = startRead;
+ SampleTime endRead0 = endRead;
+
+ CARingBufferError err = ClipTimeBounds(startRead, endRead);
+ if (err) return err;
+
+ if (startRead == endRead) {
+ ZeroABL(abl, 0, nFrames * mBytesPerFrame);
+ return kCARingBufferError_OK;
+ }
+
+ SInt32 byteSize = (SInt32)((endRead - startRead) * mBytesPerFrame);
+
+ SInt32 destStartByteOffset = std::max((SInt32)0, (SInt32)((startRead - startRead0) * mBytesPerFrame));
+
+ if (destStartByteOffset > 0) {
+ ZeroABL(abl, 0, std::min((SInt32)(nFrames * mBytesPerFrame), destStartByteOffset));
+ }
+
+ SInt32 destEndSize = std::max((SInt32)0, (SInt32)(endRead0 - endRead));
+ if (destEndSize > 0) {
+ ZeroABL(abl, destStartByteOffset + byteSize, destEndSize * mBytesPerFrame);
+ }
+
+ Byte **buffers = mBuffers;
+ int offset0 = FrameOffset(startRead);
+ int offset1 = FrameOffset(endRead);
+ int nbytes;
+
+ if (offset0 < offset1) {
+ nbytes = offset1 - offset0;
+ FetchABL(abl, destStartByteOffset, buffers, offset0, nbytes);
+ } else {
+ nbytes = mCapacityBytes - offset0;
+ FetchABL(abl, destStartByteOffset, buffers, offset0, nbytes);
+ FetchABL(abl, destStartByteOffset + nbytes, buffers, 0, offset1);
+ nbytes += offset1;
+ }
+
+ int nchannels = abl->mNumberBuffers;
+ AudioBuffer *dest = abl->mBuffers;
+ while (--nchannels >= 0)
+ {
+ dest->mDataByteSize = nbytes;
+ dest++;
+ }
+
+ return noErr;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.h b/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.h
new file mode 100644
index 0000000000..9569e9a2a8
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.h
@@ -0,0 +1,126 @@
+/*
+ File: CARingBuffer.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+
+#ifndef CARingBuffer_Header
+#define CARingBuffer_Header
+
+enum {
+ kCARingBufferError_OK = 0,
+ kCARingBufferError_TooMuch = 3, // fetch start time is earlier than buffer start time and fetch end time is later than buffer end time
+ kCARingBufferError_CPUOverload = 4 // the reader is unable to get enough CPU cycles to capture a consistent snapshot of the time bounds
+};
+
+typedef SInt32 CARingBufferError;
+
+const UInt32 kGeneralRingTimeBoundsQueueSize = 32;
+const UInt32 kGeneralRingTimeBoundsQueueMask = kGeneralRingTimeBoundsQueueSize - 1;
+
+class CARingBuffer {
+public:
+ typedef SInt64 SampleTime;
+
+ CARingBuffer();
+ ~CARingBuffer();
+
+ void Allocate(int nChannels, UInt32 bytesPerFrame, UInt32 capacityFrames);
+ // capacityFrames will be rounded up to a power of 2
+ void Deallocate();
+
+ CARingBufferError Store(const AudioBufferList *abl, UInt32 nFrames, SampleTime frameNumber);
+ // Copy nFrames of data into the ring buffer at the specified sample time.
+ // The sample time should normally increase sequentially, though gaps
+ // are filled with zeroes. A sufficiently large gap effectively empties
+ // the buffer before storing the new data.
+
+ // If frameNumber is less than the previous frame number, the behavior is undefined.
+
+ // Return false for failure (buffer not large enough).
+
+ CARingBufferError Fetch(AudioBufferList *abl, UInt32 nFrames, SampleTime frameNumber);
+ // will alter mNumDataBytes of the buffers
+
+ CARingBufferError GetTimeBounds(SampleTime &startTime, SampleTime &endTime);
+
+protected:
+
+ int FrameOffset(SampleTime frameNumber) { return (frameNumber & mCapacityFramesMask) * mBytesPerFrame; }
+
+ CARingBufferError ClipTimeBounds(SampleTime& startRead, SampleTime& endRead);
+
+ // these should only be called from Store.
+ SampleTime StartTime() const { return mTimeBoundsQueue[mTimeBoundsQueuePtr & kGeneralRingTimeBoundsQueueMask].mStartTime; }
+ SampleTime EndTime() const { return mTimeBoundsQueue[mTimeBoundsQueuePtr & kGeneralRingTimeBoundsQueueMask].mEndTime; }
+ void SetTimeBounds(SampleTime startTime, SampleTime endTime);
+
+protected:
+ Byte ** mBuffers; // allocated in one chunk of memory
+ int mNumberChannels;
+ UInt32 mBytesPerFrame; // within one deinterleaved channel
+ UInt32 mCapacityFrames; // per channel, must be a power of 2
+ UInt32 mCapacityFramesMask;
+ UInt32 mCapacityBytes; // per channel
+
+ // range of valid sample time in the buffer
+ typedef struct {
+ volatile SampleTime mStartTime;
+ volatile SampleTime mEndTime;
+ volatile UInt32 mUpdateCounter;
+ } TimeBounds;
+
+ CARingBuffer::TimeBounds mTimeBoundsQueue[kGeneralRingTimeBoundsQueueSize];
+ UInt32 mTimeBoundsQueuePtr;
+};
+
+
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.cpp b/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.cpp
new file mode 100644
index 0000000000..69bdffcb72
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.cpp
@@ -0,0 +1,737 @@
+/*
+ File: CASettingsStorage.cpp
+ Abstract: CASettingsStorage.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CASettingsStorage.h"
+
+// PublicUtility Includes
+#include "CAAutoDisposer.h"
+#include "CACFArray.h"
+#include "CACFData.h"
+#include "CACFDictionary.h"
+#include "CACFDistributedNotification.h"
+#include "CACFNumber.h"
+
+// Stamdard Library Includes
+#include <string.h>
+#include <sys/fcntl.h>
+
+//==================================================================================================
+// CASettingsStorage
+//==================================================================================================
+
+CASettingsStorage::CASettingsStorage(const char* inSettingsFilePath, mode_t inSettingsFileAccessMode, CFPropertyListFormat inSettingsCacheFormat, bool inIsSingleProcessOnly, bool inIsReadOnly)
+:
+ mSettingsFilePath(NULL),
+ mSettingsFileAccessMode(inSettingsFileAccessMode),
+ mSettingsCache(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)),
+ mSettingsCacheFormat(inSettingsCacheFormat),
+ mSettingsCacheTime(),
+ mSettingsCacheForceRefresh(true),
+ mIsSingleProcessOnly(inIsSingleProcessOnly),
+ mIsReadOnly(inIsReadOnly)
+{
+ size_t theLength = strlen(inSettingsFilePath);
+ mSettingsFilePath = new char[theLength + 2];
+ strlcpy(mSettingsFilePath, inSettingsFilePath, theLength + 2);
+
+ mSettingsCacheTime.tv_sec = 0;
+ mSettingsCacheTime.tv_nsec = 0;
+
+ mSettingsCacheForceRefresh = true;
+}
+
+CASettingsStorage::~CASettingsStorage()
+{
+ delete[] mSettingsFilePath;
+
+ if(mSettingsCache != NULL)
+ {
+ CFRelease(mSettingsCache);
+ }
+}
+
+UInt32 CASettingsStorage::GetNumberKeys() const
+{
+ // make sure our cache is up to date
+ const_cast<CASettingsStorage*>(this)->RefreshSettings();
+
+ return ToUInt32(CFDictionaryGetCount(mSettingsCache));
+}
+
+void CASettingsStorage::GetKeys(UInt32 inNumberKeys, UInt32& outNumberKeys, CFStringRef* outKeys) const
+{
+ // make sure our cache is up to date
+ const_cast<CASettingsStorage*>(this)->RefreshSettings();
+
+ CFDictionaryGetKeysAndValues(mSettingsCache, reinterpret_cast<const void**>(outKeys), NULL);
+ outNumberKeys = inNumberKeys;
+}
+
+void CASettingsStorage::CopyBoolValue(CFStringRef inKey, bool& outValue, bool inDefaultValue) const
+{
+ // initialize the return value
+ outValue = inDefaultValue;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, NULL);
+
+ // for this type, NULL is an invalid value
+ if(theValue != NULL)
+ {
+ // bools can be made from either CFBooleans or CFNumbers
+ if(CFGetTypeID(theValue) == CFBooleanGetTypeID())
+ {
+ // get the return value from the CF object
+ outValue = CFBooleanGetValue(static_cast<CFBooleanRef>(theValue));
+ }
+ else if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // get the numeric value
+ SInt32 theNumericValue = 0;
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue);
+
+ // non-zero indicates true
+ outValue = theNumericValue != 0;
+ }
+
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+ }
+}
+
+void CASettingsStorage::CopySInt32Value(CFStringRef inKey, SInt32& outValue, SInt32 inDefaultValue) const
+{
+ // initialize the return value
+ outValue = inDefaultValue;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, NULL);
+
+ // for this type, NULL is an invalid value
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // get the return value from the CF object
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+ }
+
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+ }
+}
+
+void CASettingsStorage::CopyUInt32Value(CFStringRef inKey, UInt32& outValue, UInt32 inDefaultValue) const
+{
+ // initialize the return value
+ outValue = inDefaultValue;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, NULL);
+
+ // for this type, NULL is an invalid value
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // get the return value from the CF object
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+ }
+
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+ }
+}
+
+void CASettingsStorage::CopySInt64Value(CFStringRef inKey, SInt64& outValue, SInt64 inDefaultValue) const
+{
+ // initialize the return value
+ outValue = inDefaultValue;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, NULL);
+
+ // for this type, NULL is an invalid value
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // get the return value from the CF object
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
+ }
+
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+ }
+}
+
+void CASettingsStorage::CopyUInt64Value(CFStringRef inKey, UInt64& outValue, UInt64 inDefaultValue) const
+{
+ // initialize the return value
+ outValue = inDefaultValue;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, NULL);
+
+ // for this type, NULL is an invalid value
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // get the return value from the CF object
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
+ }
+
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+ }
+}
+
+void CASettingsStorage::CopyFloat32Value(CFStringRef inKey, Float32& outValue, Float32 inDefaultValue) const
+{
+ // initialize the return value
+ outValue = inDefaultValue;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, NULL);
+
+ // for this type, NULL is an invalid value
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // get the return value from the CF object
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat32Type, &outValue);
+ }
+
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+ }
+}
+
+void CASettingsStorage::CopyFloat64Value(CFStringRef inKey, Float64& outValue, Float64 inDefaultValue) const
+{
+ // initialize the return value
+ outValue = inDefaultValue;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, NULL);
+
+ // for this type, NULL is an invalid value
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // get the return value from the CF object
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat64Type, &outValue);
+ }
+
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+ }
+}
+
+void CASettingsStorage::CopyNumberValue(CFStringRef inKey, CFNumberRef& outValue, CFNumberRef inDefaultValue) const
+{
+ // initialize the return value
+ outValue = NULL;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, inDefaultValue);
+
+ // for this type, NULL is a valid value, but requires less work
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // set the return value to the CF object we are returning
+ outValue = static_cast<CFNumberRef>(theValue);
+ }
+ else
+ {
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+
+ // set the return value to the default value
+ outValue = inDefaultValue;
+
+ // and retain it
+ CFRetain(outValue);
+ }
+ }
+}
+
+void CASettingsStorage::CopyStringValue(CFStringRef inKey, CFStringRef& outValue, CFStringRef inDefaultValue) const
+{
+ // initialize the return value
+ outValue = NULL;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, inDefaultValue);
+
+ // for this type, NULL is a valid value, but requires less work
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFStringGetTypeID())
+ {
+ // set the return value to the CF object we are returning
+ outValue = static_cast<CFStringRef>(theValue);
+ }
+ else
+ {
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+
+ // set the return value to the default value
+ outValue = inDefaultValue;
+
+ // and retain it
+ CFRetain(outValue);
+ }
+ }
+}
+
+void CASettingsStorage::CopyArrayValue(CFStringRef inKey, CFArrayRef& outValue, CFArrayRef inDefaultValue) const
+{
+ // initialize the return value
+ outValue = NULL;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, inDefaultValue);
+
+ // for this type, NULL is a valid value, but requires less work
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFArrayGetTypeID())
+ {
+ // set the return value to the CF object we are returning
+ outValue = static_cast<CFArrayRef>(theValue);
+ }
+ else
+ {
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+
+ // set the return value to the default value
+ outValue = inDefaultValue;
+
+ // and retain it
+ CFRetain(outValue);
+ }
+ }
+}
+
+void CASettingsStorage::CopyDictionaryValue(CFStringRef inKey, CFDictionaryRef& outValue, CFDictionaryRef inDefaultValue) const
+{
+ // initialize the return value
+ outValue = NULL;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, inDefaultValue);
+
+ // for this type, NULL is a valid value, but requires less work
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFDictionaryGetTypeID())
+ {
+ // set the return value to the CF object we are returning
+ outValue = static_cast<CFDictionaryRef>(theValue);
+ }
+ else
+ {
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+
+ // set the return value to the default value
+ outValue = inDefaultValue;
+
+ // and retain it
+ CFRetain(outValue);
+ }
+ }
+}
+
+void CASettingsStorage::CopyDataValue(CFStringRef inKey, CFDataRef& outValue, CFDataRef inDefaultValue) const
+{
+ // initialize the return value
+ outValue = NULL;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, inDefaultValue);
+
+ // for this type, NULL is a valid value, but requires less work
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFDataGetTypeID())
+ {
+ // set the return value to the CF object we are returning
+ outValue = static_cast<CFDataRef>(theValue);
+ }
+ else
+ {
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+
+ // set the return value to the default value
+ outValue = inDefaultValue;
+
+ // and retain it
+ CFRetain(outValue);
+ }
+ }
+}
+
+void CASettingsStorage::CopyCFTypeValue(CFStringRef inKey, CFTypeRef& outValue, CFTypeRef inDefaultValue) const
+{
+ // make sure our cache is up to date
+ const_cast<CASettingsStorage*>(this)->RefreshSettings();
+
+ // check to see if we have a value for the given key
+ if(!CFDictionaryGetValueIfPresent(mSettingsCache, inKey, &outValue))
+ {
+ // the key wasn't in the cache, so return the default value
+ outValue = inDefaultValue;
+ }
+
+ // make sure we retain the return value
+ if(outValue != NULL)
+ {
+ CFRetain(outValue);
+ }
+}
+
+void CASettingsStorage::SetSInt32Value(CFStringRef inKey, SInt32 inValue)
+{
+ CACFNumber theValue(inValue);
+ SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void CASettingsStorage::SetUInt32Value(CFStringRef inKey, UInt32 inValue)
+{
+ CACFNumber theValue(inValue);
+ SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void CASettingsStorage::SetSInt64Value(CFStringRef inKey, SInt64 inValue)
+{
+ CACFNumber theValue(inValue);
+ SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void CASettingsStorage::SetUInt64Value(CFStringRef inKey, UInt64 inValue)
+{
+ CACFNumber theValue(inValue);
+ SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void CASettingsStorage::SetFloat32Value(CFStringRef inKey, Float32 inValue)
+{
+ CACFNumber theValue(inValue);
+ SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void CASettingsStorage::SetFloat64Value(CFStringRef inKey, Float64 inValue)
+{
+ CACFNumber theValue(inValue);
+ SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void CASettingsStorage::SetNumberValue(CFStringRef inKey, CFNumberRef inValue)
+{
+ SetCFTypeValue(inKey, inValue);
+}
+
+void CASettingsStorage::SetStringValue(CFStringRef inKey, CFStringRef inValue)
+{
+ SetCFTypeValue(inKey, inValue);
+}
+
+void CASettingsStorage::SetArrayValue(CFStringRef inKey, CFArrayRef inValue)
+{
+ SetCFTypeValue(inKey, inValue);
+}
+
+void CASettingsStorage::SetDictionaryValue(CFStringRef inKey, CFDictionaryRef inValue)
+{
+ SetCFTypeValue(inKey, inValue);
+}
+
+void CASettingsStorage::SetDataValue(CFStringRef inKey, CFDataRef inValue)
+{
+ SetCFTypeValue(inKey, inValue);
+}
+
+void CASettingsStorage::SetCFTypeValue(CFStringRef inKey, CFTypeRef inValue)
+{
+ // make sure our cache is up to date
+ RefreshSettings();
+
+ // add the new key/value to the dictionary
+ CFDictionarySetValue(mSettingsCache, inKey, inValue);
+
+ // write the settings to the file
+ SaveSettings();
+}
+
+void CASettingsStorage::RemoveValue(CFStringRef inKey)
+{
+ // make sure our cache is up to date
+ RefreshSettings();
+
+ // remove the given key
+ CFDictionaryRemoveValue(mSettingsCache, inKey);
+
+ // write the settings to the file
+ SaveSettings();
+}
+
+void CASettingsStorage::RemoveAllValues()
+{
+ // make sure our cache is up to date
+ RefreshSettings();
+
+ // remove the given key
+ CFDictionaryRemoveAllValues(mSettingsCache);
+
+ // write the settings to the file
+ SaveSettings();
+}
+
+void CASettingsStorage::SendNotification(CFStringRef inName, CFDictionaryRef inData, bool inPostToAllSessions) const
+{
+ CACFDistributedNotification::PostNotification(inName, inData, inPostToAllSessions);
+}
+
+void CASettingsStorage::ForceRefresh()
+{
+ mSettingsCacheForceRefresh = true;
+}
+
+inline bool operator<(const struct timespec& inX, const struct timespec& inY)
+{
+ return ((inX.tv_sec < inY.tv_sec) || ((inX.tv_sec == inY.tv_sec) && (inX.tv_nsec < inY.tv_nsec)));
+}
+
+void CASettingsStorage::RefreshSettings()
+{
+ // if this storage is only supporting a single process, there is no need to hit the disk unless
+ // required to by it being the first time or if the refresh is specifically forced for some reason
+ if(!mIsSingleProcessOnly || (mSettingsCache == NULL) || ((mSettingsCacheTime.tv_sec == 0) && (mSettingsCacheTime.tv_nsec == 0)) || mSettingsCacheForceRefresh)
+ {
+ // first, we need to stat the file to check the mod date, this has the side effect of also
+ // telling us if the file exisits
+ struct stat theFileInfo;
+ int theStatError = stat(mSettingsFilePath, &theFileInfo);
+
+ // we use this boolean to make error recovery easier since we need a case for when there's no file anyway
+ bool theSettingsWereCached = false;
+ bool theSettingsNeedSaving = true;
+
+ if(theStatError == 0)
+ {
+ // stat says there is something there, only have to do work if we either don't have a cache or the cache is out of date
+ if((mSettingsCache == NULL) || (mSettingsCacheTime < theFileInfo.st_mtimespec) || mSettingsCacheForceRefresh)
+ {
+ // open the file
+ FILE* theFile = fopen(mSettingsFilePath, "r");
+ if(theFile != NULL)
+ {
+ // lock the file (this call blocks until the lock is taken)
+ int theError = flock(fileno(theFile), LOCK_EX);
+ if(theError == 0)
+ {
+ // get the length of the file
+ fseek(theFile, 0, SEEK_END);
+ size_t theFileLength = static_cast<size_t>(ftell(theFile));
+ fseek(theFile, 0, SEEK_SET);
+
+ if(theFileLength > 0)
+ {
+ // allocate a block of memory to hold the data in the file
+ CAAutoFree<Byte> theRawFileData(theFileLength);
+
+ // read all the data in
+ fread(static_cast<Byte*>(theRawFileData), theFileLength, 1, theFile);
+
+ // release the lock
+ flock(fileno(theFile), LOCK_UN);
+
+ // put it into a CFData object
+ CACFData theRawFileDataCFData(static_cast<Byte*>(theRawFileData), static_cast<UInt32>(theFileLength));
+
+ // get rid of the existing cache
+ if(mSettingsCache != NULL)
+ {
+ CFRelease(mSettingsCache);
+ mSettingsCache = NULL;
+ }
+
+ // parse the data as a property list
+ mSettingsCache = (CFMutableDictionaryRef)CFPropertyListCreateWithData(NULL, theRawFileDataCFData.GetCFData(), kCFPropertyListMutableContainersAndLeaves, NULL, NULL);
+
+ // check to be sure we parsed a plist out of the file
+ if(mSettingsCache != NULL)
+ {
+ // save the date of the cache
+ mSettingsCacheTime = theFileInfo.st_mtimespec;
+
+ // mark that we're done
+ theSettingsWereCached = true;
+ theSettingsNeedSaving = false;
+ }
+ }
+ }
+
+ // close the file
+ fclose(theFile);
+ mSettingsCacheForceRefresh = false;
+ }
+ }
+ else
+ {
+ // nothing to do since the file was older than the cached data
+ theSettingsNeedSaving = false;
+ theSettingsWereCached = true;
+ }
+ }
+
+ // if there was a failure, we need to clean up
+ if((theStatError != 0) || theSettingsNeedSaving || !theSettingsWereCached)
+ {
+ // we get here if either there isn't a file or something wacky happenned while parsing it
+ // so, make sure we have a valid cache dictionary
+ if(mSettingsCache == NULL)
+ {
+ mSettingsCache = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ }
+
+ mSettingsCacheTime.tv_sec = 0;
+ mSettingsCacheTime.tv_nsec = 0;
+
+ if((theStatError != 0) || theSettingsNeedSaving)
+ {
+ SaveSettings();
+ }
+ }
+ }
+}
+
+void CASettingsStorage::SaveSettings()
+{
+ if(!mIsReadOnly && (mSettingsCache != NULL))
+ {
+ // make a CFData that contains the new settings
+ CACFData theNewRawPrefsCFData(CFPropertyListCreateData(NULL, mSettingsCache, mSettingsCacheFormat, 0, NULL), true);
+
+ // open the file for writing
+ FILE* theFile = fopen(mSettingsFilePath, "w+");
+ if(theFile != NULL)
+ {
+ // lock the file (this call blocks until the lock is taken)
+ int theError = flock(fileno(theFile), LOCK_EX);
+ if(theError == 0)
+ {
+ // set the file access mode if necessary
+ if(mSettingsFileAccessMode != 0)
+ {
+ fchmod(fileno(theFile), mSettingsFileAccessMode);
+ }
+
+ // write the data
+ fwrite(theNewRawPrefsCFData.GetDataPtr(), theNewRawPrefsCFData.GetSize(), 1, theFile);
+
+ // flush the file to be sure it is all on disk
+ fflush(theFile);
+
+ // release the lock
+ flock(fileno(theFile), LOCK_UN);
+
+ // close the file
+ fclose(theFile);
+
+ // stat the file to get the mod date
+ struct stat theFileInfo;
+ stat(mSettingsFilePath, &theFileInfo);
+
+ // save the mod date
+ mSettingsCacheTime = theFileInfo.st_mtimespec;
+ }
+ else
+ {
+ // close the file
+ fclose(theFile);
+ }
+ }
+ }
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.h b/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.h
new file mode 100644
index 0000000000..d15f87dd16
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.h
@@ -0,0 +1,128 @@
+/*
+ File: CASettingsStorage.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CASettingsStorage_h__)
+#define __CASettingsStorage_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// System Includes
+#include <CoreAudio/CoreAudioTypes.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+// Stamdard Library Includes
+#include <stdio.h>
+#include <sys/stat.h>
+
+//==================================================================================================
+// CASettingsStorage
+//==================================================================================================
+
+class CASettingsStorage
+{
+
+// Construction/Destruction
+public:
+ CASettingsStorage(const char* inSettingsFilePath, mode_t inSettingsFileAccessMode = 0, CFPropertyListFormat inSettingsCacheFormat = kCFPropertyListXMLFormat_v1_0, bool inIsSingleProcessOnly = false, bool inIsReadOnly = false);
+ ~CASettingsStorage();
+
+// Operations
+public:
+ UInt32 GetNumberKeys() const;
+ void GetKeys(UInt32 inNumberKeys, UInt32& outNumberKeys, CFStringRef* outKeys) const;
+
+ void CopyBoolValue(const CFStringRef inKey, bool& outValue, bool inDefaultValue = false) const;
+ void CopySInt32Value(const CFStringRef inKey, SInt32& outValue, SInt32 inDefaultValue = 0) const;
+ void CopyUInt32Value(const CFStringRef inKey, UInt32& outValue, UInt32 inDefaultValue = 0) const;
+ void CopySInt64Value(const CFStringRef inKey, SInt64& outValue, SInt64 inDefaultValue = 0) const;
+ void CopyUInt64Value(const CFStringRef inKey, UInt64& outValue, UInt64 inDefaultValue = 0) const;
+ void CopyFloat32Value(const CFStringRef inKey, Float32& outValue, Float32 inDefaultValue = 0) const;
+ void CopyFloat64Value(const CFStringRef inKey, Float64& outValue, Float64 inDefaultValue = 0) const;
+ void CopyNumberValue(const CFStringRef inKey, CFNumberRef& outValue, CFNumberRef inDefaultValue = NULL) const;
+ void CopyStringValue(const CFStringRef inKey, CFStringRef& outValue, CFStringRef inDefaultValue = NULL) const;
+ void CopyArrayValue(const CFStringRef inKey, CFArrayRef& outValue, CFArrayRef inDefaultValue = NULL) const;
+ void CopyDictionaryValue(const CFStringRef inKey, CFDictionaryRef& outValue, CFDictionaryRef inDefaultValue = NULL) const;
+ void CopyDataValue(const CFStringRef inKey, CFDataRef& outValue, CFDataRef inDefaultValue = NULL) const;
+ void CopyCFTypeValue(const CFStringRef inKey, CFTypeRef& outValue, CFTypeRef inDefaultValue = NULL) const;
+
+ void SetSInt32Value(const CFStringRef inKey, SInt32 inValue);
+ void SetUInt32Value(const CFStringRef inKey, UInt32 inValue);
+ void SetSInt64Value(const CFStringRef inKey, SInt64 inValue);
+ void SetUInt64Value(const CFStringRef inKey, UInt64 inValue);
+ void SetFloat32Value(const CFStringRef inKey, Float32 inValue);
+ void SetFloat64Value(const CFStringRef inKey, Float64 inValue);
+ void SetNumberValue(const CFStringRef inKey, const CFNumberRef inValue);
+ void SetStringValue(const CFStringRef inKey, const CFStringRef inValue);
+ void SetArrayValue(const CFStringRef inKey, const CFArrayRef inValue);
+ void SetDictionaryValue(const CFStringRef inKey, const CFDictionaryRef inValue);
+ void SetDataValue(const CFStringRef inKey, const CFDataRef inValue);
+ void SetCFTypeValue(const CFStringRef inKey, const CFTypeRef inValue);
+
+ void RemoveValue(const CFStringRef inKey);
+ void RemoveAllValues();
+
+ void SendNotification(const CFStringRef inName, CFDictionaryRef inData = NULL, bool inPostToAllSessions = true) const;
+ void ForceRefresh();
+
+// Implementation
+private:
+ void RefreshSettings();
+ void SaveSettings();
+
+ char* mSettingsFilePath;
+ mode_t mSettingsFileAccessMode;
+ CFMutableDictionaryRef mSettingsCache;
+ CFPropertyListFormat mSettingsCacheFormat;
+ struct timespec mSettingsCacheTime;
+ bool mSettingsCacheForceRefresh;
+ bool mIsSingleProcessOnly;
+ bool mIsReadOnly;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.cpp b/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.cpp
new file mode 100644
index 0000000000..0e39ac7e52
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.cpp
@@ -0,0 +1,118 @@
+/*
+ File: CASharedLibrary.cpp
+ Abstract: CASharedLibrary.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CASharedLibrary.h"
+
+//#define CASharedLibrary_Use_DYLD 1
+#if CASharedLibrary_Use_DYLD
+ #include <mach-o/dyld.h>
+#else
+ #include <dlfcn.h>
+ #include <stddef.h>
+#endif
+
+//=============================================================================
+// CASharedLibrary
+//=============================================================================
+
+void* CASharedLibrary::LoadLibraryAndGetRoutineAddress(const char* inRoutineName, const char* /*inLibraryName*/, const char* inLibraryPath)
+{
+ void* theRoutine = 0;
+
+#if CASharedLibrary_Use_DYLD
+ const struct mach_header* theImage = NSAddImage(inLibraryPath, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+ if(theImage != 0)
+ {
+ NSSymbol theSymbol = NSLookupSymbolInImage(theImage, inRoutineName, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND);
+ if(theSymbol != 0)
+ {
+ theRoutine = NSAddressOfSymbol(theSymbol);
+ }
+ }
+#else
+ void* theImage = dlopen(inLibraryPath, RTLD_LAZY);
+ if(theImage != NULL)
+ {
+ // we assume that all routine names passed here have a leading underscore which gets shaved
+ // off when passed to dlsym
+ theRoutine = dlsym(theImage, &(inRoutineName[1]));
+ }
+
+#endif
+
+ return theRoutine;
+}
+
+void* CASharedLibrary::GetRoutineAddressIfLibraryLoaded(const char* inRoutineName, const char* /*inLibraryName*/, const char* inLibraryPath)
+{
+ void* theRoutine = 0;
+
+#if CASharedLibrary_Use_DYLD
+ const struct mach_header* theImage = NSAddImage(inLibraryPath, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED);
+ if(theImage != 0)
+ {
+ NSSymbol theSymbol = NSLookupSymbolInImage(theImage, inRoutineName, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND);
+ if(theSymbol != 0)
+ {
+ theRoutine = NSAddressOfSymbol(theSymbol);
+ }
+ }
+#else
+ void* theImage = dlopen(inLibraryPath, RTLD_LAZY | RTLD_NOLOAD);
+ if(theImage != NULL)
+ {
+ // we assume that all routine names passed here have a leading underscore which gets shaved
+ // off when passed to dlsym
+ theRoutine = dlsym(theImage, &(inRoutineName[1]));
+ }
+#endif
+
+ return theRoutine;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.h b/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.h
new file mode 100644
index 0000000000..d02e70e356
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.h
@@ -0,0 +1,64 @@
+/*
+ File: CASharedLibrary.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CASharedLibrary_h__)
+#define __CASharedLibrary_h__
+
+//=============================================================================
+// CASharedLibrary
+//=============================================================================
+
+class CASharedLibrary
+{
+
+// Symbol Operations
+public:
+ static void* LoadLibraryAndGetRoutineAddress(const char* inRoutineName, const char* inLibraryName, const char* inLibraryPath);
+ static void* GetRoutineAddressIfLibraryLoaded(const char* inRoutineName, const char* inLibraryName, const char* inLibraryPath);
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.cpp b/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.cpp
new file mode 100644
index 0000000000..ffb2da8a83
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.cpp
@@ -0,0 +1,376 @@
+/*
+ File: CASpectralProcessor.cpp
+ Abstract: CASpectralProcessor.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+
+//#include "AudioFormulas.h"
+#include "CASpectralProcessor.h"
+#include "CABitOperations.h"
+
+
+#include <Accelerate/Accelerate.h>
+
+
+#define OFFSETOF(class, field)((size_t)&((class*)0)->field)
+
+CASpectralProcessor::CASpectralProcessor(UInt32 inFFTSize, UInt32 inHopSize, UInt32 inNumChannels, UInt32 inMaxFrames)
+ : mFFTSize(inFFTSize), mHopSize(inHopSize), mNumChannels(inNumChannels), mMaxFrames(inMaxFrames),
+ mLog2FFTSize(Log2Ceil(mFFTSize)),
+ mFFTMask(mFFTSize - 1),
+ mFFTByteSize(mFFTSize * sizeof(Float32)),
+ mIOBufSize(NextPowerOfTwo(mFFTSize + mMaxFrames)),
+ mIOMask(mIOBufSize - 1),
+ mInputSize(0),
+ mInputPos(0), mOutputPos(-mFFTSize & mIOMask),
+ mInFFTPos(0), mOutFFTPos(0),
+ mSpectralFunction(0), mUserData(0)
+{
+ mWindow.alloc(mFFTSize, false);
+ SineWindow(); // set default window.
+
+ mChannels.alloc(mNumChannels);
+ mSpectralBufferList.allocBytes(OFFSETOF(SpectralBufferList, mDSPSplitComplex[mNumChannels]), true);
+ mSpectralBufferList->mNumberSpectra = mNumChannels;
+ for (UInt32 i = 0; i < mNumChannels; ++i)
+ {
+ mChannels[i].mInputBuf.alloc(mIOBufSize, true);
+ mChannels[i].mOutputBuf.alloc(mIOBufSize, true);
+ mChannels[i].mFFTBuf.alloc(mFFTSize, true);
+ mChannels[i].mSplitFFTBuf.alloc(mFFTSize, true);
+ mSpectralBufferList->mDSPSplitComplex[i].realp = mChannels[i].mSplitFFTBuf();
+ mSpectralBufferList->mDSPSplitComplex[i].imagp = mChannels[i].mSplitFFTBuf() + (mFFTSize >> 1);
+ }
+
+ mFFTSetup = vDSP_create_fftsetup (mLog2FFTSize, FFT_RADIX2);
+
+}
+
+CASpectralProcessor::~CASpectralProcessor()
+{
+ mWindow.free();
+ mChannels.free();
+ mSpectralBufferList.free();
+ vDSP_destroy_fftsetup(mFFTSetup);
+}
+
+void CASpectralProcessor::Reset()
+{
+ mInputPos = 0;
+ mOutputPos = -mFFTSize & mIOMask;
+ mInFFTPos = 0;
+ mOutFFTPos = 0;
+
+ for (UInt32 i = 0; i < mNumChannels; ++i)
+ {
+ memset(mChannels[i].mInputBuf(), 0, mIOBufSize * sizeof(Float32));
+ memset(mChannels[i].mOutputBuf(), 0, mIOBufSize * sizeof(Float32));
+ memset(mChannels[i].mFFTBuf(), 0, mFFTSize * sizeof(Float32));
+ }
+}
+
+const double two_pi = 2. * M_PI;
+
+void CASpectralProcessor::HanningWindow()
+{
+ // this is also vector optimized
+
+ double w = two_pi / (double)(mFFTSize - 1);
+ for (UInt32 i = 0; i < mFFTSize; ++i)
+ {
+ mWindow[i] = (0.5 - 0.5 * cos(w * (double)i));
+ }
+}
+
+void CASpectralProcessor::SineWindow()
+{
+ double w = M_PI / (double)(mFFTSize - 1);
+ for (UInt32 i = 0; i < mFFTSize; ++i)
+ {
+ mWindow[i] = sin(w * (double)i);
+ }
+}
+
+void CASpectralProcessor::Process(UInt32 inNumFrames, AudioBufferList* inInput, AudioBufferList* outOutput)
+{
+ // copy from buffer list to input buffer
+ CopyInput(inNumFrames, inInput);
+
+ // if enough input to process, then process.
+ while (mInputSize >= mFFTSize)
+ {
+ CopyInputToFFT(); // copy from input buffer to fft buffer
+ DoWindowing();
+ DoFwdFFT();
+ ProcessSpectrum(mFFTSize, mSpectralBufferList());
+ DoInvFFT();
+ DoWindowing();
+ OverlapAddOutput();
+ }
+
+ // copy from output buffer to buffer list
+ CopyOutput(inNumFrames, outOutput);
+}
+
+void CASpectralProcessor::DoWindowing()
+{
+ Float32 *win = mWindow();
+ if (!win) return;
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ Float32 *x = mChannels[i].mFFTBuf();
+ vDSP_vmul(x, 1, win, 1, x, 1, mFFTSize);
+ }
+ //printf("DoWindowing %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+}
+
+
+
+void CASpectralProcessor::CopyInput(UInt32 inNumFrames, AudioBufferList* inInput)
+{
+ UInt32 numBytes = inNumFrames * sizeof(Float32);
+ UInt32 firstPart = mIOBufSize - mInputPos;
+
+
+ if (firstPart < inNumFrames) {
+ UInt32 firstPartBytes = firstPart * sizeof(Float32);
+ UInt32 secondPartBytes = numBytes - firstPartBytes;
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ memcpy(mChannels[i].mInputBuf + mInputPos, inInput->mBuffers[i].mData, firstPartBytes);
+ memcpy(mChannels[i].mInputBuf, (UInt8*)inInput->mBuffers[i].mData + firstPartBytes, secondPartBytes);
+ }
+ } else {
+ UInt32 numBytes = inNumFrames * sizeof(Float32);
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ memcpy(mChannels[i].mInputBuf + mInputPos, inInput->mBuffers[i].mData, numBytes);
+ }
+ }
+ //printf("CopyInput %g %g\n", mChannels[0].mInputBuf[mInputPos], mChannels[0].mInputBuf[(mInputPos + 200) & mIOMask]);
+ //printf("CopyInput mInputPos %u mIOBufSize %u\n", (unsigned)mInputPos, (unsigned)mIOBufSize);
+ mInputSize += inNumFrames;
+ mInputPos = (mInputPos + inNumFrames) & mIOMask;
+}
+
+void CASpectralProcessor::CopyOutput(UInt32 inNumFrames, AudioBufferList* outOutput)
+{
+ //printf("->CopyOutput %g %g\n", mChannels[0].mOutputBuf[mOutputPos], mChannels[0].mOutputBuf[(mOutputPos + 200) & mIOMask]);
+ //printf("CopyOutput mOutputPos %u\n", (unsigned)mOutputPos);
+ UInt32 numBytes = inNumFrames * sizeof(Float32);
+ UInt32 firstPart = mIOBufSize - mOutputPos;
+ if (firstPart < inNumFrames) {
+ UInt32 firstPartBytes = firstPart * sizeof(Float32);
+ UInt32 secondPartBytes = numBytes - firstPartBytes;
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ memcpy(outOutput->mBuffers[i].mData, mChannels[i].mOutputBuf + mOutputPos, firstPartBytes);
+ memcpy((UInt8*)outOutput->mBuffers[i].mData + firstPartBytes, mChannels[i].mOutputBuf, secondPartBytes);
+ memset(mChannels[i].mOutputBuf + mOutputPos, 0, firstPartBytes);
+ memset(mChannels[i].mOutputBuf, 0, secondPartBytes);
+ }
+ } else {
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ memcpy(outOutput->mBuffers[i].mData, mChannels[i].mOutputBuf + mOutputPos, numBytes);
+ memset(mChannels[i].mOutputBuf + mOutputPos, 0, numBytes);
+ }
+ }
+ //printf("<-CopyOutput %g %g\n", ((Float32*)outOutput->mBuffers[0].mData)[0], ((Float32*)outOutput->mBuffers[0].mData)[200]);
+ mOutputPos = (mOutputPos + inNumFrames) & mIOMask;
+}
+
+void CASpectralProcessor::PrintSpectralBufferList()
+{
+ UInt32 half = mFFTSize >> 1;
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ DSPSplitComplex &freqData = mSpectralBufferList->mDSPSplitComplex[i];
+
+ for (UInt32 j=0; j<half; j++){
+ printf(" bin[%d]: %lf + %lfi\n", (int) j, freqData.realp[j], freqData.imagp[j]);
+ }
+ }
+}
+
+
+void CASpectralProcessor::CopyInputToFFT()
+{
+ //printf("CopyInputToFFT mInFFTPos %u\n", (unsigned)mInFFTPos);
+ UInt32 firstPart = mIOBufSize - mInFFTPos;
+ UInt32 firstPartBytes = firstPart * sizeof(Float32);
+ if (firstPartBytes < mFFTByteSize) {
+ UInt32 secondPartBytes = mFFTByteSize - firstPartBytes;
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ memcpy(mChannels[i].mFFTBuf(), mChannels[i].mInputBuf() + mInFFTPos, firstPartBytes);
+ memcpy((UInt8*)mChannels[i].mFFTBuf() + firstPartBytes, mChannels[i].mInputBuf(), secondPartBytes);
+ }
+ } else {
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ memcpy(mChannels[i].mFFTBuf(), mChannels[i].mInputBuf() + mInFFTPos, mFFTByteSize);
+ }
+ }
+ mInputSize -= mHopSize;
+ mInFFTPos = (mInFFTPos + mHopSize) & mIOMask;
+ //printf("CopyInputToFFT %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+}
+
+void CASpectralProcessor::OverlapAddOutput()
+{
+ //printf("OverlapAddOutput mOutFFTPos %u\n", (unsigned)mOutFFTPos);
+ UInt32 firstPart = mIOBufSize - mOutFFTPos;
+ if (firstPart < mFFTSize) {
+ UInt32 secondPart = mFFTSize - firstPart;
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ float* out1 = mChannels[i].mOutputBuf() + mOutFFTPos;
+ vDSP_vadd(out1, 1, mChannels[i].mFFTBuf(), 1, out1, 1, firstPart);
+ float* out2 = mChannels[i].mOutputBuf();
+ vDSP_vadd(out2, 1, mChannels[i].mFFTBuf() + firstPart, 1, out2, 1, secondPart);
+ }
+ } else {
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ float* out1 = mChannels[i].mOutputBuf() + mOutFFTPos;
+ vDSP_vadd(out1, 1, mChannels[i].mFFTBuf(), 1, out1, 1, mFFTSize);
+ }
+ }
+ //printf("OverlapAddOutput %g %g\n", mChannels[0].mOutputBuf[mOutFFTPos], mChannels[0].mOutputBuf[(mOutFFTPos + 200) & mIOMask]);
+ mOutFFTPos = (mOutFFTPos + mHopSize) & mIOMask;
+}
+
+
+void CASpectralProcessor::DoFwdFFT()
+{
+ //printf("->DoFwdFFT %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+ UInt32 half = mFFTSize >> 1;
+ for (UInt32 i=0; i<mNumChannels; ++i)
+ {
+ vDSP_ctoz((DSPComplex*)mChannels[i].mFFTBuf(), 2, &mSpectralBufferList->mDSPSplitComplex[i], 1, half);
+ vDSP_fft_zrip(mFFTSetup, &mSpectralBufferList->mDSPSplitComplex[i], 1, mLog2FFTSize, FFT_FORWARD);
+ }
+ //printf("<-DoFwdFFT %g %g\n", direction, mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+}
+
+void CASpectralProcessor::DoInvFFT()
+{
+ //printf("->DoInvFFT %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+ UInt32 half = mFFTSize >> 1;
+ for (UInt32 i=0; i<mNumChannels; ++i)
+ {
+ vDSP_fft_zrip(mFFTSetup, &mSpectralBufferList->mDSPSplitComplex[i], 1, mLog2FFTSize, FFT_INVERSE);
+ vDSP_ztoc(&mSpectralBufferList->mDSPSplitComplex[i], 1, (DSPComplex*)mChannels[i].mFFTBuf(), 2, half);
+ float scale = 0.5 / mFFTSize;
+ vDSP_vsmul(mChannels[i].mFFTBuf(), 1, &scale, mChannels[i].mFFTBuf(), 1, mFFTSize );
+ }
+ //printf("<-DoInvFFT %g %g\n", direction, mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+}
+
+void CASpectralProcessor::SetSpectralFunction(SpectralFunction inFunction, void* inUserData)
+{
+ mSpectralFunction = inFunction;
+ mUserData = inUserData;
+}
+
+void CASpectralProcessor::ProcessSpectrum(UInt32 inFFTSize, SpectralBufferList* inSpectra)
+{
+ if (mSpectralFunction)
+ (mSpectralFunction)(inSpectra, mUserData);
+}
+
+#pragma mark ___Utility___
+
+void CASpectralProcessor::GetMagnitude(AudioBufferList* list, Float32* min, Float32* max)
+{
+ UInt32 half = mFFTSize >> 1;
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ DSPSplitComplex &freqData = mSpectralBufferList->mDSPSplitComplex[i];
+
+ Float32* b = (Float32*) list->mBuffers[i].mData;
+
+ vDSP_zvabs(&freqData,1,b,1,half);
+
+ vDSP_maxmgv(b, 1, &max[i], half);
+ vDSP_minmgv(b, 1, &min[i], half);
+
+ }
+}
+
+
+void CASpectralProcessor::GetFrequencies(Float32* freqs, Float32 sampleRate)
+{
+ UInt32 half = mFFTSize >> 1;
+
+ for (UInt32 i=0; i< half; i++){
+ freqs[i] = ((Float32)(i))*sampleRate/((Float32)mFFTSize);
+ }
+}
+
+
+bool CASpectralProcessor::ProcessForwards(UInt32 inNumFrames, AudioBufferList* inInput)
+{
+ // copy from buffer list to input buffer
+ CopyInput(inNumFrames, inInput);
+
+ bool processed = false;
+ // if enough input to process, then process.
+ while (mInputSize >= mFFTSize)
+ {
+ CopyInputToFFT(); // copy from input buffer to fft buffer
+ DoWindowing();
+ DoFwdFFT();
+ ProcessSpectrum(mFFTSize, mSpectralBufferList()); // here you would copy the fft results out to a buffer indicated in mUserData, say for sonogram drawing
+ processed = true;
+ }
+
+ return processed;
+}
+
+bool CASpectralProcessor::ProcessBackwards(UInt32 inNumFrames, AudioBufferList* outOutput)
+{
+
+ ProcessSpectrum(mFFTSize, mSpectralBufferList());
+ DoInvFFT();
+ DoWindowing();
+ OverlapAddOutput();
+
+ // copy from output buffer to buffer list
+ CopyOutput(inNumFrames, outOutput);
+
+ return true;
+}
+
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.h b/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.h
new file mode 100644
index 0000000000..d7c285b6a9
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.h
@@ -0,0 +1,146 @@
+/*
+ File: CASpectralProcessor.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef _SpectralProcesor_H_
+#define _SpectralProcesor_H_
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+#include <CoreAudio/CoreAudioTypes.h>
+#include <CoreFoundation/CoreFoundation.h>
+#else
+#include <CoreAudioTypes.h>
+#include <CoreFoundation.h>
+#endif
+
+#include <Accelerate/Accelerate.h>
+
+#include "CAAutoDisposer.h"
+
+struct SpectralBufferList
+{
+ UInt32 mNumberSpectra;
+ DSPSplitComplex mDSPSplitComplex[1];
+};
+
+class CASpectralProcessor
+{
+public:
+ CASpectralProcessor(UInt32 inFFTSize, UInt32 inHopSize, UInt32 inNumChannels, UInt32 inMaxFrames);
+ virtual ~CASpectralProcessor();
+
+ void Reset();
+
+ void Process(UInt32 inNumFrames, AudioBufferList* inInput, AudioBufferList* outOutput);
+
+ typedef void (*SpectralFunction)(SpectralBufferList* inSpectra, void* inUserData);
+
+ void SetSpectralFunction(SpectralFunction inFunction, void* inUserData);
+
+ UInt32 FFTSize() const { return mFFTSize; }
+ UInt32 MaxFrames() const { return mMaxFrames; }
+ UInt32 NumChannels() const { return mNumChannels; }
+ UInt32 HopSize() const { return mHopSize; }
+ Float32* Window() const { return mWindow; }
+
+
+ void HanningWindow(); // set up a hanning window
+ void SineWindow();
+
+ void GetFrequencies(Float32* freqs, Float32 sampleRate); // only for processed forward
+ void GetMagnitude(AudioBufferList* inCopy, Float32* min, Float32* max); // only for processed forward
+
+ virtual bool ProcessForwards(UInt32 inNumFrames, AudioBufferList* inInput);
+ bool ProcessBackwards(UInt32 inNumFrames, AudioBufferList* outOutput);
+
+
+ void PrintSpectralBufferList();
+
+protected:
+ void CopyInput(UInt32 inNumFrames, AudioBufferList* inInput);
+ void CopyInputToFFT();
+ void DoWindowing();
+ void DoFwdFFT();
+ void DoInvFFT();
+ void OverlapAddOutput();
+ void CopyOutput(UInt32 inNumFrames, AudioBufferList* inOutput);
+ void ProcessSpectrum(UInt32 inFFTSize, SpectralBufferList* inSpectra);
+
+ UInt32 mFFTSize;
+ UInt32 mHopSize;
+ UInt32 mNumChannels;
+ UInt32 mMaxFrames;
+
+ UInt32 mLog2FFTSize;
+ UInt32 mFFTMask;
+ UInt32 mFFTByteSize;
+ UInt32 mIOBufSize;
+ UInt32 mIOMask;
+ UInt32 mInputSize;
+ UInt32 mInputPos;
+ UInt32 mOutputPos;
+ UInt32 mInFFTPos;
+ UInt32 mOutFFTPos;
+ FFTSetup mFFTSetup;
+
+ CAAutoFree<Float32> mWindow;
+ struct SpectralChannel
+ {
+ CAAutoFree<Float32> mInputBuf; // log2ceil(FFT size + max frames)
+ CAAutoFree<Float32> mOutputBuf; // log2ceil(FFT size + max frames)
+ CAAutoFree<Float32> mFFTBuf; // FFT size
+ CAAutoFree<Float32> mSplitFFTBuf; // FFT size
+ };
+ CAAutoArrayDelete<SpectralChannel> mChannels;
+
+ CAAutoFree<SpectralBufferList> mSpectralBufferList;
+
+ SpectralFunction mSpectralFunction;
+ void *mUserData;
+
+};
+
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.cpp
new file mode 100644
index 0000000000..d56947ab59
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.cpp
@@ -0,0 +1,879 @@
+/*
+ File: CAStreamBasicDescription.cpp
+ Abstract: CAStreamBasicDescription.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CAStreamBasicDescription.h"
+#include "CAMath.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CFByteOrder.h>
+#else
+ #include <CFByteOrder.h>
+#endif
+
+#pragma mark This file needs to compile on earlier versions of the OS, so please keep that in mind when editing it
+
+char *CAStringForOSType (OSType t, char *writeLocation, size_t bufsize)
+{
+ if (bufsize > 0) {
+ char *p = writeLocation, *pend = writeLocation + bufsize;
+ union { UInt32 i; unsigned char str[4]; } u;
+ unsigned char *q = u.str;
+ u.i = CFSwapInt32HostToBig(t);
+
+ bool hasNonPrint = false;
+ for (int i = 0; i < 4; ++i) {
+ if (!(isprint(*q) && *q != '\\')) {
+ hasNonPrint = true;
+ break;
+ }
+ q++;
+ }
+ q = u.str;
+
+ if (hasNonPrint)
+ p += snprintf (p, pend - p, "0x");
+ else if (p < pend)
+ *p++ = '\'';
+
+ for (int i = 0; i < 4 && p < pend; ++i) {
+ if (hasNonPrint) {
+ p += snprintf(p, pend - p, "%02X", *q++);
+ } else {
+ *p++ = *q++;
+ }
+ }
+ if (!hasNonPrint && p < pend)
+ *p++ = '\'';
+ if (p >= pend) p -= 1;
+ *p = '\0';
+ }
+ return writeLocation;
+}
+
+
+const AudioStreamBasicDescription CAStreamBasicDescription::sEmpty = { 0.0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+CAStreamBasicDescription::CAStreamBasicDescription()
+{
+ memset (this, 0, sizeof(AudioStreamBasicDescription));
+}
+
+CAStreamBasicDescription::CAStreamBasicDescription(const AudioStreamBasicDescription &desc)
+{
+ SetFrom(desc);
+}
+
+
+CAStreamBasicDescription::CAStreamBasicDescription(double inSampleRate, UInt32 inFormatID,
+ UInt32 inBytesPerPacket, UInt32 inFramesPerPacket,
+ UInt32 inBytesPerFrame, UInt32 inChannelsPerFrame,
+ UInt32 inBitsPerChannel, UInt32 inFormatFlags)
+{
+ mSampleRate = inSampleRate;
+ mFormatID = inFormatID;
+ mBytesPerPacket = inBytesPerPacket;
+ mFramesPerPacket = inFramesPerPacket;
+ mBytesPerFrame = inBytesPerFrame;
+ mChannelsPerFrame = inChannelsPerFrame;
+ mBitsPerChannel = inBitsPerChannel;
+ mFormatFlags = inFormatFlags;
+ mReserved = 0;
+}
+
+char *CAStreamBasicDescription::AsString(char *buf, size_t _bufsize, bool brief /*=false*/) const
+{
+ int bufsize = (int)_bufsize; // must be signed to protect against overflow
+ char *theBuffer = buf;
+ int nc;
+ char formatID[24];
+ CAStringForOSType(mFormatID, formatID, sizeof(formatID));
+ if (brief) {
+ CommonPCMFormat com;
+ bool interleaved;
+ if (IdentifyCommonPCMFormat(com, &interleaved) && com != kPCMFormatOther) {
+ const char *desc;
+ switch (com) {
+ case kPCMFormatInt16:
+ desc = "Int16";
+ break;
+ case kPCMFormatFixed824:
+ desc = "Int8.24";
+ break;
+ case kPCMFormatFloat32:
+ desc = "Float32";
+ break;
+ case kPCMFormatFloat64:
+ desc = "Float64";
+ break;
+ default:
+ desc = NULL;
+ break;
+ }
+ if (desc) {
+ const char *inter ="";
+ if (mChannelsPerFrame > 1)
+ inter = !interleaved ? ", non-inter" : ", inter";
+ snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz, %s%s", (int)mChannelsPerFrame, mSampleRate, desc, inter);
+ return theBuffer;
+ }
+ }
+ if (mChannelsPerFrame == 0 && mSampleRate == 0.0 && mFormatID == 0) {
+ snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz", (int)mChannelsPerFrame, mSampleRate);
+ return theBuffer;
+ }
+ }
+
+ nc = snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz, %s (0x%08X) ", (int)NumberChannels(), mSampleRate, formatID, (int)mFormatFlags);
+ buf += nc; if ((bufsize -= nc) <= 0) goto exit;
+ if (mFormatID == kAudioFormatLinearPCM) {
+ bool isInt = !(mFormatFlags & kLinearPCMFormatFlagIsFloat);
+ int wordSize = static_cast<int>(SampleWordSize());
+ const char *endian = (wordSize > 1) ?
+ ((mFormatFlags & kLinearPCMFormatFlagIsBigEndian) ? " big-endian" : " little-endian" ) : "";
+ const char *sign = isInt ?
+ ((mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) ? " signed" : " unsigned") : "";
+ const char *floatInt = isInt ? "integer" : "float";
+ char packed[32];
+ if (wordSize > 0 && PackednessIsSignificant()) {
+ if (mFormatFlags & kLinearPCMFormatFlagIsPacked)
+ snprintf(packed, sizeof(packed), "packed in %d bytes", wordSize);
+ else
+ snprintf(packed, sizeof(packed), "unpacked in %d bytes", wordSize);
+ } else
+ packed[0] = '\0';
+ const char *align = (wordSize > 0 && AlignmentIsSignificant()) ?
+ ((mFormatFlags & kLinearPCMFormatFlagIsAlignedHigh) ? " high-aligned" : " low-aligned") : "";
+ const char *deinter = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) ? ", deinterleaved" : "";
+ const char *commaSpace = (packed[0]!='\0') || (align[0]!='\0') ? ", " : "";
+ char bitdepth[20];
+
+ int fracbits = (mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
+ if (fracbits > 0)
+ snprintf(bitdepth, sizeof(bitdepth), "%d.%d", (int)mBitsPerChannel - fracbits, fracbits);
+ else
+ snprintf(bitdepth, sizeof(bitdepth), "%d", (int)mBitsPerChannel);
+
+ /*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%s-bit%s%s %s%s%s%s%s",
+ bitdepth, endian, sign, floatInt,
+ commaSpace, packed, align, deinter);
+ // buf += nc; if ((bufsize -= nc) <= 0) goto exit;
+ } else if (mFormatID == kAudioFormatAppleLossless) {
+ int sourceBits = 0;
+ switch (mFormatFlags)
+ {
+ case 1: // kAppleLosslessFormatFlag_16BitSourceData
+ sourceBits = 16;
+ break;
+ case 2: // kAppleLosslessFormatFlag_20BitSourceData
+ sourceBits = 20;
+ break;
+ case 3: // kAppleLosslessFormatFlag_24BitSourceData
+ sourceBits = 24;
+ break;
+ case 4: // kAppleLosslessFormatFlag_32BitSourceData
+ sourceBits = 32;
+ break;
+ }
+ if (sourceBits)
+ nc = snprintf(buf, static_cast<size_t>(bufsize), "from %d-bit source, ", sourceBits);
+ else
+ nc = snprintf(buf, static_cast<size_t>(bufsize), "from UNKNOWN source bit depth, ");
+ buf += nc; if ((bufsize -= nc) <= 0) goto exit;
+ /*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%d frames/packet", (int)mFramesPerPacket);
+ // buf += nc; if ((bufsize -= nc) <= 0) goto exit;
+ }
+ else
+ /*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%d bits/channel, %d bytes/packet, %d frames/packet, %d bytes/frame",
+ (int)mBitsPerChannel, (int)mBytesPerPacket, (int)mFramesPerPacket, (int)mBytesPerFrame);
+exit:
+ return theBuffer;
+}
+
+void CAStreamBasicDescription::NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription)
+{
+ // the only thing that changes is to make mixable linear PCM into the canonical linear PCM format
+ if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0))
+ {
+ // the canonical linear PCM format
+ ioDescription.mFormatFlags = kAudioFormatFlagsCanonical;
+ ioDescription.mBytesPerPacket = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
+ ioDescription.mFramesPerPacket = 1;
+ ioDescription.mBytesPerFrame = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
+ ioDescription.mBitsPerChannel = 8 * SizeOf32(AudioSampleType);
+ }
+}
+
+void CAStreamBasicDescription::NormalizeLinearPCMFormat(bool inNativeEndian, AudioStreamBasicDescription& ioDescription)
+{
+ // the only thing that changes is to make mixable linear PCM into the canonical linear PCM format
+ if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0))
+ {
+ // the canonical linear PCM format
+ ioDescription.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked;
+ if(inNativeEndian)
+ {
+#if TARGET_RT_BIG_ENDIAN
+ ioDescription.mFormatFlags |= kAudioFormatFlagIsBigEndian;
+#endif
+ }
+ else
+ {
+#if TARGET_RT_LITTLE_ENDIAN
+ ioDescription.mFormatFlags |= kAudioFormatFlagIsBigEndian;
+#endif
+ }
+ ioDescription.mBytesPerPacket = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
+ ioDescription.mFramesPerPacket = 1;
+ ioDescription.mBytesPerFrame = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
+ ioDescription.mBitsPerChannel = 8 * SizeOf32(AudioSampleType);
+ }
+}
+
+void CAStreamBasicDescription::ResetFormat(AudioStreamBasicDescription& ioDescription)
+{
+ ioDescription.mSampleRate = 0;
+ ioDescription.mFormatID = 0;
+ ioDescription.mBytesPerPacket = 0;
+ ioDescription.mFramesPerPacket = 0;
+ ioDescription.mBytesPerFrame = 0;
+ ioDescription.mChannelsPerFrame = 0;
+ ioDescription.mBitsPerChannel = 0;
+ ioDescription.mFormatFlags = 0;
+}
+
+void CAStreamBasicDescription::FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription)
+{
+ if(fiszero(ioDescription.mSampleRate))
+ {
+ ioDescription.mSampleRate = inTemplateDescription.mSampleRate;
+ }
+ if(ioDescription.mFormatID == 0)
+ {
+ ioDescription.mFormatID = inTemplateDescription.mFormatID;
+ }
+ if(ioDescription.mFormatFlags == 0)
+ {
+ ioDescription.mFormatFlags = inTemplateDescription.mFormatFlags;
+ }
+ if(ioDescription.mBytesPerPacket == 0)
+ {
+ ioDescription.mBytesPerPacket = inTemplateDescription.mBytesPerPacket;
+ }
+ if(ioDescription.mFramesPerPacket == 0)
+ {
+ ioDescription.mFramesPerPacket = inTemplateDescription.mFramesPerPacket;
+ }
+ if(ioDescription.mBytesPerFrame == 0)
+ {
+ ioDescription.mBytesPerFrame = inTemplateDescription.mBytesPerFrame;
+ }
+ if(ioDescription.mChannelsPerFrame == 0)
+ {
+ ioDescription.mChannelsPerFrame = inTemplateDescription.mChannelsPerFrame;
+ }
+ if(ioDescription.mBitsPerChannel == 0)
+ {
+ ioDescription.mBitsPerChannel = inTemplateDescription.mBitsPerChannel;
+ }
+}
+
+void CAStreamBasicDescription::GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, UInt32 inMaxNameLength, bool inAbbreviate, bool inIncludeSampleRate)
+{
+ if(inIncludeSampleRate)
+ {
+ int theCharactersWritten = snprintf(outName, inMaxNameLength, "%.0f ", inDescription.mSampleRate);
+ outName += theCharactersWritten;
+ inMaxNameLength -= static_cast<UInt32>(theCharactersWritten);
+ }
+
+ switch(inDescription.mFormatID)
+ {
+ case kAudioFormatLinearPCM:
+ {
+ const char* theEndianString = NULL;
+ if((inDescription.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0)
+ {
+ #if TARGET_RT_LITTLE_ENDIAN
+ theEndianString = "Big Endian";
+ #endif
+ }
+ else
+ {
+ #if TARGET_RT_BIG_ENDIAN
+ theEndianString = "Little Endian";
+ #endif
+ }
+
+ const char* theKindString = NULL;
+ if((inDescription.mFormatFlags & kAudioFormatFlagIsFloat) != 0)
+ {
+ theKindString = (inAbbreviate ? "Float" : "Floating Point");
+ }
+ else if((inDescription.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
+ {
+ theKindString = (inAbbreviate ? "SInt" : "Signed Integer");
+ }
+ else
+ {
+ theKindString = (inAbbreviate ? "UInt" : "Unsigned Integer");
+ }
+
+ const char* thePackingString = NULL;
+ if((inDescription.mFormatFlags & kAudioFormatFlagIsPacked) == 0)
+ {
+ if((inDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) != 0)
+ {
+ thePackingString = "High";
+ }
+ else
+ {
+ thePackingString = "Low";
+ }
+ }
+
+ const char* theMixabilityString = NULL;
+ if((inDescription.mFormatFlags & kIsNonMixableFlag) == 0)
+ {
+ theMixabilityString = "Mixable";
+ }
+ else
+ {
+ theMixabilityString = "Unmixable";
+ }
+
+ if(inAbbreviate)
+ {
+ if(theEndianString != NULL)
+ {
+ if(thePackingString != NULL)
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Ch %s %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
+ }
+ else
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Ch %s %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, theKindString, (int)inDescription.mBitsPerChannel);
+ }
+ }
+ else
+ {
+ if(thePackingString != NULL)
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Ch %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)((inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8));
+ }
+ else
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Ch %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theKindString, (int)inDescription.mBitsPerChannel);
+ }
+ }
+ }
+ else
+ {
+ if(theEndianString != NULL)
+ {
+ if(thePackingString != NULL)
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
+ }
+ else
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString);
+ }
+ }
+ else
+ {
+ if(thePackingString != NULL)
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
+ }
+ else
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString);
+ }
+ }
+ }
+ }
+ break;
+
+ case kAudioFormatAC3:
+ strlcpy(outName, "AC-3", sizeof(outName));
+ break;
+
+ case kAudioFormat60958AC3:
+ strlcpy(outName, "AC-3 for SPDIF", sizeof(outName));
+ break;
+
+ default:
+ CACopy4CCToCString(outName, inDescription.mFormatID);
+ break;
+ };
+}
+
+#if CoreAudio_Debug
+#include "CALogMacros.h"
+
+void CAStreamBasicDescription::PrintToLog(const AudioStreamBasicDescription& inDesc)
+{
+ PrintFloat (" Sample Rate: ", inDesc.mSampleRate);
+ Print4CharCode (" Format ID: ", inDesc.mFormatID);
+ PrintHex (" Format Flags: ", inDesc.mFormatFlags);
+ PrintInt (" Bytes per Packet: ", inDesc.mBytesPerPacket);
+ PrintInt (" Frames per Packet: ", inDesc.mFramesPerPacket);
+ PrintInt (" Bytes per Frame: ", inDesc.mBytesPerFrame);
+ PrintInt (" Channels per Frame: ", inDesc.mChannelsPerFrame);
+ PrintInt (" Bits per Channel: ", inDesc.mBitsPerChannel);
+}
+#endif
+
+bool operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
+{
+ bool theAnswer = false;
+ bool isDone = false;
+
+ // note that if either side is 0, that field is skipped
+
+ // format ID is the first order sort
+ if((!isDone) && ((x.mFormatID != 0) && (y.mFormatID != 0)))
+ {
+ if(x.mFormatID != y.mFormatID)
+ {
+ // formats are sorted numerically except that linear
+ // PCM is always first
+ if(x.mFormatID == kAudioFormatLinearPCM)
+ {
+ theAnswer = true;
+ }
+ else if(y.mFormatID == kAudioFormatLinearPCM)
+ {
+ theAnswer = false;
+ }
+ else
+ {
+ theAnswer = x.mFormatID < y.mFormatID;
+ }
+ isDone = true;
+ }
+ }
+
+
+ // mixable is always better than non-mixable for linear PCM and should be the second order sort item
+ if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
+ {
+ if(((x.mFormatFlags & kIsNonMixableFlag) == 0) && ((y.mFormatFlags & kIsNonMixableFlag) != 0))
+ {
+ theAnswer = true;
+ isDone = true;
+ }
+ else if(((x.mFormatFlags & kIsNonMixableFlag) != 0) && ((y.mFormatFlags & kIsNonMixableFlag) == 0))
+ {
+ theAnswer = false;
+ isDone = true;
+ }
+ }
+
+ // floating point vs integer for linear PCM only
+ if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
+ {
+ if((x.mFormatFlags & kAudioFormatFlagIsFloat) != (y.mFormatFlags & kAudioFormatFlagIsFloat))
+ {
+ // floating point is better than integer
+ theAnswer = y.mFormatFlags & kAudioFormatFlagIsFloat;
+ isDone = true;
+ }
+ }
+
+ // bit depth
+ if((!isDone) && ((x.mBitsPerChannel != 0) && (y.mBitsPerChannel != 0)))
+ {
+ if(x.mBitsPerChannel != y.mBitsPerChannel)
+ {
+ // deeper bit depths are higher quality
+ theAnswer = x.mBitsPerChannel < y.mBitsPerChannel;
+ isDone = true;
+ }
+ }
+
+ // sample rate
+ if((!isDone) && fnonzero(x.mSampleRate) && fnonzero(y.mSampleRate))
+ {
+ if(fnotequal(x.mSampleRate, y.mSampleRate))
+ {
+ // higher sample rates are higher quality
+ theAnswer = x.mSampleRate < y.mSampleRate;
+ isDone = true;
+ }
+ }
+
+ // number of channels
+ if((!isDone) && ((x.mChannelsPerFrame != 0) && (y.mChannelsPerFrame != 0)))
+ {
+ if(x.mChannelsPerFrame != y.mChannelsPerFrame)
+ {
+ // more channels is higher quality
+ theAnswer = x.mChannelsPerFrame < y.mChannelsPerFrame;
+ //isDone = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+void CAStreamBasicDescription::ModifyFormatFlagsForMatching(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y, UInt32& xFlags, UInt32& yFlags, bool converterOnly )
+{
+ // match wildcards
+ if (x.mFormatID == 0 || y.mFormatID == 0 || xFlags == 0 || yFlags == 0)
+ {
+ // Obliterate all flags.
+ xFlags = yFlags = 0;
+ return;
+ }
+
+ if (x.mFormatID == kAudioFormatLinearPCM) {
+ // knock off the all clear flag
+ xFlags = xFlags & ~kAudioFormatFlagsAreAllClear;
+ yFlags = yFlags & ~kAudioFormatFlagsAreAllClear;
+
+ // if both kAudioFormatFlagIsPacked bits are set, then we don't care about the kAudioFormatFlagIsAlignedHigh bit.
+ if (xFlags & yFlags & kAudioFormatFlagIsPacked) {
+ xFlags = xFlags & ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
+ yFlags = yFlags & ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
+ }
+
+ // if both kAudioFormatFlagIsFloat bits are set, then we don't care about the kAudioFormatFlagIsSignedInteger bit.
+ if (xFlags & yFlags & kAudioFormatFlagIsFloat) {
+ xFlags = xFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger);
+ yFlags = yFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger);
+ }
+
+ // if the bit depth is 8 bits or less and the format is packed, we don't care about endianness
+ if((x.mBitsPerChannel <= 8) && ((xFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked))
+ {
+ xFlags = xFlags & ~static_cast<UInt32>(kAudioFormatFlagIsBigEndian);
+ }
+ if((y.mBitsPerChannel <= 8) && ((yFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked))
+ {
+ yFlags = yFlags & ~static_cast<UInt32>(kAudioFormatFlagIsBigEndian);
+ }
+
+ // if the number of channels is 1, we don't care about non-interleavedness
+ if (x.mChannelsPerFrame == 1 && y.mChannelsPerFrame == 1) {
+ xFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsNonInterleaved);
+ yFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsNonInterleaved);
+ }
+
+ if (converterOnly) {
+ CAStreamBasicDescription cas_x = CAStreamBasicDescription(x);
+ CAStreamBasicDescription cas_y = CAStreamBasicDescription(y);
+ if (!cas_x.PackednessIsSignificant() && !cas_y.PackednessIsSignificant()) {
+ xFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsPacked);
+ yFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsPacked);
+ }
+ if (!cas_x.AlignmentIsSignificant() && !cas_y.AlignmentIsSignificant()) {
+ xFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
+ yFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
+ }
+ // We don't care about whether the streams are mixable in this case
+ xFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonMixable);
+ yFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonMixable);
+ }
+ }
+}
+
+static bool MatchFormatFlags(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
+{
+ UInt32 xFlags = x.mFormatFlags;
+ UInt32 yFlags = y.mFormatFlags;
+
+ CAStreamBasicDescription::ModifyFormatFlagsForMatching(x, y, xFlags, yFlags, false);
+ return xFlags == yFlags;
+}
+
+bool operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
+{
+ // the semantics for equality are:
+ // 1) Values must match exactly -- except for PCM format flags, see above.
+ // 2) wildcard's are ignored in the comparison
+
+#define MATCH(name) ((x.name) == 0 || (y.name) == 0 || (x.name) == (y.name))
+
+ return
+ // check all but the format flags
+ CAStreamBasicDescription::FlagIndependentEquivalence(x, y)
+ // check the format flags
+ && MatchFormatFlags(x, y);
+}
+
+bool CAStreamBasicDescription::FlagIndependentEquivalence(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y)
+{
+ return
+ // check the sample rate
+ (fiszero(x.mSampleRate) || fiszero(y.mSampleRate) || fequal(x.mSampleRate, y.mSampleRate))
+
+ // check the format ids
+ && MATCH(mFormatID)
+
+ // check the bytes per packet
+ && MATCH(mBytesPerPacket)
+
+ // check the frames per packet
+ && MATCH(mFramesPerPacket)
+
+ // check the bytes per frame
+ && MATCH(mBytesPerFrame)
+
+ // check the channels per frame
+ && MATCH(mChannelsPerFrame)
+
+ // check the channels per frame
+ && MATCH(mBitsPerChannel) ;
+}
+
+bool CAStreamBasicDescription::IsEqual(const AudioStreamBasicDescription &other, bool interpretingWildcards) const
+{
+ if (interpretingWildcards)
+ return *this == other;
+ return memcmp(this, &other, offsetof(AudioStreamBasicDescription, mReserved)) == 0;
+}
+
+bool CAStreamBasicDescription::IsFunctionallyEquivalent(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y)
+{
+ UInt32 xFlags = x.mFormatFlags, yFlags = y.mFormatFlags;
+ CAStreamBasicDescription::ModifyFormatFlagsForMatching(x, y, xFlags, yFlags, true);
+
+ return
+ // check all but the format flags
+ CAStreamBasicDescription::FlagIndependentEquivalence(x, y)
+ // check the format flags with converter focus
+ && (xFlags == yFlags);
+
+}
+
+bool SanityCheck(const AudioStreamBasicDescription& x)
+{
+ // This function returns false if there are sufficiently insane values in any field.
+ // It is very conservative so even some very unlikely values will pass.
+ // This is just meant to catch the case where the data from a file is corrupted.
+
+ return
+ (x.mSampleRate >= 0.)
+ && (x.mSampleRate < 3e6) // SACD sample rate is 2.8224 MHz
+ && (x.mBytesPerPacket < 1000000)
+ && (x.mFramesPerPacket < 1000000)
+ && (x.mBytesPerFrame < 1000000)
+ && (x.mChannelsPerFrame <= 1024)
+ && (x.mBitsPerChannel <= 1024)
+ && (x.mFormatID != 0)
+ && !(x.mFormatID == kAudioFormatLinearPCM && (x.mFramesPerPacket != 1 || x.mBytesPerPacket != x.mBytesPerFrame));
+}
+
+bool CAStreamBasicDescription::FromText(const char *inTextDesc, AudioStreamBasicDescription &fmt)
+{
+ const char *p = inTextDesc;
+
+ memset(&fmt, 0, sizeof(fmt));
+
+ bool isPCM = true; // until proven otherwise
+ UInt32 pcmFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
+
+ if (p[0] == '-') // previously we required a leading dash on PCM formats
+ ++p;
+
+ if (p[0] == 'B' && p[1] == 'E') {
+ pcmFlags |= kLinearPCMFormatFlagIsBigEndian;
+ p += 2;
+ } else if (p[0] == 'L' && p[1] == 'E') {
+ p += 2;
+ } else {
+ // default is native-endian
+#if TARGET_RT_BIG_ENDIAN
+ pcmFlags |= kLinearPCMFormatFlagIsBigEndian;
+#endif
+ }
+ if (p[0] == 'F') {
+ pcmFlags = (pcmFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger)) | kAudioFormatFlagIsFloat;
+ ++p;
+ } else {
+ if (p[0] == 'U') {
+ pcmFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger);
+ ++p;
+ }
+ if (p[0] == 'I')
+ ++p;
+ else {
+ // it's not PCM; presumably some other format (NOT VALIDATED; use AudioFormat for that)
+ isPCM = false;
+ p = inTextDesc; // go back to the beginning
+ char buf[4] = { ' ',' ',' ',' ' };
+ for (int i = 0; i < 4; ++i) {
+ if (*p != '\\') {
+ if ((buf[i] = *p++) == '\0') {
+ // special-case for 'aac'
+ if (i != 3) return false;
+ --p; // keep pointing at the terminating null
+ buf[i] = ' ';
+ break;
+ }
+ } else {
+ // "\xNN" is a hex byte
+ if (*++p != 'x') return false;
+ int x;
+ if (sscanf(++p, "%02X", &x) != 1) return false;
+ buf[i] = static_cast<char>(x);
+ p += 2;
+ }
+ }
+
+ if (strchr("-@/#", buf[3])) {
+ // further special-casing for 'aac'
+ buf[3] = ' ';
+ --p;
+ }
+
+ memcpy(&fmt.mFormatID, buf, 4);
+ fmt.mFormatID = CFSwapInt32BigToHost(fmt.mFormatID);
+ }
+ }
+
+ if (isPCM) {
+ fmt.mFormatID = kAudioFormatLinearPCM;
+ fmt.mFormatFlags = pcmFlags;
+ fmt.mFramesPerPacket = 1;
+ fmt.mChannelsPerFrame = 1;
+ UInt32 bitdepth = 0, fracbits = 0;
+ while (isdigit(*p))
+ bitdepth = 10 * bitdepth + static_cast<UInt32>(*p++ - '0');
+ if (*p == '.') {
+ ++p;
+ if (!isdigit(*p)) {
+ fprintf(stderr, "Expected fractional bits following '.'\n");
+ goto Bail;
+ }
+ while (isdigit(*p))
+ fracbits = 10 * fracbits + static_cast<UInt32>(*p++ - '0');
+ bitdepth += fracbits;
+ fmt.mFormatFlags |= (fracbits << kLinearPCMFormatFlagsSampleFractionShift);
+ }
+ fmt.mBitsPerChannel = bitdepth;
+ fmt.mBytesPerPacket = fmt.mBytesPerFrame = (bitdepth + 7) / 8;
+ if (bitdepth & 7) {
+ // assume unpacked. (packed odd bit depths are describable but not supported in AudioConverter.)
+ fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsPacked);
+ // alignment matters; default to high-aligned. use ':L_' for low.
+ fmt.mFormatFlags |= kLinearPCMFormatFlagIsAlignedHigh;
+ }
+ }
+ if (*p == '@') {
+ ++p;
+ while (isdigit(*p))
+ fmt.mSampleRate = 10 * fmt.mSampleRate + (*p++ - '0');
+ }
+ if (*p == '/') {
+ UInt32 flags = 0;
+ while (true) {
+ char c = *++p;
+ if (c >= '0' && c <= '9')
+ flags = (flags << 4) | static_cast<UInt32>(c - '0');
+ else if (c >= 'A' && c <= 'F')
+ flags = (flags << 4) | static_cast<UInt32>(c - 'A' + 10);
+ else if (c >= 'a' && c <= 'f')
+ flags = (flags << 4) | static_cast<UInt32>(c - 'a' + 10);
+ else break;
+ }
+ fmt.mFormatFlags = flags;
+ }
+ if (*p == '#') {
+ ++p;
+ while (isdigit(*p))
+ fmt.mFramesPerPacket = 10 * fmt.mFramesPerPacket + static_cast<UInt32>(*p++ - '0');
+ }
+ if (*p == ':') {
+ ++p;
+ fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsPacked);
+ if (*p == 'L')
+ fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsAlignedHigh);
+ else if (*p == 'H')
+ fmt.mFormatFlags |= kLinearPCMFormatFlagIsAlignedHigh;
+ else
+ goto Bail;
+ ++p;
+ UInt32 bytesPerFrame = 0;
+ while (isdigit(*p))
+ bytesPerFrame = 10 * bytesPerFrame + static_cast<UInt32>(*p++ - '0');
+ fmt.mBytesPerFrame = fmt.mBytesPerPacket = bytesPerFrame;
+ }
+ if (*p == ',') {
+ ++p;
+ int ch = 0;
+ while (isdigit(*p))
+ ch = 10 * ch + (*p++ - '0');
+ fmt.mChannelsPerFrame = static_cast<UInt32>(ch);
+ if (*p == 'D') {
+ ++p;
+ if (fmt.mFormatID != kAudioFormatLinearPCM) {
+ fprintf(stderr, "non-interleaved flag invalid for non-PCM formats\n");
+ goto Bail;
+ }
+ fmt.mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+ } else {
+ if (*p == 'I') ++p; // default
+ if (fmt.mFormatID == kAudioFormatLinearPCM)
+ fmt.mBytesPerPacket = fmt.mBytesPerFrame *= static_cast<UInt32>(ch);
+ }
+ }
+ if (*p != '\0') {
+ fprintf(stderr, "extra characters at end of format string: %s\n", p);
+ goto Bail;
+ }
+ return true;
+
+Bail:
+ fprintf(stderr, "Invalid format string: %s\n", inTextDesc);
+ fprintf(stderr, "Syntax of format strings is: \n");
+ return false;
+}
+
+const char *CAStreamBasicDescription::sTextParsingUsageString =
+ "format[@sample_rate_hz][/format_flags][#frames_per_packet][:LHbytesPerFrame][,channelsDI].\n"
+ "Format for PCM is [-][BE|LE]{F|I|UI}{bitdepth}; else a 4-char format code (e.g. aac, alac).\n";
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h b/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h
new file mode 100644
index 0000000000..8b81dba69a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h
@@ -0,0 +1,424 @@
+/*
+ File: CAStreamBasicDescription.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAStreamBasicDescription_h__
+#define __CAStreamBasicDescription_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include "CoreAudioTypes.h"
+ #include "CoreFoundation.h"
+#endif
+
+#include "CADebugMacros.h"
+#include <string.h> // for memset, memcpy
+#include <stdio.h> // for FILE *
+
+#pragma mark This file needs to compile on more earlier versions of the OS, so please keep that in mind when editing it
+
+extern char *CAStringForOSType (OSType t, char *writeLocation, size_t bufsize);
+
+// define Leopard specific symbols for backward compatibility if applicable
+#if COREAUDIOTYPES_VERSION < 1050
+typedef Float32 AudioSampleType;
+enum { kAudioFormatFlagsCanonical = kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked };
+#endif
+#if COREAUDIOTYPES_VERSION < 1051
+typedef Float32 AudioUnitSampleType;
+enum {
+ kLinearPCMFormatFlagsSampleFractionShift = 7,
+ kLinearPCMFormatFlagsSampleFractionMask = (0x3F << kLinearPCMFormatFlagsSampleFractionShift),
+};
+#endif
+
+// define the IsMixable format flag for all versions of the system
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3)
+ enum { kIsNonMixableFlag = kAudioFormatFlagIsNonMixable };
+#else
+ enum { kIsNonMixableFlag = (1L << 6) };
+#endif
+
+//=============================================================================
+// CAStreamBasicDescription
+//
+// This is a wrapper class for the AudioStreamBasicDescription struct.
+// It adds a number of convenience routines, but otherwise adds nothing
+// to the footprint of the original struct.
+//=============================================================================
+class CAStreamBasicDescription :
+ public AudioStreamBasicDescription
+{
+
+// Constants
+public:
+ static const AudioStreamBasicDescription sEmpty;
+
+ enum CommonPCMFormat {
+ kPCMFormatOther = 0,
+ kPCMFormatFloat32 = 1,
+ kPCMFormatInt16 = 2,
+ kPCMFormatFixed824 = 3,
+ kPCMFormatFloat64 = 4
+ };
+
+// Construction/Destruction
+public:
+ CAStreamBasicDescription();
+
+ CAStreamBasicDescription(const AudioStreamBasicDescription &desc);
+
+ CAStreamBasicDescription( double inSampleRate, UInt32 inFormatID,
+ UInt32 inBytesPerPacket, UInt32 inFramesPerPacket,
+ UInt32 inBytesPerFrame, UInt32 inChannelsPerFrame,
+ UInt32 inBitsPerChannel, UInt32 inFormatFlags);
+
+ CAStreamBasicDescription( double inSampleRate, UInt32 inNumChannels, CommonPCMFormat pcmf, bool inIsInterleaved) {
+ unsigned wordsize;
+
+ mSampleRate = inSampleRate;
+ mFormatID = kAudioFormatLinearPCM;
+ mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
+ mFramesPerPacket = 1;
+ mChannelsPerFrame = inNumChannels;
+ mBytesPerFrame = mBytesPerPacket = 0;
+ mReserved = 0;
+
+ switch (pcmf) {
+ default:
+ return;
+ case kPCMFormatFloat32:
+ wordsize = 4;
+ mFormatFlags |= kAudioFormatFlagIsFloat;
+ break;
+ case kPCMFormatFloat64:
+ wordsize = 8;
+ mFormatFlags |= kAudioFormatFlagIsFloat;
+ break;
+ case kPCMFormatInt16:
+ wordsize = 2;
+ mFormatFlags |= kAudioFormatFlagIsSignedInteger;
+ break;
+ case kPCMFormatFixed824:
+ wordsize = 4;
+ mFormatFlags |= kAudioFormatFlagIsSignedInteger | (24 << kLinearPCMFormatFlagsSampleFractionShift);
+ break;
+ }
+ mBitsPerChannel = wordsize * 8;
+ if (inIsInterleaved)
+ mBytesPerFrame = mBytesPerPacket = wordsize * inNumChannels;
+ else {
+ mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+ mBytesPerFrame = mBytesPerPacket = wordsize;
+ }
+ }
+
+// Assignment
+ CAStreamBasicDescription& operator=(const AudioStreamBasicDescription& v) { SetFrom(v); return *this; }
+
+ void SetFrom(const AudioStreamBasicDescription &desc)
+ {
+ memcpy(this, &desc, sizeof(AudioStreamBasicDescription));
+ }
+
+ bool FromText(const char *inTextDesc) { return FromText(inTextDesc, *this); }
+ static bool FromText(const char *inTextDesc, AudioStreamBasicDescription &outDesc);
+ // return true if parsing was successful
+
+ static const char *sTextParsingUsageString;
+
+ // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ //
+ // interrogation
+
+ bool IsPCM() const { return mFormatID == kAudioFormatLinearPCM; }
+
+ bool PackednessIsSignificant() const
+ {
+ Assert(IsPCM(), "PackednessIsSignificant only applies for PCM");
+ return (SampleWordSize() << 3) != mBitsPerChannel;
+ }
+
+ bool AlignmentIsSignificant() const
+ {
+ return PackednessIsSignificant() || (mBitsPerChannel & 7) != 0;
+ }
+
+ bool IsInterleaved() const
+ {
+ return !(mFormatFlags & kAudioFormatFlagIsNonInterleaved);
+ }
+
+ bool IsSignedInteger() const
+ {
+ return IsPCM() && (mFormatFlags & kAudioFormatFlagIsSignedInteger);
+ }
+
+ bool IsFloat() const
+ {
+ return IsPCM() && (mFormatFlags & kAudioFormatFlagIsFloat);
+ }
+
+ bool IsNativeEndian() const
+ {
+ return (mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian;
+ }
+
+ // for sanity with interleaved/deinterleaved possibilities, never access mChannelsPerFrame, use these:
+ UInt32 NumberInterleavedChannels() const { return IsInterleaved() ? mChannelsPerFrame : 1; }
+ UInt32 NumberChannelStreams() const { return IsInterleaved() ? 1 : mChannelsPerFrame; }
+ UInt32 NumberChannels() const { return mChannelsPerFrame; }
+ UInt32 SampleWordSize() const {
+ return (mBytesPerFrame > 0 && NumberInterleavedChannels()) ? mBytesPerFrame / NumberInterleavedChannels() : 0;
+ }
+
+ UInt32 FramesToBytes(UInt32 nframes) const { return nframes * mBytesPerFrame; }
+ UInt32 BytesToFrames(UInt32 nbytes) const {
+ Assert(mBytesPerFrame > 0, "bytesPerFrame must be > 0 in BytesToFrames");
+ return nbytes / mBytesPerFrame;
+ }
+
+ bool SameChannelsAndInterleaving(const CAStreamBasicDescription &a) const
+ {
+ return this->NumberChannels() == a.NumberChannels() && this->IsInterleaved() == a.IsInterleaved();
+ }
+
+ bool IdentifyCommonPCMFormat(CommonPCMFormat &outFormat, bool *outIsInterleaved=NULL) const
+ { // return true if it's a valid PCM format.
+
+ outFormat = kPCMFormatOther;
+ // trap out patently invalid formats.
+ if (mFormatID != kAudioFormatLinearPCM || mFramesPerPacket != 1 || mBytesPerFrame != mBytesPerPacket || mBitsPerChannel/8 > mBytesPerFrame || mChannelsPerFrame == 0)
+ return false;
+ bool interleaved = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
+ if (outIsInterleaved != NULL) *outIsInterleaved = interleaved;
+ unsigned wordsize = mBytesPerFrame;
+ if (interleaved) {
+ if (wordsize % mChannelsPerFrame != 0) return false;
+ wordsize /= mChannelsPerFrame;
+ }
+
+ if ((mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian
+ && wordsize * 8 == mBitsPerChannel) {
+ // packed and native endian, good
+ if (mFormatFlags & kLinearPCMFormatFlagIsFloat) {
+ // float: reject nonsense bits
+ if (mFormatFlags & (kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagsSampleFractionMask))
+ return false;
+ if (wordsize == 4)
+ outFormat = kPCMFormatFloat32;
+ if (wordsize == 8)
+ outFormat = kPCMFormatFloat64;
+ } else if (mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) {
+ // signed int
+ unsigned fracbits = (mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
+ if (wordsize == 4 && fracbits == 24)
+ outFormat = kPCMFormatFixed824;
+ else if (wordsize == 2 && fracbits == 0)
+ outFormat = kPCMFormatInt16;
+ }
+ }
+ return true;
+ }
+
+ bool IsCommonFloat32(bool *outIsInterleaved=NULL) const {
+ CommonPCMFormat fmt;
+ return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFloat32;
+ }
+ bool IsCommonFloat64(bool *outIsInterleaved=NULL) const {
+ CommonPCMFormat fmt;
+ return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFloat64;
+ }
+ bool IsCommonFixed824(bool *outIsInterleaved=NULL) const {
+ CommonPCMFormat fmt;
+ return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFixed824;
+ }
+ bool IsCommonInt16(bool *outIsInterleaved=NULL) const {
+ CommonPCMFormat fmt;
+ return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatInt16;
+ }
+
+ // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ //
+ // manipulation
+
+ void SetCanonical(UInt32 nChannels, bool interleaved)
+ // note: leaves sample rate untouched
+ {
+ mFormatID = kAudioFormatLinearPCM;
+ UInt32 sampleSize = SizeOf32(AudioSampleType);
+ mFormatFlags = kAudioFormatFlagsCanonical;
+ mBitsPerChannel = 8 * sampleSize;
+ mChannelsPerFrame = nChannels;
+ mFramesPerPacket = 1;
+ if (interleaved)
+ mBytesPerPacket = mBytesPerFrame = nChannels * sampleSize;
+ else {
+ mBytesPerPacket = mBytesPerFrame = sampleSize;
+ mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+ }
+ }
+
+ bool IsCanonical() const
+ {
+ if (mFormatID != kAudioFormatLinearPCM) return false;
+ UInt32 reqFormatFlags;
+ UInt32 flagsMask = (kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagsSampleFractionMask);
+ bool interleaved = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
+ unsigned sampleSize = SizeOf32(AudioSampleType);
+ reqFormatFlags = kAudioFormatFlagsCanonical;
+ UInt32 reqFrameSize = interleaved ? (mChannelsPerFrame * sampleSize) : sampleSize;
+
+ return ((mFormatFlags & flagsMask) == reqFormatFlags
+ && mBitsPerChannel == 8 * sampleSize
+ && mFramesPerPacket == 1
+ && mBytesPerFrame == reqFrameSize
+ && mBytesPerPacket == reqFrameSize);
+ }
+
+ void SetAUCanonical(UInt32 nChannels, bool interleaved)
+ {
+ mFormatID = kAudioFormatLinearPCM;
+#if CA_PREFER_FIXED_POINT
+ mFormatFlags = kAudioFormatFlagsCanonical | (kAudioUnitSampleFractionBits << kLinearPCMFormatFlagsSampleFractionShift);
+#else
+ mFormatFlags = kAudioFormatFlagsCanonical;
+#endif
+ mChannelsPerFrame = nChannels;
+ mFramesPerPacket = 1;
+ mBitsPerChannel = 8 * SizeOf32(AudioUnitSampleType);
+ if (interleaved)
+ mBytesPerPacket = mBytesPerFrame = nChannels * SizeOf32(AudioUnitSampleType);
+ else {
+ mBytesPerPacket = mBytesPerFrame = SizeOf32(AudioUnitSampleType);
+ mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+ }
+ }
+
+ void ChangeNumberChannels(UInt32 nChannels, bool interleaved)
+ // alter an existing format
+ {
+ Assert(IsPCM(), "ChangeNumberChannels only works for PCM formats");
+ UInt32 wordSize = SampleWordSize(); // get this before changing ANYTHING
+ if (wordSize == 0)
+ wordSize = (mBitsPerChannel + 7) / 8;
+ mChannelsPerFrame = nChannels;
+ mFramesPerPacket = 1;
+ if (interleaved) {
+ mBytesPerPacket = mBytesPerFrame = nChannels * wordSize;
+ mFormatFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonInterleaved);
+ } else {
+ mBytesPerPacket = mBytesPerFrame = wordSize;
+ mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+ }
+ }
+
+ // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ //
+ // other
+
+ bool IsEqual(const AudioStreamBasicDescription &other, bool interpretingWildcards=true) const;
+ static bool FlagIndependentEquivalence(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y);
+ static bool IsFunctionallyEquivalent(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y);
+
+ void Print() const {
+ Print (stdout);
+ }
+
+ void Print(FILE* file) const {
+ PrintFormat (file, "", "AudioStreamBasicDescription:");
+ }
+
+ void PrintFormat(FILE *f, const char *indent, const char *name) const {
+ char buf[256];
+ fprintf(f, "%s%s %s\n", indent, name, AsString(buf, sizeof(buf)));
+ }
+
+ void PrintFormat2(FILE *f, const char *indent, const char *name) const { // no trailing newline
+ char buf[256];
+ fprintf(f, "%s%s %s", indent, name, AsString(buf, sizeof(buf)));
+ }
+
+ char * AsString(char *buf, size_t bufsize, bool brief=false) const;
+
+ static void Print (const AudioStreamBasicDescription &inDesc)
+ {
+ CAStreamBasicDescription desc(inDesc);
+ desc.Print ();
+ }
+
+ OSStatus Save(CFPropertyListRef *outData) const;
+
+ OSStatus Restore(CFPropertyListRef &inData);
+
+// Operations
+ static bool IsMixable(const AudioStreamBasicDescription& inDescription) { return (inDescription.mFormatID == kAudioFormatLinearPCM) && ((inDescription.mFormatFlags & kIsNonMixableFlag) == 0); }
+ static void NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription);
+ static void NormalizeLinearPCMFormat(bool inNativeEndian, AudioStreamBasicDescription& ioDescription);
+ static void ResetFormat(AudioStreamBasicDescription& ioDescription);
+ static void FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription);
+ static void GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, UInt32 inMaxNameLength, bool inAbbreviate, bool inIncludeSampleRate = false);
+ static void ModifyFormatFlagsForMatching(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y, UInt32& xFlags, UInt32& yFlags, bool converterOnly);
+
+#if CoreAudio_Debug
+ static void PrintToLog(const AudioStreamBasicDescription& inDesc);
+#endif
+};
+
+bool operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y);
+bool operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y);
+#if TARGET_OS_MAC || (TARGET_OS_WIN32 && (_MSC_VER > 600))
+inline bool operator!=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x == y); }
+inline bool operator<=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return (x < y) || (x == y); }
+inline bool operator>=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x < y); }
+inline bool operator>(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !((x < y) || (x == y)); }
+#endif
+
+bool SanityCheck(const AudioStreamBasicDescription& x);
+
+
+#endif // __CAStreamBasicDescription_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.cpp
new file mode 100644
index 0000000000..9b72054101
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.cpp
@@ -0,0 +1,183 @@
+/*
+ File: CAStreamRangedDescription.cpp
+ Abstract: CAStreamRangedDescription.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CAStreamRangedDescription.h"
+#include "CAMath.h"
+
+//==================================================================================================
+// CAStreamRangedDescription
+//==================================================================================================
+
+const AudioStreamRangedDescription CAStreamRangedDescription::sEmpty = { { 0.0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0.0, 0.0 } };
+
+#if CoreAudio_Debug
+#include "CALogMacros.h"
+
+void CAStreamRangedDescription::PrintToLog(const AudioStreamRangedDescription& inDesc)
+{
+ PrintFloat (" Sample Rate: ", inDesc.mFormat.mSampleRate);
+ PrintFloat (" Max Sample Rate: ", inDesc.mSampleRateRange.mMaximum);
+ PrintFloat (" Min Sample Rate: ", inDesc.mSampleRateRange.mMinimum);
+ Print4CharCode (" Format ID: ", inDesc.mFormat.mFormatID);
+ PrintHex (" Format Flags: ", inDesc.mFormat.mFormatFlags);
+ PrintInt (" Bytes per Packet: ", inDesc.mFormat.mBytesPerPacket);
+ PrintInt (" Frames per Packet: ", inDesc.mFormat.mFramesPerPacket);
+ PrintInt (" Bytes per Frame: ", inDesc.mFormat.mBytesPerFrame);
+ PrintInt (" Channels per Frame: ", inDesc.mFormat.mChannelsPerFrame);
+ PrintInt (" Bits per Channel: ", inDesc.mFormat.mBitsPerChannel);
+}
+#endif
+
+bool CAStreamRangedDescription::Sorter(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y)
+{
+ bool theAnswer = false;
+ bool isDone = false;
+
+ // note that if either side is 0, that field is skipped
+
+ // format ID is the first order sort
+ if((!isDone) && ((x.mFormat.mFormatID != 0) && (y.mFormat.mFormatID != 0)))
+ {
+ if(x.mFormat.mFormatID != y.mFormat.mFormatID)
+ {
+ // formats are sorted numerically except that linear
+ // PCM is always first
+ if(x.mFormat.mFormatID == kAudioFormatLinearPCM)
+ {
+ theAnswer = true;
+ }
+ else if(y.mFormat.mFormatID == kAudioFormatLinearPCM)
+ {
+ theAnswer = false;
+ }
+ else
+ {
+ theAnswer = x.mFormat.mFormatID < y.mFormat.mFormatID;
+ }
+ isDone = true;
+ }
+ }
+
+
+ // mixable is always better than non-mixable for linear PCM and should be the second order sort item
+ if((!isDone) && ((x.mFormat.mFormatID == kAudioFormatLinearPCM) && (y.mFormat.mFormatID == kAudioFormatLinearPCM)))
+ {
+ if(((x.mFormat.mFormatFlags & kIsNonMixableFlag) == 0) && ((y.mFormat.mFormatFlags & kIsNonMixableFlag) != 0))
+ {
+ theAnswer = true;
+ isDone = true;
+ }
+ else if(((x.mFormat.mFormatFlags & kIsNonMixableFlag) != 0) && ((y.mFormat.mFormatFlags & kIsNonMixableFlag) == 0))
+ {
+ theAnswer = false;
+ isDone = true;
+ }
+ }
+
+ // floating point vs integer for linear PCM only
+ if((!isDone) && ((x.mFormat.mFormatID == kAudioFormatLinearPCM) && (y.mFormat.mFormatID == kAudioFormatLinearPCM)))
+ {
+ if((x.mFormat.mFormatFlags & kAudioFormatFlagIsFloat) != (y.mFormat.mFormatFlags & kAudioFormatFlagIsFloat))
+ {
+ // floating point is better than integer
+ theAnswer = y.mFormat.mFormatFlags & kAudioFormatFlagIsFloat;
+ isDone = true;
+ }
+ }
+
+ // bit depth
+ if((!isDone) && ((x.mFormat.mBitsPerChannel != 0) && (y.mFormat.mBitsPerChannel != 0)))
+ {
+ if(x.mFormat.mBitsPerChannel != y.mFormat.mBitsPerChannel)
+ {
+ // deeper bit depths are higher quality
+ theAnswer = x.mFormat.mBitsPerChannel > y.mFormat.mBitsPerChannel;
+ isDone = true;
+ }
+ }
+
+ // sample rate range
+ if((!isDone) && fnonzero(x.mSampleRateRange.mMinimum) && fnonzero(x.mSampleRateRange.mMaximum) && fnonzero(y.mSampleRateRange.mMinimum) && fnonzero(y.mSampleRateRange.mMaximum))
+ {
+ if(x.mSampleRateRange != y.mSampleRateRange)
+ {
+ // higher sample rates are higher quality
+ theAnswer = x.mSampleRateRange > y.mSampleRateRange;
+ isDone = true;
+ }
+ }
+
+ // sample rate
+ if((!isDone) && fnonzero(x.mFormat.mSampleRate) && fnonzero(y.mFormat.mSampleRate))
+ {
+ if(fnotequal(x.mFormat.mSampleRate, y.mFormat.mSampleRate))
+ {
+ // higher sample rates are higher quality
+ theAnswer = x.mFormat.mSampleRate > y.mFormat.mSampleRate;
+ isDone = true;
+ }
+ }
+
+ // number of channels
+ if((!isDone) && ((x.mFormat.mChannelsPerFrame != 0) && (y.mFormat.mChannelsPerFrame != 0)))
+ {
+ if(x.mFormat.mChannelsPerFrame != y.mFormat.mChannelsPerFrame)
+ {
+ // more channels is higher quality
+ theAnswer = x.mFormat.mChannelsPerFrame < y.mFormat.mChannelsPerFrame;
+ // commented out to prevent this from being flagged as a dead store by the static analyzer
+ //isDone = true;
+ }
+ }
+
+ return theAnswer;
+}
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.h b/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.h
new file mode 100644
index 0000000000..7f8284dee0
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.h
@@ -0,0 +1,140 @@
+/*
+ File: CAStreamRangedDescription.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAStreamRangedDescription_h__)
+#define __CAStreamRangedDescription_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Super Class Includes
+#include <CoreAudio/AudioHardware.h>
+
+// PublicUtility Includes
+#include "CAAudioValueRange.h"
+#include "CAStreamBasicDescription.h"
+
+//==================================================================================================
+// CAStreamRangedDescription
+//==================================================================================================
+
+class CAStreamRangedDescription
+:
+ public AudioStreamRangedDescription
+{
+
+// Constants
+public:
+ static const AudioStreamRangedDescription sEmpty;
+
+// Construction/Destruction
+public:
+ CAStreamRangedDescription() { memset(this, 0, sizeof(AudioStreamRangedDescription)); }
+ CAStreamRangedDescription(const CAStreamRangedDescription& inFormat) { mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; }
+ CAStreamRangedDescription(const AudioStreamRangedDescription& inFormat) { mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; }
+ CAStreamRangedDescription(const AudioStreamBasicDescription& inFormat) { mFormat = inFormat; mSampleRateRange.mMinimum = inFormat.mSampleRate; mSampleRateRange.mMaximum = inFormat.mSampleRate; }
+ CAStreamRangedDescription(const AudioStreamBasicDescription& inFormat, const AudioValueRange& inSampleRateRange) { mFormat = inFormat; mSampleRateRange = inSampleRateRange; }
+ CAStreamRangedDescription& operator=(const CAStreamRangedDescription& inFormat) { mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; return *this; }
+ CAStreamRangedDescription& operator=(const AudioStreamRangedDescription& inFormat) { mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; return *this; }
+
+ static bool IsMixable(const AudioStreamRangedDescription& inDescription) { return (inDescription.mFormat.mFormatID == kAudioFormatLinearPCM) && ((inDescription.mFormat.mFormatFlags & kIsNonMixableFlag) == 0); }
+#if CoreAudio_Debug
+ static void PrintToLog(const AudioStreamRangedDescription& inDesc);
+#endif
+ static bool Sorter(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y);
+
+};
+
+inline bool operator<(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return (x.mFormat.mFormatID == y.mFormat.mFormatID) ?
+ (x.mFormat < y.mFormat) && (x.mSampleRateRange < y.mSampleRateRange) :
+ (x.mFormat.mFormatID == kAudioFormatLinearPCM) ? false : (x.mFormat.mFormatID < y.mFormat.mFormatID); }
+inline bool operator==(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return (x.mFormat == y.mFormat) && (x.mSampleRateRange == y.mSampleRateRange); }
+#if TARGET_OS_MAC || (TARGET_OS_WIN32 && (_MSC_VER > 600))
+inline bool operator!=(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return !(x == y); }
+inline bool operator<=(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return (x < y) || (x == y); }
+inline bool operator>=(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return !(x < y); }
+inline bool operator>(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return !((x < y) || (x == y)); }
+#endif
+
+inline bool operator<(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y) { return (x.mFormatID == y.mFormat.mFormatID) ?
+ (x < y.mFormat) && (x.mSampleRate < y.mSampleRateRange.mMinimum) :
+ (x.mFormatID == kAudioFormatLinearPCM) ? false : (x.mFormatID < y.mFormat.mFormatID); }
+inline bool operator<(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y) { return (x.mFormat.mFormatID == y.mFormatID) ?
+ (x.mFormat < y) && (x.mSampleRateRange.mMinimum < y.mSampleRate) :
+ (x.mFormat.mFormatID == kAudioFormatLinearPCM) ? false : (x.mFormat.mFormatID < y.mFormatID); }
+inline bool operator==(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y) { return (x == y.mFormat) && CAAudioValueRange::ContainsValue(y.mSampleRateRange, x.mSampleRate); }
+inline bool operator==(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y) { return (x.mFormat == y) && CAAudioValueRange::ContainsValue(x.mSampleRateRange, y.mSampleRate); }
+#if TARGET_OS_MAC || (TARGET_OS_WIN32 && (_MSC_VER > 600))
+inline bool operator!=(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y) { return !(x == y); }
+inline bool operator!=(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y) { return !(x == y); }
+inline bool operator<=(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y) { return (x < y) || (x == y); }
+inline bool operator<=(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y) { return (x < y) || (x == y); }
+inline bool operator>=(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y) { return !(x < y); }
+inline bool operator>=(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y) { return !(x < y); }
+inline bool operator>(const AudioStreamBasicDescription& x, const AudioStreamRangedDescription& y) { return !((x < y) || (x == y)); }
+inline bool operator>(const AudioStreamRangedDescription& x, const AudioStreamBasicDescription& y) { return !((x < y) || (x == y)); }
+#endif
+
+// STL Functors
+struct CAStreamRangedDescription_EqualToASBD
+:
+ public std::unary_function<AudioStreamRangedDescription, bool>
+{
+ CAStreamRangedDescription_EqualToASBD(const AudioStreamBasicDescription& inFormat) : mFormat(inFormat) {}
+ bool operator()(const AudioStreamRangedDescription& x) const { return mFormat == x; }
+
+ AudioStreamBasicDescription mFormat;
+};
+
+struct CAStreamRangedDescription_ReverseSort
+:
+ public std::binary_function<AudioStreamRangedDescription, AudioStreamRangedDescription, bool>
+{
+ bool operator()(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) const { return CAStreamRangedDescription::Sorter(x, y); }
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAThreadSafeList.h b/libs/appleutility/CoreAudio/PublicUtility/CAThreadSafeList.h
new file mode 100644
index 0000000000..d0b7391476
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAThreadSafeList.h
@@ -0,0 +1,233 @@
+/*
+ File: CAThreadSafeList.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAThreadSafeList_h__
+#define __CAThreadSafeList_h__
+
+#include "CAAtomicStack.h"
+
+// linked list of T's
+// T must define operator ==
+template <class T>
+class TThreadSafeList {
+private:
+ enum EEventType { kAdd, kRemove, kClear };
+ class Node {
+ public:
+ Node * mNext;
+ EEventType mEventType;
+ T mObject;
+
+ Node *& next() { return mNext; }
+ };
+
+public:
+ class iterator {
+ public:
+ iterator() { }
+ iterator(Node *n) : mNode(n) { }
+
+ bool operator == (const iterator &other) const { return this->mNode == other.mNode; }
+ bool operator != (const iterator &other) const { return this->mNode != other.mNode; }
+
+ T & operator * () const { return mNode->mObject; }
+
+ iterator & operator ++ () { mNode = mNode->next(); return *this; } // preincrement
+ iterator operator ++ (int) { iterator tmp = *this; mNode = mNode->next(); return tmp; } // postincrement
+
+ private:
+ Node * mNode;
+ };
+
+ TThreadSafeList() { }
+ ~TThreadSafeList()
+ {
+ mActiveList.free_all();
+ mPendingList.free_all();
+ mFreeList.free_all();
+ }
+
+ // These may be called on any thread
+
+ void deferred_add(const T &obj) // can be called on any thread
+ {
+ Node *node = AllocNode();
+ node->mEventType = kAdd;
+ node->mObject = obj;
+ mPendingList.push_atomic(node);
+ //mPendingList.dump("pending after add");
+ }
+
+ void deferred_remove(const T &obj) // can be called on any thread
+ {
+ Node *node = AllocNode();
+ node->mEventType = kRemove;
+ node->mObject = obj;
+ mPendingList.push_atomic(node);
+ //mPendingList.dump("pending after remove");
+ }
+
+ void deferred_clear() // can be called on any thread
+ {
+ Node *node = AllocNode();
+ node->mEventType = kClear;
+ mPendingList.push_atomic(node);
+ }
+
+ // These must be called from only one thread
+
+ void update() // must only be called from one thread
+ {
+ NodeStack reversed;
+ Node *event, *node, *next;
+ bool workDone = false;
+
+ // reverse the events so they are in order
+ event = mPendingList.pop_all();
+ while (event != NULL) {
+ next = event->mNext;
+ reversed.push_NA(event);
+ event = next;
+ workDone = true;
+ }
+ if (workDone) {
+ //reversed.dump("pending popped");
+ //mActiveList.dump("active before update");
+
+ // now process them
+ while ((event = reversed.pop_NA()) != NULL) {
+ switch (event->mEventType) {
+ case kAdd:
+ {
+ Node **pnode;
+ bool needToInsert = true;
+ for (pnode = mActiveList.phead(); *pnode != NULL; pnode = &node->mNext) {
+ node = *pnode;
+ if (node->mObject == event->mObject) {
+ //printf("already active!!!\n");
+ FreeNode(event);
+ needToInsert = false;
+ break;
+ }
+ }
+ if (needToInsert) {
+ // link the new event in at the end of the active list
+ *pnode = event;
+ event->mNext = NULL;
+ }
+ }
+ break;
+ case kRemove:
+ // find matching node in the active list, remove it
+ for (Node **pnode = mActiveList.phead(); *pnode != NULL; ) {
+ node = *pnode;
+ if (node->mObject == event->mObject) {
+ *pnode = node->mNext; // remove from linked list
+ FreeNode(node);
+ break;
+ }
+ pnode = &node->mNext;
+ }
+ // dispose the request node
+ FreeNode(event);
+ break;
+ case kClear:
+ for (node = mActiveList.head(); node != NULL; ) {
+ next = node->mNext;
+ FreeNode(node);
+ node = next;
+ }
+ FreeNode(event);
+ break;
+ default:
+ //printf("invalid node type %d!\n", event->mEventType);
+ break;
+ }
+ }
+ //mActiveList.dump("active after update");
+ }
+ }
+
+ iterator begin() const {
+ //mActiveList.dump("active at begin");
+ return iterator(mActiveList.head());
+ }
+ iterator end() const { return iterator(NULL); }
+
+
+private:
+ Node * AllocNode()
+ {
+ Node *node = mFreeList.pop_atomic();
+ if (node == NULL)
+ node = (Node *)CA_malloc(sizeof(Node));
+ return node;
+ }
+
+ void FreeNode(Node *node)
+ {
+ mFreeList.push_atomic(node);
+ }
+
+private:
+ class NodeStack : public TAtomicStack<Node> {
+ public:
+ void free_all() {
+ Node *node;
+ while ((node = this->pop_NA()) != NULL)
+ free(node);
+ }
+
+ Node ** phead() { return &this->mHead; }
+ Node * head() const { return this->mHead; }
+ };
+
+ NodeStack mActiveList; // what's actually in the container - only accessed on one thread
+ NodeStack mPendingList; // add or remove requests - threadsafe
+ NodeStack mFreeList; // free nodes for reuse - threadsafe
+};
+
+#endif // __CAThreadSafeList_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CATink.h b/libs/appleutility/CoreAudio/PublicUtility/CATink.h
new file mode 100644
index 0000000000..f0829359a6
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CATink.h
@@ -0,0 +1,146 @@
+/*
+ File: CATink.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CATink_h__)
+#define __CATink_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreServices/CoreServices.h>
+#else
+ #include <CoreServices.h>
+#endif
+
+
+//=============================================================================
+// CATink
+//
+// A Tink is a small jump island that can make one function appear as if it
+// has many addresses. Note that Tinks are not supported for 64 bit environments
+// as the APIs that made tinks useful have been replaced by APIs that do away
+// with all the reasons for using a tink.
+//=============================================================================
+
+template <class F>
+class CATink
+{
+
+public:
+ CATink(F proc) { Set(proc); }
+
+ ~CATink() { Set((F)0xDEADDEAD); } // jump to an obviously bad (odd) address if accessed after destruction
+
+#if TARGET_CPU_PPC
+ void Set(F proc)
+ {
+ /*
+ lis r11,0x1234
+ 00000000: 3D601234 lis r11,4660
+ ori r11,r11,0x5678
+ 00000004: 616B5678 ori r11,r11,$5678
+ mtctr r11
+ 00000008: 7D6903A6 mtctr r11
+ bctr
+ 0000000C: 4E800420 bctr
+ */
+ UInt32 p = UInt32(proc);
+ mCode[0] = 0x3D600000 | (p >> 16);
+ mCode[1] = 0x616B0000 | (p & 0xFFFF);
+ mCode[2] = 0x7D6903A6;
+ mCode[3] = 0x4E800420;
+ MakeDataExecutable(mCode, sizeof(mCode));
+ }
+
+ operator F () { return F(mCode); }
+
+private:
+ UInt32 mCode[4];
+#elif TARGET_CPU_X86
+ void Set(F proc)
+ {
+ /*
+ <tink>: push $0x12345678
+ <tink+5>: ret
+ <tink>: 0x34567868
+ <tink+4>: 0x00e8c312
+ */
+ UInt32 p = UInt32(proc);
+ mCode[0] = ((p & 0xFFFFFF) << 8) | 0x00000068;
+ mCode[1] = 0xCCCCC300 | (p >> 24);
+ MakeDataExecutable(mCode, sizeof(mCode));
+ }
+
+ operator F () { return F(&mCode[0]); }
+
+private:
+ UInt32 mCode[2];
+#else
+ #warning: CPU not directly supported by CATink
+
+ // For other CPU's, just wrap the function pointer for now.
+ // this bypasses what we're trying to accomplish with the Tink
+ // (multiple unique "instances" of a function), but it will at
+ // least compile and run.
+
+ void Set(F proc) { mProcPtr = proc; }
+
+ operator F () { return mProcPtr; }
+private:
+ F mProcPtr;
+#endif
+
+// Tinks cannot be allocated in STL Containers, so we make a few key methods private
+private:
+ CATink(){}
+ CATink(const CATink&){}
+ CATink& operator=(const CATink&){ return *this;}
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CATokenMap.h b/libs/appleutility/CoreAudio/PublicUtility/CATokenMap.h
new file mode 100644
index 0000000000..f85f393022
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CATokenMap.h
@@ -0,0 +1,212 @@
+/*
+ File: CATokenMap.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CATokenMap_h__)
+#define __CATokenMap_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+// PublicUtility Includes
+#include "CAMutex.h"
+
+// Standard Library Includes
+#include <map>
+#include <iterator>
+
+//=============================================================================
+// CATokenMap
+//=============================================================================
+
+template <class T>
+class CATokenMap
+{
+
+// Types
+private:
+ typedef std::map<UInt32, T*> TokenMap;
+
+// Construction/Destruction
+public:
+ CATokenMap() : mTokenMap(), mNextToken(256), mTokenMapMutex("CATokenMap Mutex") {}
+ ~CATokenMap() {}
+
+// Operations
+public:
+ bool Lock()
+ {
+ return mTokenMapMutex.Lock();
+ }
+
+ void Unlock()
+ {
+ mTokenMapMutex.Unlock();
+ }
+
+ UInt32 GetToken(T* inObject) const
+ {
+ CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex));
+ UInt32 theAnswer = 0;
+ typename TokenMap::const_iterator i = mTokenMap.begin();
+ while((theAnswer == 0) && (i != mTokenMap.end()))
+ {
+ if(i->second == inObject)
+ {
+ theAnswer = i->first;
+ }
+ std::advance(i, 1);
+ }
+ return theAnswer;
+ }
+
+ T* GetObject(UInt32 inToken) const
+ {
+ CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex));
+ typename TokenMap::const_iterator i = mTokenMap.find(inToken);
+ return i != mTokenMap.end() ? i->second : NULL;
+ }
+
+ T* GetObject(const void* inToken) const
+ {
+ #if __LP64__
+ return GetObject((UInt32)((UInt64)inToken));
+ #else
+ return GetObject((UInt32)inToken);
+ #endif
+ }
+
+ UInt32 GetNumberObjects() const
+ {
+ CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex));
+ return static_cast<UInt32>(mTokenMap.size());
+ }
+
+ T* GetObjectByIndex(UInt32 inIndex) const
+ {
+ T* theAnswer = NULL;
+ CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex));
+ if(inIndex < mTokenMap.size())
+ {
+ typename TokenMap::const_iterator i = mTokenMap.begin();
+ std::advance(i, inIndex);
+ theAnswer = (i != mTokenMap.end()) ? i->second : NULL;
+ }
+ return theAnswer;
+ }
+
+ void AddMapping(UInt32 inToken, T* inObject)
+ {
+ CAMutex::Locker theLocker(mTokenMapMutex);
+ typename TokenMap::iterator i = mTokenMap.find(inToken);
+ if(i != mTokenMap.end())
+ {
+ i->second = inObject;
+ }
+ else
+ {
+ mTokenMap.insert(typename TokenMap::value_type(inToken, inObject));
+ }
+ }
+
+ void RemoveMapping(UInt32 inToken, T* /*inObject*/)
+ {
+ CAMutex::Locker theLocker(mTokenMapMutex);
+ typename TokenMap::iterator i = mTokenMap.find(inToken);
+ if(i != mTokenMap.end())
+ {
+ mTokenMap.erase(i);
+ }
+ }
+
+ UInt32 GetNextToken()
+ {
+ return mNextToken++;
+ }
+
+ UInt32 MapObject(T* inObject)
+ {
+ CAMutex::Locker theLocker(mTokenMapMutex);
+ UInt32 theToken = GetNextToken();
+ mTokenMap.insert(typename TokenMap::value_type(theToken, inObject));
+ return theToken;
+ }
+
+ void UnmapObject(T* inObject)
+ {
+ CAMutex::Locker theLocker(mTokenMapMutex);
+ bool isDone = false;
+ typename TokenMap::iterator i = mTokenMap.begin();
+ while(!isDone && (i != mTokenMap.end()))
+ {
+ if(i->second == inObject)
+ {
+ mTokenMap.erase(i);
+ isDone = true;
+ }
+ else
+ {
+ std::advance(i, 1);
+ }
+ }
+ }
+
+// Implementation
+private:
+ TokenMap mTokenMap;
+ UInt32 mNextToken;
+ CAMutex mTokenMapMutex;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.cpp
new file mode 100644
index 0000000000..83bfb8c889
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.cpp
@@ -0,0 +1,195 @@
+/*
+ File: CAVectorUnit.cpp
+ Abstract: CAVectorUnit.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CAVectorUnit.h"
+
+#if !TARGET_OS_WIN32
+ #include <sys/sysctl.h>
+#elif HAS_IPP
+ #include "ippdefs.h"
+ #include "ippcore.h"
+#endif
+
+int gCAVectorUnitType = kVecUninitialized;
+
+#if TARGET_OS_WIN32
+// Use cpuid to check if SSE2 is available.
+// Before calling this function make sure cpuid is available
+static SInt32 IsSSE2Available()
+{
+ int return_value;
+
+ {
+ int r_edx;
+ _asm
+ {
+ mov eax, 0x01
+ cpuid
+ mov r_edx, edx
+ }
+ return_value = (r_edx >> 26) & 0x1;
+ }
+ return return_value;
+}
+
+// Use cpuid to check if SSE3 is available.
+// Before calling this function make sure cpuid is available
+static SInt32 IsSSE3Available()
+{
+ SInt32 return_value;
+
+ {
+ SInt32 r_ecx;
+ _asm
+ {
+ mov eax, 0x01
+ cpuid
+ mov r_ecx, ecx
+ }
+ return_value = r_ecx & 0x1;
+ }
+ return return_value;
+}
+
+// Return true if the cpuid instruction is available.
+// The cpuid instruction is available if bit 21 in the EFLAGS register can be changed
+// This function may not work on Intel CPUs prior to Pentium (didn't test)
+static bool IsCpuidAvailable()
+{
+ SInt32 return_value = 0x0;
+ _asm{
+ pushfd ; //push original EFLAGS
+ pop eax ; //get original EFLAGS
+ mov ecx, eax ; //save original EFLAGS
+ xor eax, 200000h ; //flip ID bit in EFLAGS
+ push eax ; //save new EFLAGS value on stack
+ popfd ; //replace current EFLAGS value
+ pushfd ; //get new EFLAGS
+ pop eax ; //store new EFLAGS in EAX
+ xor eax, ecx ;
+ je end_cpuid_identify ; //can't toggle ID bit
+ mov return_value, 0x1;
+end_cpuid_identify:
+ nop;
+ }
+ return return_value;
+}
+
+#endif
+
+SInt32 CAVectorUnit_Examine()
+{
+ int result = kVecNone;
+
+#if TARGET_OS_WIN32
+#if HAS_IPP
+ // Initialize the static IPP library! This needs to be done before
+ // any IPP function calls, otherwise we may have a performance penalty
+ int status = ippStaticInit();
+ if ( status == ippStsNonIntelCpu )
+ {
+ IppCpuType cpuType = ippGetCpuType();
+ if ( cpuType >= ippCpuSSE || cpuType <= ippCpuSSE42 )
+ ippStaticInitCpu( cpuType );
+ }
+#endif
+ {
+ // On Windows we use cpuid to detect the vector unit because it works on Intel and AMD.
+ // The IPP library does not detect SSE on AMD processors.
+ if (IsCpuidAvailable())
+ {
+ if(IsSSE3Available())
+ {
+ result = kVecSSE3;
+ }
+ else if(IsSSE2Available())
+ {
+ result = kVecSSE2;
+ }
+ }
+ }
+#elif TARGET_OS_MAC
+#if DEBUG
+ if (getenv("CA_NoVector")) {
+ fprintf(stderr, "CA_NoVector set; Vector unit optimized routines will be bypassed\n");
+ return result;
+ }
+ else
+#endif
+ {
+ #if (TARGET_CPU_PPC || TARGET_CPU_PPC64)
+ int sels[2] = { CTL_HW, HW_VECTORUNIT };
+ int vType = 0; //0 == scalar only
+ size_t length = sizeof(vType);
+ int error = sysctl(sels, 2, &vType, &length, NULL, 0);
+ if (!error && vType > 0)
+ result = kVecAltivec;
+ #elif (TARGET_CPU_X86 || TARGET_CPU_X86_64)
+ static const struct { const char* kName; const int kVectype; } kStringVectypes[] = {
+ { "hw.optional.avx1_0", kVecAVX1 }, { "hw.optional.sse3", kVecSSE3 }, { "hw.optional.sse2", kVecSSE2 }
+ };
+ static const size_t kNumStringVectypes = sizeof(kStringVectypes)/sizeof(kStringVectypes[0]);
+ int i = 0, answer = 0;
+ while(i != kNumStringVectypes)
+ {
+ size_t length = sizeof(answer);
+ int error = sysctlbyname(kStringVectypes[i].kName, &answer, &length, NULL, 0);
+ if (!error && answer)
+ {
+ result = kStringVectypes[i].kVectype;
+ break;
+ }
+ ++i;
+ };
+ #elif CA_ARM_NEON
+ result = kVecNeon;
+ #endif
+ }
+#endif
+ gCAVectorUnitType = result;
+ return result;
+}
+
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.h b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.h
new file mode 100644
index 0000000000..cf3a16c7a9
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.h
@@ -0,0 +1,101 @@
+/*
+ File: CAVectorUnit.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAVectorUnit_h__
+#define __CAVectorUnit_h__
+
+#include <TargetConditionals.h>
+#include "CAVectorUnitTypes.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CFBase.h>
+#else
+ #include "CFBase.h"
+#endif
+
+// Unify checks for vector units.
+// Allow setting an environment variable "CA_NoVector" to turn off vectorized code at runtime (very useful for performance testing).
+
+extern int gCAVectorUnitType;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern SInt32 CAVectorUnit_Examine(); // expensive. use GetType() for lazy initialization and caching.
+
+static inline SInt32 CAVectorUnit_GetType()
+{
+ int x = gCAVectorUnitType;
+ return (x != kVecUninitialized) ? x : CAVectorUnit_Examine();
+}
+
+static inline Boolean CAVectorUnit_HasVectorUnit()
+{
+ return CAVectorUnit_GetType() > kVecNone;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifdef __cplusplus
+class CAVectorUnit {
+public:
+ static SInt32 GetVectorUnitType() { return CAVectorUnit_GetType(); }
+ static bool HasVectorUnit() { return GetVectorUnitType() > kVecNone; }
+ static bool HasAltivec() { return GetVectorUnitType() == kVecAltivec; }
+ static bool HasSSE2() { return GetVectorUnitType() >= kVecSSE2; }
+ static bool HasSSE3() { return GetVectorUnitType() >= kVecSSE3; }
+ static bool HasAVX1() { return GetVectorUnitType() >= kVecAVX1; }
+ static bool HasNeon() { return GetVectorUnitType() == kVecNeon; }
+};
+#endif
+
+#endif // __CAVectorUnit_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnitTypes.h b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnitTypes.h
new file mode 100644
index 0000000000..85ff837afe
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAVectorUnitTypes.h
@@ -0,0 +1,60 @@
+/*
+ File: CAVectorUnitTypes.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAVectorUnitTypes_h__
+#define __CAVectorUnitTypes_h__
+
+enum {
+ kVecUninitialized = -1,
+ kVecNone = 0,
+ kVecAltivec = 1,
+ kVecSSE2 = 100,
+ kVecSSE3 = 101,
+ kVecAVX1 = 110,
+ kVecNeon = 200
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.cpp
new file mode 100644
index 0000000000..bb6e70cb8e
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.cpp
@@ -0,0 +1,482 @@
+/*
+ File: CAVolumeCurve.cpp
+ Abstract: CAVolumeCurve.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CAVolumeCurve.h"
+#include "CADebugMacros.h"
+#include <math.h>
+
+//=============================================================================
+// CAVolumeCurve
+//=============================================================================
+
+CAVolumeCurve::CAVolumeCurve()
+:
+ mTag(0),
+ mCurveMap(),
+ mIsApplyingTransferFunction(true),
+ mTransferFunction(kPow2Over1Curve),
+ mRawToScalarExponentNumerator(2.0f),
+ mRawToScalarExponentDenominator(1.0f)
+{
+}
+
+CAVolumeCurve::~CAVolumeCurve()
+{
+}
+
+SInt32 CAVolumeCurve::GetMinimumRaw() const
+{
+ SInt32 theAnswer = 0;
+
+ if(!mCurveMap.empty())
+ {
+ CurveMap::const_iterator theIterator = mCurveMap.begin();
+ theAnswer = theIterator->first.mMinimum;
+ }
+
+ return theAnswer;
+}
+
+SInt32 CAVolumeCurve::GetMaximumRaw() const
+{
+ SInt32 theAnswer = 0;
+
+ if(!mCurveMap.empty())
+ {
+ CurveMap::const_iterator theIterator = mCurveMap.begin();
+ std::advance(theIterator, static_cast<int>(mCurveMap.size() - 1));
+ theAnswer = theIterator->first.mMaximum;
+ }
+
+ return theAnswer;
+}
+
+Float32 CAVolumeCurve::GetMinimumDB() const
+{
+ Float32 theAnswer = 0;
+
+ if(!mCurveMap.empty())
+ {
+ CurveMap::const_iterator theIterator = mCurveMap.begin();
+ theAnswer = theIterator->second.mMinimum;
+ }
+
+ return theAnswer;
+}
+
+Float32 CAVolumeCurve::GetMaximumDB() const
+{
+ Float32 theAnswer = 0;
+
+ if(!mCurveMap.empty())
+ {
+ CurveMap::const_iterator theIterator = mCurveMap.begin();
+ std::advance(theIterator, static_cast<int>(mCurveMap.size() - 1));
+ theAnswer = theIterator->second.mMaximum;
+ }
+
+ return theAnswer;
+}
+
+void CAVolumeCurve::SetTransferFunction(UInt32 inTransferFunction)
+{
+ mTransferFunction = inTransferFunction;
+
+ // figure out the co-efficients
+ switch(inTransferFunction)
+ {
+ case kLinearCurve:
+ mIsApplyingTransferFunction = false;
+ mRawToScalarExponentNumerator = 1.0f;
+ mRawToScalarExponentDenominator = 1.0f;
+ break;
+
+ case kPow1Over3Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 1.0f;
+ mRawToScalarExponentDenominator = 3.0f;
+ break;
+
+ case kPow1Over2Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 1.0f;
+ mRawToScalarExponentDenominator = 2.0f;
+ break;
+
+ case kPow3Over4Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 3.0f;
+ mRawToScalarExponentDenominator = 4.0f;
+ break;
+
+ case kPow3Over2Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 3.0f;
+ mRawToScalarExponentDenominator = 2.0f;
+ break;
+
+ case kPow2Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 2.0f;
+ mRawToScalarExponentDenominator = 1.0f;
+ break;
+
+ case kPow3Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 3.0f;
+ mRawToScalarExponentDenominator = 1.0f;
+ break;
+
+ case kPow4Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 4.0f;
+ mRawToScalarExponentDenominator = 1.0f;
+ break;
+
+ case kPow5Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 5.0f;
+ mRawToScalarExponentDenominator = 1.0f;
+ break;
+
+ case kPow6Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 6.0f;
+ mRawToScalarExponentDenominator = 1.0f;
+ break;
+
+ case kPow7Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 7.0f;
+ mRawToScalarExponentDenominator = 1.0f;
+ break;
+
+ case kPow8Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 8.0f;
+ mRawToScalarExponentDenominator = 1.0f;
+ break;
+
+ case kPow9Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 9.0f;
+ mRawToScalarExponentDenominator = 1.0f;
+ break;
+
+ case kPow10Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 10.0f;
+ mRawToScalarExponentDenominator = 1.0f;
+ break;
+
+ case kPow11Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 11.0f;
+ mRawToScalarExponentDenominator = 1.0f;
+ break;
+
+ case kPow12Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 12.0f;
+ mRawToScalarExponentDenominator = 1.0f;
+ break;
+
+ default:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 2.0f;
+ mRawToScalarExponentDenominator = 1.0f;
+ break;
+ };
+}
+
+void CAVolumeCurve::AddRange(SInt32 inMinRaw, SInt32 inMaxRaw, Float32 inMinDB, Float32 inMaxDB)
+{
+ CARawPoint theRaw(inMinRaw, inMaxRaw);
+ CADBPoint theDB(inMinDB, inMaxDB);
+
+ bool isOverlapped = false;
+ bool isDone = false;
+ CurveMap::iterator theIterator = mCurveMap.begin();
+ while((theIterator != mCurveMap.end()) && !isOverlapped && !isDone)
+ {
+ isOverlapped = CARawPoint::Overlap(theRaw, theIterator->first);
+ isDone = theRaw >= theIterator->first;
+
+ if(!isOverlapped && !isDone)
+ {
+ std::advance(theIterator, 1);
+ }
+ }
+
+ if(!isOverlapped)
+ {
+ mCurveMap.insert(CurveMap::value_type(theRaw, theDB));
+ }
+ else
+ {
+ DebugMessage("CAVolumeCurve::AddRange: new point overlaps");
+ }
+}
+
+void CAVolumeCurve::ResetRange()
+{
+ mCurveMap.clear();
+}
+
+bool CAVolumeCurve::CheckForContinuity() const
+{
+ bool theAnswer = true;
+
+ CurveMap::const_iterator theIterator = mCurveMap.begin();
+ if(theIterator != mCurveMap.end())
+ {
+ SInt32 theRaw = theIterator->first.mMinimum;
+ Float32 theDB = theIterator->second.mMinimum;
+ do
+ {
+ SInt32 theRawMin = theIterator->first.mMinimum;
+ SInt32 theRawMax = theIterator->first.mMaximum;
+ SInt32 theRawRange = theRawMax - theRawMin;
+
+ Float32 theDBMin = theIterator->second.mMinimum;
+ Float32 theDBMax = theIterator->second.mMaximum;
+ Float32 theDBRange = theDBMax - theDBMin;
+
+ theAnswer = theRaw == theRawMin;
+ theAnswer = theAnswer && (theDB == theDBMin);
+
+ theRaw += theRawRange;
+ theDB += theDBRange;
+
+ std::advance(theIterator, 1);
+ }
+ while((theIterator != mCurveMap.end()) && theAnswer);
+ }
+
+ return theAnswer;
+}
+
+SInt32 CAVolumeCurve::ConvertDBToRaw(Float32 inDB) const
+{
+ // clamp the value to the dB range
+ Float32 theOverallDBMin = GetMinimumDB();
+ Float32 theOverallDBMax = GetMaximumDB();
+
+ if(inDB < theOverallDBMin) inDB = theOverallDBMin;
+ if(inDB > theOverallDBMax) inDB = theOverallDBMax;
+
+ // get the first entry in the curve map;
+ CurveMap::const_iterator theIterator = mCurveMap.begin();
+
+ // initialize the answer to the minimum raw of the first item in the curve map
+ SInt32 theAnswer = theIterator->first.mMinimum;
+
+ // iterate through the curve map until we run out of dB
+ bool isDone = false;
+ while(!isDone && (theIterator != mCurveMap.end()))
+ {
+ SInt32 theRawMin = theIterator->first.mMinimum;
+ SInt32 theRawMax = theIterator->first.mMaximum;
+ SInt32 theRawRange = theRawMax - theRawMin;
+
+ Float32 theDBMin = theIterator->second.mMinimum;
+ Float32 theDBMax = theIterator->second.mMaximum;
+ Float32 theDBRange = theDBMax - theDBMin;
+
+ Float32 theDBPerRaw = theDBRange / static_cast<Float32>(theRawRange);
+
+ // figure out how many steps we are into this entry in the curve map
+ if(inDB > theDBMax)
+ {
+ // we're past the end of this one, so add in the whole range for this entry
+ theAnswer += theRawRange;
+ }
+ else
+ {
+ // it's somewhere within the current entry
+ // figure out how many steps it is
+ Float32 theNumberRawSteps = inDB - theDBMin;
+ theNumberRawSteps /= theDBPerRaw;
+
+ // only move in whole steps
+ theNumberRawSteps = roundf(theNumberRawSteps);
+
+ // add this many steps to the answer
+ theAnswer += static_cast<SInt32>(theNumberRawSteps);
+
+ // mark that we are done
+ isDone = true;
+ }
+
+ // go to the next entry in the curve map
+ std::advance(theIterator, 1);
+ }
+
+ return theAnswer;
+}
+
+Float32 CAVolumeCurve::ConvertRawToDB(SInt32 inRaw) const
+{
+ Float32 theAnswer = 0;
+
+ // clamp the raw value
+ SInt32 theOverallRawMin = GetMinimumRaw();
+ SInt32 theOverallRawMax = GetMaximumRaw();
+
+ if(inRaw < theOverallRawMin) inRaw = theOverallRawMin;
+ if(inRaw > theOverallRawMax) inRaw = theOverallRawMax;
+
+ // figure out how many raw steps need to be taken from the first one
+ SInt32 theNumberRawSteps = inRaw - theOverallRawMin;
+
+ // get the first item in the curve map
+ CurveMap::const_iterator theIterator = mCurveMap.begin();
+
+ // initialize the answer to the minimum dB of the first item in the curve map
+ theAnswer = theIterator->second.mMinimum;
+
+ // iterate through the curve map until we run out of steps
+ while((theNumberRawSteps > 0) && (theIterator != mCurveMap.end()))
+ {
+ // compute some values
+ SInt32 theRawMin = theIterator->first.mMinimum;
+ SInt32 theRawMax = theIterator->first.mMaximum;
+ SInt32 theRawRange = theRawMax - theRawMin;
+
+ Float32 theDBMin = theIterator->second.mMinimum;
+ Float32 theDBMax = theIterator->second.mMaximum;
+ Float32 theDBRange = theDBMax - theDBMin;
+
+ Float32 theDBPerRaw = theDBRange / static_cast<Float32>(theRawRange);
+
+ // there might be more steps than the current map entry accounts for
+ SInt32 theRawStepsToAdd = std::min(theRawRange, theNumberRawSteps);
+
+ // add this many steps worth of db to the answer;
+ theAnswer += theRawStepsToAdd * theDBPerRaw;
+
+ // figure out how many steps are left
+ theNumberRawSteps -= theRawStepsToAdd;
+
+ // go to the next map entry
+ std::advance(theIterator, 1);
+ }
+
+ return theAnswer;
+}
+
+Float32 CAVolumeCurve::ConvertRawToScalar(SInt32 inRaw) const
+{
+ // get some important values
+ Float32 theDBMin = GetMinimumDB();
+ Float32 theDBMax = GetMaximumDB();
+ Float32 theDBRange = theDBMax - theDBMin;
+ SInt32 theRawMin = GetMinimumRaw();
+ SInt32 theRawMax = GetMaximumRaw();
+ SInt32 theRawRange = theRawMax - theRawMin;
+
+ // range the raw value
+ if(inRaw < theRawMin) inRaw = theRawMin;
+ if(inRaw > theRawMax) inRaw = theRawMax;
+
+ // calculate the distance in the range inRaw is
+ Float32 theAnswer = static_cast<Float32>(inRaw - theRawMin) / static_cast<Float32>(theRawRange);
+
+ // only apply a curve to the scalar values if the dB range is greater than 30
+ if(mIsApplyingTransferFunction && (theDBRange > 30.0f))
+ {
+ theAnswer = powf(theAnswer, mRawToScalarExponentNumerator / mRawToScalarExponentDenominator);
+ }
+
+ return theAnswer;
+}
+
+Float32 CAVolumeCurve::ConvertDBToScalar(Float32 inDB) const
+{
+ SInt32 theRawValue = ConvertDBToRaw(inDB);
+ Float32 theAnswer = ConvertRawToScalar(theRawValue);
+ return theAnswer;
+}
+
+SInt32 CAVolumeCurve::ConvertScalarToRaw(Float32 inScalar) const
+{
+ // range the scalar value
+ inScalar = std::min(1.0f, std::max(0.0f, inScalar));
+
+ // get some important values
+ Float32 theDBMin = GetMinimumDB();
+ Float32 theDBMax = GetMaximumDB();
+ Float32 theDBRange = theDBMax - theDBMin;
+ SInt32 theRawMin = GetMinimumRaw();
+ SInt32 theRawMax = GetMaximumRaw();
+ SInt32 theRawRange = theRawMax - theRawMin;
+
+ // have to undo the curve if the dB range is greater than 30
+ if(mIsApplyingTransferFunction && (theDBRange > 30.0f))
+ {
+ inScalar = powf(inScalar, mRawToScalarExponentDenominator / mRawToScalarExponentNumerator);
+ }
+
+ // now we can figure out how many raw steps this is
+ Float32 theNumberRawSteps = inScalar * static_cast<Float32>(theRawRange);
+ theNumberRawSteps = roundf(theNumberRawSteps);
+
+ // the answer is the minimum raw value plus the number of raw steps
+ SInt32 theAnswer = theRawMin + static_cast<SInt32>(theNumberRawSteps);
+
+ return theAnswer;
+}
+
+Float32 CAVolumeCurve::ConvertScalarToDB(Float32 inScalar) const
+{
+ SInt32 theRawValue = ConvertScalarToRaw(inScalar);
+ Float32 theAnswer = ConvertRawToDB(theRawValue);
+ return theAnswer;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.h b/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.h
new file mode 100644
index 0000000000..4f9544682a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.h
@@ -0,0 +1,178 @@
+/*
+ File: CAVolumeCurve.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__CAVolumeCurve_h__)
+#define __CAVolumeCurve_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+#include <map>
+
+//=============================================================================
+// Types
+//=============================================================================
+
+struct CARawPoint
+{
+ SInt32 mMinimum;
+ SInt32 mMaximum;
+
+ CARawPoint() : mMinimum(0), mMaximum(0) {}
+ CARawPoint(const CARawPoint& inPoint) : mMinimum(inPoint.mMinimum), mMaximum(inPoint.mMaximum) {}
+ CARawPoint(SInt32 inMinimum, SInt32 inMaximum) : mMinimum(inMinimum), mMaximum(inMaximum) {}
+ CARawPoint& operator=(const CARawPoint& inPoint) { mMinimum = inPoint.mMinimum; mMaximum = inPoint.mMaximum; return *this; }
+
+ static bool Overlap(const CARawPoint& x, const CARawPoint& y) { return (x.mMinimum < y.mMaximum) && (x.mMaximum > y.mMinimum); }
+};
+
+inline bool operator<(const CARawPoint& x, const CARawPoint& y) { return x.mMinimum < y.mMinimum; }
+inline bool operator==(const CARawPoint& x, const CARawPoint& y) { return (x.mMinimum == y.mMinimum) && (x.mMaximum == y.mMaximum); }
+inline bool operator!=(const CARawPoint& x, const CARawPoint& y) { return !(x == y); }
+inline bool operator<=(const CARawPoint& x, const CARawPoint& y) { return (x < y) || (x == y); }
+inline bool operator>=(const CARawPoint& x, const CARawPoint& y) { return !(x < y); }
+inline bool operator>(const CARawPoint& x, const CARawPoint& y) { return !((x < y) || (x == y)); }
+
+struct CADBPoint
+{
+ Float32 mMinimum;
+ Float32 mMaximum;
+
+ CADBPoint() : mMinimum(0), mMaximum(0) {}
+ CADBPoint(const CADBPoint& inPoint) : mMinimum(inPoint.mMinimum), mMaximum(inPoint.mMaximum) {}
+ CADBPoint(Float32 inMinimum, Float32 inMaximum) : mMinimum(inMinimum), mMaximum(inMaximum) {}
+ CADBPoint& operator=(const CADBPoint& inPoint) { mMinimum = inPoint.mMinimum; mMaximum = inPoint.mMaximum; return *this; }
+
+ static bool Overlap(const CADBPoint& x, const CADBPoint& y) { return (x.mMinimum < y.mMaximum) && (x.mMaximum >= y.mMinimum); }
+};
+
+inline bool operator<(const CADBPoint& x, const CADBPoint& y) { return x.mMinimum < y.mMinimum; }
+inline bool operator==(const CADBPoint& x, const CADBPoint& y) { return (x.mMinimum == y.mMinimum) && (x.mMaximum == y.mMaximum); }
+inline bool operator!=(const CADBPoint& x, const CADBPoint& y) { return !(x == y); }
+inline bool operator<=(const CADBPoint& x, const CADBPoint& y) { return (x < y) || (x == y); }
+inline bool operator>=(const CADBPoint& x, const CADBPoint& y) { return !(x < y); }
+inline bool operator>(const CADBPoint& x, const CADBPoint& y) { return !((x < y) || (x == y)); }
+
+//=============================================================================
+// CAVolumeCurve
+//=============================================================================
+
+class CAVolumeCurve
+{
+
+// Constants
+public:
+ enum
+ {
+ kLinearCurve = 0,
+ kPow1Over3Curve = 1,
+ kPow1Over2Curve = 2,
+ kPow3Over4Curve = 3,
+ kPow3Over2Curve = 4,
+ kPow2Over1Curve = 5,
+ kPow3Over1Curve = 6,
+ kPow4Over1Curve = 7,
+ kPow5Over1Curve = 8,
+ kPow6Over1Curve = 9,
+ kPow7Over1Curve = 10,
+ kPow8Over1Curve = 11,
+ kPow9Over1Curve = 12,
+ kPow10Over1Curve = 13,
+ kPow11Over1Curve = 14,
+ kPow12Over1Curve = 15
+ };
+
+// Construction/Destruction
+public:
+ CAVolumeCurve();
+ virtual ~CAVolumeCurve();
+
+// Attributes
+public:
+ UInt32 GetTag() const { return mTag; }
+ void SetTag(UInt32 inTag) { mTag = inTag; }
+ SInt32 GetMinimumRaw() const;
+ SInt32 GetMaximumRaw() const;
+ Float32 GetMinimumDB() const;
+ Float32 GetMaximumDB() const;
+
+ void SetIsApplyingTransferFunction(bool inIsApplyingTransferFunction) { mIsApplyingTransferFunction = inIsApplyingTransferFunction; }
+ UInt32 GetTransferFunction() const { return mTransferFunction; }
+ void SetTransferFunction(UInt32 inTransferFunction);
+
+// Operations
+public:
+ void AddRange(SInt32 mMinRaw, SInt32 mMaxRaw, Float32 inMinDB, Float32 inMaxDB);
+ void ResetRange();
+ bool CheckForContinuity() const;
+
+ SInt32 ConvertDBToRaw(Float32 inDB) const;
+ Float32 ConvertRawToDB(SInt32 inRaw) const;
+ Float32 ConvertRawToScalar(SInt32 inRaw) const;
+ Float32 ConvertDBToScalar(Float32 inDB) const;
+ SInt32 ConvertScalarToRaw(Float32 inScalar) const;
+ Float32 ConvertScalarToDB(Float32 inScalar) const;
+
+// Implementation
+private:
+ typedef std::map<CARawPoint, CADBPoint> CurveMap;
+
+ UInt32 mTag;
+ CurveMap mCurveMap;
+ bool mIsApplyingTransferFunction;
+ UInt32 mTransferFunction;
+ Float32 mRawToScalarExponentNumerator;
+ Float32 mRawToScalarExponentDenominator;
+
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAXException.cpp b/libs/appleutility/CoreAudio/PublicUtility/CAXException.cpp
new file mode 100644
index 0000000000..c2dbac5d60
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAXException.cpp
@@ -0,0 +1,49 @@
+/*
+ File: CAXException.cpp
+ Abstract: CAXException.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CAXException.h"
+
+CAXException::WarningHandler CAXException::sWarningHandler = NULL;
diff --git a/libs/appleutility/CoreAudio/PublicUtility/CAXException.h b/libs/appleutility/CoreAudio/PublicUtility/CAXException.h
new file mode 100644
index 0000000000..90dabe97de
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/CAXException.h
@@ -0,0 +1,361 @@
+/*
+ File: CAXException.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CAXException_h__
+#define __CAXException_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include <ConditionalMacros.h>
+ #include <CoreFoundation.h>
+#endif
+#include "CADebugMacros.h"
+#include <ctype.h>
+//#include <stdio.h>
+#include <string.h>
+
+
+class CAX4CCString {
+public:
+ CAX4CCString(OSStatus error) {
+ // see if it appears to be a 4-char-code
+ UInt32 beErr = CFSwapInt32HostToBig(error);
+ char *str = mStr;
+ memcpy(str + 1, &beErr, 4);
+ if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) {
+ str[0] = str[5] = '\'';
+ str[6] = '\0';
+ } else if (error > -200000 && error < 200000)
+ // no, format it as an integer
+ snprintf(str, sizeof(mStr), "%d", (int)error);
+ else
+ snprintf(str, sizeof(mStr), "0x%x", (int)error);
+ }
+ const char *get() const { return mStr; }
+ operator const char *() const { return mStr; }
+private:
+ char mStr[16];
+};
+
+class CAX4CCStringNoQuote {
+public:
+ CAX4CCStringNoQuote(OSStatus error) {
+ // see if it appears to be a 4-char-code
+ UInt32 beErr = CFSwapInt32HostToBig(error);
+ char *str = mStr;
+ memcpy(str, &beErr, 4);
+ if (isprint(str[0]) && isprint(str[1]) && isprint(str[2]) && isprint(str[3])) {
+ str[4] = '\0';
+ } else if (error > -200000 && error < 200000)
+ // no, format it as an integer
+ snprintf(str, sizeof(mStr), "%d", (int)error);
+ else
+ snprintf(str, sizeof(mStr), "0x%x", (int)error);
+ }
+ const char *get() const { return mStr; }
+ operator const char *() const { return mStr; }
+private:
+ char mStr[16];
+};
+
+
+// An extended exception class that includes the name of the failed operation
+class CAXException {
+public:
+ CAXException(const char *operation, OSStatus err) :
+ mError(err)
+ {
+ if (operation == NULL)
+ mOperation[0] = '\0';
+ else if (strlen(operation) >= sizeof(mOperation)) {
+ memcpy(mOperation, operation, sizeof(mOperation) - 1);
+ mOperation[sizeof(mOperation) - 1] = '\0';
+ } else
+
+ strlcpy(mOperation, operation, sizeof(mOperation));
+ }
+
+ char *FormatError(char *str, size_t strsize) const
+ {
+ return FormatError(str, strsize, mError);
+ }
+
+ char mOperation[256];
+ const OSStatus mError;
+
+ // -------------------------------------------------
+
+ typedef void (*WarningHandler)(const char *msg, OSStatus err);
+
+ static char *FormatError(char *str, size_t strsize, OSStatus error)
+ {
+ strlcpy(str, CAX4CCString(error), strsize);
+ return str;
+ }
+
+ static void Warning(const char *s, OSStatus error)
+ {
+ if (sWarningHandler)
+ (*sWarningHandler)(s, error);
+ }
+
+ static void SetWarningHandler(WarningHandler f) { sWarningHandler = f; }
+private:
+ static WarningHandler sWarningHandler;
+};
+
+#if DEBUG || CoreAudio_Debug
+ #define XThrowIfError(error, operation) \
+ do { \
+ OSStatus __err = error; \
+ if (__err) { \
+ DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), operation);\
+ __THROW_STOP; \
+ throw CAXException(operation, __err); \
+ } \
+ } while (0)
+
+ #define XThrowIf(condition, error, operation) \
+ do { \
+ if (condition) { \
+ OSStatus __err = error; \
+ DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), operation);\
+ __THROW_STOP; \
+ throw CAXException(operation, __err); \
+ } \
+ } while (0)
+
+ #define XRequireNoError(error, label) \
+ do { \
+ OSStatus __err = error; \
+ if (__err) { \
+ DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), #error);\
+ STOP; \
+ goto label; \
+ } \
+ } while (0)
+
+ #define XAssert(assertion) \
+ do { \
+ if (!(assertion)) { \
+ DebugMessageN3("%s:%d: error: failed assertion: %s", __FILE__, __LINE__, #assertion); \
+ __ASSERT_STOP; \
+ } \
+ } while (0)
+
+ #define XAssertNoError(error) \
+ do { \
+ OSStatus __err = error; \
+ if (__err) { \
+ DebugMessageN4("%s:%d: error %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), #error);\
+ STOP; \
+ } \
+ } while (0)
+
+ #define ca_require_noerr(errorCode, exceptionLabel) \
+ do \
+ { \
+ int evalOnceErrorCode = (errorCode); \
+ if ( __builtin_expect(0 != evalOnceErrorCode, 0) ) \
+ { \
+ DebugMessageN5("ca_require_noerr: [%s, %d] (goto %s;) %s:%d", \
+ #errorCode, evalOnceErrorCode, \
+ #exceptionLabel, \
+ __FILE__, \
+ __LINE__); \
+ goto exceptionLabel; \
+ } \
+ } while ( 0 )
+
+ #define ca_verify_noerr(errorCode) \
+ do \
+ { \
+ int evalOnceErrorCode = (errorCode); \
+ if ( __builtin_expect(0 != evalOnceErrorCode, 0) ) \
+ { \
+ DebugMessageN4("ca_verify_noerr: [%s, %d] %s:%d", \
+ #errorCode, evalOnceErrorCode, \
+ __FILE__, \
+ __LINE__); \
+ } \
+ } while ( 0 )
+
+ #define ca_debug_string(message) \
+ do \
+ { \
+ DebugMessageN3("ca_debug_string: %s %s:%d", \
+ message, \
+ __FILE__, \
+ __LINE__); \
+ } while ( 0 )
+
+
+ #define ca_verify(assertion) \
+ do \
+ { \
+ if ( __builtin_expect(!(assertion), 0) ) \
+ { \
+ DebugMessageN3("ca_verify: %s %s:%d", \
+ #assertion, \
+ __FILE__, \
+ __LINE__); \
+ } \
+ } while ( 0 )
+
+ #define ca_require(assertion, exceptionLabel) \
+ do \
+ { \
+ if ( __builtin_expect(!(assertion), 0) ) \
+ { \
+ DebugMessageN4("ca_require: %s %s %s:%d", \
+ #assertion, \
+ #exceptionLabel, \
+ __FILE__, \
+ __LINE__); \
+ goto exceptionLabel; \
+ } \
+ } while ( 0 )
+
+ #define ca_check(assertion) \
+ do \
+ { \
+ if ( __builtin_expect(!(assertion), 0) ) \
+ { \
+ DebugMessageN3("ca_check: %s %s:%d", \
+ #assertion, \
+ __FILE__, \
+ __LINE__); \
+ } \
+ } while ( 0 )
+
+#else
+ #define XThrowIfError(error, operation) \
+ do { \
+ OSStatus __err = error; \
+ if (__err) { \
+ throw CAXException(operation, __err); \
+ } \
+ } while (0)
+
+ #define XThrowIf(condition, error, operation) \
+ do { \
+ if (condition) { \
+ OSStatus __err = error; \
+ throw CAXException(operation, __err); \
+ } \
+ } while (0)
+
+ #define XRequireNoError(error, label) \
+ do { \
+ OSStatus __err = error; \
+ if (__err) { \
+ goto label; \
+ } \
+ } while (0)
+
+ #define XAssert(assertion) \
+ do { \
+ if (!(assertion)) { \
+ } \
+ } while (0)
+
+ #define XAssertNoError(error) \
+ do { \
+ /*OSStatus __err =*/ error; \
+ } while (0)
+
+ #define ca_require_noerr(errorCode, exceptionLabel) \
+ do \
+ { \
+ if ( __builtin_expect(0 != (errorCode), 0) ) \
+ { \
+ goto exceptionLabel; \
+ } \
+ } while ( 0 )
+
+ #define ca_verify_noerr(errorCode) \
+ do \
+ { \
+ if ( 0 != (errorCode) ) \
+ { \
+ } \
+ } while ( 0 )
+
+ #define ca_debug_string(message)
+
+ #define ca_verify(assertion) \
+ do \
+ { \
+ if ( !(assertion) ) \
+ { \
+ } \
+ } while ( 0 )
+
+ #define ca_require(assertion, exceptionLabel) \
+ do \
+ { \
+ if ( __builtin_expect(!(assertion), 0) ) \
+ { \
+ goto exceptionLabel; \
+ } \
+ } while ( 0 )
+
+ #define ca_check(assertion) \
+ do \
+ { \
+ if ( !(assertion) ) \
+ { \
+ } \
+ } while ( 0 )
+
+
+#endif
+
+#define XThrow(error, operation) XThrowIf(true, error, operation)
+#define XThrowIfErr(error) XThrowIfError(error, #error)
+
+#endif // __CAXException_h__
diff --git a/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.cpp b/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.cpp
new file mode 100644
index 0000000000..98d868eb73
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.cpp
@@ -0,0 +1,149 @@
+/*
+ File: MatrixMixerVolumes.cpp
+ Abstract: MatrixMixerVolumes.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "MatrixMixerVolumes.h"
+#include "CAXException.h"
+
+OSStatus NumberChannels (AudioUnit au,
+ AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ UInt32 &outChans);
+
+
+OSStatus PrintBuses (FILE* file, const char* str, AudioUnit au, AudioUnitScope inScope)
+{
+ OSStatus result;
+ UInt32 busCount;
+ UInt32 theSize = sizeof(busCount);
+
+ ca_require_noerr (result = AudioUnitGetProperty (au, kAudioUnitProperty_ElementCount,
+ inScope, 0, &busCount, &theSize), home);
+
+ fprintf (file, "\t%s Elements:\n\t\t", str);
+ for (UInt32 i = 0; i < busCount; ++i) {
+ Float32 val;
+ ca_require_noerr (result = AudioUnitGetParameter (au, kMatrixMixerParam_Enable, inScope, i, &val), home);
+ UInt32 numChans;
+ ca_require_noerr (result = NumberChannels (au, inScope, i, numChans), home);
+ char frameCharStart = (val != 0 ? '[' : '{');
+ char frameCharEnd = (val != 0 ? ']' : '}');
+ fprintf (file, "%d:%c%d, %c%c ", (int)i, frameCharStart, (int)numChans, (val != 0 ? 'T' : 'F'), frameCharEnd);
+ }
+ fprintf (file, "\n");
+home:
+ return result;
+}
+
+void PrintMatrixMixerVolumes (FILE* file, AudioUnit au)
+{
+ UInt32 dims[2];
+ UInt32 theSize = sizeof(UInt32) * 2;
+ Float32 *theVols = NULL;
+ OSStatus result;
+
+// this call will fail if the unit is NOT initialized as it would present an incomplete state
+ ca_require_noerr (result = AudioUnitGetProperty (au, kAudioUnitProperty_MatrixDimensions,
+ kAudioUnitScope_Global, 0, dims, &theSize), home);
+
+ theSize = ((dims[0] + 1) * (dims[1] + 1)) * sizeof(Float32);
+
+ theVols = static_cast<Float32*> (malloc (theSize));
+
+ ca_require_noerr (result = AudioUnitGetProperty (au, kAudioUnitProperty_MatrixLevels,
+ kAudioUnitScope_Global, 0, theVols, &theSize), home);
+
+home:
+ if (result) {
+ if (theVols)
+ free(theVols);
+ return;
+ }
+
+ theSize /= sizeof(Float32);
+
+ unsigned int inputs = dims[0];
+ unsigned int outputs = dims[1];
+
+ fprintf (file, "\tInput Channels = %d, Output Channels = %d\n", (int)dims[0], (int)dims[1]);
+ PrintBuses (file, "Input", au, kAudioUnitScope_Input);
+ PrintBuses (file, "Output", au, kAudioUnitScope_Output);
+ fprintf (file, "\tGlobal Volume: %.3f\n", theVols [theSize - 1]);
+ for (unsigned int i = 0; i < (inputs + 1); ++i) {
+ if (i < inputs) {
+ fprintf (file, "\t%.3f ", theVols[(i + 1) * (outputs + 1) - 1]);
+
+ for (unsigned int j = 0; j < outputs; ++j)
+ fprintf (file, "(%.3f) ", theVols[(i * (outputs + 1)) + j]);
+ } else {
+ fprintf (file, "\t ");
+ for (unsigned int j = 0; j < outputs; ++j)
+ fprintf (file, " %.3f ", theVols[(i * (outputs + 1)) + j]);
+ }
+ fprintf (file, "\n");
+ }
+
+#if 0
+ for (unsigned int i = 0; i < theSize; ++i)
+ printf ("%f, ", theVols[i]);
+#endif
+ free(theVols);
+}
+
+// Utility routine that gets the number of channels from an audio unit
+OSStatus NumberChannels (AudioUnit au,
+ AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ UInt32 &outChans)
+{
+ AudioStreamBasicDescription desc;
+ UInt32 dataSize = sizeof (AudioStreamBasicDescription);
+ OSStatus result = AudioUnitGetProperty (au, kAudioUnitProperty_StreamFormat,
+ inScope, inEl,
+ &desc, &dataSize);
+ if (!result)
+ outChans = desc.mChannelsPerFrame;
+ return result;
+}
diff --git a/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.h b/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.h
new file mode 100644
index 0000000000..06854f0774
--- /dev/null
+++ b/libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.h
@@ -0,0 +1,71 @@
+/*
+ File: MatrixMixerVolumes.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __MatrixMixerVolumes_h__
+#define __MatrixMixerVolumes_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnit.h>
+#else
+ #include <AudioUnit.h>
+#endif
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+// prints the matrix mixer volumes of a specific audio unit to the given file
+void PrintMatrixMixerVolumes (FILE* file, AudioUnit au);
+
+// prints the mixer volumes for the specific scope of the audio unit
+// results will be printed to the speficied file "file" with identifiying string tag "str"
+OSStatus PrintBuses (FILE* file, char* str, AudioUnit au, AudioUnitScope inScope);
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/libs/appleutility/AUOutputBL.cpp b/libs/appleutility/CoreAudio105/AUOutputBL.cpp
index 3e6444855a..3e6444855a 100644
--- a/libs/appleutility/AUOutputBL.cpp
+++ b/libs/appleutility/CoreAudio105/AUOutputBL.cpp
diff --git a/libs/appleutility/AUOutputBL.h b/libs/appleutility/CoreAudio105/AUOutputBL.h
index 39887b6a3f..39887b6a3f 100644
--- a/libs/appleutility/AUOutputBL.h
+++ b/libs/appleutility/CoreAudio105/AUOutputBL.h
diff --git a/libs/appleutility/AUParamInfo.cpp b/libs/appleutility/CoreAudio105/AUParamInfo.cpp
index 6379e5642c..6379e5642c 100644
--- a/libs/appleutility/AUParamInfo.cpp
+++ b/libs/appleutility/CoreAudio105/AUParamInfo.cpp
diff --git a/libs/appleutility/AUParamInfo.h b/libs/appleutility/CoreAudio105/AUParamInfo.h
index e20e14b259..e20e14b259 100644
--- a/libs/appleutility/AUParamInfo.h
+++ b/libs/appleutility/CoreAudio105/AUParamInfo.h
diff --git a/libs/appleutility/CAAUParameter.cpp b/libs/appleutility/CoreAudio105/CAAUParameter.cpp
index 4953a3cd23..4953a3cd23 100644
--- a/libs/appleutility/CAAUParameter.cpp
+++ b/libs/appleutility/CoreAudio105/CAAUParameter.cpp
diff --git a/libs/appleutility/CAAUParameter.h b/libs/appleutility/CoreAudio105/CAAUParameter.h
index 82d75e560b..82d75e560b 100644
--- a/libs/appleutility/CAAUParameter.h
+++ b/libs/appleutility/CoreAudio105/CAAUParameter.h
diff --git a/libs/appleutility/CAAudioChannelLayout.cpp b/libs/appleutility/CoreAudio105/CAAudioChannelLayout.cpp
index 5ca0b76ca0..5ca0b76ca0 100644
--- a/libs/appleutility/CAAudioChannelLayout.cpp
+++ b/libs/appleutility/CoreAudio105/CAAudioChannelLayout.cpp
diff --git a/libs/appleutility/CAAudioChannelLayout.h b/libs/appleutility/CoreAudio105/CAAudioChannelLayout.h
index 388f087ef9..388f087ef9 100644
--- a/libs/appleutility/CAAudioChannelLayout.h
+++ b/libs/appleutility/CoreAudio105/CAAudioChannelLayout.h
diff --git a/libs/appleutility/CAAudioChannelLayoutObject.cpp b/libs/appleutility/CoreAudio105/CAAudioChannelLayoutObject.cpp
index 9e3cf586e9..9e3cf586e9 100644
--- a/libs/appleutility/CAAudioChannelLayoutObject.cpp
+++ b/libs/appleutility/CoreAudio105/CAAudioChannelLayoutObject.cpp
diff --git a/libs/appleutility/CAAudioFile.cpp b/libs/appleutility/CoreAudio105/CAAudioFile.cpp
index 148565e7fb..148565e7fb 100644
--- a/libs/appleutility/CAAudioFile.cpp
+++ b/libs/appleutility/CoreAudio105/CAAudioFile.cpp
diff --git a/libs/appleutility/CAAudioFile.h b/libs/appleutility/CoreAudio105/CAAudioFile.h
index 8dd1d8690b..8dd1d8690b 100644
--- a/libs/appleutility/CAAudioFile.h
+++ b/libs/appleutility/CoreAudio105/CAAudioFile.h
diff --git a/libs/appleutility/CAAudioUnit.cpp b/libs/appleutility/CoreAudio105/CAAudioUnit.cpp
index f0b0890c51..f0b0890c51 100644
--- a/libs/appleutility/CAAudioUnit.cpp
+++ b/libs/appleutility/CoreAudio105/CAAudioUnit.cpp
diff --git a/libs/appleutility/CAAudioUnit.h b/libs/appleutility/CoreAudio105/CAAudioUnit.h
index 7be48464e7..7be48464e7 100644
--- a/libs/appleutility/CAAudioUnit.h
+++ b/libs/appleutility/CoreAudio105/CAAudioUnit.h
diff --git a/libs/appleutility/CABufferList.cpp b/libs/appleutility/CoreAudio105/CABufferList.cpp
index 581f1adda7..581f1adda7 100644
--- a/libs/appleutility/CABufferList.cpp
+++ b/libs/appleutility/CoreAudio105/CABufferList.cpp
diff --git a/libs/appleutility/CABufferList.h b/libs/appleutility/CoreAudio105/CABufferList.h
index fc94769458..fc94769458 100644
--- a/libs/appleutility/CABufferList.h
+++ b/libs/appleutility/CoreAudio105/CABufferList.h
diff --git a/libs/appleutility/CACFDictionary.cpp b/libs/appleutility/CoreAudio105/CACFDictionary.cpp
index ed983a828f..ed983a828f 100644
--- a/libs/appleutility/CACFDictionary.cpp
+++ b/libs/appleutility/CoreAudio105/CACFDictionary.cpp
diff --git a/libs/appleutility/CACFDictionary.h b/libs/appleutility/CoreAudio105/CACFDictionary.h
index 3221436a16..3221436a16 100644
--- a/libs/appleutility/CACFDictionary.h
+++ b/libs/appleutility/CoreAudio105/CACFDictionary.h
diff --git a/libs/appleutility/CACFNumber.cpp b/libs/appleutility/CoreAudio105/CACFNumber.cpp
index edbf3db2d9..edbf3db2d9 100644
--- a/libs/appleutility/CACFNumber.cpp
+++ b/libs/appleutility/CoreAudio105/CACFNumber.cpp
diff --git a/libs/appleutility/CACFNumber.h b/libs/appleutility/CoreAudio105/CACFNumber.h
index 450a94dd47..450a94dd47 100644
--- a/libs/appleutility/CACFNumber.h
+++ b/libs/appleutility/CoreAudio105/CACFNumber.h
diff --git a/libs/appleutility/CACFString.cpp b/libs/appleutility/CoreAudio105/CACFString.cpp
index 5e00b11db6..5e00b11db6 100644
--- a/libs/appleutility/CACFString.cpp
+++ b/libs/appleutility/CoreAudio105/CACFString.cpp
diff --git a/libs/appleutility/CACFString.h b/libs/appleutility/CoreAudio105/CACFString.h
index 4adc460e70..4adc460e70 100644
--- a/libs/appleutility/CACFString.h
+++ b/libs/appleutility/CoreAudio105/CACFString.h
diff --git a/libs/appleutility/CAComponent.cpp b/libs/appleutility/CoreAudio105/CAComponent.cpp
index 5c9686df36..5c9686df36 100644
--- a/libs/appleutility/CAComponent.cpp
+++ b/libs/appleutility/CoreAudio105/CAComponent.cpp
diff --git a/libs/appleutility/CAComponent.h b/libs/appleutility/CoreAudio105/CAComponent.h
index 4009bc42fe..4009bc42fe 100644
--- a/libs/appleutility/CAComponent.h
+++ b/libs/appleutility/CoreAudio105/CAComponent.h
diff --git a/libs/appleutility/CAComponentDescription.cpp b/libs/appleutility/CoreAudio105/CAComponentDescription.cpp
index 70e0285501..70e0285501 100644
--- a/libs/appleutility/CAComponentDescription.cpp
+++ b/libs/appleutility/CoreAudio105/CAComponentDescription.cpp
diff --git a/libs/appleutility/CAComponentDescription.h b/libs/appleutility/CoreAudio105/CAComponentDescription.h
index a70d1eb2ec..a70d1eb2ec 100644
--- a/libs/appleutility/CAComponentDescription.h
+++ b/libs/appleutility/CoreAudio105/CAComponentDescription.h
diff --git a/libs/appleutility/CAConditionalMacros.h b/libs/appleutility/CoreAudio105/CAConditionalMacros.h
index 4f504699c7..4f504699c7 100644
--- a/libs/appleutility/CAConditionalMacros.h
+++ b/libs/appleutility/CoreAudio105/CAConditionalMacros.h
diff --git a/libs/appleutility/CADebugMacros.cpp b/libs/appleutility/CoreAudio105/CADebugMacros.cpp
index edee1f3d51..edee1f3d51 100644
--- a/libs/appleutility/CADebugMacros.cpp
+++ b/libs/appleutility/CoreAudio105/CADebugMacros.cpp
diff --git a/libs/appleutility/CADebugMacros.h b/libs/appleutility/CoreAudio105/CADebugMacros.h
index 58e5387862..58e5387862 100644
--- a/libs/appleutility/CADebugMacros.h
+++ b/libs/appleutility/CoreAudio105/CADebugMacros.h
diff --git a/libs/appleutility/CAMath.h b/libs/appleutility/CoreAudio105/CAMath.h
index bc9ec51661..bc9ec51661 100644
--- a/libs/appleutility/CAMath.h
+++ b/libs/appleutility/CoreAudio105/CAMath.h
diff --git a/libs/appleutility/CAReferenceCounted.h b/libs/appleutility/CoreAudio105/CAReferenceCounted.h
index c17b5c38bd..c17b5c38bd 100644
--- a/libs/appleutility/CAReferenceCounted.h
+++ b/libs/appleutility/CoreAudio105/CAReferenceCounted.h
diff --git a/libs/appleutility/CAStreamBasicDescription.cpp b/libs/appleutility/CoreAudio105/CAStreamBasicDescription.cpp
index bc48dd0f76..bc48dd0f76 100644
--- a/libs/appleutility/CAStreamBasicDescription.cpp
+++ b/libs/appleutility/CoreAudio105/CAStreamBasicDescription.cpp
diff --git a/libs/appleutility/CAStreamBasicDescription.h b/libs/appleutility/CoreAudio105/CAStreamBasicDescription.h
index db3faaea0d..db3faaea0d 100644
--- a/libs/appleutility/CAStreamBasicDescription.h
+++ b/libs/appleutility/CoreAudio105/CAStreamBasicDescription.h
diff --git a/libs/appleutility/CAXException.cpp b/libs/appleutility/CoreAudio105/CAXException.cpp
index 744a77ffa8..744a77ffa8 100644
--- a/libs/appleutility/CAXException.cpp
+++ b/libs/appleutility/CoreAudio105/CAXException.cpp
diff --git a/libs/appleutility/CAXException.h b/libs/appleutility/CoreAudio105/CAXException.h
index b27f833805..b27f833805 100644
--- a/libs/appleutility/CAXException.h
+++ b/libs/appleutility/CoreAudio105/CAXException.h
diff --git a/libs/appleutility/wscript b/libs/appleutility/wscript
index 2c54b28d1f..cf596b29a6 100644
--- a/libs/appleutility/wscript
+++ b/libs/appleutility/wscript
@@ -1,5 +1,6 @@
#!/usr/bin/env python
from waflib.extras import autowaf as autowaf
+from waflib import Options
import os
libappleutility_sources = [
@@ -7,7 +8,6 @@ libappleutility_sources = [
'AUParamInfo.cpp',
'CAAudioChannelLayout.cpp',
'CAAudioChannelLayoutObject.cpp',
- 'CAAudioFile.cpp',
'CAAudioUnit.cpp',
'CAAUParameter.cpp',
'CABufferList.cpp',
@@ -26,15 +26,29 @@ def options(opt):
def configure(conf):
autowaf.configure(conf)
+ if not conf.env['build_target'] in ['panther', 'tiger', 'leopard']:
+ if not (Options.options.ppc and conf.env['build_target'] == 'snowleopard'):
+ conf.env.append_value ('CFLAGS', '-DCOREAUDIO105')
+ conf.env.append_value ('CXXFLAGS', '-DCOREAUDIO105')
+ conf.define ('COREAUDIO105', 1)
def build(bld):
obj = bld(features = 'cxx cxxshlib')
obj.uselib = 'AUDIOUNITS OSX'
- obj.source = libappleutility_sources
+ obj.source = '';
+ if bld.is_defined('COREAUDIO105'):
+ obj.export_includes = ['CoreAudio105']
+ obj.source += ' CoreAudio105/CAAudioFile.cpp';
+ for src in libappleutility_sources:
+ obj.source += ' CoreAudio105/' + src;
+ else:
+ obj.export_includes = ['CoreAudio/PublicUtility']
+ for src in libappleutility_sources:
+ obj.source += ' CoreAudio/PublicUtility/' + src;
+
# apple did not write this library with full symbol export control
# so we need to override any visibility default.
autowaf.ensure_visible_symbols (obj, True)
- obj.export_includes = ['.']
obj.includes = ['.']
obj.name = 'libappleutility'
obj.target = 'appleutility'