From 66704eefcbe132eac0415434340f788808c40302 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Sat, 17 Oct 2015 20:46:58 -0400 Subject: alternative new version of the AppleUtility library --- libs/appleutility/AUOutputBL.cpp | 160 -- libs/appleutility/AUOutputBL.h | 115 - libs/appleutility/AUParamInfo.cpp | 134 -- libs/appleutility/AUParamInfo.h | 107 - libs/appleutility/CAAUParameter.cpp | 316 --- libs/appleutility/CAAUParameter.h | 187 -- libs/appleutility/CAAudioChannelLayout.cpp | 138 -- libs/appleutility/CAAudioChannelLayout.h | 162 -- libs/appleutility/CAAudioChannelLayoutObject.cpp | 199 -- libs/appleutility/CAAudioFile.cpp | 1241 ---------- libs/appleutility/CAAudioFile.h | 442 ---- libs/appleutility/CAAudioUnit.cpp | 1277 ----------- libs/appleutility/CAAudioUnit.h | 384 ---- libs/appleutility/CABufferList.cpp | 179 -- libs/appleutility/CABufferList.h | 300 --- libs/appleutility/CACFDictionary.cpp | 478 ---- libs/appleutility/CACFDictionary.h | 141 -- libs/appleutility/CACFNumber.cpp | 65 - libs/appleutility/CACFNumber.h | 102 - libs/appleutility/CACFString.cpp | 106 - libs/appleutility/CACFString.h | 156 -- libs/appleutility/CAComponent.cpp | 257 --- libs/appleutility/CAComponent.h | 120 - libs/appleutility/CAComponentDescription.cpp | 123 - libs/appleutility/CAComponentDescription.h | 148 -- libs/appleutility/CAConditionalMacros.h | 74 - libs/appleutility/CADebugMacros.cpp | 84 - libs/appleutility/CADebugMacros.h | 414 ---- libs/appleutility/CAMath.h | 64 - libs/appleutility/CAReferenceCounted.h | 83 - libs/appleutility/CAStreamBasicDescription.cpp | 520 ----- libs/appleutility/CAStreamBasicDescription.h | 224 -- libs/appleutility/CAXException.cpp | 45 - libs/appleutility/CAXException.h | 158 -- .../CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.cpp | 580 +++++ .../CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.h | 147 ++ .../CoreAudio/AudioCodecs/ACPublic/ACCodec.cpp | 329 +++ .../CoreAudio/AudioCodecs/ACPublic/ACCodec.h | 115 + .../AudioCodecs/ACPublic/ACCodecDispatchTypes.h | 259 +++ .../AudioCodecs/ACPublic/ACComponentResources.r | 196 ++ .../AudioCodecs/ACPublic/ACConditionalMacros.h | 73 + .../AudioCodecs/ACPublic/ACPlugInDispatch.cpp | 283 +++ .../AudioCodecs/ACPublic/ACPlugInDispatch.h | 88 + .../AudioCodecs/ACPublic/ACSimpleCodec.cpp | 364 +++ .../CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.h | 105 + .../AudioCodecs/ACPublic/GetCodecBundle.cpp | 76 + .../AudioCodecs/ACPublic/GetCodecBundle.h | 60 + .../AudioFile/AFPublic/AudioFileComponentBase.cpp | 1040 +++++++++ .../AudioFile/AFPublic/AudioFileComponentBase.h | 311 +++ .../AudioFile/AFPublic/AudioFileFormat.cpp | 71 + .../CoreAudio/AudioFile/AFPublic/AudioFileFormat.h | 125 + .../AudioFile/AFPublic/AudioFileObject.cpp | 1966 ++++++++++++++++ .../CoreAudio/AudioFile/AFPublic/AudioFileObject.h | 667 ++++++ .../AudioFile/AFPublic/CompressedPacketTable.cpp | 216 ++ .../AudioFile/AFPublic/CompressedPacketTable.h | 186 ++ .../CoreAudio/AudioFile/AFPublic/DataSource.cpp | 689 ++++++ .../CoreAudio/AudioFile/AFPublic/DataSource.h | 372 +++ .../AudioUnits/AUPublic/AUBase/AUBase.cpp | 2393 ++++++++++++++++++++ .../CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.h | 1048 +++++++++ .../AudioUnits/AUPublic/AUBase/AUDispatch.cpp | 438 ++++ .../AudioUnits/AUPublic/AUBase/AUDispatch.h | 82 + .../AudioUnits/AUPublic/AUBase/AUInputElement.cpp | 151 ++ .../AudioUnits/AUPublic/AUBase/AUInputElement.h | 119 + .../AudioUnits/AUPublic/AUBase/AUOutputElement.cpp | 62 + .../AudioUnits/AUPublic/AUBase/AUOutputElement.h | 66 + .../AUPublic/AUBase/AUPlugInDispatch.cpp | 669 ++++++ .../AudioUnits/AUPublic/AUBase/AUPlugInDispatch.h | 144 ++ .../AudioUnits/AUPublic/AUBase/AUResources.r | 140 ++ .../AudioUnits/AUPublic/AUBase/AUScopeElement.cpp | 565 +++++ .../AudioUnits/AUPublic/AUBase/AUScopeElement.h | 553 +++++ .../AudioUnits/AUPublic/AUBase/ComponentBase.cpp | 370 +++ .../AudioUnits/AUPublic/AUBase/ComponentBase.h | 353 +++ .../AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp | 403 ++++ .../AUPublic/AUCarbonViewBase/AUCarbonViewBase.h | 188 ++ .../AUCarbonViewBase/AUCarbonViewControl.cpp | 710 ++++++ .../AUCarbonViewBase/AUCarbonViewControl.h | 230 ++ .../AUCarbonViewBase/AUCarbonViewDispatch.cpp | 125 + .../AUPublic/AUCarbonViewBase/AUControlGroup.cpp | 359 +++ .../AUPublic/AUCarbonViewBase/AUControlGroup.h | 90 + .../AUCarbonViewBase/CarbonEventHandler.cpp | 90 + .../AUPublic/AUCarbonViewBase/CarbonEventHandler.h | 71 + .../AUPublic/AUInstrumentBase/AUInstrumentBase.cpp | 843 +++++++ .../AUPublic/AUInstrumentBase/AUInstrumentBase.h | 269 +++ .../AUPublic/AUInstrumentBase/LockFreeFIFO.h | 168 ++ .../AUPublic/AUInstrumentBase/MIDIControlHandler.h | 92 + .../AUPublic/AUInstrumentBase/SynthElement.cpp | 419 ++++ .../AUPublic/AUInstrumentBase/SynthElement.h | 227 ++ .../AUPublic/AUInstrumentBase/SynthEvent.h | 145 ++ .../AUPublic/AUInstrumentBase/SynthNote.cpp | 140 ++ .../AUPublic/AUInstrumentBase/SynthNote.h | 187 ++ .../AUPublic/AUInstrumentBase/SynthNoteList.cpp | 93 + .../AUPublic/AUInstrumentBase/SynthNoteList.h | 232 ++ .../AUViewBase/AUViewLocalizedStringKeys.h | 88 + .../AUPublic/OtherBases/AUEffectBase.cpp | 466 ++++ .../AudioUnits/AUPublic/OtherBases/AUEffectBase.h | 377 +++ .../AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp | 495 ++++ .../AudioUnits/AUPublic/OtherBases/AUMIDIBase.h | 213 ++ .../AUPublic/OtherBases/AUMIDIEffectBase.cpp | 164 ++ .../AUPublic/OtherBases/AUMIDIEffectBase.h | 104 + .../AUPublic/OtherBases/AUOutputBase.cpp | 76 + .../AudioUnits/AUPublic/OtherBases/AUOutputBase.h | 82 + .../AUPublic/OtherBases/AUPannerBase.cpp | 706 ++++++ .../AudioUnits/AUPublic/OtherBases/AUPannerBase.h | 272 +++ .../AUPublic/OtherBases/MusicDeviceBase.cpp | 354 +++ .../AUPublic/OtherBases/MusicDeviceBase.h | 126 ++ .../AudioUnits/AUPublic/Utility/AUBaseHelper.cpp | 125 + .../AudioUnits/AUPublic/Utility/AUBaseHelper.h | 75 + .../AudioUnits/AUPublic/Utility/AUBuffer.cpp | 219 ++ .../AudioUnits/AUPublic/Utility/AUBuffer.h | 267 +++ .../AUPublic/Utility/AUInputFormatConverter.h | 155 ++ .../AudioUnits/AUPublic/Utility/AUMIDIDefs.h | 138 ++ .../AudioUnits/AUPublic/Utility/AUSilentTimeout.h | 93 + .../AUPublic/Utility/AUTimestampGenerator.cpp | 203 ++ .../AUPublic/Utility/AUTimestampGenerator.h | 163 ++ .../CoreAudio/PublicUtility/AUOutputBL.cpp | 169 ++ .../CoreAudio/PublicUtility/AUOutputBL.h | 118 + .../CoreAudio/PublicUtility/AUParamInfo.cpp | 139 ++ .../CoreAudio/PublicUtility/AUParamInfo.h | 112 + .../CoreAudio/PublicUtility/CAAUMIDIMap.cpp | 227 ++ .../CoreAudio/PublicUtility/CAAUMIDIMap.h | 541 +++++ .../CoreAudio/PublicUtility/CAAUMIDIMapManager.cpp | 233 ++ .../CoreAudio/PublicUtility/CAAUMIDIMapManager.h | 102 + .../CoreAudio/PublicUtility/CAAUParameter.cpp | 400 ++++ .../CoreAudio/PublicUtility/CAAUParameter.h | 191 ++ .../CoreAudio/PublicUtility/CAAUProcessor.cpp | 707 ++++++ .../CoreAudio/PublicUtility/CAAUProcessor.h | 293 +++ .../CoreAudio/PublicUtility/CAAtomic.h | 305 +++ .../CoreAudio/PublicUtility/CAAtomicStack.h | 239 ++ .../CoreAudio/PublicUtility/CAAudioBufferList.cpp | 239 ++ .../CoreAudio/PublicUtility/CAAudioBufferList.h | 108 + .../PublicUtility/CAAudioChannelLayout.cpp | 153 ++ .../CoreAudio/PublicUtility/CAAudioChannelLayout.h | 199 ++ .../PublicUtility/CAAudioChannelLayoutObject.cpp | 210 ++ .../CoreAudio/PublicUtility/CAAudioFileFormats.cpp | 424 ++++ .../CoreAudio/PublicUtility/CAAudioFileFormats.h | 149 ++ .../CoreAudio/PublicUtility/CAAudioTimeStamp.cpp | 135 ++ .../CoreAudio/PublicUtility/CAAudioTimeStamp.h | 97 + .../CoreAudio/PublicUtility/CAAudioUnit.cpp | 1421 ++++++++++++ .../CoreAudio/PublicUtility/CAAudioUnit.h | 439 ++++ .../PublicUtility/CAAudioUnitOutputCapturer.h | 143 ++ .../CoreAudio/PublicUtility/CAAudioValueRange.cpp | 262 +++ .../CoreAudio/PublicUtility/CAAudioValueRange.h | 121 + .../CoreAudio/PublicUtility/CAAutoDisposer.h | 508 +++++ .../CoreAudio/PublicUtility/CABitOperations.h | 206 ++ libs/appleutility/CoreAudio/PublicUtility/CABool.h | 89 + .../CoreAudio/PublicUtility/CABufferList.cpp | 259 +++ .../CoreAudio/PublicUtility/CABufferList.h | 324 +++ .../CoreAudio/PublicUtility/CABundleLocker.cpp | 84 + .../CoreAudio/PublicUtility/CABundleLocker.h | 69 + .../CoreAudio/PublicUtility/CAByteOrder.h | 161 ++ .../CoreAudio/PublicUtility/CACFArray.cpp | 821 +++++++ .../CoreAudio/PublicUtility/CACFArray.h | 195 ++ .../CoreAudio/PublicUtility/CACFData.h | 108 + .../CoreAudio/PublicUtility/CACFDictionary.cpp | 581 +++++ .../CoreAudio/PublicUtility/CACFDictionary.h | 176 ++ .../PublicUtility/CACFDistributedNotification.cpp | 107 + .../PublicUtility/CACFDistributedNotification.h | 73 + .../CoreAudio/PublicUtility/CACFMachPort.cpp | 168 ++ .../CoreAudio/PublicUtility/CACFMachPort.h | 95 + .../CoreAudio/PublicUtility/CACFMessagePort.cpp | 163 ++ .../CoreAudio/PublicUtility/CACFMessagePort.h | 119 + .../CoreAudio/PublicUtility/CACFNumber.cpp | 83 + .../CoreAudio/PublicUtility/CACFNumber.h | 151 ++ .../CoreAudio/PublicUtility/CACFObject.h | 138 ++ .../CoreAudio/PublicUtility/CACFPlugIn.h | 101 + .../CoreAudio/PublicUtility/CACFPreferences.cpp | 287 +++ .../CoreAudio/PublicUtility/CACFPreferences.h | 92 + .../CoreAudio/PublicUtility/CACFString.cpp | 110 + .../CoreAudio/PublicUtility/CACFString.h | 196 ++ .../CoreAudio/PublicUtility/CAComponent.cpp | 182 ++ .../CoreAudio/PublicUtility/CAComponent.h | 121 + .../PublicUtility/CAComponentDescription.cpp | 110 + .../PublicUtility/CAComponentDescription.h | 145 ++ .../CoreAudio/PublicUtility/CADebugMacros.cpp | 90 + .../CoreAudio/PublicUtility/CADebugMacros.h | 581 +++++ .../CoreAudio/PublicUtility/CADebugPrintf.cpp | 89 + .../CoreAudio/PublicUtility/CADebugPrintf.h | 115 + .../CoreAudio/PublicUtility/CADebugger.cpp | 103 + .../CoreAudio/PublicUtility/CADebugger.h | 69 + .../CoreAudio/PublicUtility/CAException.h | 83 + .../CoreAudio/PublicUtility/CAExtAudioFile.h | 300 +++ .../CoreAudio/PublicUtility/CAFilePathUtils.cpp | 188 ++ .../CoreAudio/PublicUtility/CAFilePathUtils.h | 70 + .../CoreAudio/PublicUtility/CAGuard.cpp | 343 +++ .../appleutility/CoreAudio/PublicUtility/CAGuard.h | 133 ++ .../CoreAudio/PublicUtility/CAHALAudioDevice.cpp | 1156 ++++++++++ .../CoreAudio/PublicUtility/CAHALAudioDevice.h | 238 ++ .../CoreAudio/PublicUtility/CAHALAudioObject.cpp | 370 +++ .../CoreAudio/PublicUtility/CAHALAudioObject.h | 155 ++ .../CoreAudio/PublicUtility/CAHALAudioStream.cpp | 182 ++ .../CoreAudio/PublicUtility/CAHALAudioStream.h | 94 + .../PublicUtility/CAHALAudioSystemObject.cpp | 181 ++ .../PublicUtility/CAHALAudioSystemObject.h | 90 + .../CoreAudio/PublicUtility/CAHostTimeBase.cpp | 99 + .../CoreAudio/PublicUtility/CAHostTimeBase.h | 234 ++ .../CoreAudio/PublicUtility/CALogMacros.h | 140 ++ libs/appleutility/CoreAudio/PublicUtility/CAMath.h | 68 + .../CoreAudio/PublicUtility/CAMixMap.h | 157 ++ .../CoreAudio/PublicUtility/CAMutex.cpp | 345 +++ .../appleutility/CoreAudio/PublicUtility/CAMutex.h | 163 ++ .../CoreAudio/PublicUtility/CAPThread.cpp | 450 ++++ .../CoreAudio/PublicUtility/CAPThread.h | 191 ++ .../CoreAudio/PublicUtility/CAPersistence.cpp | 468 ++++ .../CoreAudio/PublicUtility/CAProcess.cpp | 92 + .../CoreAudio/PublicUtility/CAProcess.h | 75 + .../CoreAudio/PublicUtility/CAPropertyAddress.h | 312 +++ .../CoreAudio/PublicUtility/CAReferenceCounted.h | 97 + .../CoreAudio/PublicUtility/CARingBuffer.cpp | 319 +++ .../CoreAudio/PublicUtility/CARingBuffer.h | 126 ++ .../CoreAudio/PublicUtility/CASettingsStorage.cpp | 737 ++++++ .../CoreAudio/PublicUtility/CASettingsStorage.h | 128 ++ .../CoreAudio/PublicUtility/CASharedLibrary.cpp | 118 + .../CoreAudio/PublicUtility/CASharedLibrary.h | 64 + .../PublicUtility/CASpectralProcessor.cpp | 376 +++ .../CoreAudio/PublicUtility/CASpectralProcessor.h | 146 ++ .../PublicUtility/CAStreamBasicDescription.cpp | 879 +++++++ .../PublicUtility/CAStreamBasicDescription.h | 424 ++++ .../PublicUtility/CAStreamRangedDescription.cpp | 183 ++ .../PublicUtility/CAStreamRangedDescription.h | 140 ++ .../CoreAudio/PublicUtility/CAThreadSafeList.h | 233 ++ libs/appleutility/CoreAudio/PublicUtility/CATink.h | 146 ++ .../CoreAudio/PublicUtility/CATokenMap.h | 212 ++ .../CoreAudio/PublicUtility/CAVectorUnit.cpp | 195 ++ .../CoreAudio/PublicUtility/CAVectorUnit.h | 101 + .../CoreAudio/PublicUtility/CAVectorUnitTypes.h | 60 + .../CoreAudio/PublicUtility/CAVolumeCurve.cpp | 482 ++++ .../CoreAudio/PublicUtility/CAVolumeCurve.h | 178 ++ .../CoreAudio/PublicUtility/CAXException.cpp | 49 + .../CoreAudio/PublicUtility/CAXException.h | 361 +++ .../CoreAudio/PublicUtility/MatrixMixerVolumes.cpp | 149 ++ .../CoreAudio/PublicUtility/MatrixMixerVolumes.h | 71 + libs/appleutility/CoreAudio105/AUOutputBL.cpp | 160 ++ libs/appleutility/CoreAudio105/AUOutputBL.h | 115 + libs/appleutility/CoreAudio105/AUParamInfo.cpp | 134 ++ libs/appleutility/CoreAudio105/AUParamInfo.h | 107 + libs/appleutility/CoreAudio105/CAAUParameter.cpp | 316 +++ libs/appleutility/CoreAudio105/CAAUParameter.h | 187 ++ .../CoreAudio105/CAAudioChannelLayout.cpp | 138 ++ .../CoreAudio105/CAAudioChannelLayout.h | 162 ++ .../CoreAudio105/CAAudioChannelLayoutObject.cpp | 199 ++ libs/appleutility/CoreAudio105/CAAudioFile.cpp | 1241 ++++++++++ libs/appleutility/CoreAudio105/CAAudioFile.h | 442 ++++ libs/appleutility/CoreAudio105/CAAudioUnit.cpp | 1277 +++++++++++ libs/appleutility/CoreAudio105/CAAudioUnit.h | 384 ++++ libs/appleutility/CoreAudio105/CABufferList.cpp | 179 ++ libs/appleutility/CoreAudio105/CABufferList.h | 300 +++ libs/appleutility/CoreAudio105/CACFDictionary.cpp | 478 ++++ libs/appleutility/CoreAudio105/CACFDictionary.h | 141 ++ libs/appleutility/CoreAudio105/CACFNumber.cpp | 65 + libs/appleutility/CoreAudio105/CACFNumber.h | 102 + libs/appleutility/CoreAudio105/CACFString.cpp | 106 + libs/appleutility/CoreAudio105/CACFString.h | 156 ++ libs/appleutility/CoreAudio105/CAComponent.cpp | 257 +++ libs/appleutility/CoreAudio105/CAComponent.h | 120 + .../CoreAudio105/CAComponentDescription.cpp | 123 + .../CoreAudio105/CAComponentDescription.h | 148 ++ .../CoreAudio105/CAConditionalMacros.h | 74 + libs/appleutility/CoreAudio105/CADebugMacros.cpp | 84 + libs/appleutility/CoreAudio105/CADebugMacros.h | 414 ++++ libs/appleutility/CoreAudio105/CAMath.h | 64 + .../appleutility/CoreAudio105/CAReferenceCounted.h | 83 + .../CoreAudio105/CAStreamBasicDescription.cpp | 520 +++++ .../CoreAudio105/CAStreamBasicDescription.h | 224 ++ libs/appleutility/CoreAudio105/CAXException.cpp | 45 + libs/appleutility/CoreAudio105/CAXException.h | 158 ++ libs/appleutility/wscript | 20 +- 266 files changed, 61529 insertions(+), 8706 deletions(-) delete mode 100644 libs/appleutility/AUOutputBL.cpp delete mode 100644 libs/appleutility/AUOutputBL.h delete mode 100644 libs/appleutility/AUParamInfo.cpp delete mode 100644 libs/appleutility/AUParamInfo.h delete mode 100644 libs/appleutility/CAAUParameter.cpp delete mode 100644 libs/appleutility/CAAUParameter.h delete mode 100644 libs/appleutility/CAAudioChannelLayout.cpp delete mode 100644 libs/appleutility/CAAudioChannelLayout.h delete mode 100644 libs/appleutility/CAAudioChannelLayoutObject.cpp delete mode 100644 libs/appleutility/CAAudioFile.cpp delete mode 100644 libs/appleutility/CAAudioFile.h delete mode 100644 libs/appleutility/CAAudioUnit.cpp delete mode 100644 libs/appleutility/CAAudioUnit.h delete mode 100644 libs/appleutility/CABufferList.cpp delete mode 100644 libs/appleutility/CABufferList.h delete mode 100644 libs/appleutility/CACFDictionary.cpp delete mode 100644 libs/appleutility/CACFDictionary.h delete mode 100644 libs/appleutility/CACFNumber.cpp delete mode 100644 libs/appleutility/CACFNumber.h delete mode 100644 libs/appleutility/CACFString.cpp delete mode 100644 libs/appleutility/CACFString.h delete mode 100644 libs/appleutility/CAComponent.cpp delete mode 100644 libs/appleutility/CAComponent.h delete mode 100644 libs/appleutility/CAComponentDescription.cpp delete mode 100644 libs/appleutility/CAComponentDescription.h delete mode 100644 libs/appleutility/CAConditionalMacros.h delete mode 100644 libs/appleutility/CADebugMacros.cpp delete mode 100644 libs/appleutility/CADebugMacros.h delete mode 100644 libs/appleutility/CAMath.h delete mode 100644 libs/appleutility/CAReferenceCounted.h delete mode 100644 libs/appleutility/CAStreamBasicDescription.cpp delete mode 100644 libs/appleutility/CAStreamBasicDescription.h delete mode 100644 libs/appleutility/CAXException.cpp delete mode 100644 libs/appleutility/CAXException.h create mode 100644 libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.cpp create mode 100644 libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACBaseCodec.h create mode 100644 libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.cpp create mode 100644 libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodec.h create mode 100644 libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACCodecDispatchTypes.h create mode 100644 libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACComponentResources.r create mode 100644 libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACConditionalMacros.h create mode 100644 libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.cpp create mode 100644 libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACPlugInDispatch.h create mode 100644 libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.cpp create mode 100644 libs/appleutility/CoreAudio/AudioCodecs/ACPublic/ACSimpleCodec.h create mode 100644 libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.cpp create mode 100644 libs/appleutility/CoreAudio/AudioCodecs/ACPublic/GetCodecBundle.h create mode 100644 libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.cpp create mode 100644 libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.h create mode 100644 libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.cpp create mode 100644 libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.h create mode 100644 libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.cpp create mode 100644 libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.h create mode 100644 libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp create mode 100644 libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.h create mode 100644 libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.cpp create mode 100644 libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUResources.r create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/MIDIControlHandler.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUMIDIDefs.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUSilentTimeout.h create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp create mode 100644 libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/AUOutputBL.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/AUParamInfo.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMap.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAUMIDIMapManager.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAUParameter.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAUProcessor.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAtomic.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAtomicStack.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAudioBufferList.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayout.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAudioChannelLayoutObject.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAudioFileFormats.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAudioTimeStamp.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAudioUnit.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAudioUnitOutputCapturer.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAudioValueRange.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAAutoDisposer.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CABitOperations.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CABool.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CABufferList.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CABufferList.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CABundleLocker.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAByteOrder.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFArray.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFArray.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFData.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFDictionary.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFDistributedNotification.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFMachPort.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFMessagePort.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFNumber.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFNumber.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFObject.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFPlugIn.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFPreferences.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFString.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CACFString.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAComponent.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAComponent.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAComponentDescription.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CADebugMacros.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CADebugPrintf.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CADebugger.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CADebugger.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAException.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAExtAudioFile.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAFilePathUtils.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAGuard.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAGuard.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAHALAudioDevice.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAHALAudioObject.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAHALAudioStream.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAHALAudioSystemObject.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAHostTimeBase.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CALogMacros.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAMath.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAMixMap.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAMutex.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAMutex.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAPThread.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAPThread.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAPersistence.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAProcess.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAProcess.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAPropertyAddress.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAReferenceCounted.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CARingBuffer.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CASettingsStorage.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CASharedLibrary.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CASpectralProcessor.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAStreamBasicDescription.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAStreamRangedDescription.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAThreadSafeList.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CATink.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CATokenMap.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAVectorUnit.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAVectorUnitTypes.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAVolumeCurve.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAXException.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/CAXException.h create mode 100644 libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.cpp create mode 100644 libs/appleutility/CoreAudio/PublicUtility/MatrixMixerVolumes.h create mode 100644 libs/appleutility/CoreAudio105/AUOutputBL.cpp create mode 100644 libs/appleutility/CoreAudio105/AUOutputBL.h create mode 100644 libs/appleutility/CoreAudio105/AUParamInfo.cpp create mode 100644 libs/appleutility/CoreAudio105/AUParamInfo.h create mode 100644 libs/appleutility/CoreAudio105/CAAUParameter.cpp create mode 100644 libs/appleutility/CoreAudio105/CAAUParameter.h create mode 100644 libs/appleutility/CoreAudio105/CAAudioChannelLayout.cpp create mode 100644 libs/appleutility/CoreAudio105/CAAudioChannelLayout.h create mode 100644 libs/appleutility/CoreAudio105/CAAudioChannelLayoutObject.cpp create mode 100644 libs/appleutility/CoreAudio105/CAAudioFile.cpp create mode 100644 libs/appleutility/CoreAudio105/CAAudioFile.h create mode 100644 libs/appleutility/CoreAudio105/CAAudioUnit.cpp create mode 100644 libs/appleutility/CoreAudio105/CAAudioUnit.h create mode 100644 libs/appleutility/CoreAudio105/CABufferList.cpp create mode 100644 libs/appleutility/CoreAudio105/CABufferList.h create mode 100644 libs/appleutility/CoreAudio105/CACFDictionary.cpp create mode 100644 libs/appleutility/CoreAudio105/CACFDictionary.h create mode 100644 libs/appleutility/CoreAudio105/CACFNumber.cpp create mode 100644 libs/appleutility/CoreAudio105/CACFNumber.h create mode 100644 libs/appleutility/CoreAudio105/CACFString.cpp create mode 100644 libs/appleutility/CoreAudio105/CACFString.h create mode 100644 libs/appleutility/CoreAudio105/CAComponent.cpp create mode 100644 libs/appleutility/CoreAudio105/CAComponent.h create mode 100644 libs/appleutility/CoreAudio105/CAComponentDescription.cpp create mode 100644 libs/appleutility/CoreAudio105/CAComponentDescription.h create mode 100644 libs/appleutility/CoreAudio105/CAConditionalMacros.h create mode 100644 libs/appleutility/CoreAudio105/CADebugMacros.cpp create mode 100644 libs/appleutility/CoreAudio105/CADebugMacros.h create mode 100644 libs/appleutility/CoreAudio105/CAMath.h create mode 100644 libs/appleutility/CoreAudio105/CAReferenceCounted.h create mode 100644 libs/appleutility/CoreAudio105/CAStreamBasicDescription.cpp create mode 100644 libs/appleutility/CoreAudio105/CAStreamBasicDescription.h create mode 100644 libs/appleutility/CoreAudio105/CAXException.cpp create mode 100644 libs/appleutility/CoreAudio105/CAXException.h diff --git a/libs/appleutility/AUOutputBL.cpp b/libs/appleutility/AUOutputBL.cpp deleted file mode 100644 index 3e6444855a..0000000000 --- a/libs/appleutility/AUOutputBL.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - AUOutputBL.h - -=============================================================================*/ -#include "AUOutputBL.h" - -/* -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(new Byte[sizeof(UInt32) + (mNumberBuffers * sizeof(AudioBuffer))]); -} - -AUOutputBL::~AUOutputBL() -{ - if (mBufferMemory) - delete[] mBufferMemory; - - if (mBufferList) - delete [] 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(-10874);//(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:%ld, mFrames:%ld, allocatedMemory:%c\n", mBufferList->mNumberBuffers, mFrames, (mBufferMemory != NULL ? 'T' : 'F')); - AudioBuffer *buf = &mBufferList->mBuffers[0]; - for (UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i, ++buf) - printf ("\tBuffer:%ld, Size:%ld, Chans:%ld, Buffer:%X\n", i, buf->mDataByteSize, buf->mNumberChannels, int(buf->mData)); -} -#endif - diff --git a/libs/appleutility/AUOutputBL.h b/libs/appleutility/AUOutputBL.h deleted file mode 100644 index 39887b6a3f..0000000000 --- a/libs/appleutility/AUOutputBL.h +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - AUOutputBL.h - -=============================================================================*/ - -#ifndef __AUOutputBL_h__ -#define __AUOutputBL_h__ - -#include "CAStreamBasicDescription.h" -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#else - #include -#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 (const AUOutputBL &) {} - AUOutputBL& operator= (const AUOutputBL&) { return *this; } -}; - -#endif // __AUOutputBL_h__ diff --git a/libs/appleutility/AUParamInfo.cpp b/libs/appleutility/AUParamInfo.cpp deleted file mode 100644 index 6379e5642c..0000000000 --- a/libs/appleutility/AUParamInfo.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - AUParamInfo.cpp - -=============================================================================*/ -#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 ¶mInfo = 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 (*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/AUParamInfo.h b/libs/appleutility/AUParamInfo.h deleted file mode 100644 index e20e14b259..0000000000 --- a/libs/appleutility/AUParamInfo.h +++ /dev/null @@ -1,107 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - AUParamInfo.h - -=============================================================================*/ -#include -#include -#include -#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) - - 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 ParameterList; - typedef std::map > 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 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 &) {} - AUParamInfo& operator= (const AUParamInfo&) { return *this; } -}; diff --git a/libs/appleutility/CAAUParameter.cpp b/libs/appleutility/CAAUParameter.cpp deleted file mode 100644 index 4953a3cd23..0000000000 --- a/libs/appleutility/CAAUParameter.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAAUParameter.cpp - -=============================================================================*/ - -#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); - - 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 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, - mParameterID, - &stringValue, - &propertySize); - - if (err == noErr && stringValue.outString != NULL) - return stringValue.outString; - } - - Float32 val = (value == NULL ? GetValue() : *value); - char valstr[32]; - AUParameterFormatValue (val, this, valstr, 4); - return CFStringCreateWithCString(NULL, valstr, kCFStringEncodingUTF8); -} - -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, - mParameterID, - &valueString, - &propertySize); - - if (err == noErr) { - return valueString.outValue; - } - } - - Float32 paramValue = mParamInfo.defaultValue; - char valstr[32]; - CFStringGetCString(str, valstr, sizeof(valstr), kCFStringEncodingUTF8); - sscanf(valstr, "%f", ¶mValue); - return paramValue; -} - -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 = 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: %ld, Name: %s\n", mParameterID, clump, chars); - free (chars); -} -#endif diff --git a/libs/appleutility/CAAUParameter.h b/libs/appleutility/CAAUParameter.h deleted file mode 100644 index 82d75e560b..0000000000 --- a/libs/appleutility/CAAUParameter.h +++ /dev/null @@ -1,187 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAAUParameter.h - -=============================================================================*/ - -#ifndef __CAAUParameter_h__ -#define __CAAUParameter_h__ - -#include - -// ____________________________________________________________________________ -// 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/CAAudioChannelLayout.cpp b/libs/appleutility/CAAudioChannelLayout.cpp deleted file mode 100644 index 5ca0b76ca0..0000000000 --- a/libs/appleutility/CAAudioChannelLayout.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAAudioChannelLayout.cpp - -=============================================================================*/ - -//============================================================================= -// Includes -//============================================================================= - -// Self Include -#include "CAAudioChannelLayout.h" -#include -#include - -//============================================================================= -// CAAudioChannelLayout -//============================================================================= - -AudioChannelLayout* CAAudioChannelLayout::Create(UInt32 inNumberChannelDescriptions) -{ - UInt32 theSize = CalculateByteSize(inNumberChannelDescriptions); - AudioChannelLayout* theAnswer = static_cast(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); -} - -// 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) -{ - fprintf (file, "\tTag=0x%lX, ", layout->mChannelLayoutTag); - if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) - fprintf (file, "Using Bitmap:0x%lX\n", layout->mChannelBitmap); - else { - fprintf (file, "Num Chan Descs=%ld\n", layout->mNumberChannelDescriptions); - const AudioChannelDescription *desc = layout->mChannelDescriptions; - for (unsigned int i = 0; i < layout->mNumberChannelDescriptions; ++i, ++desc) { - fprintf (file, "\t\tLabel=%ld, Flags=0x%lX, ", desc->mChannelLabel, 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/CAAudioChannelLayout.h b/libs/appleutility/CAAudioChannelLayout.h deleted file mode 100644 index 388f087ef9..0000000000 --- a/libs/appleutility/CAAudioChannelLayout.h +++ /dev/null @@ -1,162 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAAudioChannelLayout.h - -=============================================================================*/ -#if !defined(__CAAudioChannelLayout_h__) -#define __CAAudioChannelLayout_h__ - -//============================================================================= -// Includes -//============================================================================= - -// System Includes -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include - #include -#else - #include - #include -#endif -#include -#include -#include - -#if !HAL_Build - #include "CAReferenceCounted.h" -#endif - -//============================================================================= -// CAAudioChannelLayout -//============================================================================= - -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 offsetof(AudioChannelLayout, mChannelDescriptions) + inNumberChannelDescriptions * sizeof(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; - - void SetWithTag(AudioChannelLayoutTag inTag); - - bool IsValid() const { return NumberChannels() > 0; } - UInt32 Size() const { return mLayoutHolder ? mLayoutHolder->Size() : 0; } - - UInt32 NumberChannels() const { return NumberChannels(Layout()); } - - AudioChannelLayoutTag Tag() const { return Layout().mChannelLayoutTag; } - const AudioChannelLayout& Layout() const { return mLayoutHolder->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 ACLRefCounter : public CAReferenceCounted { - public: - ACLRefCounter (UInt32 inDataSize) - { - if (inDataSize < offsetof(AudioChannelLayout, mChannelDescriptions)) - inDataSize = offsetof(AudioChannelLayout, mChannelDescriptions); - - mLayout = static_cast(malloc (inDataSize)); - memset (mLayout, 0, inDataSize); - mByteSize = inDataSize; - } - - const AudioChannelLayout & Layout() const { return *mLayout; } - - UInt32 Size () const { return mByteSize; } - - private: - AudioChannelLayout *mLayout; - UInt32 mByteSize; - - // 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 mLayout; } - ~ACLRefCounter() { if (mLayout) { free(mLayout); mLayout = NULL; } } - - private: - ACLRefCounter () : mLayout(NULL) { } - ACLRefCounter(const ACLRefCounter& other) : CAReferenceCounted (other), mLayout(NULL) { } - ACLRefCounter& operator=(const ACLRefCounter&) { return *this; } - }; - - ACLRefCounter *mLayoutHolder; -#endif // HAL_Build - -}; - -#endif diff --git a/libs/appleutility/CAAudioChannelLayoutObject.cpp b/libs/appleutility/CAAudioChannelLayoutObject.cpp deleted file mode 100644 index 9e3cf586e9..0000000000 --- a/libs/appleutility/CAAudioChannelLayoutObject.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAAudioChannelLayoutObject.cpp - -=============================================================================*/ - -#include "CAAudioChannelLayout.h" -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include - #include -#else - #include - #include -#endif - - -CAAudioChannelLayout::CAAudioChannelLayout () -{ - mLayoutHolder = new ACLRefCounter (offsetof(AudioChannelLayout, mChannelDescriptions)); -} - -//============================================================================= -// CAAudioChannelLayout::CAAudioChannelLayout -//============================================================================= -CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround) -{ - // this chooses default layouts based on the number of channels... - UInt32 theSize = CalculateByteSize (inNumberChannels); - - mLayoutHolder = new ACLRefCounter (theSize); - - AudioChannelLayout* layout = mLayoutHolder->GetLayout(); - - layout->mNumberChannelDescriptions = inNumberChannels; - - switch (inNumberChannels) - { - case 1: - layout->mChannelLayoutTag = kAudioChannelLayoutTag_Mono; - break; - case 2: - layout->mChannelLayoutTag = inChooseSurround ? kAudioChannelLayoutTag_Binaural : kAudioChannelLayoutTag_Stereo; - break; - case 4: - layout->mChannelLayoutTag = inChooseSurround ? kAudioChannelLayoutTag_Ambisonic_B_Format : kAudioChannelLayoutTag_AudioUnit_4; - break; - case 5: - layout->mChannelLayoutTag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_5_0 : kAudioChannelLayoutTag_AudioUnit_5; - break; - case 6: - layout->mChannelLayoutTag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_6_0 : kAudioChannelLayoutTag_AudioUnit_6; - break; - case 7: - layout->mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_7_0; - break; - case 8: - layout->mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_8; - break; - default: - // here we have a "broken" layout, in the sense that we haven't any idea how to lay this out - // the layout itself is all set to zeros - // ### no longer true ### - SetAllToUnknown(*layout, inNumberChannels); - break; - } -} - -//============================================================================= -// CAAudioChannelLayout::CAAudioChannelLayout -//============================================================================= -CAAudioChannelLayout::CAAudioChannelLayout (AudioChannelLayoutTag inLayoutTag) - : mLayoutHolder(NULL) -{ - SetWithTag(inLayoutTag); -} - -//============================================================================= -// CAAudioChannelLayout::CAAudioChannelLayout -//============================================================================= -CAAudioChannelLayout::CAAudioChannelLayout (const CAAudioChannelLayout &c) - : mLayoutHolder(NULL) -{ - *this = c; -} - - -//============================================================================= -// CAAudioChannelLayout::AudioChannelLayout -//============================================================================= -CAAudioChannelLayout::CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout) - : mLayoutHolder(NULL) -{ - *this = inChannelLayout; -} - -//============================================================================= -// CAAudioChannelLayout::~CAAudioChannelLayout -//============================================================================= -CAAudioChannelLayout::~CAAudioChannelLayout () -{ - if (mLayoutHolder) { - mLayoutHolder->release(); - mLayoutHolder = NULL; - } -} - -//============================================================================= -// CAAudioChannelLayout::CAAudioChannelLayout -//============================================================================= -CAAudioChannelLayout& CAAudioChannelLayout::operator= (const CAAudioChannelLayout &c) -{ - if (mLayoutHolder != c.mLayoutHolder) { - if (mLayoutHolder) - mLayoutHolder->release(); - - if ((mLayoutHolder = c.mLayoutHolder) != NULL) - mLayoutHolder->retain(); - } - - return *this; -} - -CAAudioChannelLayout& CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout) -{ - if (mLayoutHolder) - mLayoutHolder->release(); - - UInt32 theSize = CalculateByteSize (inChannelLayout->mNumberChannelDescriptions); - - mLayoutHolder = new ACLRefCounter (theSize); - - memcpy(mLayoutHolder->mLayout, inChannelLayout, theSize); - return *this; -} - -void CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag) -{ - if (mLayoutHolder) - mLayoutHolder->release(); - - mLayoutHolder = new ACLRefCounter(offsetof(AudioChannelLayout, mChannelDescriptions[0])); - AudioChannelLayout* layout = mLayoutHolder->GetLayout(); - layout->mChannelLayoutTag = inTag; -} - -//============================================================================= -// CAAudioChannelLayout::operator== -//============================================================================= -bool CAAudioChannelLayout::operator== (const CAAudioChannelLayout &c) const -{ - if (mLayoutHolder == c.mLayoutHolder) - return true; - return Layout() == c.Layout(); -} - -//============================================================================= -// CAAudioChannelLayout::Print -//============================================================================= -void CAAudioChannelLayout::Print (FILE* file) const -{ - CAShowAudioChannelLayout (file, &Layout()); -} - diff --git a/libs/appleutility/CAAudioFile.cpp b/libs/appleutility/CAAudioFile.cpp deleted file mode 100644 index 148565e7fb..0000000000 --- a/libs/appleutility/CAAudioFile.cpp +++ /dev/null @@ -1,1241 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAAudioFile.cpp - -=============================================================================*/ - -#include "CAAudioFile.h" - -#if !CAAF_USE_EXTAUDIOFILE - -#include "CAXException.h" -#include -#include "CAHostTimeBase.h" -#include "CADebugMacros.h" - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#else - #include -#endif - -#if DEBUG - //#define VERBOSE_IO 1 - //#define VERBOSE_CONVERTER 1 - //#define VERBOSE_CHANNELMAP 1 - //#define LOG_FUNCTION_ENTRIES 1 - - #if VERBOSE_CHANNELMAP - #include "CAChannelLayouts.h" // this is in Source/Tests/AudioFileTools/Utility - #endif -#endif - -#if LOG_FUNCTION_ENTRIES - class FunctionLogger { - public: - FunctionLogger(const char *name, const char *fmt=NULL, ...) : mName(name) { - Indent(); - printf("-> %s ", name); - if (fmt) { - va_list args; - va_start(args, fmt); - vprintf(fmt, args); - va_end(args); - } - printf("\n"); - ++sIndent; - } - ~FunctionLogger() { - --sIndent; - Indent(); - printf("<- %s\n", mName); - if (sIndent == 0) - printf("\n"); - } - - static void Indent() { - for (int i = sIndent; --i >= 0; ) { - putchar(' '); putchar(' '); - } - } - - const char *mName; - static int sIndent; - }; - int FunctionLogger::sIndent = 0; - - #define LOG_FUNCTION(name, format, ...) FunctionLogger _flog(name, format, ## __VA_ARGS__); -#else - #define LOG_FUNCTION(name, format, foo) -#endif - -static const UInt32 kDefaultIOBufferSizeBytes = 0x10000; - -#if CAAUDIOFILE_PROFILE - #define StartTiming(af, starttime) UInt64 starttime = af->mProfiling ? CAHostTimeBase::GetTheCurrentTime() : 0 - #define ElapsedTime(af, starttime, counter) if (af->mProfiling) counter += (CAHostTimeBase::GetTheCurrentTime() - starttime) -#else - #define StartTiming(af, starttime) - #define ElapsedTime(af, starttime, counter) -#endif - -#define kNoMoreInputRightNow 'nein' - -// _______________________________________________________________________________________ -// -CAAudioFile::CAAudioFile() : - mAudioFile(0), - mUseCache(false), - mFinishingEncoding(false), - mMode(kClosed), - mFileDataOffset(-1), - mFramesToSkipFollowingSeek(0), - - mClientOwnsIOBuffer(false), - mPacketDescs(NULL), - mNumPacketDescs(0), - mConverter(NULL), - mMagicCookie(NULL), - mWriteBufferList(NULL) -#if CAAUDIOFILE_PROFILE - , - mProfiling(false), - mTicksInConverter(0), - mTicksInReadInConverter(0), - mTicksInIO(0), - mInConverter(false) -#endif -{ - mIOBufferList.mBuffers[0].mData = NULL; - mIOBufferList.mBuffers[0].mDataByteSize = 0; - mClientMaxPacketSize = 0; - mIOBufferSizeBytes = kDefaultIOBufferSizeBytes; -} - -// _______________________________________________________________________________________ -// -CAAudioFile::~CAAudioFile() -{ - Close(); -} - -// _______________________________________________________________________________________ -// -void CAAudioFile::Close() -{ - LOG_FUNCTION("CAAudioFile::Close", NULL, NULL); - if (mMode == kClosed) - return; - if (mMode == kWriting) - FlushEncoder(); - CloseConverter(); - if (mAudioFile != 0 && mOwnOpenFile) { - AudioFileClose(mAudioFile); - mAudioFile = 0; - } - if (!mClientOwnsIOBuffer) { - delete[] (Byte *)mIOBufferList.mBuffers[0].mData; - mIOBufferList.mBuffers[0].mData = NULL; - mIOBufferList.mBuffers[0].mDataByteSize = 0; - } - delete[] mPacketDescs; mPacketDescs = NULL; mNumPacketDescs = 0; - delete[] mMagicCookie; mMagicCookie = NULL; - delete mWriteBufferList; mWriteBufferList = NULL; - mMode = kClosed; -} - -// _______________________________________________________________________________________ -// -void CAAudioFile::CloseConverter() -{ - if (mConverter) { -#if VERBOSE_CONVERTER - printf("CAAudioFile %p : CloseConverter\n", this); -#endif - AudioConverterDispose(mConverter); - mConverter = NULL; - } -} - -// ======================================================================================= - -// _______________________________________________________________________________________ -// -void CAAudioFile::Open(const FSRef &fsref) -{ - LOG_FUNCTION("CAAudioFile::Open", "%p", this); - XThrowIf(mMode != kClosed, kExtAudioFileError_InvalidOperationOrder, "file already open"); - mFSRef = fsref; - XThrowIfError(AudioFileOpen(&mFSRef, fsRdPerm, 0, &mAudioFile), "open audio file"); - mOwnOpenFile = true; - mMode = kReading; - GetExistingFileInfo(); -} - -// _______________________________________________________________________________________ -// -void CAAudioFile::Wrap(AudioFileID fileID, bool forWriting) -{ - LOG_FUNCTION("CAAudioFile::Wrap", "%p", this); - XThrowIf(mMode != kClosed, kExtAudioFileError_InvalidOperationOrder, "file already open"); - - mAudioFile = fileID; - mOwnOpenFile = false; - mMode = forWriting ? kPreparingToWrite : kReading; - GetExistingFileInfo(); - if (forWriting) - FileFormatChanged(); -} - -// _______________________________________________________________________________________ -// -void CAAudioFile::CreateNew(const FSRef &parentDir, CFStringRef filename, AudioFileTypeID filetype, const AudioStreamBasicDescription &dataFormat, const AudioChannelLayout *layout) -{ - LOG_FUNCTION("CAAudioFile::CreateNew", "%p", this); - XThrowIf(mMode != kClosed, kExtAudioFileError_InvalidOperationOrder, "file already open"); - - mFileDataFormat = dataFormat; - if (layout) { - mFileChannelLayout = layout; -#if VERBOSE_CHANNELMAP - printf("PrepareNew passed channel layout: %s\n", CAChannelLayouts::ConstantToString(mFileChannelLayout.Tag())); -#endif - } - mMode = kPreparingToCreate; - FileFormatChanged(&parentDir, filename, filetype); -} - -// _______________________________________________________________________________________ -// -// called to create the file -- or update its format/channel layout/properties based on an encoder -// setting change -void CAAudioFile::FileFormatChanged(const FSRef *parentDir, CFStringRef filename, AudioFileTypeID filetype) -{ - LOG_FUNCTION("CAAudioFile::FileFormatChanged", "%p", this); - XThrowIf(mMode != kPreparingToCreate && mMode != kPreparingToWrite, kExtAudioFileError_InvalidOperationOrder, "new file not prepared"); - - UInt32 propertySize; - OSStatus err; - AudioStreamBasicDescription saveFileDataFormat = mFileDataFormat; - -#if VERBOSE_CONVERTER - mFileDataFormat.PrintFormat(stdout, "", "Specified file data format"); -#endif - - // Find out the actual format the converter will produce. This is necessary in - // case the bitrate has forced a lower sample rate, which needs to be set correctly - // in the stream description passed to AudioFileCreate. - if (mConverter != NULL) { - propertySize = sizeof(AudioStreamBasicDescription); - Float64 origSampleRate = mFileDataFormat.mSampleRate; - XThrowIfError(AudioConverterGetProperty(mConverter, kAudioConverterCurrentOutputStreamDescription, &propertySize, &mFileDataFormat), "get audio converter's output stream description"); - // do the same for the channel layout being output by the converter -#if VERBOSE_CONVERTER - mFileDataFormat.PrintFormat(stdout, "", "Converter output"); -#endif - if (fiszero(mFileDataFormat.mSampleRate)) - mFileDataFormat.mSampleRate = origSampleRate; - err = AudioConverterGetPropertyInfo(mConverter, kAudioConverterOutputChannelLayout, &propertySize, NULL); - if (err == noErr && propertySize > 0) { - AudioChannelLayout *layout = static_cast(malloc(propertySize)); - err = AudioConverterGetProperty(mConverter, kAudioConverterOutputChannelLayout, &propertySize, layout); - if (err) { - free(layout); - XThrow(err, "couldn't get audio converter's output channel layout"); - } - mFileChannelLayout = layout; -#if VERBOSE_CHANNELMAP - printf("got new file's channel layout from converter: %s\n", CAChannelLayouts::ConstantToString(mFileChannelLayout.Tag())); -#endif - free(layout); - } - } - - // create the output file - if (mMode == kPreparingToCreate) { - CAStreamBasicDescription newFileDataFormat = mFileDataFormat; - if (fiszero(newFileDataFormat.mSampleRate)) - newFileDataFormat.mSampleRate = 44100; // just make something up for now -#if VERBOSE_CONVERTER - newFileDataFormat.PrintFormat(stdout, "", "Applied to new file"); -#endif - XThrowIfError(AudioFileCreate(parentDir, filename, filetype, &newFileDataFormat, 0, &mFSRef, &mAudioFile), "create audio file"); - mMode = kPreparingToWrite; - mOwnOpenFile = true; - } else if (saveFileDataFormat != mFileDataFormat || fnotequal(saveFileDataFormat.mSampleRate, mFileDataFormat.mSampleRate)) { - // second check must be explicit since operator== on ASBD treats SR of zero as "don't care" - if (fiszero(mFileDataFormat.mSampleRate)) - mFileDataFormat.mSampleRate = mClientDataFormat.mSampleRate; -#if VERBOSE_CONVERTER - mFileDataFormat.PrintFormat(stdout, "", "Applied to new file"); -#endif - XThrowIf(fiszero(mFileDataFormat.mSampleRate), kExtAudioFileError_InvalidDataFormat, "file's sample rate is 0"); - XThrowIfError(AudioFileSetProperty(mAudioFile, kAudioFilePropertyDataFormat, sizeof(AudioStreamBasicDescription), &mFileDataFormat), "couldn't update file's data format"); - } - - UInt32 deferSizeUpdates = 1; - err = AudioFileSetProperty(mAudioFile, kAudioFilePropertyDeferSizeUpdates, sizeof(UInt32), &deferSizeUpdates); - - if (mConverter != NULL) { - // encoder - // get the magic cookie, if any, from the converter - delete[] mMagicCookie; mMagicCookie = NULL; - mMagicCookieSize = 0; - - err = AudioConverterGetPropertyInfo(mConverter, kAudioConverterCompressionMagicCookie, &propertySize, NULL); - - // we can get a noErr result and also a propertySize == 0 - // -- if the file format does support magic cookies, but this file doesn't have one. - if (err == noErr && propertySize > 0) { - mMagicCookie = new Byte[propertySize]; - XThrowIfError(AudioConverterGetProperty(mConverter, kAudioConverterCompressionMagicCookie, &propertySize, mMagicCookie), "get audio converter's magic cookie"); - mMagicCookieSize = propertySize; // the converter lies and tell us the wrong size - // now set the magic cookie on the output file - UInt32 willEatTheCookie = false; - // the converter wants to give us one; will the file take it? - err = AudioFileGetPropertyInfo(mAudioFile, kAudioFilePropertyMagicCookieData, - NULL, &willEatTheCookie); - if (err == noErr && willEatTheCookie) { -#if VERBOSE_CONVERTER - printf("Setting cookie on encoded file\n"); -#endif - XThrowIfError(AudioFileSetProperty(mAudioFile, kAudioFilePropertyMagicCookieData, mMagicCookieSize, mMagicCookie), "set audio file's magic cookie"); - } - } - - // get maximum packet size - propertySize = sizeof(UInt32); - XThrowIfError(AudioConverterGetProperty(mConverter, kAudioConverterPropertyMaximumOutputPacketSize, &propertySize, &mFileMaxPacketSize), "get audio converter's maximum output packet size"); - - AllocateBuffers(true /* okToFail */); - } else { - InitFileMaxPacketSize(); - } - - if (mFileChannelLayout.IsValid() && mFileChannelLayout.NumberChannels() > 2) { - // don't bother tagging mono/stereo files - UInt32 isWritable; - err = AudioFileGetPropertyInfo(mAudioFile, kAudioFilePropertyChannelLayout, NULL, &isWritable); - if (!err && isWritable) { -#if VERBOSE_CHANNELMAP - printf("writing file's channel layout: %s\n", CAChannelLayouts::ConstantToString(mFileChannelLayout.Tag())); -#endif - err = AudioFileSetProperty(mAudioFile, kAudioFilePropertyChannelLayout, - mFileChannelLayout.Size(), &mFileChannelLayout.Layout()); - if (err) - CAXException::Warning("could not set the file's channel layout", err); - } else { -#if VERBOSE_CHANNELMAP - printf("file won't accept a channel layout (write)\n"); -#endif - } - } - - UpdateClientMaxPacketSize(); // also sets mFrame0Offset - mPacketMark = 0; - mFrameMark = 0; -} - -// _______________________________________________________________________________________ -// -void CAAudioFile::InitFileMaxPacketSize() -{ - LOG_FUNCTION("CAAudioFile::InitFileMaxPacketSize", "%p", this); - UInt32 propertySize = sizeof(UInt32); - OSStatus err = AudioFileGetProperty(mAudioFile, kAudioFilePropertyMaximumPacketSize, - &propertySize, &mFileMaxPacketSize); - if (err) { - // workaround for 3361377: not all file formats' maximum packet sizes are supported - if (!mFileDataFormat.IsPCM()) - XThrowIfError(err, "get audio file's maximum packet size"); - mFileMaxPacketSize = mFileDataFormat.mBytesPerFrame; - } - AllocateBuffers(true /* okToFail */); -} - - -// _______________________________________________________________________________________ -// -SInt64 CAAudioFile::FileDataOffset() -{ - if (mFileDataOffset < 0) { - UInt32 propertySize = sizeof(SInt64); - XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyDataOffset, &propertySize, &mFileDataOffset), "couldn't get file's data offset"); - } - return mFileDataOffset; -} - -// _______________________________________________________________________________________ -// -SInt64 CAAudioFile::GetNumberFrames() const -{ - AudioFilePacketTableInfo pti; - UInt32 propertySize = sizeof(pti); - OSStatus err = AudioFileGetProperty(mAudioFile, kAudioFilePropertyPacketTableInfo, &propertySize, &pti); - if (err == noErr) - return pti.mNumberValidFrames; - return mFileDataFormat.mFramesPerPacket * GetNumberPackets() - mFrame0Offset; -} - -// _______________________________________________________________________________________ -// -void CAAudioFile::SetNumberFrames(SInt64 nFrames) -{ - XThrowIf(mFileDataFormat.mFramesPerPacket != 1, kExtAudioFileError_InvalidDataFormat, "SetNumberFrames only supported for PCM"); - XThrowIfError(AudioFileSetProperty(mAudioFile, kAudioFilePropertyAudioDataPacketCount, sizeof(SInt64), &nFrames), "Couldn't set number of packets on audio file"); -} - -// _______________________________________________________________________________________ -// -// call for existing file, NOT new one - from Open() or Wrap() -void CAAudioFile::GetExistingFileInfo() -{ - LOG_FUNCTION("CAAudioFile::GetExistingFileInfo", "%p", this); - UInt32 propertySize; - OSStatus err; - - // get mFileDataFormat - propertySize = sizeof(AudioStreamBasicDescription); - XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyDataFormat, &propertySize, &mFileDataFormat), "get audio file's data format"); - - // get mFileChannelLayout - err = AudioFileGetPropertyInfo(mAudioFile, kAudioFilePropertyChannelLayout, &propertySize, NULL); - if (err == noErr && propertySize > 0) { - AudioChannelLayout *layout = static_cast(malloc(propertySize)); - err = AudioFileGetProperty(mAudioFile, kAudioFilePropertyChannelLayout, &propertySize, layout); - if (err == noErr) { - mFileChannelLayout = layout; -#if VERBOSE_CHANNELMAP - printf("existing file's channel layout: %s\n", CAChannelLayouts::ConstantToString(mFileChannelLayout.Tag())); -#endif - } - free(layout); - XThrowIfError(err, "get audio file's channel layout"); - } - if (mMode != kReading) - return; - -#if 0 - // get mNumberPackets - propertySize = sizeof(mNumberPackets); - XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyAudioDataPacketCount, &propertySize, &mNumberPackets), "get audio file's packet count"); -#if VERBOSE_IO - printf("CAAudioFile::GetExistingFileInfo: %qd packets\n", mNumberPackets); -#endif -#endif - - // get mMagicCookie - err = AudioFileGetPropertyInfo(mAudioFile, kAudioFilePropertyMagicCookieData, &propertySize, NULL); - if (err == noErr && propertySize > 0) { - mMagicCookie = new Byte[propertySize]; - mMagicCookieSize = propertySize; - XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyMagicCookieData, &propertySize, mMagicCookie), "get audio file's magic cookie"); - } - InitFileMaxPacketSize(); - mPacketMark = 0; - mFrameMark = 0; - - UpdateClientMaxPacketSize(); -} - -// ======================================================================================= - -// _______________________________________________________________________________________ -// -void CAAudioFile::SetFileChannelLayout(const CAAudioChannelLayout &layout) -{ - LOG_FUNCTION("CAAudioFile::SetFileChannelLayout", "%p", this); - mFileChannelLayout = layout; -#if VERBOSE_CHANNELMAP - printf("file channel layout set explicitly (%s): %s\n", mMode == kReading ? "read" : "write", CAChannelLayouts::ConstantToString(mFileChannelLayout.Tag())); -#endif - if (mMode != kReading) - FileFormatChanged(); -} - -// _______________________________________________________________________________________ -// -void CAAudioFile::SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout) -{ - LOG_FUNCTION("CAAudioFile::SetClientFormat", "%p", this); - XThrowIf(!dataFormat.IsPCM(), kExtAudioFileError_NonPCMClientFormat, "non-PCM client format on audio file"); - - bool dataFormatChanging = (mClientDataFormat.mFormatID == 0 || mClientDataFormat != dataFormat); - - if (dataFormatChanging) { - CloseConverter(); - if (mWriteBufferList) { - delete mWriteBufferList; - mWriteBufferList = NULL; - } - mClientDataFormat = dataFormat; - } - - if (layout && layout->IsValid()) { - XThrowIf(layout->NumberChannels() != mClientDataFormat.NumberChannels(), kExtAudioFileError_InvalidChannelMap, "inappropriate channel map"); - mClientChannelLayout = *layout; - } - - bool differentLayouts; - if (mClientChannelLayout.IsValid()) { - if (mFileChannelLayout.IsValid()) { - differentLayouts = mClientChannelLayout.Tag() != mFileChannelLayout.Tag(); -#if VERBOSE_CHANNELMAP - printf("two valid layouts, %s\n", differentLayouts ? "different" : "same"); -#endif - } else { - differentLayouts = false; -#if VERBOSE_CHANNELMAP - printf("valid client layout, unknown file layout\n"); -#endif - } - } else { - differentLayouts = false; -#if VERBOSE_CHANNELMAP - if (mFileChannelLayout.IsValid()) - printf("valid file layout, unknown client layout\n"); - else - printf("two invalid layouts\n"); -#endif - } - - if (mClientDataFormat != mFileDataFormat || differentLayouts) { - // We need an AudioConverter. - if (mMode == kReading) { - // file -> client (decode) -//mFileDataFormat.PrintFormat( stdout, "", "File: "); -//mClientDataFormat.PrintFormat(stdout, "", "Client: "); - - if (mConverter == NULL) - XThrowIfError(AudioConverterNew(&mFileDataFormat, &mClientDataFormat, &mConverter), - "create audio converter"); - -#if VERBOSE_CONVERTER - printf("CAAudioFile %p -- created converter\n", this); - CAShow(mConverter); -#endif - // set the magic cookie, if any (for decode) - if (mMagicCookie) - SetConverterProperty(kAudioConverterDecompressionMagicCookie, mMagicCookieSize, mMagicCookie, mFileDataFormat.IsPCM()); - // we get cookies from some AIFF's but the converter barfs on them, - // so we set canFail to true for PCM - - SetConverterChannelLayout(false, mFileChannelLayout); - SetConverterChannelLayout(true, mClientChannelLayout); - - // propagate leading/trailing frame counts - if (mFileDataFormat.mBitsPerChannel == 0) { - UInt32 propertySize; - OSStatus err; - AudioFilePacketTableInfo pti; - propertySize = sizeof(pti); - err = AudioFileGetProperty(mAudioFile, kAudioFilePropertyPacketTableInfo, &propertySize, &pti); - if (err == noErr && (pti.mPrimingFrames > 0 || pti.mRemainderFrames > 0)) { - AudioConverterPrimeInfo primeInfo; - primeInfo.leadingFrames = pti.mPrimingFrames; - primeInfo.trailingFrames = pti.mRemainderFrames; - /* ignore any error. better to play it at all than not. */ - /*err = */AudioConverterSetProperty(mConverter, kAudioConverterPrimeInfo, sizeof(primeInfo), &primeInfo); - //XThrowIfError(err, "couldn't set prime info on converter"); - } - } - } else if (mMode == kPreparingToCreate || mMode == kPreparingToWrite) { - // client -> file (encode) - if (mConverter == NULL) - XThrowIfError(AudioConverterNew(&mClientDataFormat, &mFileDataFormat, &mConverter), "create audio converter"); - mWriteBufferList = CABufferList::New("", mClientDataFormat); - SetConverterChannelLayout(false, mClientChannelLayout); - SetConverterChannelLayout(true, mFileChannelLayout); - if (mMode == kPreparingToWrite) - FileFormatChanged(); - } else - XThrowIfError(kExtAudioFileError_InvalidOperationOrder, "audio file format not yet known"); - } - UpdateClientMaxPacketSize(); -} - -// _______________________________________________________________________________________ -// -OSStatus CAAudioFile::SetConverterProperty( - AudioConverterPropertyID inPropertyID, - UInt32 inPropertyDataSize, - const void* inPropertyData, - bool inCanFail) -{ - OSStatus err = noErr; - //LOG_FUNCTION("ExtAudioFile::SetConverterProperty", "%p %-4.4s", this, (char *)&inPropertyID); - if (inPropertyID == kAudioConverterPropertySettings && *(CFPropertyListRef *)inPropertyData == NULL) - ; - else { - err = AudioConverterSetProperty(mConverter, inPropertyID, inPropertyDataSize, inPropertyData); - if (!inCanFail) { - XThrowIfError(err, "set audio converter property"); - } - } - UpdateClientMaxPacketSize(); - if (mMode == kPreparingToWrite) - FileFormatChanged(); - return err; -} - -// _______________________________________________________________________________________ -// -void CAAudioFile::SetConverterChannelLayout(bool output, const CAAudioChannelLayout &layout) -{ - LOG_FUNCTION("CAAudioFile::SetConverterChannelLayout", "%p", this); - OSStatus err; - - if (layout.IsValid()) { -#if VERBOSE_CHANNELMAP - printf("Setting converter's %s channel layout: %s\n", output ? "output" : "input", - CAChannelLayouts::ConstantToString(mFileChannelLayout.Tag())); -#endif - if (output) { - err = AudioConverterSetProperty(mConverter, kAudioConverterOutputChannelLayout, - layout.Size(), &layout.Layout()); - XThrowIf(err && err != kAudioConverterErr_OperationNotSupported, err, "couldn't set converter's output channel layout"); - } else { - err = AudioConverterSetProperty(mConverter, kAudioConverterInputChannelLayout, - layout.Size(), &layout.Layout()); - XThrowIf(err && err != kAudioConverterErr_OperationNotSupported, err, "couldn't set converter's input channel layout"); - } - if (mMode == kPreparingToWrite) - FileFormatChanged(); - } -} - -// _______________________________________________________________________________________ -// -CFArrayRef CAAudioFile::GetConverterConfig() -{ - CFArrayRef plist; - UInt32 propertySize = sizeof(plist); - XThrowIfError(AudioConverterGetProperty(mConverter, kAudioConverterPropertySettings, &propertySize, &plist), "get converter property settings"); - return plist; -} - -// _______________________________________________________________________________________ -// -void CAAudioFile::UpdateClientMaxPacketSize() -{ - LOG_FUNCTION("CAAudioFile::UpdateClientMaxPacketSize", "%p", this); - mFrame0Offset = 0; - if (mConverter != NULL) { - AudioConverterPropertyID property = (mMode == kReading) ? - kAudioConverterPropertyMaximumOutputPacketSize : - kAudioConverterPropertyMaximumInputPacketSize; - - UInt32 propertySize = sizeof(UInt32); - XThrowIfError(AudioConverterGetProperty(mConverter, property, &propertySize, &mClientMaxPacketSize), - "get audio converter's maximum packet size"); - - if (mFileDataFormat.mBitsPerChannel == 0) { - AudioConverterPrimeInfo primeInfo; - propertySize = sizeof(primeInfo); - OSStatus err = AudioConverterGetProperty(mConverter, kAudioConverterPrimeInfo, &propertySize, &primeInfo); - if (err == noErr) - mFrame0Offset = primeInfo.leadingFrames; -#if VERBOSE_CONVERTER - printf("kAudioConverterPrimeInfo: err = %ld, leadingFrames = %ld\n", err, mFrame0Offset); -#endif - } - } else { - mClientMaxPacketSize = mFileMaxPacketSize; - } -} - -// _______________________________________________________________________________________ -// Allocates: mIOBufferList, mIOBufferSizePackets, mPacketDescs -// Dependent on: mFileMaxPacketSize, mIOBufferSizeBytes -void CAAudioFile::AllocateBuffers(bool okToFail) -{ - LOG_FUNCTION("CAAudioFile::AllocateBuffers", "%p", this); - if (mFileMaxPacketSize == 0) { - if (okToFail) - return; - XThrowIf(true, kExtAudioFileError_MaxPacketSizeUnknown, "file's maximum packet size is 0"); - } - UInt32 bufferSizeBytes = mIOBufferSizeBytes = std::max(mIOBufferSizeBytes, mFileMaxPacketSize); - // must be big enough for at least one maximum size packet - - if (mIOBufferList.mBuffers[0].mDataByteSize != bufferSizeBytes) { - mIOBufferList.mNumberBuffers = 1; - mIOBufferList.mBuffers[0].mNumberChannels = mFileDataFormat.mChannelsPerFrame; - if (!mClientOwnsIOBuffer) { - //printf("reallocating I/O buffer\n"); - delete[] (Byte *)mIOBufferList.mBuffers[0].mData; - mIOBufferList.mBuffers[0].mData = new Byte[bufferSizeBytes]; - } - mIOBufferList.mBuffers[0].mDataByteSize = bufferSizeBytes; - mIOBufferSizePackets = bufferSizeBytes / mFileMaxPacketSize; - } - - UInt32 propertySize = sizeof(UInt32); - UInt32 externallyFramed; - XThrowIfError(AudioFormatGetProperty(kAudioFormatProperty_FormatIsExternallyFramed, - sizeof(AudioStreamBasicDescription), &mFileDataFormat, &propertySize, &externallyFramed), - "is format externally framed"); - if (mNumPacketDescs != (externallyFramed ? mIOBufferSizePackets : 0)) { - delete[] mPacketDescs; - mPacketDescs = NULL; - mNumPacketDescs = 0; - - if (externallyFramed) { - //printf("reallocating packet descs\n"); - mPacketDescs = new AudioStreamPacketDescription[mIOBufferSizePackets]; - mNumPacketDescs = mIOBufferSizePackets; - } - } -} - -// _______________________________________________________________________________________ -// -void CAAudioFile::SetIOBuffer(void *buf) -{ - if (!mClientOwnsIOBuffer) - delete[] (Byte *)mIOBufferList.mBuffers[0].mData; - mIOBufferList.mBuffers[0].mData = buf; - - if (buf == NULL) { - mClientOwnsIOBuffer = false; - SetIOBufferSizeBytes(mIOBufferSizeBytes); - } else { - mClientOwnsIOBuffer = true; - AllocateBuffers(); - } -// printf("CAAudioFile::SetIOBuffer %p: %p, 0x%lx bytes, mClientOwns = %d\n", this, mIOBufferList.mBuffers[0].mData, mIOBufferSizeBytes, mClientOwnsIOBuffer); -} - -// =============================================================================== - -/* -For Tiger: -added kAudioFilePropertyPacketToFrame and kAudioFilePropertyFrameToPacket. -You pass in an AudioFramePacketTranslation struct, with the appropriate field filled in, to AudioFileGetProperty. - - kAudioFilePropertyPacketToFrame = 'pkfr', - // pass a AudioFramePacketTranslation with mPacket filled out and get mFrame back. mFrameOffsetInPacket is ignored. - kAudioFilePropertyFrameToPacket = 'frpk', - // pass a AudioFramePacketTranslation with mFrame filled out and get mPacket and mFrameOffsetInPacket back. - -struct AudioFramePacketTranslation -{ - SInt64 mFrame; - SInt64 mPacket; - UInt32 mFrameOffsetInPacket; -}; -*/ - -SInt64 CAAudioFile::PacketToFrame(SInt64 packet) const -{ - AudioFramePacketTranslation trans; - UInt32 propertySize; - - switch (mFileDataFormat.mFramesPerPacket) { - case 1: - return packet; - case 0: - trans.mPacket = packet; - propertySize = sizeof(trans); - XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyPacketToFrame, &propertySize, &trans), - "packet <-> frame translation unimplemented for format with variable frames/packet"); - return trans.mFrame; - } - return packet * mFileDataFormat.mFramesPerPacket; -} - -SInt64 CAAudioFile::FrameToPacket(SInt64 inFrame) const -{ - AudioFramePacketTranslation trans; - UInt32 propertySize; - - switch (mFileDataFormat.mFramesPerPacket) { - case 1: - return inFrame; - case 0: - trans.mFrame = inFrame; - propertySize = sizeof(trans); - XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyFrameToPacket, &propertySize, &trans), - "packet <-> frame translation unimplemented for format with variable frames/packet"); - return trans.mPacket; - } - return inFrame / mFileDataFormat.mFramesPerPacket; -} - -// _______________________________________________________________________________________ -// - -SInt64 CAAudioFile::Tell() const // frameNumber -{ - return mFrameMark - mFrame0Offset; -} - -void CAAudioFile::SeekToPacket(SInt64 packetNumber) -{ -#if VERBOSE_IO - printf("CAAudioFile::SeekToPacket: %qd\n", packetNumber); -#endif - XThrowIf(mMode != kReading || packetNumber < 0 /*|| packetNumber >= mNumberPackets*/ , kExtAudioFileError_InvalidSeek, "seek to packet in audio file"); - if (mPacketMark == packetNumber) - return; // already there! don't reset converter - mPacketMark = packetNumber; - - mFrameMark = PacketToFrame(packetNumber) - mFrame0Offset; - mFramesToSkipFollowingSeek = 0; - if (mConverter) - // must reset -- if we reached end of stream. converter will no longer work otherwise - AudioConverterReset(mConverter); -} - -/* - Example: AAC, 1024 frames/packet, 2112 frame offset - - 2112 - | - Absolute frames: 0 1024 2048 | 3072 - +---------+---------+--|------+---------+---------+ - Packets: | 0 | 1 | | 2 | 3 | 4 | - +---------+---------+--|------+---------+---------+ - Client frames: -2112 -1088 -64 | 960 SeekToFrame, TellFrame - | - 0 - - * Offset between absolute and client frames is mFrame0Offset. - *** mFrameMark is in client frames *** - - Examples: - clientFrame 0 960 1000 1024 - absoluteFrame 2112 3072 3112 3136 - packet 0 0 0 1 - tempFrameMark* -2112 -2112 -2112 -1088 - mFramesToSkipFollowingSeek 2112 3072 3112 2112 -*/ -void CAAudioFile::Seek(SInt64 clientFrame) -{ - if (clientFrame == mFrameMark) - return; // already there! don't reset converter - - //SInt64 absoluteFrame = clientFrame + mFrame0Offset; - XThrowIf(mMode != kReading || clientFrame < 0 || !mClientDataFormat.IsPCM(), kExtAudioFileError_InvalidSeek, "seek to frame in audio file"); - -#if VERBOSE_IO - SInt64 prevFrameMark = mFrameMark; -#endif - - SInt64 packet; - packet = FrameToPacket(clientFrame); - if (packet < 0) - packet = 0; - SeekToPacket(packet); - // this will have backed up mFrameMark to match the beginning of the packet - mFramesToSkipFollowingSeek = std::max(UInt32(clientFrame - mFrameMark), UInt32(0)); - mFrameMark = clientFrame; - -#if VERBOSE_IO - printf("CAAudioFile::SeekToFrame: frame %qd (from %qd), packet %qd, skip %ld frames\n", mFrameMark, prevFrameMark, packet, mFramesToSkipFollowingSeek); -#endif -} - -// _______________________________________________________________________________________ -// -void CAAudioFile::Read(UInt32 &ioNumPackets, AudioBufferList *ioData) - // May read fewer packets than requested if: - // buffer is not big enough - // file does not contain that many more packets - // Note that eofErr is not fatal, just results in 0 packets returned - // ioData's buffer sizes may be shortened -{ - XThrowIf(mClientMaxPacketSize == 0, kExtAudioFileError_MaxPacketSizeUnknown, "client maximum packet size is 0"); - if (mIOBufferList.mBuffers[0].mData == NULL) { -#if DEBUG - printf("warning: CAAudioFile::AllocateBuffers called from ReadPackets\n"); -#endif - AllocateBuffers(); - } - UInt32 bufferSizeBytes = ioData->mBuffers[0].mDataByteSize; - UInt32 maxNumPackets = bufferSizeBytes / mClientMaxPacketSize; - // older versions of AudioConverterFillComplexBuffer don't do this, so do our own sanity check - UInt32 nPackets = std::min(ioNumPackets, maxNumPackets); - - mMaxPacketsToRead = ~0UL; - - if (mClientDataFormat.mFramesPerPacket == 1) { // PCM or equivalent - while (mFramesToSkipFollowingSeek > 0) { - UInt32 skipFrames = std::min(mFramesToSkipFollowingSeek, maxNumPackets); - UInt32 framesPerPacket; - if ((framesPerPacket=mFileDataFormat.mFramesPerPacket) > 0) - mMaxPacketsToRead = (skipFrames + framesPerPacket - 1) / framesPerPacket; - - if (mConverter == NULL) { - XThrowIfError(ReadInputProc(NULL, &skipFrames, ioData, NULL, this), "read audio file"); - } else { -#if CAAUDIOFILE_PROFILE - mInConverter = true; -#endif - StartTiming(this, fill); - XThrowIfError(AudioConverterFillComplexBuffer(mConverter, ReadInputProc, this, &skipFrames, ioData, NULL), "convert audio packets (pcm read)"); - ElapsedTime(this, fill, mTicksInConverter); -#if CAAUDIOFILE_PROFILE - mInConverter = false; -#endif - } - if (skipFrames == 0) { // hit EOF - ioNumPackets = 0; - return; - } - mFrameMark += skipFrames; -#if VERBOSE_IO - printf("CAAudioFile::ReadPackets: skipped %ld frames\n", skipFrames); -#endif - - mFramesToSkipFollowingSeek -= skipFrames; - - // restore mDataByteSize - for (int i = ioData->mNumberBuffers; --i >= 0 ; ) - ioData->mBuffers[i].mDataByteSize = bufferSizeBytes; - } - } - - if (mFileDataFormat.mFramesPerPacket > 0) - // don't read more packets than we are being asked to produce - mMaxPacketsToRead = nPackets / mFileDataFormat.mFramesPerPacket + 1; - if (mConverter == NULL) { - XThrowIfError(ReadInputProc(NULL, &nPackets, ioData, NULL, this), "read audio file"); - } else { -#if CAAUDIOFILE_PROFILE - mInConverter = true; -#endif - StartTiming(this, fill); - XThrowIfError(AudioConverterFillComplexBuffer(mConverter, ReadInputProc, this, &nPackets, ioData, NULL), "convert audio packets (read)"); - ElapsedTime(this, fill, mTicksInConverter); -#if CAAUDIOFILE_PROFILE - mInConverter = false; -#endif - } - if (mClientDataFormat.mFramesPerPacket == 1) - mFrameMark += nPackets; - - ioNumPackets = nPackets; -} - -// _______________________________________________________________________________________ -// -OSStatus CAAudioFile::ReadInputProc( AudioConverterRef inAudioConverter, - UInt32* ioNumberDataPackets, - AudioBufferList* ioData, - AudioStreamPacketDescription** outDataPacketDescription, - void* inUserData) -{ - CAAudioFile *This = static_cast(inUserData); - -#if 0 - SInt64 remainingPacketsInFile = This->mNumberPackets - This->mPacketMark; - if (remainingPacketsInFile <= 0) { - *ioNumberDataPackets = 0; - ioData->mBuffers[0].mDataByteSize = 0; - if (outDataPacketDescription) - *outDataPacketDescription = This->mPacketDescs; -#if VERBOSE_IO - printf("CAAudioFile::ReadInputProc: EOF\n"); -#endif - return noErr; // not eofErr; EOF is signified by 0 packets/0 bytes - } -#endif - - // determine how much to read - AudioBufferList *readBuffer; - UInt32 readPackets; - if (inAudioConverter != NULL) { - // getting called from converter, need to use our I/O buffer - readBuffer = &This->mIOBufferList; - readPackets = This->mIOBufferSizePackets; - } else { - // getting called directly from ReadPackets, use supplied buffer - if (This->mFileMaxPacketSize == 0) - return kExtAudioFileError_MaxPacketSizeUnknown; - readBuffer = ioData; - readPackets = std::min(*ioNumberDataPackets, readBuffer->mBuffers[0].mDataByteSize / This->mFileMaxPacketSize); - // don't attempt to read more packets than will fit in the buffer - } - // don't try to read past EOF -// if (readPackets > remainingPacketsInFile) -// readPackets = remainingPacketsInFile; - // don't read more packets than necessary to produce the requested amount of converted data - if (readPackets > This->mMaxPacketsToRead) { -#if VERBOSE_IO - printf("CAAudioFile::ReadInputProc: limiting read to %ld packets (from %ld)\n", This->mMaxPacketsToRead, readPackets); -#endif - readPackets = This->mMaxPacketsToRead; - } - - // read - UInt32 bytesRead; - OSStatus err; - - StartTiming(This, read); - StartTiming(This, readinconv); - err = AudioFileReadPackets(This->mAudioFile, This->mUseCache, &bytesRead, This->mPacketDescs, This->mPacketMark, &readPackets, readBuffer->mBuffers[0].mData); -#if CAAUDIOFILE_PROFILE - if (This->mInConverter) ElapsedTime(This, readinconv, This->mTicksInReadInConverter); -#endif - ElapsedTime(This, read, This->mTicksInIO); - - if (err) { - DebugMessageN1("Error %ld from AudioFileReadPackets!!!\n", err); - return err; - } - -#if VERBOSE_IO - printf("CAAudioFile::ReadInputProc: read %ld packets (%qd-%qd), %ld bytes, err %ld\n", readPackets, This->mPacketMark, This->mPacketMark + readPackets, bytesRead, err); -#if VERBOSE_IO >= 2 - if (This->mPacketDescs) { - for (UInt32 i = 0; i < readPackets; ++i) { - printf(" read packet %qd : offset %qd, length %ld\n", This->mPacketMark + i, This->mPacketDescs[i].mStartOffset, This->mPacketDescs[i].mDataByteSize); - } - } - printf(" read buffer:"); CAShowAudioBufferList(readBuffer, 0, 4); -#endif -#endif - if (readPackets == 0) { - *ioNumberDataPackets = 0; - ioData->mBuffers[0].mDataByteSize = 0; - return noErr; - } - - if (outDataPacketDescription) - *outDataPacketDescription = This->mPacketDescs; - ioData->mBuffers[0].mDataByteSize = bytesRead; - ioData->mBuffers[0].mData = readBuffer->mBuffers[0].mData; - - This->mPacketMark += readPackets; - if (This->mClientDataFormat.mFramesPerPacket != 1) { // for PCM client formats we update in Read - // but for non-PCM client format (weird case) we must update here/now - if (This->mFileDataFormat.mFramesPerPacket > 0) - This->mFrameMark += readPackets * This->mFileDataFormat.mFramesPerPacket; - else { - for (UInt32 i = 0; i < readPackets; ++i) - This->mFrameMark += This->mPacketDescs[i].mVariableFramesInPacket; - } - } - *ioNumberDataPackets = readPackets; - return noErr; -} - -// _______________________________________________________________________________________ -// -void CAAudioFile::Write(UInt32 numPackets, const AudioBufferList *data) -{ - if (mIOBufferList.mBuffers[0].mData == NULL) { -#if DEBUG - printf("warning: CAAudioFile::AllocateBuffers called from WritePackets\n"); -#endif - AllocateBuffers(); - } - - if (mMode == kPreparingToWrite) - mMode = kWriting; - else - XThrowIf(mMode != kWriting, kExtAudioFileError_InvalidOperationOrder, "can't write to this file"); - if (mConverter != NULL) { - mWritePackets = numPackets; - mWriteBufferList->SetFrom(data); - WritePacketsFromCallback(WriteInputProc, this); - } else { - StartTiming(this, write); - XThrowIfError(AudioFileWritePackets(mAudioFile, mUseCache, data->mBuffers[0].mDataByteSize, - NULL, mPacketMark, &numPackets, data->mBuffers[0].mData), - "write audio file"); - ElapsedTime(this, write, mTicksInIO); -#if VERBOSE_IO - printf("CAAudioFile::WritePackets: wrote %ld packets at %qd, %ld bytes\n", numPackets, mPacketMark, data->mBuffers[0].mDataByteSize); -#endif - //mNumberPackets = - mPacketMark += numPackets; - if (mFileDataFormat.mFramesPerPacket > 0) - mFrameMark += numPackets * mFileDataFormat.mFramesPerPacket; - // else: shouldn't happen since we're only called when there's no converter - } -} - -// _______________________________________________________________________________________ -// -void CAAudioFile::FlushEncoder() -{ - if (mConverter != NULL) { - mFinishingEncoding = true; - WritePacketsFromCallback(WriteInputProc, this); - mFinishingEncoding = false; - - // get priming info from converter, set it on the file - if (mFileDataFormat.mBitsPerChannel == 0) { - UInt32 propertySize; - OSStatus err; - AudioConverterPrimeInfo primeInfo; - propertySize = sizeof(primeInfo); - - err = AudioConverterGetProperty(mConverter, kAudioConverterPrimeInfo, &propertySize, &primeInfo); - if (err == noErr) { - AudioFilePacketTableInfo pti; - propertySize = sizeof(pti); - err = AudioFileGetProperty(mAudioFile, kAudioFilePropertyPacketTableInfo, &propertySize, &pti); - if (err == noErr) { -//printf("old packet table info: %qd valid, %ld priming, %ld remainder\n", pti.mNumberValidFrames, pti.mPrimingFrames, pti.mRemainderFrames); - UInt64 totalFrames = pti.mNumberValidFrames + pti.mPrimingFrames + pti.mRemainderFrames; - pti.mPrimingFrames = primeInfo.leadingFrames; - pti.mRemainderFrames = primeInfo.trailingFrames; - pti.mNumberValidFrames = totalFrames - pti.mPrimingFrames - pti.mRemainderFrames; -//printf("new packet table info: %qd valid, %ld priming, %ld remainder\n", pti.mNumberValidFrames, pti.mPrimingFrames, pti.mRemainderFrames); - XThrowIfError(AudioFileSetProperty(mAudioFile, kAudioFilePropertyPacketTableInfo, sizeof(pti), &pti), "couldn't set packet table info on audio file"); - } - } - } - } -} - -// _______________________________________________________________________________________ -// -OSStatus CAAudioFile::WriteInputProc( AudioConverterRef /*inAudioConverter*/, - UInt32 * ioNumberDataPackets, - AudioBufferList* ioData, - AudioStreamPacketDescription ** outDataPacketDescription, - void* inUserData) -{ - CAAudioFile *This = static_cast(inUserData); - if (This->mFinishingEncoding) { - *ioNumberDataPackets = 0; - ioData->mBuffers[0].mDataByteSize = 0; - ioData->mBuffers[0].mData = NULL; - if (outDataPacketDescription) - *outDataPacketDescription = NULL; - return noErr; - } - UInt32 numPackets = This->mWritePackets; - if (numPackets == 0) { - return kNoMoreInputRightNow; - } - This->mWriteBufferList->ToAudioBufferList(ioData); - This->mWriteBufferList->BytesConsumed(numPackets * This->mClientDataFormat.mBytesPerFrame); - *ioNumberDataPackets = numPackets; - if (outDataPacketDescription) - *outDataPacketDescription = NULL; - This->mWritePackets -= numPackets; - return noErr; -} - -// _______________________________________________________________________________________ -// -#if VERBOSE_IO -static void hexdump(const void *addr, long len) -{ - const Byte *p = (Byte *)addr; - UInt32 offset = 0; - - if (len > 0x400) len = 0x400; - - while (len > 0) { - int n = len > 16 ? 16 : len; - printf("%08lX: ", offset); - for (int i = 0; i < 16; ++i) - if (i < n) - printf("%02X ", p[i]); - else printf(" "); - for (int i = 0; i < 16; ++i) - if (i < n) - putchar(p[i] >= ' ' && p[i] < 127 ? p[i] : '.'); - else putchar(' '); - putchar('\n'); - p += 16; - len -= 16; - offset += 16; - } -} -#endif - -// _______________________________________________________________________________________ -// -void CAAudioFile::WritePacketsFromCallback( - AudioConverterComplexInputDataProc inInputDataProc, - void * inInputDataProcUserData) -{ - while (true) { - // keep writing until we exhaust the input (temporary stop), or produce no output (EOF) - UInt32 numEncodedPackets = mIOBufferSizePackets; - mIOBufferList.mBuffers[0].mDataByteSize = mIOBufferSizeBytes; -#if CAAUDIOFILE_PROFILE - mInConverter = true; -#endif - StartTiming(this, fill); - OSStatus err = AudioConverterFillComplexBuffer(mConverter, inInputDataProc, inInputDataProcUserData, - &numEncodedPackets, &mIOBufferList, mPacketDescs); - ElapsedTime(this, fill, mTicksInConverter); -#if CAAUDIOFILE_PROFILE - mInConverter = false; -#endif - XThrowIf(err != 0 && err != kNoMoreInputRightNow, err, "convert audio packets (write)"); - if (numEncodedPackets == 0) - break; - Byte *buf = (Byte *)mIOBufferList.mBuffers[0].mData; -#if VERBOSE_IO - printf("CAAudioFile::WritePacketsFromCallback: wrote %ld packets, %ld bytes\n", numEncodedPackets, mIOBufferList.mBuffers[0].mDataByteSize); - if (mPacketDescs) { - for (UInt32 i = 0; i < numEncodedPackets; ++i) { - printf(" write packet %qd : offset %qd, length %ld\n", mPacketMark + i, mPacketDescs[i].mStartOffset, mPacketDescs[i].mDataByteSize); -#if VERBOSE_IO >= 2 - hexdump(buf + mPacketDescs[i].mStartOffset, mPacketDescs[i].mDataByteSize); -#endif - } - } -#endif - StartTiming(this, write); - XThrowIfError(AudioFileWritePackets(mAudioFile, mUseCache, mIOBufferList.mBuffers[0].mDataByteSize, mPacketDescs, mPacketMark, &numEncodedPackets, buf), "write audio file"); - ElapsedTime(this, write, mTicksInIO); - mPacketMark += numEncodedPackets; - //mNumberPackets += numEncodedPackets; - if (mFileDataFormat.mFramesPerPacket > 0) - mFrameMark += numEncodedPackets * mFileDataFormat.mFramesPerPacket; - else { - for (UInt32 i = 0; i < numEncodedPackets; ++i) - mFrameMark += mPacketDescs[i].mVariableFramesInPacket; - } - if (err == kNoMoreInputRightNow) - break; - } -} - -#endif // !CAAF_USE_EXTAUDIOFILE diff --git a/libs/appleutility/CAAudioFile.h b/libs/appleutility/CAAudioFile.h deleted file mode 100644 index 8dd1d8690b..0000000000 --- a/libs/appleutility/CAAudioFile.h +++ /dev/null @@ -1,442 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAAudioFile.h - -=============================================================================*/ - -#ifndef __CAAudioFile_h__ -#define __CAAudioFile_h__ - -#include -#include - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#else - #include -#endif - -#include "CAStreamBasicDescription.h" -#include "CABufferList.h" -#include "CAAudioChannelLayout.h" -#include "CAXException.h" -#include "CAMath.h" - -#ifndef CAAF_USE_EXTAUDIOFILE -// option: use AudioToolbox/ExtAudioFile.h? Only available on Tiger. - #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3 - // we are building software that must be deployable on Panther or earlier - #define CAAF_USE_EXTAUDIOFILE 0 - #else - // else we require Tiger and can use the API - #define CAAF_USE_EXTAUDIOFILE 1 - #endif -#endif - -#ifndef MAC_OS_X_VERSION_10_4 - // we have pre-Tiger headers; add our own declarations - typedef UInt32 AudioFileTypeID; - enum { - kExtAudioFileError_InvalidProperty = -66561, - kExtAudioFileError_InvalidPropertySize = -66562, - kExtAudioFileError_NonPCMClientFormat = -66563, - kExtAudioFileError_InvalidChannelMap = -66564, // number of channels doesn't match format - kExtAudioFileError_InvalidOperationOrder = -66565, - kExtAudioFileError_InvalidDataFormat = -66566, - kExtAudioFileError_MaxPacketSizeUnknown = -66567, - kExtAudioFileError_InvalidSeek = -66568, // writing, or offset out of bounds - kExtAudioFileError_AsyncWriteTooLarge = -66569, - kExtAudioFileError_AsyncWriteBufferOverflow = -66570 // an async write could not be completed in time - }; -#else - #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include - #else - #include "ExtendedAudioFile.h" - #endif -#endif - -// _______________________________________________________________________________________ -// Wrapper class for an AudioFile, supporting encode/decode to/from a PCM client format -class CAAudioFile { -public: - // implementation-independent helpers - void Open(const char *filePath) { - FSRef fsref; - std::cerr << "Opening " << filePath << std::endl; - XThrowIfError(FSPathMakeRef((UInt8 *)filePath, &fsref, NULL), "locate audio file"); - Open(fsref); - } - - bool HasConverter() const { return GetConverter() != NULL; } - - double GetDurationSeconds() { - double sr = GetFileDataFormat().mSampleRate; - return fnonzero(sr) ? GetNumberFrames() / sr : 0.; - } - // will be 0 if the file's frames/packet is 0 (variable) - // or the file's sample rate is 0 (unknown) - -#if CAAF_USE_EXTAUDIOFILE -public: - CAAudioFile() : mExtAF(NULL) { std::cerr << "Constructing CAAudioFile\n"; } - virtual ~CAAudioFile() { std::cerr << "Destroying CAAudiofile @ " << this << std::endl; if (mExtAF) Close(); } - - void Open(const FSRef &fsref) { - // open an existing file - XThrowIfError(ExtAudioFileOpen(&fsref, &mExtAF), "ExtAudioFileOpen failed"); - } - - void CreateNew(const FSRef &inParentDir, CFStringRef inFileName, AudioFileTypeID inFileType, const AudioStreamBasicDescription &inStreamDesc, const AudioChannelLayout *inChannelLayout=NULL) { - XThrowIfError(ExtAudioFileCreateNew(&inParentDir, inFileName, inFileType, &inStreamDesc, inChannelLayout, &mExtAF), "ExtAudioFileCreateNew failed"); - } - - void Wrap(AudioFileID fileID, bool forWriting) { - // use this to wrap an AudioFileID opened externally - XThrowIfError(ExtAudioFileWrapAudioFileID(fileID, forWriting, &mExtAF), "ExtAudioFileWrapAudioFileID failed"); - } - - void Close() { - std::cerr << "\tdisposeo of ext audio file @ " << mExtAF << std::endl; - XThrowIfError(ExtAudioFileDispose(mExtAF), "ExtAudioFileClose failed"); - mExtAF = NULL; - } - - const CAStreamBasicDescription &GetFileDataFormat() { - UInt32 size = sizeof(mFileDataFormat); - XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_FileDataFormat, &size, &mFileDataFormat), "Couldn't get file's data format"); - return mFileDataFormat; - } - - const CAAudioChannelLayout & GetFileChannelLayout() { - return FetchChannelLayout(mFileChannelLayout, kExtAudioFileProperty_FileChannelLayout); - } - - void SetFileChannelLayout(const CAAudioChannelLayout &layout) { - XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_FileChannelLayout, layout.Size(), &layout.Layout()), "Couldn't set file's channel layout"); - mFileChannelLayout = layout; - } - - const CAStreamBasicDescription &GetClientDataFormat() { - UInt32 size = sizeof(mClientDataFormat); - XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_ClientDataFormat, &size, &mClientDataFormat), "Couldn't get client data format"); - return mClientDataFormat; - } - - const CAAudioChannelLayout & GetClientChannelLayout() { - return FetchChannelLayout(mClientChannelLayout, kExtAudioFileProperty_ClientChannelLayout); - } - - void SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout=NULL) { - XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_ClientDataFormat, sizeof(dataFormat), &dataFormat), "Couldn't set client format"); - if (layout) - SetClientChannelLayout(*layout); - } - - void SetClientChannelLayout(const CAAudioChannelLayout &layout) { - XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_ClientChannelLayout, layout.Size(), &layout.Layout()), "Couldn't set client channel layout"); - } - - AudioConverterRef GetConverter() const { - UInt32 size = sizeof(AudioConverterRef); - AudioConverterRef converter; - XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_AudioConverter, &size, &converter), "Couldn't get file's AudioConverter"); - return converter; - } - - 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; - XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_ConverterConfig, sizeof(CFPropertyListRef), &config), "couldn't signal the file that the converter has changed"); - } - return err; - } - - SInt64 GetNumberFrames() { - SInt64 length; - UInt32 size = sizeof(SInt64); - XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_FileLengthFrames, &size, &length), "Couldn't get file's length"); - return length; - } - - void SetNumberFrames(SInt64 length) { - XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_FileLengthFrames, sizeof(SInt64), &length), "Couldn't set file's length"); - } - - void Seek(SInt64 pos) { - XThrowIfError(ExtAudioFileSeek(mExtAF, pos), "Couldn't seek in audio file"); - } - - SInt64 Tell() { - SInt64 pos; - XThrowIfError(ExtAudioFileTell(mExtAF, &pos), "Couldn't get file's mark"); - return pos; - } - - void Read(UInt32 &ioFrames, AudioBufferList *ioData) { - XThrowIfError(ExtAudioFileRead(mExtAF, &ioFrames, ioData), "Couldn't read audio file"); - } - - void Write(UInt32 inFrames, const AudioBufferList *inData) { - XThrowIfError(ExtAudioFileWrite(mExtAF, inFrames, inData), "Couldn't write audio file"); - } - - void SetIOBufferSizeBytes(UInt32 bufferSizeBytes) { - XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_IOBufferSizeBytes, sizeof(UInt32), &bufferSizeBytes), "Couldn't set audio file's I/O buffer size"); - } - -private: - const CAAudioChannelLayout & FetchChannelLayout(CAAudioChannelLayout &layoutObj, ExtAudioFilePropertyID propID) { - UInt32 size; - XThrowIfError(ExtAudioFileGetPropertyInfo(mExtAF, propID, &size, NULL), "Couldn't get info about channel layout"); - AudioChannelLayout *layout = (AudioChannelLayout *)malloc(size); - OSStatus err = ExtAudioFileGetProperty(mExtAF, propID, &size, layout); - if (err) { - free(layout); - XThrowIfError(err, "Couldn't get channel layout"); - } - layoutObj = layout; - free(layout); - return layoutObj; - } - - -private: - ExtAudioFileRef mExtAF; - - CAStreamBasicDescription mFileDataFormat; - CAAudioChannelLayout mFileChannelLayout; - - CAStreamBasicDescription mClientDataFormat; - CAAudioChannelLayout mClientChannelLayout; -#endif - -#if !CAAF_USE_EXTAUDIOFILE - CAAudioFile(); - virtual ~CAAudioFile(); - - // --- second-stage initializers --- - // Use exactly one of the following: - // - Open - // - PrepareNew followed by Create - // - Wrap - - void Open(const FSRef &fsref); - // open an existing file - - void CreateNew(const FSRef &inParentDir, CFStringRef inFileName, AudioFileTypeID inFileType, const AudioStreamBasicDescription &inStreamDesc, const AudioChannelLayout *inChannelLayout=NULL); - - void Wrap(AudioFileID fileID, bool forWriting); - // use this to wrap an AudioFileID opened externally - - // --- - - void Close(); - // In case you want to close the file before the destructor executes - - // --- Data formats --- - - // Allow specifying the file's channel layout. Must be called before SetClientFormat. - // When writing, the specified channel layout is written to the file (if the file format supports - // the channel layout). When reading, the specified layout overrides the one read from the file, - // if any. - void SetFileChannelLayout(const CAAudioChannelLayout &layout); - - // This specifies the data format which the client will use for reading/writing the file, - // which may be different from the file's format. An AudioConverter is created if necessary. - // The client format must be linear PCM. - void SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout=NULL); - void SetClientDataFormat(const CAStreamBasicDescription &dataFormat) { SetClientFormat(dataFormat, NULL); } - void SetClientChannelLayout(const CAAudioChannelLayout &layout) { SetClientFormat(mClientDataFormat, &layout); } - - // Wrapping the underlying converter, if there is one - OSStatus SetConverterProperty(AudioConverterPropertyID inPropertyID, - UInt32 inPropertyDataSize, - const void * inPropertyData, - bool inCanFail = false); - void SetConverterConfig(CFArrayRef config) { - SetConverterProperty(kAudioConverterPropertySettings, sizeof(config), &config); } - CFArrayRef GetConverterConfig(); - - // --- I/O --- - // All I/O is sequential, but you can seek to an arbitrary position when reading. - // SeekToPacket and TellPacket's packet numbers are in the file's data format, not the client's. - // However, ReadPackets/WritePackets use packet counts in the client data format. - - void Read(UInt32 &ioNumFrames, AudioBufferList *ioData); - void Write(UInt32 numFrames, const AudioBufferList *data); - - // These can fail for files without a constant mFramesPerPacket - void Seek(SInt64 frameNumber); - SInt64 Tell() const; // frameNumber - - // --- Accessors --- - // note: client parameters only valid if SetClientFormat has been called - AudioFileID GetAudioFileID() const { return mAudioFile; } - const CAStreamBasicDescription &GetFileDataFormat() const { return mFileDataFormat; } - const CAStreamBasicDescription &GetClientDataFormat() const { return mClientDataFormat; } - const CAAudioChannelLayout & GetFileChannelLayout() const { return mFileChannelLayout; } - const CAAudioChannelLayout & GetClientChannelLayout() const { return mClientChannelLayout; } - AudioConverterRef GetConverter() const { return mConverter; } - - UInt32 GetFileMaxPacketSize() const { return mFileMaxPacketSize; } - UInt32 GetClientMaxPacketSize() const { return mClientMaxPacketSize; } - SInt64 GetNumberPackets() const { - SInt64 npackets; - UInt32 propertySize = sizeof(npackets); - XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyAudioDataPacketCount, &propertySize, &npackets), "get audio file's packet count"); - return npackets; - } - SInt64 GetNumberFrames() const; - // will be 0 if the file's frames/packet is 0 (variable) - void SetNumberFrames(SInt64 length); // should only be set on a PCM file - - // --- Tunable performance parameters --- - void SetUseCache(bool b) { mUseCache = b; } - void SetIOBufferSizeBytes(UInt32 bufferSizeBytes) { mIOBufferSizeBytes = bufferSizeBytes; } - UInt32 GetIOBufferSizeBytes() { return mIOBufferSizeBytes; } - void * GetIOBuffer() { return mIOBufferList.mBuffers[0].mData; } - void SetIOBuffer(void *buf); - - // -- Profiling --- -#if CAAUDIOFILE_PROFILE - void EnableProfiling(bool b) { mProfiling = b; } - UInt64 TicksInConverter() const { return (mTicksInConverter > 0) ? (mTicksInConverter - mTicksInReadInConverter) : 0; } - UInt64 TicksInIO() const { return mTicksInIO; } -#endif - -// _______________________________________________________________________________________ -private: - SInt64 FileDataOffset(); - void SeekToPacket(SInt64 packetNumber); - SInt64 TellPacket() const { return mPacketMark; } // will be imprecise if SeekToFrame was called - - void SetConverterChannelLayout(bool output, const CAAudioChannelLayout &layout); - void WritePacketsFromCallback( - AudioConverterComplexInputDataProc inInputDataProc, - void * inInputDataProcUserData); - // will use I/O buffer size - void InitFileMaxPacketSize(); - void FileFormatChanged(const FSRef *parentDir=0, CFStringRef filename=0, AudioFileTypeID filetype=0); - - void GetExistingFileInfo(); - void FlushEncoder(); - void CloseConverter(); - void UpdateClientMaxPacketSize(); - void AllocateBuffers(bool okToFail=false); - SInt64 PacketToFrame(SInt64 packet) const; - SInt64 FrameToPacket(SInt64 inFrame) const; - - static OSStatus ReadInputProc( AudioConverterRef inAudioConverter, - UInt32* ioNumberDataPackets, - AudioBufferList* ioData, - AudioStreamPacketDescription** outDataPacketDescription, - void* inUserData); - - static OSStatus WriteInputProc( AudioConverterRef inAudioConverter, - UInt32* ioNumberDataPackets, - AudioBufferList* ioData, - AudioStreamPacketDescription** outDataPacketDescription, - void* inUserData); -// _______________________________________________________________________________________ -private: - - // the file - FSRef mFSRef; - AudioFileID mAudioFile; - bool mOwnOpenFile; - bool mUseCache; - bool mFinishingEncoding; - enum { kClosed, kReading, kPreparingToCreate, kPreparingToWrite, kWriting } mMode; - -// SInt64 mNumberPackets; // in file's format - SInt64 mFileDataOffset; - SInt64 mPacketMark; // in file's format - SInt64 mFrameMark; // this may be offset from the start of the file - // by the codec's latency; i.e. our frame 0 could - // lie at frame 2112 of a decoded AAC file - SInt32 mFrame0Offset; - UInt32 mFramesToSkipFollowingSeek; - - // buffers - UInt32 mIOBufferSizeBytes; - UInt32 mIOBufferSizePackets; - AudioBufferList mIOBufferList; // only one buffer -- USE ACCESSOR so it can be lazily initialized - bool mClientOwnsIOBuffer; - AudioStreamPacketDescription *mPacketDescs; - UInt32 mNumPacketDescs; - - // formats/conversion - AudioConverterRef mConverter; - CAStreamBasicDescription mFileDataFormat; - CAStreamBasicDescription mClientDataFormat; - CAAudioChannelLayout mFileChannelLayout; - CAAudioChannelLayout mClientChannelLayout; - UInt32 mFileMaxPacketSize; - UInt32 mClientMaxPacketSize; - - // cookie - Byte * mMagicCookie; - UInt32 mMagicCookieSize; - - // for ReadPackets - UInt32 mMaxPacketsToRead; - - // for WritePackets - UInt32 mWritePackets; - CABufferList * mWriteBufferList; - -#if CAAUDIOFILE_PROFILE - // performance - bool mProfiling; - UInt64 mTicksInConverter; - UInt64 mTicksInReadInConverter; - UInt64 mTicksInIO; - bool mInConverter; -#endif - -#endif // CAAF_USE_EXTAUDIOFILE -}; - -#endif // __CAAudioFile_h__ diff --git a/libs/appleutility/CAAudioUnit.cpp b/libs/appleutility/CAAudioUnit.cpp deleted file mode 100644 index f0b0890c51..0000000000 --- a/libs/appleutility/CAAudioUnit.cpp +++ /dev/null @@ -1,1277 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAAudioUnit.cpp - -=============================================================================*/ - -#include "CAAudioUnit.h" - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#else - #include -#endif - -#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; -}; - - - -class CAAudioUnit::AUState : public CAReferenceCounted { -public: - AUState (Component inComp) - : mUnit(0), mNode (0) - { - OSStatus result = ::OpenAComponent (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 (mGetParamProc != NULL) { - return reinterpret_cast(mGetParamProc) (mConnInstanceStorage, - inID, scope, element, &outValue); - } - return AudioUnitGetParameter(mUnit, inID, scope, element, &outValue); - } - - OSStatus SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, - Float32 value, UInt32 bufferOffsetFrames) - { - if (mSetParamProc != NULL) { - return reinterpret_cast(mSetParamProc) (mConnInstanceStorage, - inID, scope, element, value, bufferOffsetFrames); - } - return AudioUnitSetParameter(mUnit, inID, scope, element, value, bufferOffsetFrames); - } - - OSStatus Render (AudioUnitRenderActionFlags * ioActionFlags, - const AudioTimeStamp * inTimeStamp, - UInt32 inOutputBusNumber, - UInt32 inNumberFrames, - AudioBufferList * ioData) - { - if (mRenderProc != NULL) { - return reinterpret_cast(mRenderProc) (mConnInstanceStorage, - ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData); - } - return AudioUnitRender(mUnit, ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData); - } - - OSStatus MIDIEvent (UInt32 inStatus, - UInt32 inData1, - UInt32 inData2, - UInt32 inOffsetSampleFrame) - { -#if !TARGET_OS_WIN32 - if (mMIDIEventProc != NULL) { - return reinterpret_cast(mMIDIEventProc) (mConnInstanceStorage, - inStatus, inData1, inData2, inOffsetSampleFrame); - } - return MusicDeviceMIDIEvent (mUnit, inStatus, inData1, inData2, inOffsetSampleFrame); -#else - return paramErr; -#endif - } - - OSStatus StartNote (MusicDeviceInstrumentID inInstrument, - MusicDeviceGroupID inGroupID, - NoteInstanceID * outNoteInstanceID, - UInt32 inOffsetSampleFrame, - const MusicDeviceNoteParams * inParams) - { -#if !TARGET_OS_WIN32 - return MusicDeviceStartNote (mUnit, inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams); -#else - return paramErr; -#endif - } - OSStatus StopNote (MusicDeviceGroupID inGroupID, - NoteInstanceID inNoteInstanceID, - UInt32 inOffsetSampleFrame) - { -#if !TARGET_OS_WIN32 - return MusicDeviceStopNote (mUnit, inGroupID, inNoteInstanceID, inOffsetSampleFrame); -#else - return paramErr; -#endif - } - -private: - // get the fast dispatch pointers - void Init() - { - UInt32 size = sizeof(AudioUnitRenderProc); - if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch, - kAudioUnitScope_Global, kAudioUnitRenderSelect, - &mRenderProc, &size) != noErr) - mRenderProc = NULL; - if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch, - kAudioUnitScope_Global, kAudioUnitGetParameterSelect, - &mGetParamProc, &size) != noErr) - mGetParamProc = NULL; - if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch, - kAudioUnitScope_Global, kAudioUnitSetParameterSelect, - &mSetParamProc, &size) != noErr) - mSetParamProc = NULL; - - if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch, - kAudioUnitScope_Global, kMusicDeviceMIDIEventSelect, - &mMIDIEventProc, &size) != noErr) - mMIDIEventProc = NULL; - - if (mRenderProc || mGetParamProc || mSetParamProc || mMIDIEventProc) - mConnInstanceStorage = GetComponentInstanceStorage(mUnit); - else - mConnInstanceStorage = NULL; - } - - ProcPtr mRenderProc, mGetParamProc, mSetParamProc, mMIDIEventProc; - - void * mConnInstanceStorage; - -private: - // get the compiler to tell us when we do a bad thing!!! - AUState () {} - AUState (const AUState& other) : CAReferenceCounted (other) {} - AUState& operator= (const AUState&) { return *this; } -}; - - -CAAudioUnit::AUState::~AUState () -{ - if (mUnit && (mNode == 0)) { - ::CloseComponent (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 (-1, inUnit)) -{ -} - -CAAudioUnit::CAAudioUnit (const CAComponent& inComp) - : mComp (inComp), mDataPtr (0) -{ - mDataPtr = new AUState (mComp.Comp()); -} - -CAAudioUnit::CAAudioUnit (const AUNode &inNode, const AudioUnit& inUnit) - : mComp (inUnit), mDataPtr(new AUState (inNode, inUnit)) -{ -} - -CAAudioUnit::~CAAudioUnit () -{ - 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; -} - -#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 (inChannelsOut == inChannelsIn) { - return true; - } - } - 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; -} - -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; -} - -bool CAAudioUnit::GetChannelLayouts (AudioUnitScope inScope, - AudioUnitElement inEl, - ChannelTagVector &outChannelVector) const -{ - if (HasChannelLayouts (inScope, inEl) == false) return false; - - UInt32 dataSize; - OSStatus result = AudioUnitGetPropertyInfo (AU(), - kAudioUnitProperty_SupportedChannelLayoutTags, - inScope, inEl, - &dataSize, NULL); - - if (result == kAudioUnitErr_InvalidProperty) { - // if we get here we can do layouts but we've got the speaker config property - outChannelVector.erase (outChannelVector.begin(), outChannelVector.end()); - outChannelVector.push_back (kAudioChannelLayoutTag_Stereo); - outChannelVector.push_back (kAudioChannelLayoutTag_StereoHeadphones); - outChannelVector.push_back (kAudioChannelLayoutTag_Quadraphonic); - outChannelVector.push_back (kAudioChannelLayoutTag_AudioUnit_5_0); - return true; - } - - if (result) return false; - - bool canDo = false; - // 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 canDo; -} - -bool CAAudioUnit::HasChannelLayouts (AudioUnitScope inScope, - AudioUnitElement inEl) const -{ - OSStatus result = AudioUnitGetPropertyInfo (AU(), - kAudioUnitProperty_SupportedChannelLayoutTags, - inScope, inEl, - NULL, NULL); - return !result; -} - -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); - - 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, - CAAudioChannelLayout &inLayout) -{ - OSStatus result = AudioUnitSetProperty (AU(), - kAudioUnitProperty_AudioChannelLayout, - inScope, inEl, - inLayout, inLayout.Size()); - return result; -} - -OSStatus CAAudioUnit::SetChannelLayout (AudioUnitScope inScope, - AudioUnitElement inEl, - 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(&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; - require_noerr (result = GetElementCount(kAudioUnitScope_Input, elCount), home); - if (elCount) { - for (unsigned int i = 0; i < elCount; ++i) { - require_noerr (result = SetSampleRate (kAudioUnitScope_Input, i, inSampleRate), home); - } - } - - require_noerr (result = GetElementCount(kAudioUnitScope_Output, elCount), home); - if (elCount) { - for (unsigned int i = 0; i < elCount; ++i) { - 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.SetCanonical (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; - - CAStreamBasicDescription desc; - desc.mSampleRate = inSampleRate; - for (unsigned int i = 0; i < inNumElements; ++i) { - desc.SetCanonical (inChannelsPerElement[i], false); - 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)); -} - -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)); -} - -OSStatus CAAudioUnit::GetPresentPreset (AUPreset &outData) const -{ - UInt32 dataSize = sizeof(outData); - OSStatus result = AudioUnitGetProperty (AU(), kAudioUnitProperty_PresentPreset, - kAudioUnitScope_Global, 0, - &outData, &dataSize); - 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); - } - } - return result; -} - -OSStatus CAAudioUnit::SetPresentPreset (AUPreset &inData) -{ - OSStatus result = AudioUnitSetProperty (AU(), kAudioUnitProperty_PresentPreset, - kAudioUnitScope_Global, 0, - &inData, sizeof (AUPreset)); - if (result == kAudioUnitErr_InvalidProperty) { - result = AudioUnitSetProperty (AU(), kAudioUnitProperty_CurrentPreset, - kAudioUnitScope_Global, 0, - &inData, sizeof (AUPreset)); - } - return result; -} - -bool CAAudioUnit::HasCustomView () const -{ - UInt32 dataSize = 0; - OSStatus result = GetPropertyInfo(kAudioUnitProperty_GetUIComponentList, - kAudioUnitScope_Global, 0, - &dataSize, NULL); - if (result || !dataSize) { - dataSize = 0; - result = GetPropertyInfo(kAudioUnitProperty_CocoaUI, - kAudioUnitScope_Global, 0, - &dataSize, NULL); - if (result || !dataSize) - return false; - } - return true; -} - -OSStatus CAAudioUnit::GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, - Float32 &outValue) const -{ - return mDataPtr ? (OSStatus) mDataPtr->GetParameter (inID, scope, element, outValue) : paramErr; -} - -OSStatus CAAudioUnit::SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element, - Float32 value, UInt32 bufferOffsetFrames) -{ - return mDataPtr ? (OSStatus) mDataPtr->SetParameter (inID, scope, element, value, bufferOffsetFrames) : paramErr; -} - -OSStatus CAAudioUnit::MIDIEvent (UInt32 inStatus, - UInt32 inData1, - UInt32 inData2, - UInt32 inOffsetSampleFrame) -{ - return mDataPtr ? (OSStatus) mDataPtr->MIDIEvent (inStatus, inData1, inData2, inOffsetSampleFrame) : paramErr; -} - -OSStatus CAAudioUnit::StartNote (MusicDeviceInstrumentID inInstrument, - MusicDeviceGroupID inGroupID, - NoteInstanceID * outNoteInstanceID, - UInt32 inOffsetSampleFrame, - const MusicDeviceNoteParams * inParams) -{ - return mDataPtr ? (OSStatus) mDataPtr->StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams) - : paramErr; -} - -OSStatus CAAudioUnit::StopNote (MusicDeviceGroupID inGroupID, - NoteInstanceID inNoteInstanceID, - UInt32 inOffsetSampleFrame) -{ - return mDataPtr ? (OSStatus) 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 ? (OSStatus) mDataPtr->Render (ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData) : paramErr; -} - -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 CAAudioUnit::Preroll (UInt32 inFrameSize) -{ - CAStreamBasicDescription desc; - OSStatus result = GetFormat (kAudioUnitScope_Input, 0, desc); - bool hasInput = false; - //we have input - if (result == noErr) - { - sRenderCallback.inputProc = PrerollRenderProc; - sRenderCallback.inputProcRefCon = 0; - - result = 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; - require_noerr (result = GetFormat (kAudioUnitScope_Output, 0, outputFormat), home); - { - AUOutputBL list (outputFormat, inFrameSize); - list.Prepare (); - - require_noerr (result = Render (&flags, &time, 0, inFrameSize, list.ABL()), home); - require_noerr (result = GlobalReset(), home); - } - -home: - if (hasInput) { - // remove our installed callback - sRenderCallback.inputProc = 0; - sRenderCallback.inputProcRefCon = 0; - - SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, - 0, &sRenderCallback, sizeof(sRenderCallback)); - } - return result; -} - -#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 > 8) { - mChans = new UInt32[elCount]; - mDidAllocate = true; - memset (mChans, 0, sizeof(int) * elCount); - } else { - mChans = mStaticChans; - memset (mChans, 0, sizeof(int) * 8); - } - for (unsigned int i = 0; i < elCount; ++i) { - UInt32 numChans; - if (inAU.NumberChannels (inScope, i, numChans)) return; - mChans[i] = numChans; - } - mNumEls = elCount; -} - -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); - } -} diff --git a/libs/appleutility/CAAudioUnit.h b/libs/appleutility/CAAudioUnit.h deleted file mode 100644 index 7be48464e7..0000000000 --- a/libs/appleutility/CAAudioUnit.h +++ /dev/null @@ -1,384 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAAudioUnit.h - -=============================================================================*/ - -#ifndef __CAAudioUnit_h__ -#define __CAAudioUnit_h__ - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include - #include - #include - #include -#else - #include - #include - #include - #include - #include -#endif - -#include -#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 { -public: - typedef std::vector 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 (); - - - 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; } - - bool FromAUGraph () const { return GetAUNode() != 0 || GetAUNode() != -1; } - - 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 Reset (AudioUnitScope scope, AudioUnitElement element) - { - return AudioUnitReset (AU(), scope, element); - } - OSStatus GlobalReset () - { - return AudioUnitReset (AU(), kAudioUnitScope_Global, 0); - } - - OSStatus Preroll (UInt32 inFrameSize); - - OSStatus AddRenderNotify (AURenderCallback inProc, void *inProcRefCon) - { - return AudioUnitAddRenderNotify (AU(), inProc, inProcRefCon); - } - - OSStatus RemoveRenderNotify (AURenderCallback inProc, void *inProcRefCon) - { - return AudioUnitRemoveRenderNotify (AU(), inProc, inProcRefCon); - } - - -// Fast dispatch support for MIDI Effects or Music Devices - 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); - bool GetChannelLayouts (AudioUnitScope inScope, - AudioUnitElement inEl, - ChannelTagVector &outChannelVector) const; - - OSStatus GetChannelLayout (AudioUnitScope inScope, - AudioUnitElement inEl, - CAAudioChannelLayout &outLayout) const; - - OSStatus SetChannelLayout (AudioUnitScope inScope, - AudioUnitElement inEl, - CAAudioChannelLayout &inLayout); - - OSStatus SetChannelLayout (AudioUnitScope inScope, - AudioUnitElement inEl, - 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; - - 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 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; - -}; - -class CAAUChanHelper { -public: - CAAUChanHelper() - : mChans(mStaticChans), mNumEls(0), mDidAllocate(false) - { - memset (mChans, 0, sizeof(UInt32) * 8); - } - 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: - UInt32 mStaticChans[8]; - bool mDidAllocate; -}; - -#endif diff --git a/libs/appleutility/CABufferList.cpp b/libs/appleutility/CABufferList.cpp deleted file mode 100644 index 581f1adda7..0000000000 --- a/libs/appleutility/CABufferList.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CABufferList.cpp - -=============================================================================*/ - -#include "CABufferList.h" -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#else - #include -#endif - -void CABufferList::AllocateBuffers(UInt32 nBytes) -{ - if (nBytes <= GetNumBytes()) return; - - if (mNumberBuffers > 1) - // align successive buffers for Altivec and to take alternating - // cache line hits by spacing them by odd multiples of 16 - nBytes = (nBytes + (0x10 - (nBytes & 0xF))) | 0x10; - UInt32 memorySize = nBytes * mNumberBuffers; - Byte *newMemory = new Byte[memorySize], *p = newMemory; - memset(newMemory, 0, memorySize); // get page faults now, not later - - AudioBuffer *buf = mBuffers; - for (UInt32 i = 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; - delete[] oldMemory; -} - -void CABufferList::AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inSrcList, CABufferList *inSetPtrList) -{ - if (mNumberBuffers != inSrcList->mNumberBuffers) return; - if (mNumberBuffers != inSetPtrList->mNumberBuffers) return; - if (nBytes <= GetNumBytes()) { - CopyAllFrom(inSrcList, inSetPtrList); - return; - } - inSetPtrList->VerifyNotTrashingOwnedBuffer(); - UInt32 fromByteSize = inSrcList->GetNumBytes(); - - if (mNumberBuffers > 1) - // align successive buffers for Altivec and to take alternating - // cache line hits by spacing them by odd multiples of 16 - nBytes = (nBytes + (0x10 - (nBytes & 0xF))) | 0x10; - UInt32 memorySize = nBytes * mNumberBuffers; - Byte *newMemory = new Byte[memorySize], *p = newMemory; - memset(newMemory, 0, memorySize); // make buffer "hot" - - AudioBuffer *buf = mBuffers; - AudioBuffer *ptrBuf = inSetPtrList->mBuffers; - AudioBuffer *srcBuf = inSrcList->mBuffers; - for (UInt32 i = 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; - if (inSrcList != inSetPtrList) - inSrcList->BytesConsumed(fromByteSize); - delete[] oldMemory; -} - -void CABufferList::DeallocateBuffers() -{ - AudioBuffer *buf = mBuffers; - for (UInt32 i = mNumberBuffers; i--; ++buf) { - buf->mData = NULL; - buf->mDataByteSize = 0; - } - if (mBufferMemory != NULL) { - delete[] mBufferMemory; - mBufferMemory = NULL; - } - -} - -extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize) -{ - printf("AudioBufferList @ %p:\n", abl); - const AudioBuffer *buf = abl->mBuffers; - for (UInt32 i = 0; i < abl->mNumberBuffers; ++i, ++buf) { - printf(" [%2ld]: %2ldch, %5ld bytes @ %8p", - i, buf->mNumberChannels, buf->mDataByteSize, buf->mData); - if (framesToPrint) { - printf(":"); - Byte *p = (Byte *)buf->mData; - for (int j = framesToPrint * buf->mNumberChannels; --j >= 0; ) - switch (wordSize) { - case 0: - printf(" %6.3f", *(Float32 *)p); - p += sizeof(Float32); - break; - case 1: - case -1: - printf(" %02X", *p); - p += 1; - break; - case 2: - printf(" %04X", EndianU16_BtoN(*(UInt16 *)p)); - p += 2; - break; - case 3: - printf(" %06X", (p[0] << 16) | (p[1] << 8) | p[2]); - p += 3; - break; - case 4: - printf(" %08lX", EndianU32_BtoN(*(UInt32 *)p)); - p += 4; - break; - case -2: - printf(" %04X", EndianU16_LtoN(*(UInt16 *)p)); - p += 2; - break; - case -3: - printf(" %06X", (p[2] << 16) | (p[1] << 8) | p[0]); - p += 3; - break; - case -4: - printf(" %08lX", EndianU32_LtoN(*(UInt32 *)p)); - p += 4; - break; - } - } - printf("\n"); - } -} - diff --git a/libs/appleutility/CABufferList.h b/libs/appleutility/CABufferList.h deleted file mode 100644 index fc94769458..0000000000 --- a/libs/appleutility/CABufferList.h +++ /dev/null @@ -1,300 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CABufferList.h - -=============================================================================*/ - -#ifndef __CABufferList_h__ -#define __CABufferList_h__ - -#include -#include "CAStreamBasicDescription.h" -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#else - #include -#endif - -extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize); - // wordSize: 0 = float32, else integer word size, negative if little-endian - -/* ____________________________________________________________________________ -// 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); - } - -protected: - CABufferList(const char *name, UInt32 numBuffers, UInt32 channelsPerBuffer) : - mName(name), - mBufferMemory(NULL) - { - check(numBuffers > 0 /*&& channelsPerBuffer > 0*/); - mNumberBuffers = numBuffers; - AudioBuffer *buf = mBuffers; - for (UInt32 i = 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 *(AudioBufferList *)&mNumberBuffers; } - - AudioBufferList & GetModifiableBufferList() - { - VerifyNotTrashingOwnedBuffer(); - return _GetBufferList(); - } - - UInt32 GetNumBytes() const - { - return mBuffers[0].mDataByteSize; - } - - void SetBytes(UInt32 nBytes, void *data) - { - VerifyNotTrashingOwnedBuffer(); - check(mNumberBuffers == 1); - mBuffers[0].mDataByteSize = nBytes; - 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 = mBuffers, *srcbuf = srcbl->mBuffers, - *ptrbuf = ptrbl->mBuffers; - for (UInt32 i = 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); - } - - void AppendFrom(CABufferList *blp, UInt32 nBytes) - { - VerifyNotTrashingOwnedBuffer(); - AudioBuffer *mybuf = mBuffers, *srcbuf = blp->mBuffers; - for (UInt32 i = mNumberBuffers; i--; ++mybuf, ++srcbuf) { - check(nBytes <= srcbuf->mDataByteSize); - 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 - { - VerifyNotTrashingOwnedBuffer(); - if (GetNumBytes() > desiredBufferSize) return; - AudioBuffer *buf = mBuffers; - for (UInt32 i = mNumberBuffers; i--; ++buf) { - memset((Byte *)buf->mData + buf->mDataByteSize, 0, desiredBufferSize - buf->mDataByteSize); - buf->mDataByteSize = desiredBufferSize; - } - } - - void SetToZeroes(UInt32 nBytes) - { - VerifyNotTrashingOwnedBuffer(); - AudioBuffer *buf = mBuffers; - for (UInt32 i = 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 (mNumberBuffers != anotherBufferList->mNumberBuffers) return false; - - for (UInt32 i = 0; i < mNumberBuffers; ++i) { - if (mBuffers[i].mData != anotherBufferList->mBuffers[i].mData) return false; - } - return true; - } - - void BytesConsumed(UInt32 nBytes) - // advance buffer pointers, decrease buffer sizes - { - VerifyNotTrashingOwnedBuffer(); - AudioBuffer *buf = mBuffers; - for (UInt32 i = mNumberBuffers; i--; ++buf) { - check(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 = mBuffers; - const AudioBuffer *srcbuf = abl->mBuffers; - for (UInt32 i = 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[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) - // this is for bufferlists that function simply as - // an array of pointers into another bufferlist, being advanced, - // as in RenderOutput implementations - { - VerifyNotTrashingOwnedBuffer(); - AudioBuffer *buf = mBuffers; - for (UInt32 i = mNumberBuffers; i--; ++buf) { - buf->mData = (Byte *)buf->mData + nBytes; - buf->mDataByteSize -= nBytes; - } - } - - void SetNumBytes(UInt32 nBytes) - { - VerifyNotTrashingOwnedBuffer(); - AudioBuffer *buf = mBuffers; - for (UInt32 i = 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); - } - -protected: - AudioBufferList & _GetBufferList() { return *(AudioBufferList *)&mNumberBuffers; } // 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 list. - // It's an error to modify the buffer pointers or lengths if we own the buffer memory. - check(mBufferMemory == NULL); - } - - const char * mName; // for debugging - Byte * mBufferMemory; - // the rest must exactly mirror the structure of AudioBufferList - UInt32 mNumberBuffers; - AudioBuffer mBuffers[1]; -}; - -#endif // __CABufferList_h__ diff --git a/libs/appleutility/CACFDictionary.cpp b/libs/appleutility/CACFDictionary.cpp deleted file mode 100644 index ed983a828f..0000000000 --- a/libs/appleutility/CACFDictionary.cpp +++ /dev/null @@ -1,478 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CACFDictionary.cpp - CAAudioEngine - -=============================================================================*/ - -//============================================================================= -// Includes -//============================================================================= - -// Self Include -#include "CACFDictionary.h" - -// PublicUtility Includes -#include "CACFString.h" -#include "CACFNumber.h" - -//============================================================================= -// CACFDictionary -//============================================================================= - -bool CACFDictionary::HasKey(const CFStringRef inKey) const -{ - return CFDictionaryContainsKey(mCFDictionary, inKey) != 0; -} - -UInt32 CACFDictionary::Size () const -{ - return CFDictionaryGetCount(mCFDictionary); -} - -void CACFDictionary::GetKeys (const void **keys) const -{ - CFDictionaryGetKeysAndValues(mCFDictionary, keys, NULL); -} - -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(theValue)); - theAnswer = true; - } - else if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID())) - { - SInt32 theNumericValue = 0; - CFNumberGetValue(static_cast(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(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(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(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(theValue), kCFNumberSInt64Type, &outValue); - theAnswer = true; - } - } - - 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(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(theValue), kCFNumberFloat64Type, &outValue); - theAnswer = true; - } - } - - 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(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(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(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(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::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; -} - -bool CACFDictionary::AddSInt32(const CFStringRef inKey, SInt32 inValue) -{ - bool theAnswer = false; - - if(mMutable && (mCFDictionary != NULL)) - { - CACFNumber theValue(inValue); - theAnswer = AddCFType(inKey, theValue.GetCFNumber()); - } - - return theAnswer; -} - -bool CACFDictionary::AddUInt32(const CFStringRef inKey, UInt32 inValue) -{ - bool theAnswer = false; - - if(mMutable && (mCFDictionary != NULL)) - { - CACFNumber theValue(inValue); - theAnswer = AddCFType(inKey, theValue.GetCFNumber()); - } - - return theAnswer; -} - -bool CACFDictionary::AddSInt64(const CFStringRef inKey, SInt64 inValue) -{ - bool theAnswer = false; - - if(mMutable && (mCFDictionary != NULL)) - { - CACFNumber theValue(inValue); - theAnswer = AddCFType(inKey, theValue.GetCFNumber()); - } - - return theAnswer; -} - -bool CACFDictionary::AddUInt64(const CFStringRef inKey, UInt64 inValue) -{ - bool theAnswer = false; - - if(mMutable && (mCFDictionary != NULL)) - { - CACFNumber theValue(inValue); - theAnswer = AddCFType(inKey, theValue.GetCFNumber()); - } - - return theAnswer; -} - -bool CACFDictionary::AddFloat32(const CFStringRef inKey, Float32 inValue) -{ - bool theAnswer = false; - - if(mMutable && (mCFDictionary != NULL)) - { - CACFNumber theValue(inValue); - theAnswer = AddCFType(inKey, theValue.GetCFNumber()); - } - - return theAnswer; -} - -bool CACFDictionary::AddFloat64(const CFStringRef inKey, Float64 inValue) -{ - bool theAnswer = false; - - if(mMutable && (mCFDictionary != NULL)) - { - CACFNumber theValue(inValue); - theAnswer = AddCFType(inKey, theValue.GetCFNumber()); - } - - return theAnswer; -} - -bool CACFDictionary::AddNumber(const CFStringRef inKey, const CFNumberRef inValue) -{ - bool theAnswer = false; - - if(mMutable && (mCFDictionary != NULL)) - { - theAnswer = AddCFType(inKey, inValue); - } - - return theAnswer; -} - -bool CACFDictionary::AddString(const CFStringRef inKey, const CFStringRef inValue) -{ - bool theAnswer = false; - - if(mMutable && (mCFDictionary != NULL)) - { - theAnswer = AddCFType(inKey, inValue); - } - - return theAnswer; -} - -bool CACFDictionary::AddArray(const CFStringRef inKey, const CFArrayRef inValue) -{ - bool theAnswer = false; - - if(mMutable && (mCFDictionary != NULL)) - { - theAnswer = AddCFType(inKey, inValue); - } - - return theAnswer; -} - -bool CACFDictionary::AddDictionary(const CFStringRef inKey, const CFDictionaryRef inValue) -{ - bool theAnswer = false; - - if(mMutable && (mCFDictionary != NULL)) - { - theAnswer = AddCFType(inKey, inValue); - } - - return theAnswer; -} - -bool CACFDictionary::AddData(const CFStringRef inKey, const CFDataRef inValue) -{ - bool theAnswer = false; - - if(mMutable && (mCFDictionary != NULL)) - { - theAnswer = AddCFType(inKey, inValue); - } - - return theAnswer; -} - -bool CACFDictionary::AddCFType(const CFStringRef inKey, const CFTypeRef inValue) -{ - bool theAnswer = false; - - if(mMutable && (mCFDictionary != NULL)) - { - CFDictionarySetValue(mCFDictionary, inKey, inValue); - theAnswer = true; - } - - return theAnswer; -} - -bool CACFDictionary::AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue) -{ - bool theAnswer = false; - - if(mMutable && (mCFDictionary != NULL)) - { - 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(mMutable && (mCFDictionary != NULL)) - { - CACFString theValue(inValue); - if(theValue.IsValid()) - { - theAnswer = AddCFType(inKey, theValue.GetCFString()); - } - } - - return theAnswer; -} diff --git a/libs/appleutility/CACFDictionary.h b/libs/appleutility/CACFDictionary.h deleted file mode 100644 index 3221436a16..0000000000 --- a/libs/appleutility/CACFDictionary.h +++ /dev/null @@ -1,141 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CACFDictionary.h - -=============================================================================*/ -#if !defined(__CACFDictionary_h__) -#define __CACFDictionary_h__ - -//============================================================================= -// Includes -//============================================================================= - -// System Includes -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#else - #include -#endif - -//============================================================================= -// CACFDictionary -//============================================================================= - -class CACFDictionary -{ - -// Construction/Destruction -public: - CACFDictionary(bool inRelease) : mCFDictionary(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)), mRelease(inRelease), mMutable(true) {} - CACFDictionary(const CFDictionaryRef inCFDictionary, bool inRelease) : mCFDictionary(const_cast(inCFDictionary)), mRelease(inRelease), mMutable(true) {} - CACFDictionary(const CFMutableDictionaryRef inCFDictionary, bool inRelease) : mCFDictionary(inCFDictionary), mRelease(inRelease), mMutable(true) {} - CACFDictionary(const CACFDictionary& inDictionary) : mCFDictionary(inDictionary.mCFDictionary), mRelease(inDictionary.mRelease), mMutable(inDictionary.mMutable) { if(mRelease && (mCFDictionary != NULL)) { CFRetain(mCFDictionary); } } - CACFDictionary& operator=(const CACFDictionary& inDictionary) { mCFDictionary = inDictionary.mCFDictionary; mRelease = inDictionary.mRelease; mMutable = inDictionary.mMutable; if(mRelease && (mCFDictionary != NULL)) { CFRetain(mCFDictionary); } return *this; } - ~CACFDictionary() { 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) { if(mRelease && (mCFDictionary != NULL)) { CFRelease(mCFDictionary); } mCFDictionary = CFDictionaryCreateMutableCopy(NULL, 0, inDictionary); 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; - - 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 GetSInt64(const CFStringRef inKey, SInt64& outValue) const; - bool GetUInt64(const CFStringRef inKey, UInt64& outValue) const; - bool GetFloat32(const CFStringRef inKey, Float32& outValue) const; - bool GetFloat64(const CFStringRef inKey, Float64& 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 GetCFTypeWithCStringKey(const char* inKey, CFTypeRef& outValue) const; - - 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 AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue); - bool AddCString(const CFStringRef inKey, const char* inValue); - - void Clear() { if(CanModify()) { CFDictionaryRemoveAllValues(mCFDictionary); } } - - void Show() { CFShow(mCFDictionary); } - -// Implementation -private: - CFMutableDictionaryRef mCFDictionary; - bool mRelease; - bool mMutable; -}; - -#endif //__CACFDictionary_h__ diff --git a/libs/appleutility/CACFNumber.cpp b/libs/appleutility/CACFNumber.cpp deleted file mode 100644 index edbf3db2d9..0000000000 --- a/libs/appleutility/CACFNumber.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CACFNumber.cp - -=============================================================================*/ - -//============================================================================= -// 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.0 : 1.0; - theFixedValue *= (SInt32)theSign; - Float32 theWholePart = (theFixedValue & 0x7FFF0000) >> 16; - Float32 theFractPart = theFixedValue & 0x0000FFFF; - theFractPart /= 65536.0; - - return theSign * (theWholePart + theFractPart); -} diff --git a/libs/appleutility/CACFNumber.h b/libs/appleutility/CACFNumber.h deleted file mode 100644 index 450a94dd47..0000000000 --- a/libs/appleutility/CACFNumber.h +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CACFNumber.h - -=============================================================================*/ -#if !defined(__CACFNumber_h__) -#define __CACFNumber_h__ - -//============================================================================= -// Includes -//============================================================================= - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include - #include -#else - #include - #include -#endif - -//============================================================================= -// CACFNumber -//============================================================================= - -class CACFNumber -{ -// Construction/Destruction -public: - CACFNumber(CFNumberRef inCFNumber, bool inWillRelease = true) : 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() { 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; } - Float32 GetFloat32() const { Float32 theAnswer = 0.0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberFloat32Type, &theAnswer); } return theAnswer; } - Float32 GetFixed32() const; - SInt64 GetSInt64() const { SInt64 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt64Type, &theAnswer); } return theAnswer; } -}; - -#endif diff --git a/libs/appleutility/CACFString.cpp b/libs/appleutility/CACFString.cpp deleted file mode 100644 index 5e00b11db6..0000000000 --- a/libs/appleutility/CACFString.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CACFString.cp - -=============================================================================*/ - -//============================================================================= -// Includes -//============================================================================= - -#include "CACFString.h" - -//============================================================================= -// CACFString -//============================================================================= - -UInt32 CACFString::GetStringByteLength(CFStringRef inCFString, CFStringEncoding inEncoding) -{ - UInt32 theAnswer = 0; - - if(inCFString != NULL) - { - CFRange theRange = { 0, CFStringGetLength(inCFString) }; - CFStringGetBytes(inCFString, theRange, inEncoding, 0, false, NULL, 0x7FFFFFFF, (CFIndex*)&theAnswer); - } - - return 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, ioStringSize - 1, &theLength); - outString[theLength] = 0; - ioStringSize = 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(theStringRange.length) > ioStringSize) - { - theStringRange.length = ioStringSize; - } - CFStringGetCharacters(inCFString, theStringRange, outString); - ioStringSize = theStringRange.length; - } - else - { - outString[0] = 0; - ioStringSize = 0; - } - } -} diff --git a/libs/appleutility/CACFString.h b/libs/appleutility/CACFString.h deleted file mode 100644 index 4adc460e70..0000000000 --- a/libs/appleutility/CACFString.h +++ /dev/null @@ -1,156 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CACFString.h - -=============================================================================*/ -#if !defined(__CACFString_h__) -#define __CACFString_h__ - -//============================================================================= -// Includes -//============================================================================= - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include - #include -#else - #include - #include -#endif - -//============================================================================= -// CACFString -//============================================================================= - -class CACFString -{ -// Construction/Destruction -public: - CACFString() : mCFString(NULL), mWillRelease(true) {} - CACFString(CFStringRef inCFString, bool inWillRelease = true) : mCFString(inCFString), mWillRelease(inWillRelease) {} - CACFString(const char* inCString, bool inWillRelease = true) : 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) { Release(); mCFString = inString.mCFString; mWillRelease = inString.mWillRelease; Retain(); return *this; } - CACFString& operator=(CFStringRef inCFString) { Release(); mCFString = inCFString; mWillRelease = true; return *this; } - -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 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; } - UInt32 GetLength() const { UInt32 theAnswer = 0; if(mCFString != NULL) { theAnswer = 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); } - - 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); - -}; - -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)); } - -//============================================================================= -// 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 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 = 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); } - -}; - -#endif diff --git a/libs/appleutility/CAComponent.cpp b/libs/appleutility/CAComponent.cpp deleted file mode 100644 index 5c9686df36..0000000000 --- a/libs/appleutility/CAComponent.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAComponent.cpp - -=============================================================================*/ - -#include "CAComponent.h" -#include "CAComponentDescription.h" -#include "CACFDictionary.h" -#include - -CAComponent::CAComponent (const ComponentDescription& inDesc, CAComponent* next) - : mManuName(0), mAUName(0), mCompName(0), mCompInfo (0) -{ - mComp = FindNextComponent ((next ? next->Comp() : NULL), const_cast(&inDesc)); - if (mComp) - GetComponentInfo (Comp(), &mDesc, NULL, NULL, NULL); - else - memcpy (&mDesc, &inDesc, sizeof(ComponentDescription)); -} - -CAComponent::CAComponent (const Component& comp) - : mComp (comp), - mManuName(0), - mAUName(0), - mCompName(0), - mCompInfo (0) -{ - GetComponentInfo (Comp(), &mDesc, NULL, NULL, NULL); -} - -CAComponent::CAComponent (const ComponentInstance& compInst) - : mComp (Component(compInst)), - mManuName(0), - mAUName(0), - mCompName(0), - mCompInfo (0) -{ - GetComponentInfo (Comp(), &mDesc, NULL, NULL, NULL); -} - -CAComponent::CAComponent (OSType inType, OSType inSubtype, OSType inManu) - : mDesc (inType, inSubtype, inManu), - mManuName(0), mAUName(0), mCompName(0), mCompInfo (0) -{ - mComp = FindNextComponent (NULL, &mDesc); - GetComponentInfo (Comp(), &mDesc, NULL, NULL, NULL); -} - -CAComponent::~CAComponent () -{ - Clear(); -} - -OSStatus CAComponent::GetResourceVersion (UInt32 &outVersion) const -{ - bool versionFound = false; - ResFileRefNum componentResFileID = kResFileNotOpened; - OSStatus result; - short thngResourceCount; - - short curRes = CurResFile(); - require_noerr (result = OpenAComponentResFile( mComp, &componentResFileID), home); - require_noerr (result = componentResFileID <= 0, home); - - UseResFile(componentResFileID); - - thngResourceCount = Count1Resources(kComponentResourceType); - - require_noerr (result = ResError(), home); - // only go on if we successfully found at least 1 thng resource - require_noerr (thngResourceCount <= 0 ? -1 : 0, home); - - // loop through all of the Component thng resources trying to - // find one that matches this Component description - for (short i = 0; i < thngResourceCount && (!versionFound); i++) - { - // try to get a handle to this code resource - Handle thngResourceHandle = Get1IndResource(kComponentResourceType, i+1); - if (thngResourceHandle != NULL && ((*thngResourceHandle) != NULL)) - { - if (UInt32(GetHandleSize(thngResourceHandle)) >= sizeof(ExtComponentResource)) - { - ExtComponentResource * componentThng = (ExtComponentResource*) (*thngResourceHandle); - - // check to see if this is the thng resource for the particular Component that we are looking at - // (there often is more than one Component described in the resource) - if ((componentThng->cd.componentType == mDesc.Type()) - && (componentThng->cd.componentSubType == mDesc.SubType()) - && (componentThng->cd.componentManufacturer == mDesc.Manu())) - { - outVersion = componentThng->componentVersion; - versionFound = true; - } - } - ReleaseResource(thngResourceHandle); - } - } - - if (!versionFound) - result = resNotFound; - - UseResFile(curRes); // revert - - if ( componentResFileID != kResFileNotOpened ) - CloseComponentResFile(componentResFileID); - -home: - return result; -} - -void CAComponent::Clear () -{ - if (mManuName) { CFRelease (mManuName); mManuName = 0; } - if (mAUName) { CFRelease (mAUName); mAUName = 0; } - if (mCompName) { CFRelease (mCompName); mCompName = 0; } - if (mCompInfo) { CFRelease (mCompInfo); mCompInfo = 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); } - if (y.mCompInfo) { mCompInfo = y.mCompInfo; CFRetain (mCompInfo); } - - return *this; -} - -void CAComponent::SetCompNames () const -{ - if (!mCompName) { - Handle h1 = NewHandle(4); - CAComponentDescription desc; - OSStatus err = GetComponentInfo (Comp(), &desc, h1, 0, 0); - - if (err) { DisposeHandle(h1); return; } - - HLock(h1); - char* ptr1 = *h1; - // Get the manufacturer's name... look for the ':' character convention - int len = *ptr1++; - char* displayStr = 0; - - const_cast(this)->mCompName = CFStringCreateWithPascalString(NULL, (const unsigned char*)*h1, kCFStringEncodingMacRoman); - - for (int i = 0; i < len; ++i) { - if (ptr1[i] == ':') { // found the name - ptr1[i] = 0; - displayStr = ptr1; - break; - } - } - - if (displayStr) - { - const_cast(this)->mManuName = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingMacRoman); - - //move displayStr ptr past the manu, to the name - // we move the characters down a 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; - - const_cast(this)->mAUName = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingMacRoman); - } - - DisposeHandle (h1); - } -} - -void CAComponent::SetCompInfo () const -{ - if (!mCompInfo) { - Handle h1 = NewHandle(4); - CAComponentDescription desc; - OSStatus err = GetComponentInfo (Comp(), &desc, 0, h1, 0); - if (err) return; - HLock (h1); - const_cast(this)->mCompInfo = CFStringCreateWithPascalString(NULL, (const unsigned char*)*h1, kCFStringEncodingMacRoman); - - DisposeHandle (h1); - } -} - -void _ShowCF (FILE* file, CFStringRef str) -{ - if (CFGetTypeID(str) != CFStringGetTypeID()) { - CFShow(str); - return; - } - - UInt32 len = CFStringGetLength(str); - char* chars = (char*)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", (void*)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/CAComponent.h b/libs/appleutility/CAComponent.h deleted file mode 100644 index 4009bc42fe..0000000000 --- a/libs/appleutility/CAComponent.h +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAComponent.h - -=============================================================================*/ - -#ifndef __CAComponent_h__ -#define __CAComponent_h__ - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#else - #include - #include -#endif - -#include "CAComponentDescription.h" - -class CAComponent -{ -public: - CAComponent () - : mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0), mCompInfo (0) {} - - // if next is specifed that is used to find the next component after that one - CAComponent (const ComponentDescription& inDesc, CAComponent* next = 0); - - CAComponent (const CAComponent& y) - : mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0), mCompInfo (0) { *this = y; } - - CAComponent (const Component& comp); - - CAComponent (const ComponentInstance& 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; } - CFStringRef GetCompInfo () const { SetCompInfo(); return mCompInfo; } - - const CAComponentDescription& Desc () const { return mDesc; } - - OSStatus Open (ComponentInstance& outInst) const - { - return OpenAComponent (Comp(), &outInst); - } - - OSStatus GetResourceVersion (UInt32 &outVersion) const; - - const Component& Comp() const { return mComp; } - - void Print(FILE* file = stdout) const; - - OSStatus Save (CFPropertyListRef *outData) const; - - OSStatus Restore (CFPropertyListRef &inData); - -private: - Component mComp; - CAComponentDescription mDesc; - - CFStringRef mManuName, mAUName, mCompName, mCompInfo; - - void SetCompNames () const; - void SetCompInfo () const; - void Clear (); -}; - -#endif diff --git a/libs/appleutility/CAComponentDescription.cpp b/libs/appleutility/CAComponentDescription.cpp deleted file mode 100644 index 70e0285501..0000000000 --- a/libs/appleutility/CAComponentDescription.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAComponentDescription.cpp - -=============================================================================*/ - -#include "CAComponentDescription.h" -#include - -extern "C" void CAShowComponentDescription(const ComponentDescription *desc) -{ - CAComponentDescription::_CAShowComponentDescription (desc, stdout); -} - -char *StringForOSType (OSType t, char *writeLocation) -{ - char *p = writeLocation; - unsigned char str[4], *q = str; - *(UInt32 *)str = EndianU32_NtoB(t); - for (int i = 0; i < 4; ++i) { - if (isprint(*q) && *q != '\\') - *p++ = *q++; - else { - sprintf(p, "\\x%02X", *q++); - p += 4; - } - } - *p = '\0'; - return writeLocation; -} - - -void CAComponentDescription::_CAShowComponentDescription(const ComponentDescription *desc, FILE* file) -{ - if (desc) - { - char str[24]; - fprintf (file, "ComponentDescription: %s - ", StringForOSType(desc->componentType, str)); - fprintf (file, "%s - ", StringForOSType(desc->componentSubType, str)); - fprintf (file, "%s", StringForOSType(desc->componentManufacturer, str)); - fprintf (file, ", 0x%lX, 0x%lX\n", desc->componentFlags, 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 ComponentDescription &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/CAComponentDescription.h b/libs/appleutility/CAComponentDescription.h deleted file mode 100644 index a70d1eb2ec..0000000000 --- a/libs/appleutility/CAComponentDescription.h +++ /dev/null @@ -1,148 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAComponentDescription.h - -=============================================================================*/ - -#ifndef __CAComponentDescription_h__ -#define __CAComponentDescription_h__ - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include - #include -#else - #include - #include - #include -#endif - -#include "CACFDictionary.h" -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -void CAShowComponentDescription(const ComponentDescription *desc); - -#ifdef __cplusplus -} -#endif - - -// ____________________________________________________________________________ -// -// CAComponentDescription -class CAComponentDescription : public ComponentDescription { -public: - CAComponentDescription() { memset (this, 0, sizeof (ComponentDescription)); } - - CAComponentDescription (OSType inType, OSType inSubtype = 0, OSType inManu = 0); - - CAComponentDescription(const ComponentDescription& desc) { memcpy (this, &desc, sizeof (ComponentDescription)); } - - // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - // - // interrogation - - bool IsAU () const; - - bool IsAUFX() const { return componentType == kAudioUnitType_Effect; } - bool IsAUFM() const { return componentType == kAudioUnitType_MusicEffect; } - - bool IsEffect () const { return IsAUFX() || IsAUFM() || IsPanner(); } - - bool IsOffline () const { return componentType == 'auol'; } - - 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 CountComponents(const_cast(this)); } - - // does a semantic match where "wild card" values for type, subtype, manu will match - bool Matches (const ComponentDescription &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 ComponentDescription *desc, FILE* file); - friend void CAShowComponentDescription (const ComponentDescription *desc); -}; - -inline bool operator< (const ComponentDescription& x, const ComponentDescription& y) -{ - return memcmp (&x, &y, offsetof (ComponentDescription, componentFlags)) < 0; -} - -inline bool operator== (const ComponentDescription& x, const ComponentDescription& y) -{ - return !memcmp (&x, &y, offsetof (ComponentDescription, componentFlags)); -} - -inline bool operator!= (const ComponentDescription& x, const ComponentDescription& y) -{ - return !(x == y); -} - -#endif diff --git a/libs/appleutility/CAConditionalMacros.h b/libs/appleutility/CAConditionalMacros.h deleted file mode 100644 index 4f504699c7..0000000000 --- a/libs/appleutility/CAConditionalMacros.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAConditionalMacros.h - -=============================================================================*/ -#if !defined(__CAConditionalMacros_h__) -#define __CAConditionalMacros_h__ - -//============================================================================= -// This file exists to make figuring out how to include system headers -// easier in a cross platform world. We throw in an include of the standard -// ConditionalMacros too. -//============================================================================= - -// ########## THIS FILE SHOULD GO AWAY SOON, replaced by __COREAUDIO_USE_FLAT_INCLUDES__ -// but for now, use this as a way to define __COREAUDIO_USE_FLAT_INCLUDES__ programmatically - -// 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(CoreAudio_Use_Framework_Includes) && !defined(__COREAUDIO_USE_FLAT_INCLUDES__) && !defined (CARBON_FLAT_HEADERS) - #if TARGET_RT_MAC_MACHO - #define CoreAudio_Use_Framework_Includes 1 - #else - #define CoreAudio_Use_Framework_Includes 0 - #endif -#endif - -// Include the regular ConditionalMacros.h too, since it has useful stuff that -// TargetConditionals.h lacks for some reason. -#if CoreAudio_Use_Framework_Includes - #include -#else - #include "ConditionalMacros.h" -#endif - -#endif diff --git a/libs/appleutility/CADebugMacros.cpp b/libs/appleutility/CADebugMacros.cpp deleted file mode 100644 index edee1f3d51..0000000000 --- a/libs/appleutility/CADebugMacros.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CADebugMacros.cp - -=============================================================================*/ - -#include "CADebugMacros.h" -#include -#include -#if TARGET_API_MAC_OSX - #include -#endif - -#if DEBUG -#include - -void DebugPrint(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - vprintf(fmt, args); - va_end(args); -} -#endif // DEBUG - -#if TARGET_API_MAC_OSX -void LogError(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); -#if DEBUG - vprintf(fmt, args); -#endif - vsyslog(LOG_ERR, fmt, args); - va_end(args); -} - -void LogWarning(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); -#if DEBUG - vprintf(fmt, args); -#endif - vsyslog(LOG_WARNING, fmt, args); - va_end(args); -} -#endif diff --git a/libs/appleutility/CADebugMacros.h b/libs/appleutility/CADebugMacros.h deleted file mode 100644 index 58e5387862..0000000000 --- a/libs/appleutility/CADebugMacros.h +++ /dev/null @@ -1,414 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CADebugMacros.h - -=============================================================================*/ -#if !defined(__CADebugMacros_h__) -#define __CADebugMacros_h__ - -//============================================================================= -// CADebugMacros -//============================================================================= - -//#define CoreAudio_StopOnFailure 1 -//#define CoreAudio_TimeStampMessages 1 -//#define CoreAudio_ThreadStampMessages 1 -//#define CoreAudio_FlushDebugMessages 1 - -#define CA4CCToCString(the4CC) { ((char*)&the4CC)[0], ((char*)&the4CC)[1], ((char*)&the4CC)[2], ((char*)&the4CC)[3], 0 } - -#pragma mark Basic Definitions - -#if DEBUG || CoreAudio_Debug - - // can be used to break into debugger immediately, also see CADebugger - #define BusError() (*(long *)0 = 0) - - // basic debugging print routines - #if TARGET_OS_MAC && !TARGET_API_MAC_CARBON - extern pascal 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 - #include "CAHostTimeBase.h" - #define DebugMessage(msg) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: %s"DebugPrintfLineEnding, pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), msg) FlushRtn - #define DebugMessageN1(msg, N1) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1) FlushRtn - #define DebugMessageN2(msg, N1, N2) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2) FlushRtn - #define DebugMessageN3(msg, N1, N2, N3) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3) FlushRtn - #define DebugMessageN4(msg, N1, N2, N3, N4) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4) FlushRtn - #define DebugMessageN5(msg, N1, N2, N3, N4, N5) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5) FlushRtn - #define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6) FlushRtn - #define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7) FlushRtn - #define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8) FlushRtn - #define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8, N9) FlushRtn - #elif CoreAudio_TimeStampMessages - #include "CAHostTimeBase.h" - #define DebugMessage(msg) DebugPrintfRtn(DebugPrintfFile, "%.4f: %s"DebugPrintfLineEnding, pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), msg) FlushRtn - #define DebugMessageN1(msg, N1) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1) FlushRtn - #define DebugMessageN2(msg, N1, N2) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2) FlushRtn - #define DebugMessageN3(msg, N1, N2, N3) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3) FlushRtn - #define DebugMessageN4(msg, N1, N2, N3, N4) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4) FlushRtn - #define DebugMessageN5(msg, N1, N2, N3, N4, N5) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5) FlushRtn - #define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6) FlushRtn - #define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7) FlushRtn - #define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8) FlushRtn - #define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8, N9) FlushRtn - #else - #define DebugMessage(msg) DebugPrintfRtn(DebugPrintfFile, "%s"DebugPrintfLineEnding, msg) FlushRtn - #define DebugMessageN1(msg, N1) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1) FlushRtn - #define DebugMessageN2(msg, N1, N2) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2) FlushRtn - #define DebugMessageN3(msg, N1, N2, N3) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3) FlushRtn - #define DebugMessageN4(msg, N1, N2, N3, N4) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4) FlushRtn - #define DebugMessageN5(msg, N1, N2, N3, N4, N5) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4, N5) FlushRtn - #define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6) FlushRtn - #define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6, N7) FlushRtn - #define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6, N7, N8) FlushRtn - #define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6, N7, N8, N9) FlushRtn - #endif - #endif - void DebugPrint(const char *fmt, ...); // can be used like printf - #define DEBUGPRINT(msg) DebugPrint msg // have to double-parenthesize arglist (see Debugging.h) - #if VERBOSE - #define vprint(msg) DEBUGPRINT(msg) - #else - #define vprint(msg) - #endif - - #if CoreAudio_StopOnFailure - #include "CADebugger.h" - #define STOP CADebuggerStop() - #else - #define STOP - #endif - -#else - #define DebugMessage(msg) - #define DebugMessageN1(msg, N1) - #define DebugMessageN2(msg, N1, N2) - #define DebugMessageN3(msg, N1, N2, N3) - #define DebugMessageN4(msg, N1, N2, N3, N4) - #define DebugMessageN5(msg, N1, N2, N3, N4, N5) - #define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) - #define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) - #define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) - #define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) - #define DEBUGPRINT(msg) - #define vprint(msg) - #define STOP -#endif - -void LogError(const char *fmt, ...); // writes to syslog (and stderr if debugging) -void LogWarning(const char *fmt, ...); // writes to syslog (and stderr if debugging) - -#if DEBUG || CoreAudio_Debug - -#pragma mark Debug Macros - -#define Assert(inCondition, inMessage) \ - if(!(inCondition)) \ - { \ - DebugMessage(inMessage); \ - STOP; \ - } - -#define AssertNoError(inError, inMessage) \ - { \ - SInt32 __Err = (inError); \ - if(__Err != 0) \ - { \ - char __4CC[5] = CA4CCToCString(__Err); \ - DebugMessageN2(inMessage ", Error: %ld (%s)", __Err, __4CC); \ - STOP; \ - } \ - } - -#define AssertNoKernelError(inError, inMessage) \ - { \ - unsigned int __Err = (unsigned int)(inError); \ - if(__Err != 0) \ - { \ - DebugMessageN1(inMessage ", Error: 0x%X", __Err); \ - 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, inException, inMessage) \ - { \ - kern_return_t __Err = (inKernelError); \ - if(__Err != 0) \ - { \ - DebugMessageN1(inMessage ", Error: 0x%X", __Err); \ - STOP; \ - { inAction; } \ - goto inHandler; \ - } \ - } - -#define FailIfError(inError, inException, inMessage) \ - { \ - SInt32 __Err = (inError); \ - if(__Err != 0) \ - { \ - char __4CC[5] = CA4CCToCString(__Err); \ - DebugMessageN2(inMessage ", Error: %ld (%s)", __Err, __4CC); \ - STOP; \ - { inAction; } \ - goto inHandler; \ - } \ - } - -#if defined(__cplusplus) - -#define Throw(inException) 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) \ - { \ - kern_return_t __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: %ld (%s)", __Err, __4CC); \ - Throw(inException); \ - } \ - } - -#if TARGET_OS_WIN32 -#define ThrowIfWinError(inError, inException, inMessage) \ - { \ - HRESULT __Err = (inError); \ - if(FAILED(__Err)) \ - { \ - DebugMessageN1(inMessage ", Error: 0x%X", __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)) \ - { \ - STOP; \ - } - -#define AssertNoError(inError, inMessage) \ - { \ - SInt32 __Err = (inError); \ - if(__Err != 0) \ - { \ - STOP; \ - } \ - } - -#define AssertNoKernelError(inError, inMessage) \ - { \ - unsigned int __Err = (unsigned int)(inError); \ - if(__Err != 0) \ - { \ - 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, inException, inMessage) \ - if((inKernelError) != 0) \ - { \ - STOP; \ - { inAction; } \ - goto inHandler; \ - } - -#define FailIfError(inError, inException, inMessage) \ - if((inError) != 0) \ - { \ - STOP; \ - { inAction; } \ - goto inHandler; \ - } - -#if defined(__cplusplus) - -#define Throw(inException) 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) \ - { \ - kern_return_t __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/CAMath.h b/libs/appleutility/CAMath.h deleted file mode 100644 index bc9ec51661..0000000000 --- a/libs/appleutility/CAMath.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAMath.h - -=============================================================================*/ - -#ifndef __CAMath_h__ -#define __CAMath_h__ - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#else - #include -#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/CAReferenceCounted.h b/libs/appleutility/CAReferenceCounted.h deleted file mode 100644 index c17b5c38bd..0000000000 --- a/libs/appleutility/CAReferenceCounted.h +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAReferenceCounted.h - -=============================================================================*/ - -#ifndef __CAReferenceCounted_h__ -#define __CAReferenceCounted_h__ - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#else - #include -#endif - -#if TARGET_OS_WIN32 - #include "CAWindows.h" -#endif - -// base class for reference-counted objects -class CAReferenceCounted { -public: - CAReferenceCounted() : mRefCount(1) {} - - void retain() { IncrementAtomic(&mRefCount); } - - void release() - { - // this returns the ORIGINAL value, not the new one. - SInt32 rc = DecrementAtomic(&mRefCount); - if (rc == 1) { - delete this; - } - } - -protected: - virtual ~CAReferenceCounted() { } - CAReferenceCounted(const CAReferenceCounted &) : mRefCount(0) { } - -private: - SInt32 mRefCount; - - CAReferenceCounted operator=(const CAReferenceCounted &) { return *this; } -}; - - -#endif // __CAReferenceCounted_h__ diff --git a/libs/appleutility/CAStreamBasicDescription.cpp b/libs/appleutility/CAStreamBasicDescription.cpp deleted file mode 100644 index bc48dd0f76..0000000000 --- a/libs/appleutility/CAStreamBasicDescription.cpp +++ /dev/null @@ -1,520 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAStreamBasicDescription.cpp - -=============================================================================*/ - -#include "CAConditionalMacros.h" - -#include "CAStreamBasicDescription.h" -#include "CAMath.h" - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#else - #include -#endif - -#pragma mark This file needs to compile on more earlier versions of the OS, so please keep that in mind when editing it - -const AudioStreamBasicDescription CAStreamBasicDescription::sEmpty = { 0.0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -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; -} - -void CAStreamBasicDescription::PrintFormat(FILE *f, const char *indent, const char *name) const -{ - fprintf(f, "%s%s ", indent, name); - char formatID[5]; - *(UInt32 *)formatID = CFSwapInt32HostToBig(mFormatID); - formatID[4] = '\0'; - fprintf(f, "%2ld ch, %6.0f Hz, '%-4.4s' (0x%08lX) ", - NumberChannels(), mSampleRate, formatID, - mFormatFlags); - if (mFormatID == kAudioFormatLinearPCM) { - bool isInt = !(mFormatFlags & kLinearPCMFormatFlagIsFloat); - int wordSize = 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) - sprintf(packed, "packed in %d bytes", wordSize); - else - sprintf(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') ? ", " : ""; - - fprintf(f, "%ld-bit%s%s %s%s%s%s%s\n", - mBitsPerChannel, endian, sign, floatInt, - commaSpace, packed, align, deinter); - } else if (mFormatID == 'alac') { // 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) - fprintf(f, "from %d-bit source, ", sourceBits); - else - fprintf(f, "from UNKNOWN source bit depth, "); - - fprintf(f, "%ld frames/packet\n", mFramesPerPacket); - } - else - fprintf(f, "%ld bits/channel, %ld bytes/packet, %ld frames/packet, %ld bytes/frame\n", - mBitsPerChannel, mBytesPerPacket, mFramesPerPacket, mBytesPerFrame); -} - -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 is 32 bit native endian floats - ioDescription.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; - ioDescription.mBytesPerPacket = sizeof(Float32) * ioDescription.mChannelsPerFrame; - ioDescription.mFramesPerPacket = 1; - ioDescription.mBytesPerFrame = sizeof(Float32) * ioDescription.mChannelsPerFrame; - ioDescription.mBitsPerChannel = 8 * sizeof(Float32); - } -} - -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, bool inAbbreviate) -{ - 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) - { - sprintf(outName, "%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 - { - sprintf(outName, "%s %d Ch %s %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, theKindString, (int)inDescription.mBitsPerChannel); - } - } - else - { - if(thePackingString != NULL) - { - sprintf(outName, "%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 - { - sprintf(outName, "%s %d Ch %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theKindString, (int)inDescription.mBitsPerChannel); - } - } - } - else - { - if(theEndianString != NULL) - { - if(thePackingString != NULL) - { - sprintf(outName, "%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 - { - sprintf(outName, "%s %d Channel %d Bit %s %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString); - } - } - else - { - if(thePackingString != NULL) - { - sprintf(outName, "%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 - { - sprintf(outName, "%s %d Channel %d Bit %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString); - } - } - } - } - break; - - case kAudioFormatAC3: - strcpy(outName, "AC-3"); - break; - - case kAudioFormat60958AC3: - strcpy(outName, "AC-3 for SPDIF"); - break; - - default: - { - char* the4CCString = (char*)&inDescription.mFormatID; - outName[0] = the4CCString[0]; - outName[1] = the4CCString[1]; - outName[2] = the4CCString[2]; - outName[3] = the4CCString[3]; - outName[4] = 0; - } - 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; -} - -static bool MatchFormatFlags(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) -{ - UInt32 xFlags = x.mFormatFlags; - UInt32 yFlags = y.mFormatFlags; - - // match wildcards - if (x.mFormatID == 0 || y.mFormatID == 0 || xFlags == 0 || yFlags == 0) - return true; - - 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 & ~kAudioFormatFlagIsAlignedHigh; - yFlags = yFlags & ~kAudioFormatFlagIsAlignedHigh; - } - - // if both kAudioFormatFlagIsFloat bits are set, then we don't care about the kAudioFormatFlagIsSignedInteger bit. - if (xFlags & yFlags & kAudioFormatFlagIsFloat) { - xFlags = xFlags & ~kAudioFormatFlagIsSignedInteger; - yFlags = yFlags & ~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 & ~kAudioFormatFlagIsBigEndian; - } - if((y.mBitsPerChannel <= 8) && ((yFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked)) - { - yFlags = yFlags & ~kAudioFormatFlagIsBigEndian; - } - - // if the number of channels is 0 or 1, we don't care about non-interleavedness - if (x.mChannelsPerFrame <= 1 && y.mChannelsPerFrame <= 1) { - xFlags &= ~kLinearPCMFormatFlagIsNonInterleaved; - yFlags &= ~kLinearPCMFormatFlagIsNonInterleaved; - } - } - return xFlags == yFlags; -} - -bool operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) -{ - // the semantics for equality are: - // 1) Values must match exactly - // 2) wildcard's are ignored in the comparison - -#define MATCH(name) ((x.name) == 0 || (y.name) == 0 || (x.name) == (y.name)) - - return - // check the sample rate - (fiszero(x.mSampleRate) || fiszero(y.mSampleRate) || fequal(x.mSampleRate, y.mSampleRate)) - - // check the format ids - && MATCH(mFormatID) - - // check the format flags - && MatchFormatFlags(x, y) - - // 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 SanityCheck(const AudioStreamBasicDescription& x) -{ - return (x.mSampleRate >= 0.); -} diff --git a/libs/appleutility/CAStreamBasicDescription.h b/libs/appleutility/CAStreamBasicDescription.h deleted file mode 100644 index db3faaea0d..0000000000 --- a/libs/appleutility/CAStreamBasicDescription.h +++ /dev/null @@ -1,224 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAStreamBasicDescription.h - -=============================================================================*/ - -#ifndef __CAStreamBasicDescription_h__ -#define __CAStreamBasicDescription_h__ - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include - #include -#else - #include "CoreAudioTypes.h" - #include "CoreFoundation.h" -#endif - -#include "CADebugMacros.h" -#include // for memset, memcpy -#include // 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 - -// 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; - -// Construction/Destruction -public: - CAStreamBasicDescription() { memset (this, 0, sizeof(AudioStreamBasicDescription)); } - - CAStreamBasicDescription(const AudioStreamBasicDescription &desc) - { - SetFrom(desc); - } - - CAStreamBasicDescription( double inSampleRate, UInt32 inFormatID, - UInt32 inBytesPerPacket, UInt32 inFramesPerPacket, - UInt32 inBytesPerFrame, UInt32 inChannelsPerFrame, - UInt32 inBitsPerChannel, UInt32 inFormatFlags); - -// Assignment - CAStreamBasicDescription& operator=(const AudioStreamBasicDescription& v) { SetFrom(v); return *this; } - - void SetFrom(const AudioStreamBasicDescription &desc) - { - memcpy(this, &desc, sizeof(AudioStreamBasicDescription)); - } - - // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - // - // 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 !IsPCM() || !(mFormatFlags & kAudioFormatFlagIsNonInterleaved); - } - - // 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) ? 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(); - } - - // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - // - // manipulation - - void SetCanonical(UInt32 nChannels, bool interleaved) - // note: leaves sample rate untouched - { - mFormatID = kAudioFormatLinearPCM; - mFormatFlags = kAudioFormatFlagsNativeFloatPacked; - mBitsPerChannel = 32; - mChannelsPerFrame = nChannels; - mFramesPerPacket = 1; - if (interleaved) - mBytesPerPacket = mBytesPerFrame = nChannels * sizeof(Float32); - else { - mBytesPerPacket = mBytesPerFrame = sizeof(Float32); - 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 &= ~kAudioFormatFlagIsNonInterleaved; - } else { - mBytesPerPacket = mBytesPerFrame = wordSize; - mFormatFlags |= kAudioFormatFlagIsNonInterleaved; - } - } - - // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - // - // other - - void Print() const - { - Print (stdout); - } - - void Print(FILE* file) const - { - PrintFormat (file, "", "AudioStreamBasicDescription:"); - } - - void PrintFormat(FILE *f, const char *indent, const char *name) const; - - 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 ResetFormat(AudioStreamBasicDescription& ioDescription); - static void FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription); - static void GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, bool inAbbreviate); -#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/CAXException.cpp b/libs/appleutility/CAXException.cpp deleted file mode 100644 index 744a77ffa8..0000000000 --- a/libs/appleutility/CAXException.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAXException.cpp - -=============================================================================*/ - -#include "CAXException.h" - -CAXException::WarningHandler CAXException::sWarningHandler = NULL; diff --git a/libs/appleutility/CAXException.h b/libs/appleutility/CAXException.h deleted file mode 100644 index b27f833805..0000000000 --- a/libs/appleutility/CAXException.h +++ /dev/null @@ -1,158 +0,0 @@ -/* Copyright: © Copyright 2005 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. -*/ -/*============================================================================= - CAXException.h - -=============================================================================*/ - -#ifndef __CAXException_h__ -#define __CAXException_h__ - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#else - #include - #include -#endif -#include "CADebugMacros.h" -#include -#include -#include - -// 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 - strcpy(mOperation, operation); - } - - char *FormatError(char *str) const - { - return FormatError(str, mError); - } - - char mOperation[256]; - const OSStatus mError; - - // ------------------------------------------------- - - typedef void (*WarningHandler)(const char *msg, OSStatus err); - - /*static void Throw(const char *operation, OSStatus err) - { - throw CAXException(operation, err); - }*/ - - static char *FormatError(char *str, OSStatus error) - { - // see if it appears to be a 4-char-code - *(UInt32 *)(str + 1) = EndianU32_NtoB(error); - if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) { - str[0] = str[5] = '\''; - str[6] = '\0'; - } else - // no, format it as an integer - sprintf(str, "%ld", error); - 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) { \ - char __buf[12]; \ - DebugMessageN2("error %s: %4s\n", CAXException::FormatError(__buf, __err), operation);\ - STOP; \ - throw CAXException(operation, __err); \ - } \ - } while (0) - - #define XThrowIf(condition, error, operation) \ - do { \ - if (condition) { \ - OSStatus __err = error; \ - char __buf[12]; \ - DebugMessageN2("error %s: %4s\n", CAXException::FormatError(__buf, __err), operation);\ - STOP; \ - throw CAXException(operation, __err); \ - } \ - } 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) - -#endif - -#define XThrow(error, operation) XThrowIf(true, error, operation) -#define XThrowIfErr(error) XThrowIfError(error, #error) - -#endif // __CAXException_h__ 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 +#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(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(outPropertyData)); + } + else + { + CODEC_THROW(kAudioCodecBadPropertySizeError); + } + break; + + case kAudioCodecPropertySupportedInputFormats: + case kAudioCodecPropertyInputFormatsForOutputFormat: + thePacketsToGet = ioPropertyDataSize / SizeOf32(AudioStreamBasicDescription); + GetSupportedInputFormats(reinterpret_cast(outPropertyData), thePacketsToGet); + ioPropertyDataSize = thePacketsToGet * SizeOf32(AudioStreamBasicDescription); + break; + + case kAudioCodecPropertyCurrentOutputFormat: + if(ioPropertyDataSize == SizeOf32(AudioStreamBasicDescription)) + { + GetCurrentOutputFormat(*reinterpret_cast(outPropertyData)); + } + else + { + CODEC_THROW(kAudioCodecBadPropertySizeError); + } + break; + + case kAudioCodecPropertySupportedOutputFormats: + case kAudioCodecPropertyOutputFormatsForInputFormat: + thePacketsToGet = ioPropertyDataSize / SizeOf32(AudioStreamBasicDescription); + GetSupportedOutputFormats(reinterpret_cast(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(outPropertyData) = GetInputBufferByteSize(); + } + else + { + CODEC_THROW(kAudioCodecBadPropertySizeError); + } + break; + + case kAudioCodecPropertyUsedInputBufferSize: + if(ioPropertyDataSize == SizeOf32(UInt32)) + { + *reinterpret_cast(outPropertyData) = GetUsedInputBufferByteSize(); + } + else + { + CODEC_THROW(kAudioCodecBadPropertySizeError); + } + break; + + case kAudioCodecPropertyIsInitialized: + if(ioPropertyDataSize == SizeOf32(UInt32)) + { + *reinterpret_cast(outPropertyData) = IsInitialized() ? 1 : 0; + } + else + { + CODEC_THROW(kAudioCodecBadPropertySizeError); + } + break; + + case kAudioCodecPropertyAvailableNumberChannels: + if(ioPropertyDataSize == SizeOf32(UInt32) * 2) + { + (reinterpret_cast(outPropertyData))[0] = 1; + (reinterpret_cast(outPropertyData))[1] = 2; + } + else + { + CODEC_THROW(kAudioCodecBadPropertySizeError); + } + break; + + case kAudioCodecPropertyPrimeMethod: + if(ioPropertyDataSize == SizeOf32(UInt32)) + { + *reinterpret_cast(outPropertyData) = (UInt32)kAudioCodecPrimeMethod_None; + } + else + { + CODEC_THROW(kAudioCodecBadPropertySizeError); + } + break; + + case kAudioCodecPropertyPrimeInfo: + if(ioPropertyDataSize == SizeOf32(AudioCodecPrimeInfo) ) + { + (reinterpret_cast(outPropertyData))->leadingFrames = 0; + (reinterpret_cast(outPropertyData))->trailingFrames = 0; + } + else + { + CODEC_THROW(kAudioCodecBadPropertySizeError); + } + break; + + case kAudioCodecPropertyDoesSampleRateConversion: + if(ioPropertyDataSize == SizeOf32(UInt32)) + { + *reinterpret_cast(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(inPropertyData)); + } + else + { + CODEC_THROW(kAudioCodecBadPropertySizeError); + } + break; + + case kAudioCodecPropertyCurrentOutputFormat: + if(inPropertyDataSize == SizeOf32(AudioStreamBasicDescription)) + { + SetCurrentOutputFormat(*reinterpret_cast(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 +#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 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 +#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(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 +#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 + +#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 AudioCodecFactory : public APFactory +{ +}; + +#if AC_NON_INTERLEAVED_SUPPORT +struct AudioCodecNonInterleavedEncoderLookup { + static AudioComponentMethod Lookup (SInt16 selector); +}; +template +class AudioCodecNonInterleavedEncoderFactory : public APFactory +{ +}; + +struct AudioCodecNonInterleavedDecoderLookup { + static AudioComponentMethod Lookup (SInt16 selector); +}; +template +class AudioCodecNonInterleavedDecoderFactory : public APFactory +{ +}; +#endif + +#if TARGET_OS_IPHONE +struct AudioCodecHWCodecLookup { + static AudioComponentMethod Lookup (SInt16 selector); +}; +template +class AudioCodecHWCodecFactory : public APFactory +{ +}; +#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 + +//============================================================================= +// 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(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: 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; + + // < 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(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 + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include +#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 +#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 *)¶ms->params[_index + 1]; + #else + // parameters in reverse order, then comp instance + #define PARAM(_typ, _name, _index, _nparams) \ + _typ _name = *(_typ *)¶ms->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 *)¶ms->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 AudioFileComponentFactory : public APFactory +{ +}; + +/* 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 +#include + +#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(ioPropertyData)); + break; + + case kAudioFilePropertyRegionList : + memset(ioPropertyData, 0, *ioDataSize); + err = GetRegionList(ioDataSize, static_cast(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(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(inPropertyData)); + break; + + case kAudioFilePropertyRegionList : + err = SetRegionList(inDataSize, static_cast(inPropertyData)); + break; + + case kAudioFilePropertyChannelLayout : + err = SetChannelLayout(inDataSize, static_cast(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 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 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 + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include + #include + #include +#else + #include "CoreAudioTypes.h" + #include "AudioFile.h" + #include "AudioFormat.h" +#endif + +#include "CompressedPacketTable.h" +#include "CACFDictionary.h" +#include "DataSource.h" +#include +#include + +#if TARGET_OS_WIN32 +#include +#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 +#include + +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 +#include +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include +#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 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 +#else + #include + #include +#endif +#include +#include + +#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(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(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(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("<= 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(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(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 +#else + #include + #include "AudioFile.h" +#endif +#include +#include +#include +#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 mHeaderCache; + UInt32 mHeaderCacheSize; + CAAutoFree 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 +#include +#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(outData) : NULL; + UInt32 numLayouts = GetChannelLayoutTags (inScope, inElement, ptr); + if (numLayouts == 0) + result = kAudioUnitErr_InvalidProperty; + } + break; + + case kAudioUnitProperty_AudioChannelLayout: + { + AudioChannelLayout* ptr = outData ? static_cast(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(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(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(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(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(CFDictionaryGetValue (dict, kSubtypeString)); + if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue; + CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value); + if (UInt32(value) != desc.componentSubType) return kAudioUnitErr_InvalidPropertyValue; + + cfnum = reinterpret_cast(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(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(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(&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(&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(&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(&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(this)->mLogString = new char[logStringSize]; + char str[24]; + char str1[24]; + char str2[24]; + snprintf (const_cast(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 + +#if TARGET_OS_MAC + #include +#elif TARGET_OS_WIN32 + #include +#else + #error Unsupported Operating System +#endif + +#include + +#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 + #if !CA_BASIC_AU_FEATURES + #include + #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(Inputs().SafeGetElement(inElement)); + } + + /*! @method GetOutput */ + AUOutputElement * GetOutput( AudioUnitElement inElement) + { + return static_cast(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(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 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 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 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(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 *)¶ms->params[_index + 1]; + #else + // parameters in reverse order, then comp instance + #define PARAM(_typ, _name, _index, _nparams) \ + _typ _name = *(_typ *)¶ms->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 *)¶ms->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 +#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 + #if !CA_BASIC_AU_FEATURES + #include + #endif +#else + #include "AudioComponent.h" + #include "MusicDevice.h" +#endif + +#include "ComponentBase.h" + +struct AUBaseLookup { + static AudioComponentMethod Lookup (SInt16 selector); +}; +template +class AUBaseFactory : public APFactory +{ +}; + +struct AUOutputLookup { + static AudioComponentMethod Lookup (SInt16 selector); +}; +template +class AUOutputBaseFactory : public APFactory +{ +}; + +struct AUComplexOutputLookup { + static AudioComponentMethod Lookup (SInt16 selector); +}; +template +class AUOutputComplexBaseFactory : public APFactory +{ +}; + +struct AUBaseProcessLookup { + static AudioComponentMethod Lookup (SInt16 selector); +}; +template +class AUBaseProcessFactory : public APFactory +{ +}; + +struct AUBaseProcessMultipleLookup { + static AudioComponentMethod Lookup (SInt16 selector); +}; +template +class AUBaseProcessMultipleFactory : public APFactory +{ +}; + +struct AUBaseProcessAndMultipleLookup { + static AudioComponentMethod Lookup (SInt16 selector); +}; +template +class AUBaseProcessAndMultipleFactory : public APFactory +{ +}; + +#if !CA_BASIC_AU_FEATURES +struct AUMIDILookup { + static AudioComponentMethod Lookup (SInt16 selector); +}; +template +class AUMIDIEffectFactory : public APFactory +{ +}; + +struct AUMIDIProcessLookup { + static AudioComponentMethod Lookup (SInt16 selector); +}; +template +class AUMIDIProcessFactory : public APFactory +{ +}; + +struct AUMusicLookup { + static AudioComponentMethod Lookup (SInt16 selector); +}; +template +class AUMusicDeviceFactory : public APFactory +{ +}; + +struct AUAuxBaseLookup { + static AudioComponentMethod Lookup (SInt16 selector); +}; +template +class AUAuxBaseFactory : public APFactory +{ +}; +#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 + +// 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(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(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(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(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(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(CFDictionaryGetCount(inNameDict)); + CFStringRef * keys = (CFStringRef*)CA_malloc (dictSize * sizeof (CFStringRef)); + CFDictionaryGetKeysAndValues (inNameDict, reinterpret_cast(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(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 +#include + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include +#else + #include +#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(mIndexedParameters.size()); else return static_cast(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 > ParameterMap; + +/*! @var mAudioUnit */ + AUBase * mAudioUnit; +/*! @var mParameters */ + ParameterMap mParameters; + +/*! @var mUseIndexedParameters */ + bool mUseIndexedParameters; +/*! @var mIndexedParameters */ + std::vector 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(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch; + else + return static_cast(mIOBuffer.GetBufferList().mBuffers[ch].mData); + } + Float32 * GetFloat32ChannelData(int ch) const { + if (mStreamFormat.IsInterleaved()) + return static_cast(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch; + else + return static_cast(mIOBuffer.GetBufferList().mBuffers[ch].mData); + } + SInt32 * GetSInt32ChannelData(int ch) const { + if (mStreamFormat.IsInterleaved()) + return static_cast(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch; + else + return static_cast(mIOBuffer.GetBufferList().mBuffers[ch].mData); + } + SInt16 * GetInt16ChannelData(int ch) const { + if (mStreamFormat.IsInterleaved()) + return static_cast(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch; + else + return static_cast(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(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 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 + +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 +#include +#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 + +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 +#include "CADebugMacros.h" +#include "CAXException.h" + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include + #include + + #if !CA_USE_AUDIO_PLUGIN_ONLY + #include + + #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 + #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(throw_err); } while (0) + #else + #define COMPONENT_THROW(throw_err) \ + throw static_cast(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 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 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::Dispatch(params, obj); \ + } \ + extern "C" void * Class##Factory(const AudioComponentDescription *inDesc); \ + extern "C" void * Class##Factory(const AudioComponentDescription *inDesc) { \ + return FactoryType::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::Dispatch(params, obj); \ + } + + /*! @class ComponentRegistrar */ +template +class ComponentRegistrar { +public: + /*! @ctor ComponentRegistrar */ + ComponentRegistrar() { ComponentEntryPoint::Register(Type, Subtype, Manufacturer); } +}; + +#define COMPONENT_REGISTER(Class,Type,Subtype,Manufacturer) \ + static ComponentRegistrar 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::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 + +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 ¶m, 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(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 +#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 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 ¶m, 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(¶mValue); + + 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, ¤tPreset, &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 +#include +#include +#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 ¶m, 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 +#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 + +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(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 + + /*! @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; iReset(); + mFreeNotes.AddNote(note); + } +} + +UInt32 AUInstrumentBase::CountActiveNotes() +{ + // debugging tool. + UInt32 sum = 0; + for (UInt32 i=0; iGetState() <= 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; iIsSounding()) + 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(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(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(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(groups.GetElement(i)); + if (el->GetNote(inNoteID) != NULL) // searches for any note state + return el; + } + throw static_cast(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 +#include +#include +#include +#include +#include "MusicDeviceBase.h" +#include "LockFreeFIFO.h" +#include "SynthEvent.h" +#include "SynthNote.h" +#include "SynthElement.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +typedef LockFreeFIFOWithFree 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 + +template +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 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 + +/*! 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(kAudioUnitErr_InvalidElement); + mGroupID = inGroup; +} + +void SynthGroupElement::Reset() +{ +#if DEBUG_PRINT + printf("SynthGroupElement::Reset\n"); +#endif + mMidiControlHandler->Reset(); + for (UInt32 i=0; imNoteID != 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, ¬eState); // 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 ; imNext; + + 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 ; imNext; + + 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 +#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 +#include +#include "MusicDeviceBase.h" +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +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 +#include +#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 + +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(ioActionFlags, inBuffer, outBuffer, inFramesToProcess); + break; + case CAStreamBasicDescription::kPCMFormatFixed824 : + ProcessBufferListsT(ioActionFlags, inBuffer, outBuffer, inFramesToProcess); + break; + case CAStreamBasicDescription::kPCMFormatInt16 : + ProcessBufferListsT(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 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 + 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 +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 +#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(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(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(startFrame)); + // note that we're generating a bogus channel number for system messages (0xF0-FF) + } + event = NextMIDIEvent(event, packetEnd); + } + pkt = reinterpret_cast(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 *)¶ms->params[_index + 1]; + #else + // parameters in reverse order, then comp instance + #define PARAM(_typ, _name, _index, _nparams) \ + _typ _name = *(_typ *)¶ms->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 *)¶ms->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(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 +#include + +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 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 +#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 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 *)¶ms->params[_index + 1]; + #else + // parameters in reverse order, then comp instance + #define PARAM(_typ, _name, _index, _nparams) \ + _typ _name = *(_typ *)¶ms->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 *)¶ms->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(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(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(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 +#else + #include +#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 + #include +#else + #include + #include +#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 + +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 +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include +#else + #include +#endif + +#include +#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(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 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 +#include "CAHostTimeBase.h" +#include + +#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 + // 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 +#else + #include +#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(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 ¶mInfo = 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((*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 +#include +#include +#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) + + 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 ParameterList; + typedef std::map > 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(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 + +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 +#include + +/* +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 + +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 +#include + +class CAAUMIDIMapManager { + +protected: + + typedef std::vector ParameterMaps; + ParameterMaps mParameterMaps; + + bool hotMapping; + AUParameterMIDIMapping mHotMap; + +public: + + CAAUMIDIMapManager(); + + UInt32 NumMaps(){return static_cast(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(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 + +// ____________________________________________________________________________ +// 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("<<< 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 +#include "CAStreamBasicDescription.h" +#include "CAAudioUnit.h" +#include "AUOutputBL.h" + +#if TARGET_OS_IPHONE + #include +#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 + #include + #pragma intrinsic(_InterlockedOr) + #pragma intrinsic(_InterlockedAnd) +#else + #include + #include +#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 +#else + #include +#endif + +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4 + #include +#endif + +// linked list LIFO or FIFO (pop_all_reversed) stack, elements are pushed and popped atomically +// class T must implement T *& next(). +template +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. + // 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 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 + +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 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 +#include + +//============================================================================= +// CAAudioBufferList +//============================================================================= + +AudioBufferList* CAAudioBufferList::Create(UInt32 inNumberBuffers) +{ + UInt32 theSize = CalculateByteSize(inNumberBuffers); + AudioBufferList* theAnswer = static_cast(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(inSource.mData); + Float32* theDestination = static_cast(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(inSourceBufferList.mBuffers[theBufferIndex].mData); + Float32* theSummedBuffer = static_cast(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 +#else + #include +#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 +#include + +//============================================================================= +// CAAudioChannelLayout +//============================================================================= + +AudioChannelLayout* CAAudioChannelLayout::Create(UInt32 inNumberChannelDescriptions) +{ + UInt32 theSize = CalculateByteSize(inNumberChannelDescriptions); + AudioChannelLayout* theAnswer = static_cast(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 + #include +#else + #include + #include +#endif +#include +#include +#include + +#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 +#else + #include +#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 +#include + +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(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 +#else + #include +#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(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 +#else + #include +#endif + +#include + +//============================================================================= +// 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 + #include +#else + #include +#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(&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(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(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(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 + #include + #include + #include +#else + #include + #include + #include + #include + #include + #include +#endif + +#include +#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 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 + +/* + 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 + +//================================================================================================== +// 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 +#else + #include +#endif +// Standard Library Includes +#include +#include + +//============================================================================= +// 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 + { + 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 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 // for malloc +#include // for bad_alloc +#include // 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 +struct CAPtrRef +{ + T* ptr_; + + explicit CAPtrRef(T* ptr) : ptr_(ptr) {} +}; + +template +class CAAutoFree +{ +private: + T* ptr_; + +public: + + CAAutoFree() : ptr_(0) {} + + explicit CAAutoFree(T* ptr) : ptr_(ptr) {} + + template + CAAutoFree(CAAutoFree& that) : ptr_(that.release()) {} // take ownership + + // C++ std says: a template constructor is never a copy constructor + CAAutoFree(CAAutoFree& 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(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(clear ? CA_calloc(numItems, sizeof(T)) : CA_malloc(numItems * sizeof(T))); + } + + void allocBytes(size_t numBytes, bool clear = false) + { + free(); + ptr_ = static_cast(clear ? CA_calloc(1, numBytes) : CA_malloc(numBytes)); + } + + void reallocBytes(size_t numBytes) + { + ptr_ = static_cast(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(CA_realloc(ptr_, numItems * sizeof(T))); + } + + template + CAAutoFree& operator=(CAAutoFree& 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 + 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 ref) : ptr_(ref.ptr_) { } + + CAAutoFree& operator=(CAPtrRef ref) + { + set(ref.ptr_); + return *this; + } + + template + operator CAPtrRef() + { return CAPtrRef(release()); } + + template + operator CAAutoFree() + { return CAAutoFree(release()); } + +}; + + +template +class CAAutoDelete +{ +private: + T* ptr_; + +public: + CAAutoDelete() : ptr_(0) {} + + explicit CAAutoDelete(T* ptr) : ptr_(ptr) {} + + template + CAAutoDelete(CAAutoDelete& that) : ptr_(that.release()) {} // take ownership + + // C++ std says: a template constructor is never a copy constructor + CAAutoDelete(CAAutoDelete& that) : ptr_(that.release()) {} // take ownership + + ~CAAutoDelete() { free(); } + + template + CAAutoDelete& operator=(CAAutoDelete& 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 + 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 ref) : ptr_(ref.ptr_) { } + + CAAutoDelete& operator=(CAPtrRef ref) + { + set(ref.ptr_); + return *this; + } + + template + operator CAPtrRef() + { return CAPtrRef(release()); } + + template + operator CAAutoFree() + { return CAAutoFree(release()); } + +}; + + +template +class CAAutoArrayDelete +{ +private: + T* ptr_; + +public: + CAAutoArrayDelete() : ptr_(0) {} + + explicit CAAutoArrayDelete(T* ptr) : ptr_(ptr) {} + + template + CAAutoArrayDelete(CAAutoArrayDelete& that) : ptr_(that.release()) {} // take ownership + + // C++ std says: a template constructor is never a copy constructor + CAAutoArrayDelete(CAAutoArrayDelete& 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 + CAAutoArrayDelete& operator=(CAAutoArrayDelete& 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 + 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 ref) : ptr_(ref.ptr_) { } + + CAAutoArrayDelete& operator=(CAPtrRef ref) + { + set(ref.ptr_); + return *this; + } + + template + operator CAPtrRef() + { return CAPtrRef(release()); } + + template + operator CAAutoArrayDelete() + { return CAAutoFree(release()); } + +}; + + + + + +// convenience function +template +void free(CAAutoFree& p) +{ + p.free(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +#if 0 +// example program showing ownership transfer + +CAAutoFree source() +{ + // source allocates and returns ownership to the caller. + const char* str = "this is a test"; + size_t size = strlen(str) + 1; + CAAutoFree captr(size, false); + strlcpy(captr(), str, size); + printf("source %08X %08X '%s'\n", &captr, captr(), captr()); + return captr; +} + +void user(CAAutoFree 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 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 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 + #include +#else +// #include + #include "CFBase.h" +#endif +#include + +// 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 +#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 + T* GetData(UInt32 inBuffer) { + return static_cast(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 + +/* +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 + +/* +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 +#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(theValue)); + theAnswer = true; + } + else if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID())) + { + SInt32 theNumericValue = 0; + CFNumberGetValue(static_cast(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(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(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(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(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(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(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(theValue), kCFNumberSInt32Type, &outValue); + theAnswer = true; + } + else if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID())) + { + CFStringRef theString = static_cast(theValue); + if(CFStringGetLength(theString) == 4) + { + char theCString[5]; + CFStringGetCString(theString, theCString, 5, kCFStringEncodingASCII); + outValue = CFSwapInt32BigToHost(*reinterpret_cast(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(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(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(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(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(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(inIndex)); + theAnswer = outItem != NULL; + } + + return theAnswer; +} + +void CACFArray::GetCACFString(UInt32 inIndex, CACFString& outItem) const +{ + outItem = static_cast(NULL); + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFStringGetTypeID())) + { + outItem = static_cast(theItem); + } + } +} + +void CACFArray::GetCACFArray(UInt32 inIndex, CACFArray& outItem) const +{ + outItem = static_cast(NULL); + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFArrayGetTypeID())) + { + outItem = static_cast(theItem); + } + } +} + +void CACFArray::GetCACFDictionary(UInt32 inIndex, CACFDictionary& outItem) const +{ + outItem = static_cast(NULL); + CFTypeRef theItem = NULL; + if(GetCFType(inIndex, theItem)) + { + if((theItem != NULL) && (CFGetTypeID(theItem) == CFDictionaryGetTypeID())) + { + outItem = static_cast(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(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(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 + #include +#else + #include + #include +#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(inMaxNumberItems), &kCFTypeArrayCallBacks)), mRelease(inRelease), mMutable(true) {} + CACFArray(CFArrayRef inCFArray, bool inRelease) : mCFArray(const_cast(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(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(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 + #include +#else + #include + #include +#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(inData), static_cast(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(inStartOffset), static_cast(inDataSize) }; CFDataGetBytes(mCFData, theRange, static_cast(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(theValue)); + theAnswer = true; + } + else if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID())) + { + SInt32 theNumericValue = 0; + CFNumberGetValue(static_cast(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(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(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(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(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(CFStringGetDoubleValue(static_cast(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(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(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(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(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(theValue), kCFNumberSInt64Type, &theFixed64); + outValue = static_cast(theFixed64 >> 32); + outValue += static_cast(theFixed64 & 0x00000000FFFFFFFFLL) / static_cast(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(theValue), kCFNumberSInt32Type, &outValue); + theAnswer = true; + } + else if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID())) + { + CFStringRef theString = static_cast(theValue); + if(CFStringGetLength(theString) == 4) + { + char theCString[5]; + CFStringGetCString(theString, theCString, 5, kCFStringEncodingASCII); + outValue = CFSwapInt32BigToHost(*reinterpret_cast(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(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(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(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(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(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(NULL); + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID())) + { + outValue = static_cast(theValue); + } + } +} + +void CACFDictionary::GetCACFArray(const CFStringRef inKey, CACFArray& outValue) const +{ + outValue = static_cast(NULL); + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFArrayGetTypeID())) + { + outValue = static_cast(theValue); + } + } +} + +void CACFDictionary::GetCACFDictionary(const CFStringRef inKey, CACFDictionary& outValue) const +{ + outValue = static_cast(NULL); + CFTypeRef theValue = NULL; + if(GetCFType(inKey, theValue)) + { + if((theValue != NULL) && (CFGetTypeID(theValue) == CFDictionaryGetTypeID())) + { + outValue = static_cast(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 +#else + #include +#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(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(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(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 +#include + +//================================================================================================== +// 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 +#include + +//================================================================================================== +// 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(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(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 +#else + #include +#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 + #include +#else + #include + #include +#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 + #include +#else + #include + #include +#endif + +//============================================================================= +// Wrappers for CFRetain and CFRelease that check for NULL +//============================================================================= + +template +CFObjectType CACFRetain(CFObjectType inObject) +{ + CFObjectType theAnswer = inObject; + if(inObject != NULL) + { + theAnswer = reinterpret_cast(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 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 CACFBundle; +typedef CACFObject CACFPropertyList; +typedef CACFObject CACFType; +typedef CACFObject CACFUUID; +typedef CACFObject 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 +#include + +//================================================================================================== +// 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(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(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(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(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 +#else + #include +#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(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(theStringRange.length) > ioStringSize) + { + theStringRange.length = static_cast(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 + #include +#else + #include + #include +#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 +#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(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(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(this)->mAUName = mstr; + } else + const_cast(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 +#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 + +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 +#else + #include + #include +#endif + +#include "CACFDictionary.h" +#include +#include + +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(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 +#include +#if TARGET_API_MAC_OSX + #include +#endif + +#if DEBUG +#include + +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 +#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 + #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 + #include + #include + 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 + 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 +#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 + #define DebugPrintfRtn syslog + #define DebugPrintfFile LOG_NOTICE + #define DebugPrintfLineEnding "" + #define DebugPrintfFileComma DebugPrintfFile, + #elif defined(CoreAudio_UseSideFile) + #include + #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 + #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 +#include +#include + +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 +#else + #include +#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 +#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 + +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include + #include +#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 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 + +#if !CA_NO_CORE_SERVICES +#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) + #include // FSRef + #include +#else + #include + #include +#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 + #include +#else + #include + #include + #include +#endif + +struct FSRef; + +OSStatus PosixPathToParentFSRefAndName(const char *path, FSRef &outParentDir, CFStringRef &outFileName); + +#if !TARGET_OS_WIN32 + #include +#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 +#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(inNanos / kNanosPerSecond); + theTimeSpec.tv_nsec = static_cast(inNanos % kNanosPerSecond); + } + else + { + theTimeSpec.tv_sec = 0; + theTimeSpec.tv_nsec = static_cast(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(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 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 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 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 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 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(theAnswer.mMinimum); + outMaximum = static_cast(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 theStreamUsage(theSize); + + // set it up + theStreamUsage->mIOProc = reinterpret_cast(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 theStreamUsage(theSize); + + // set it up + theStreamUsage->mIOProc = reinterpret_cast(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 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 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 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 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 + #include +#else + #include + #include +#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 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 void SetPropertyData_Struct(const AudioObjectPropertyAddress& inAddress, T& inStruct, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(T), &inStruct); } + + template UInt32 GetPropertyData_ArraySize(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { return GetPropertyDataSize(inAddress, inQualifierDataSize, inQualifierData) / SizeOf32(T); } + template 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 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 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 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 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 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(sToNanosDenominator) / static_cast(sToNanosNumerator); + sFrequency *= 1000000000.0; + #elif TARGET_OS_WIN32 + LARGE_INTEGER theFrequency; + QueryPerformanceFrequency(&theFrequency); + sMinDelta = 1; + sToNanosNumerator = 1000000000ULL; + sToNanosDenominator = *((UInt64*)&theFrequency); + sFrequency = static_cast(*((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 +#else + #include +#endif + +#if TARGET_OS_MAC + #include + #include +#elif TARGET_OS_WIN32 + #include + #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(inEndTime - inStartTime); + } + else + { + theAnswer = static_cast(inStartTime - inEndTime); + theSign = -1; + } + + return theSign * static_cast(ConvertToNanos(static_cast(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(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 + #include + + #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 +#else + #include +#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 +#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 +#else + #include +#endif + +#if TARGET_OS_MAC + #include +#elif TARGET_OS_WIN32 + #include +#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 +#endif + +// Standard Library Includes +#include + +//================================================================================================== +// 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(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(thePolicyInfo.ts.cur_priority); + } + return static_cast(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(thePolicyInfo.fifo.depress_priority); + } + return static_cast(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(thePolicyInfo.rr.depress_priority); + } + return static_cast(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(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=