summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfalkTX <falktx@gmail.com>2019-01-24 11:49:56 +0100
committerfalkTX <falktx@gmail.com>2019-01-24 11:49:56 +0100
commitf73640618c6b9dde4854b1f847f10fdcb5c5b52f (patch)
treea9e0b165cc512c3986b1cce3bdec521545066a35
parent9f8ff46e7ddef2224fcf432bc4dc410e4b3d003e (diff)
Add CoreAudio 10.6 files
Signed-off-by: falkTX <falktx@gmail.com>
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUBase.cpp2124
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUBase.h893
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUDispatch.cpp477
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUDispatch.h71
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUInputElement.cpp146
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUInputElement.h111
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp56
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUOutputElement.h60
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUResources.r134
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp506
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.h535
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/ComponentBase.cpp189
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/ComponentBase.h226
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp386
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h182
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp667
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h224
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp119
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp343
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h84
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp84
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h65
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp760
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h246
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h167
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp266
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h262
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h140
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp113
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h170
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp87
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h226
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h82
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp483
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUEffectBase.h269
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp481
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h207
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp158
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h83
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp105
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUOutputBase.h76
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp700
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUPannerBase.h263
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp343
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h123
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp128
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBaseHelper.h74
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBuffer.cpp203
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBuffer.h261
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUDebugDispatcher.cpp423
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUDebugDispatcher.h131
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h149
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUSilentTimeout.h87
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp185
-rwxr-xr-xdistrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h148
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/AUOutputBL.cpp163
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/AUOutputBL.h112
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/AUParamInfo.cpp133
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/AUParamInfo.h106
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAUMIDIMap.cpp194
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAUMIDIMap.h535
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAUMIDIMapManager.cpp227
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAUMIDIMapManager.h96
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAUParameter.cpp394
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAUParameter.h185
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAtomic.h288
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAtomicStack.h209
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAudioBufferList.cpp225
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAudioBufferList.h93
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayout.cpp142
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayout.h191
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayoutObject.cpp193
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAudioFileFormats.cpp415
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAudioFileFormats.h143
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAudioTimeStamp.cpp127
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAudioTimeStamp.h90
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAudioUnit.cpp1257
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAudioUnit.h417
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAudioUnitOutputCapturer.h137
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAudioValueRange.cpp244
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAudioValueRange.h114
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAutoDisposer.h502
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CABitOperations.h192
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CABool.h82
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CABufferList.cpp252
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CABufferList.h298
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CABundleLocker.cpp78
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CABundleLocker.h61
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAByteOrder.h155
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFArray.cpp788
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFArray.h186
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFData.h101
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFDictionary.cpp561
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFDictionary.h162
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFDistributedNotification.cpp100
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFDistributedNotification.h67
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFMachPort.cpp138
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFMachPort.h83
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFMessagePort.cpp129
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFMessagePort.h109
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFNumber.cpp77
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFNumber.h140
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFObject.h100
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFPlugIn.h95
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFPreferences.cpp281
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFPreferences.h86
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFString.cpp104
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CACFString.h163
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAComponent.cpp176
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAComponent.h115
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAComponentDescription.cpp104
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAComponentDescription.h135
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CADebugMacros.cpp82
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CADebugMacros.h448
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CADebugPrintf.cpp83
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CADebugPrintf.h107
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CADebugger.cpp71
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CADebugger.h50
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAException.h77
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAFilePathUtils.cpp180
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAFilePathUtils.h62
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAGuard.cpp333
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAGuard.h127
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAHALAudioDevice.cpp1151
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAHALAudioDevice.h219
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAHALAudioObject.cpp357
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAHALAudioObject.h131
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAHALAudioStream.cpp176
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAHALAudioStream.h88
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAHALAudioSystemObject.cpp146
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAHALAudioSystemObject.h83
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAHostTimeBase.cpp104
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAHostTimeBase.h225
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CALogMacros.h134
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAMath.h62
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAMixMap.h121
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAMutex.cpp320
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAMutex.h138
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAPThread.cpp375
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAPThread.h178
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAPersistence.cpp462
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAProcess.cpp79
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAProcess.h69
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAPropertyAddress.h161
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAReferenceCounted.h78
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CARingBuffer.cpp328
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CARingBuffer.h124
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CASettingsStorage.cpp686
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CASettingsStorage.h116
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CASharedLibrary.cpp112
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CASharedLibrary.h58
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CASpectralProcessor.cpp370
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CASpectralProcessor.h140
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAStreamBasicDescription.cpp573
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAStreamBasicDescription.h297
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAStreamRangedDescription.cpp70
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAStreamRangedDescription.h93
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAThreadSafeList.h250
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CATink.h140
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CATokenMap.h206
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAVectorUnit.cpp183
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAVectorUnit.h72
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAVectorUnitTypes.h52
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAVolumeCurve.cpp476
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAVolumeCurve.h172
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAXException.cpp43
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAXException.h330
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/MatrixMixerVolumes.cpp143
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/MatrixMixerVolumes.h65
169 files changed, 38907 insertions, 0 deletions
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUBase.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUBase.cpp
new file mode 100755
index 00000000..26ae4562
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUBase.cpp
@@ -0,0 +1,2124 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "AUBase.h"
+#include "AUDispatch.h"
+#include "AUInputElement.h"
+#include "AUOutputElement.h"
+#include <algorithm>
+#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,
+ UInt32 numPartElements) :
+ ComponentBase(inInstance),
+ mElementsCreated(false),
+ mInitialized(false),
+ mHasBegunInitializing(false),
+ mInitNumInputEls(numInputElements), mInitNumOutputEls(numOutputElements),
+#if !TARGET_OS_IPHONE
+ mInitNumGroupEls(numGroupElements), mInitNumPartEls(numPartElements),
+#endif
+ mRenderCallbacksTouched(false),
+ mRenderThreadID (NULL),
+ mWantsRenderThreadID (false),
+ mLastRenderedSampleTime(kNoLastRenderedSampleTime),
+ mLastRenderError(0),
+ mBuffersAllocated(false),
+ mLogString (NULL)
+ #if !TARGET_OS_IPHONE
+ ,
+ mContextName(NULL),
+ mDebugDispatcher (NULL)
+ #endif
+{
+ 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 (mAudioUnitAPIVersion > 1)
+ mParamList.reserve (24);
+
+#if !TARGET_OS_IPHONE
+ memset (&mHostCallbackInfo, 0, sizeof (mHostCallbackInfo));
+#endif
+
+
+ mCurrentPreset.presetNumber = -1;
+ mCurrentPreset.presetName = kUntitledString;
+ CFRetain (mCurrentPreset.presetName);
+}
+
+//_____________________________________________________________________________
+//
+AUBase::~AUBase()
+{
+ if (mCurrentPreset.presetName) CFRelease (mCurrentPreset.presetName);
+#if !TARGET_OS_IPHONE
+ if (mContextName) CFRelease (mContextName);
+#endif
+ if (mLogString) delete [] mLogString;
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::CreateElements()
+{
+ if (!mElementsCreated) {
+ Inputs().Initialize(this, kAudioUnitScope_Input, mInitNumInputEls);
+ Outputs().Initialize(this, kAudioUnitScope_Output, mInitNumOutputEls);
+#if !TARGET_OS_IPHONE
+ Groups().Initialize(this, kAudioUnitScope_Group, mInitNumGroupEls);
+ Parts().Initialize(this, kAudioUnitScope_Part, mInitNumPartEls);
+#endif
+ 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();
+
+ int i;
+ int nOutputs = Outputs().GetNumberOfElements();
+ for (i = 0; i < nOutputs; ++i) {
+ AUOutputElement *output = GetOutput(i);
+ output->AllocateBuffer(); // does no work if already allocated
+ }
+ int nInputs = Inputs().GetNumberOfElements();
+ for (i = 0; i < nInputs; ++i) {
+ AUInputElement *input = GetInput(i);
+ input->AllocateBuffer(); // does no work if already allocated
+ }
+ mBuffersAllocated = true;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DoInitialize()
+{
+ OSStatus result = noErr;
+
+ if (!mInitialized) {
+ result = Initialize();
+ if (result == noErr) {
+ mHasBegunInitializing = true;
+ ReallocateBuffers(); // calls CreateElements()
+ mInitialized = true; // signal that it's okay to render
+#if TARGET_OS_WIN32
+ MemoryBarrier();
+#else
+ OSMemoryBarrier();
+#endif
+ }
+ }
+
+ return result;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::Initialize()
+{
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::PreDestructor()
+{
+ DoCleanup();
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::DoCleanup()
+{
+ if (mInitialized)
+ Cleanup();
+ mInitialized = false;
+ mHasBegunInitializing = false;
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::Cleanup()
+{
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ mLastRenderedSampleTime = kNoLastRenderedSampleTime;
+ 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 !TARGET_OS_IPHONE
+#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_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_AU_IS_ONLY_PLUGIN
+ case kAudioUnitProperty_FastDispatch:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(void *);
+ outWritable = false;
+ validateElement = false;
+ break;
+#endif
+
+#if !TARGET_OS_IPHONE
+ case kAudioUnitProperty_ContextName:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(CFStringRef);
+ outWritable = true;
+ break;
+
+ case kAudioUnitProperty_GetUIComponentList:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = GetNumCustomUIComponents();
+ if (outDataSize == 0)
+ goto InvalidProperty;
+ outDataSize *= sizeof (AudioComponentDescription);
+
+ outWritable = false;
+ break;
+
+ case kAudioUnitProperty_ParameterValueStrings:
+ result = GetParameterValueStrings(inScope, inElement, NULL);
+ if (result == noErr) {
+ outDataSize = sizeof(CFArrayRef);
+ outWritable = false;
+ validateElement = false;
+ }
+ break;
+
+ case kAudioUnitProperty_HostCallbacks:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof (HostCallbackInfo);
+ 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 // !TARGET_OS_IPHONE
+
+ case 'lrst' : // kAudioUnitProperty_LastRenderedSampleTime
+ outDataSize = sizeof(Float64);
+ outWritable = false;
+ 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_ClassInfo:
+ {
+ *(CFPropertyListRef *)outData = NULL;
+ result = SaveState((CFPropertyListRef *)outData);
+ }
+ break;
+
+ case kAudioUnitProperty_FactoryPresets:
+ {
+ *(CFArrayRef *)outData = NULL;
+ result = GetPresets ((CFArrayRef *)outData);
+ }
+ break;
+
+ case kAudioUnitProperty_PresentPreset:
+#if !TARGET_OS_IPHONE
+#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;
+ UInt32 num = SupportedNumChannels (&infoPtr);
+ memcpy (outData, infoPtr, num * sizeof (AUChannelInfo));
+ }
+ break;
+
+ case kAudioUnitProperty_SupportedChannelLayoutTags:
+ {
+ AudioChannelLayoutTag* ptr = outData ? static_cast<AudioChannelLayoutTag*>(outData) : NULL;
+ UInt32 numLayouts = GetChannelLayoutTags (inScope, inElement, ptr);
+ if (numLayouts == 0)
+ result = kAudioUnitErr_InvalidProperty;
+ }
+ break;
+
+ case kAudioUnitProperty_AudioChannelLayout:
+ {
+ AudioChannelLayout* ptr = outData ? static_cast<AudioChannelLayout*>(outData) : NULL;
+ Boolean writable;
+ UInt32 dataSize = GetAudioChannelLayout(inScope, inElement, ptr, writable);
+ if (!dataSize) {
+ result = kAudioUnitErr_InvalidProperty;
+ }
+ break;
+ }
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE
+ case kAudioUnitProperty_ShouldAllocateBuffer:
+ {
+ AUIOElement * element = GetIOElement(inScope, inElement);
+ *(UInt32*)outData = element->WillAllocateBuffer();
+ break;
+ }
+#endif
+
+
+#if !CA_AU_IS_ONLY_PLUGIN
+ case kAudioUnitProperty_FastDispatch:
+ switch (inElement) {
+ case kAudioUnitGetParameterSelect:
+ *(AudioUnitGetParameterProc *)outData = (AudioUnitGetParameterProc)AudioUnitBaseGetParameter;
+ break;
+ case kAudioUnitSetParameterSelect:
+ *(AudioUnitSetParameterProc *)outData = (AudioUnitSetParameterProc)AudioUnitBaseSetParameter;
+ break;
+ case kAudioUnitRenderSelect:
+ if (AudioUnitAPIVersion() > 1)
+ *(AudioUnitRenderProc *)outData = (AudioUnitRenderProc)AudioUnitBaseRender;
+ else result = kAudioUnitErr_InvalidElement;
+ break;
+ default:
+ result = GetProperty(inID, inScope, inElement, outData);
+ break;
+ }
+ break;
+#endif
+
+#if !TARGET_OS_IPHONE
+ case kAudioUnitProperty_ParameterValueStrings:
+ result = GetParameterValueStrings(inScope, inElement, (CFArrayRef *)outData);
+ break;
+
+ case kAudioUnitProperty_IconLocation:
+ {
+ CFURLRef iconLocation = CopyIconLocation();
+ if (iconLocation) {
+ *(CFURLRef*)outData = iconLocation;
+ } else
+ result = kAudioUnitErr_InvalidProperty;
+ }
+ break;
+
+ case kAudioUnitProperty_HostCallbacks:
+ *(HostCallbackInfo *)outData = mHostCallbackInfo;
+ break;
+
+ case kAudioUnitProperty_GetUIComponentList:
+ GetUIComponentDescs ((ComponentDescription*)outData);
+ 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 // !TARGET_OS_IPHONE
+
+ case 'lrst' : // kAudioUnitProperty_LastRenderedSampleTime
+ *(Float64*)outData = mLastRenderedSampleTime;
+ break;
+
+ default:
+ result = GetProperty(inID, inScope, inElement, outData);
+ break;
+ }
+ return result;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DispatchSetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ OSStatus result = noErr;
+
+ switch (inID) {
+ case kAudioUnitProperty_MakeConnection:
+ ca_require(inDataSize >= sizeof(AudioUnitConnection), InvalidPropertyValue);
+ {
+ AudioUnitConnection &connection = *(AudioUnitConnection *)inData;
+ result = SetConnection(connection);
+ }
+ break;
+
+
+ case kAudioUnitProperty_SetRenderCallback:
+ {
+ ca_require(inDataSize >= sizeof(AURenderCallbackStruct), InvalidPropertyValue);
+ ca_require(AudioUnitAPIVersion() > 1, InvalidProperty);
+ AURenderCallbackStruct &callback = *(AURenderCallbackStruct*)inData;
+ result = SetInputCallback(kAudioUnitProperty_SetRenderCallback, inElement, callback.inputProc, callback.inputProcRefCon);
+ }
+ break;
+
+ case kAudioUnitProperty_ElementCount:
+ ca_require(inDataSize == sizeof(UInt32), InvalidPropertyValue);
+ ca_require(BusCountWritable(inScope), NotWritable);
+ result = SetBusCount(inScope, *(UInt32*)inData);
+ if (result == noErr) {
+ PropertyChanged(inID, inScope, inElement);
+ }
+ break;
+
+ case kAudioUnitProperty_MaximumFramesPerSlice:
+ ca_require(inDataSize == sizeof(UInt32), InvalidPropertyValue);
+ result = CanSetMaxFrames();
+ if (result) return result;
+ SetMaxFramesPerSlice(*(UInt32 *)inData);
+ break;
+
+ case kAudioUnitProperty_StreamFormat:
+ {
+ if (inDataSize < 36) goto InvalidPropertyValue;
+ ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+
+ CAStreamBasicDescription newDesc;
+ // now we're going to be ultra conservative! because of discrepancies between
+ // sizes of this struct based on aligment padding inconsistencies
+ memset (&newDesc, 0, sizeof(newDesc));
+ memcpy (&newDesc, inData, 36);
+
+ ca_require(ValidFormat(inScope, inElement, newDesc), InvalidFormat);
+
+ const CAStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement);
+
+ if ( !curDesc.IsEqual(newDesc, false) ) {
+ ca_require(IsStreamFormatWritable(inScope, inElement), NotWritable);
+ result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc);
+ }
+ }
+ break;
+
+ case kAudioUnitProperty_SampleRate:
+ {
+ ca_require(inDataSize == sizeof(Float64), InvalidPropertyValue);
+ ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+
+ const CAStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement);
+ CAStreamBasicDescription newDesc = curDesc;
+ newDesc.mSampleRate = *(Float64 *)inData;
+
+ ca_require(ValidFormat(inScope, inElement, newDesc), InvalidFormat);
+
+ if ( !curDesc.IsEqual(newDesc, false) ) {
+ ca_require(IsStreamFormatWritable(inScope, inElement), NotWritable);
+ result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc);
+ }
+ }
+ break;
+
+ case kAudioUnitProperty_AudioChannelLayout:
+ {
+ const AudioChannelLayout *layout = static_cast<const AudioChannelLayout *>(inData);
+ ca_require(inDataSize >= offsetof(AudioChannelLayout, mChannelDescriptions) + 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 !TARGET_OS_IPHONE
+#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)
+ {
+ CFRelease (mCurrentPreset.presetName);
+ mCurrentPreset = newPreset;
+ CFRetain (mCurrentPreset.presetName);
+ 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 !TARGET_OS_IPHONE
+ case kAudioUnitProperty_SetExternalBuffer:
+ ca_require(inDataSize >= sizeof(AudioUnitExternalBuffer), InvalidPropertyValue);
+ ca_require(IsInitialized(), Uninitialized);
+ {
+ AudioUnitExternalBuffer &buf = *(AudioUnitExternalBuffer*)inData;
+ if (intptr_t(buf.buffer) & 0x0F) result = paramErr;
+ 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;
+
+ case kAudioUnitProperty_HostCallbacks:
+ {
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ UInt32 availSize = (inDataSize < sizeof (mHostCallbackInfo) ? inDataSize : sizeof (mHostCallbackInfo));
+ bool hasChanged = !memcmp (&mHostCallbackInfo, inData, availSize);
+ memset (&mHostCallbackInfo, 0, sizeof (mHostCallbackInfo));
+ memcpy (&mHostCallbackInfo, inData, availSize);
+ if (hasChanged)
+ PropertyChanged(inID, inScope, inElement);
+ break;
+ }
+#endif // !TARGET_OS_IPHONE
+
+ 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 !TARGET_OS_IPHONE
+Uninitialized:
+ return kAudioUnitErr_Uninitialized;
+#endif
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE
+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 !TARGET_OS_IPHONE
+ case kAudioUnitProperty_ContextName:
+ if (mContextName) CFRelease(mContextName);
+ mContextName = NULL;
+ result = noErr;
+ break;
+
+ case kAudioUnitProperty_HostCallbacks:
+ {
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ bool hasValue = false;
+ void* ptr = &mHostCallbackInfo;
+ for (unsigned int i = 0; i < sizeof (HostCallbackInfo); ++i) {
+ if (static_cast<char*>(ptr)[i]) {
+ hasValue = true;
+ break;
+ }
+ }
+ if (hasValue) {
+ memset (&mHostCallbackInfo, 0, sizeof (HostCallbackInfo));
+ PropertyChanged(inID, inScope, inElement);
+ }
+ break;
+ }
+#endif // !TARGET_OS_IPHONE
+
+ default:
+ result = RemovePropertyValue (inID, inScope, inElement);
+ break;
+ }
+
+ return result;
+#if !TARGET_OS_IPHONE
+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 = 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 paramErr;
+
+ 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)
+{
+#if !TARGET_OS_IPHONE
+ if (inScope == kAudioUnitScope_Group) {
+ return GetGroupParameter (inID, inElement, outValue);
+ }
+#endif
+
+ AUElement *elem = SafeGetElement(inScope, inElement);
+ outValue = elem->GetParameter(inID);
+ return noErr;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::SetParameter( AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioUnitParameterValue inValue,
+ UInt32 inBufferOffsetInFrames)
+{
+#if !TARGET_OS_IPHONE
+ if (inScope == kAudioUnitScope_Group) {
+ return SetGroupParameter (inID, inElement, inValue, inBufferOffsetInFrames);
+ }
+#endif
+
+ AUElement *elem = SafeGetElement(inScope, inElement);
+ elem->SetParameter(inID, inValue);
+ return noErr;
+}
+
+#if !TARGET_OS_IPHONE
+//_____________________________________________________________________________
+//
+OSStatus AUBase::SetGroupParameter( AudioUnitParameterID inID,
+ AudioUnitElement inElement,
+ AudioUnitParameterValue inValue,
+ UInt32 inBufferOffsetInFrames)
+{
+ return kAudioUnitErr_InvalidScope;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::GetGroupParameter( AudioUnitParameterID inID,
+ AudioUnitElement inElement,
+ AudioUnitParameterValue & outValue)
+{
+ return kAudioUnitErr_InvalidScope;
+}
+#endif
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::ScheduleParameter ( const AudioUnitParameterEvent *inParameterEvent,
+ UInt32 inNumEvents)
+{
+ 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);
+ }
+ 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;
+
+ CATRACE(kCATrace_AUBaseRenderStart, (int)this, inBusNumber, inFramesToProcess, 0);
+ DISABLE_DENORMALS
+
+ try {
+ ca_require(IsInitialized(), Uninitialized);
+ ca_require(mAudioUnitAPIVersion >= 2, ParamErr);
+ ca_require(inFramesToProcess <= mMaxFramesPerSlice, TooManyFrames);
+
+ 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; paramErr",
+ __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. paramErr.
+ DebugMessageN7("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; ioData.mBuffers[%u].mDataByteSize=%u; paramErr",
+ __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;
+ CATRACE(kCATrace_AUBaseRenderCallbackStart, (int)this, (int)rc.mRenderNotify, 1, 0);
+ (*(AURenderCallback)rc.mRenderNotify)(rc.mRenderNotifyRefCon,
+ &flags,
+ &inTimeStamp, inBusNumber, inFramesToProcess, &ioData);
+ CATRACE(kCATrace_AUBaseRenderCallbackEnd, (int)this, (int)rc.mRenderNotify, 1, 0);
+ }
+ }
+
+ theError = DoRenderBus(ioActionFlags, inTimeStamp, inBusNumber, output, inFramesToProcess, ioData);
+
+ flags = ioActionFlags | kAudioUnitRenderAction_PostRender;
+
+ if (SetRenderError (theError)) {
+ flags |= kAudioUnitRenderAction_PostRenderError;
+ }
+
+ if (mRenderCallbacksTouched) {
+ for (rcit = mRenderCallbacks.begin(); rcit != mRenderCallbacks.end(); ++rcit) {
+ RenderCallback &rc = *rcit;
+ CATRACE(kCATrace_AUBaseRenderCallbackStart, (int)this, (int)rc.mRenderNotify, 2, 0);
+ (*(AURenderCallback)rc.mRenderNotify)(rc.mRenderNotifyRefCon,
+ &flags,
+ &inTimeStamp, inBusNumber, inFramesToProcess, &ioData);
+ CATRACE(kCATrace_AUBaseRenderCallbackEnd, (int)this, (int)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
+ CATRACE(kCATrace_AUBaseRenderEnd, (int)this, theError, 0, 0);
+
+ return theError;
+
+Uninitialized: theError = kAudioUnitErr_Uninitialized; goto errexit;
+ParamErr: theError = paramErr; goto errexit;
+TooManyFrames: theError = kAudioUnitErr_TooManyFramesToProcess; goto errexit;
+errexit:
+ DebugMessageN2 (" from %s, render 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);
+ AudioUnitElement nElems = scope.GetNumberOfElements();
+ for (AudioUnitElement ielem = 0; ielem < nElems; ++ielem) {
+ AUElement *element = scope.GetElement(ielem);
+ UInt32 nparams = element->GetNumberOfParameters();
+ if (nparams > 0) {
+ struct {
+ UInt32 scope;
+ UInt32 element;
+ } hdr;
+
+ hdr.scope = CFSwapInt32HostToBig(iscope);
+ hdr.element = CFSwapInt32HostToBig(ielem);
+ CFDataAppendBytes(data, (UInt8 *)&hdr, sizeof(hdr));
+
+ element->SaveState(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);
+ }
+
+#if !TARGET_OS_IPHONE
+// Does the unit support the CPULoad Quality property - if so, save it...
+ Float32 cpuLoad;
+ result = DispatchGetProperty (kAudioUnitProperty_CPULoad,
+ kAudioUnitScope_Global,
+ 0,
+ &cpuLoad);
+
+ if (result == noErr) {
+ CFNumberRef num = CFNumberCreate (NULL, kCFNumberFloatType, &cpuLoad);
+ CFDictionarySetValue (dict, kCPULoadString, num);
+ CFRelease (num);
+ }
+#endif
+
+// Do we have any element names for any of our scopes?
+ // first check to see if we have any names...
+ bool foundName = false;
+ for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
+ foundName = GetScope (i).HasElementWithName();
+ if (foundName)
+ break;
+ }
+ // OK - we found a name away we go...
+ if (foundName) {
+ CFMutableDictionaryRef nameDict = CFDictionaryCreateMutable (NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
+ GetScope (i).AddElementNamesToDict (nameDict);
+ }
+
+ CFDictionarySetValue (dict, kElementNameString, nameDict);
+ CFRelease (nameDict);
+ }
+
+// we're done!!!
+ *outData = dict;
+
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::RestoreState( CFPropertyListRef plist)
+{
+ if (CFGetTypeID(plist) != CFDictionaryGetTypeID()) return kAudioUnitErr_InvalidPropertyValue;
+
+ AudioComponentDescription desc = GetComponentDescription();
+
+ CFDictionaryRef dict = static_cast<CFDictionaryRef>(plist);
+
+// zeroeth step - make sure the Part key is NOT present, as this method is used
+// to restore the GLOBAL state of the dictionary
+ if (CFDictionaryContainsKey (dict, kPartString))
+ return kAudioUnitErr_InvalidPropertyValue;
+
+// first step -> check the saved version in the data ref
+// at this point we're only dealing with version==0
+ CFNumberRef cfnum = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue (dict, kVersionString));
+ if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue;
+ SInt32 value;
+ CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+ if (value != kCurrentSavedStateVersion) return kAudioUnitErr_InvalidPropertyValue;
+
+// second step -> check that this data belongs to this kind of audio unit
+// by checking the component subtype and manuID
+// We're not checking the type, since there may be different versions (effect, format-converter, offline)
+// of essentially the same AU
+ cfnum = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue (dict, kSubtypeString));
+ if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue;
+ CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+ if (UInt32(value) != desc.componentSubType) return kAudioUnitErr_InvalidPropertyValue;
+
+ cfnum = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue (dict, kManufacturerString));
+ if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue;
+ CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+ if (UInt32(value) != desc.componentManufacturer) return kAudioUnitErr_InvalidPropertyValue;
+
+// fourth step -> restore the state of all of the parameters for each scope and element
+ CFDataRef data = reinterpret_cast<CFDataRef>(CFDictionaryGetValue (dict, kDataString));
+ if (data != NULL)
+ {
+ const UInt8 *p, *pend;
+
+ p = CFDataGetBytePtr(data);
+ pend = p + CFDataGetLength(data);
+
+ // we have a zero length data, which may just mean there were no parameters to save!
+ // if (p >= pend) return noErr;
+
+ while (p < pend) {
+ struct {
+ UInt32 scope;
+ UInt32 element;
+ } hdr;
+
+ hdr.scope = CFSwapInt32BigToHost(*(UInt32 *)p); p += sizeof(UInt32);
+ hdr.element = CFSwapInt32BigToHost(*(UInt32 *)p); p += sizeof(UInt32);
+
+ AUScope &scope = GetScope(hdr.scope);
+ AUElement *element = scope.GetElement(hdr.element);
+ // $$$ order of operations issue: what if the element does not yet exist?
+ // then we just break out of the loop
+ if (!element)
+ break;
+ p = element->RestoreState(p);
+ }
+ }
+
+//OK - now we're going to do some properties
+//restore the preset name...
+ CFStringRef name = reinterpret_cast<CFStringRef>(CFDictionaryGetValue (dict, kNameString));
+ if (mCurrentPreset.presetName) CFRelease (mCurrentPreset.presetName);
+ if (name)
+ {
+ mCurrentPreset.presetName = name;
+ mCurrentPreset.presetNumber = -1;
+ }
+ else { // no name entry make the default one
+ mCurrentPreset.presetName = kUntitledString;
+ mCurrentPreset.presetNumber = -1;
+ }
+
+ CFRetain (mCurrentPreset.presetName);
+#if !TARGET_OS_IPHONE
+#ifndef __LP64__
+ PropertyChanged(kAudioUnitProperty_CurrentPreset, kAudioUnitScope_Global, 0);
+#endif
+#endif
+ PropertyChanged(kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global, 0);
+
+// Does the dict contain render quality information?
+ if (CFDictionaryGetValueIfPresent (dict, kRenderQualityString, reinterpret_cast<const void**>(&cfnum)))
+ {
+ CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+ DispatchSetProperty (kAudioUnitProperty_RenderQuality,
+ kAudioUnitScope_Global,
+ 0,
+ &value,
+ sizeof(value));
+ }
+
+#if !TARGET_OS_IPHONE
+// Does the unit support the CPULoad Quality property - if so, save it...
+ if (CFDictionaryGetValueIfPresent (dict, kCPULoadString, reinterpret_cast<const void**>(&cfnum)))
+ {
+ Float32 floatValue;
+ CFNumberGetValue (cfnum, kCFNumberFloatType, &floatValue);
+ DispatchSetProperty (kAudioUnitProperty_CPULoad,
+ kAudioUnitScope_Global,
+ 0,
+ &floatValue,
+ sizeof(floatValue));
+ }
+#endif
+
+// Do we have any element names for any of our scopes?
+ CFDictionaryRef nameDict;
+ if (CFDictionaryGetValueIfPresent (dict, kElementNameString, reinterpret_cast<const void**>(&nameDict)))
+ {
+ char string[64];
+ for (int i = 0; i < kNumScopes; ++i)
+ {
+ sprintf (string, "%d", i);
+ CFStringRef key = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
+ CFDictionaryRef elementDict;
+ if (CFDictionaryGetValueIfPresent (nameDict, key, reinterpret_cast<const void**>(&elementDict)))
+ {
+ bool didAddElements = GetScope (i).RestoreElementNames (elementDict);
+ if (didAddElements)
+ PropertyChanged (kAudioUnitProperty_ElementCount, i, 0);
+ }
+ CFRelease (key);
+ }
+ }
+
+ return noErr;
+}
+
+OSStatus AUBase::GetPresets ( CFArrayRef * outData) const
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+OSStatus AUBase::NewFactoryPresetSet (const AUPreset & inNewFactoryPreset)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+ // 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;
+}
+
+int AUBase::GetNumCustomUIComponents ()
+{
+ return 0;
+}
+
+#if !TARGET_OS_IPHONE
+void AUBase::GetUIComponentDescs (ComponentDescription* inDescArray) {}
+#endif
+
+bool AUBase::HasIcon ()
+{
+ CFURLRef url = CopyIconLocation();
+ if (url) {
+ CFRelease (url);
+ return true;
+ }
+ 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::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 AUGlobalElement(this);
+ case kAudioUnitScope_Input:
+ return new AUInputElement(this);
+ case kAudioUnitScope_Output:
+ return new AUOutputElement(this);
+#if !TARGET_OS_IPHONE
+ case kAudioUnitScope_Group:
+ return new AUGroupElement(this);
+ case kAudioUnitScope_Part:
+ return new AUPartElement(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.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_cast<AUBase*>(this)->mLogString = new char[256];
+ char str[24];
+ char str1[24];
+ char str2[24];
+ sprintf (const_cast<AUBase*>(this)->mLogString, "AU (%p): %s %s %s",
+ GetComponentInstance(),
+ CAStringForOSType(desc.componentType, str),
+ CAStringForOSType(desc.componentSubType, str1),
+ CAStringForOSType(desc.componentManufacturer, str2));
+
+ return mLogString;
+}
+
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUBase.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUBase.h
new file mode 100755
index 00000000..18e0981e
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUBase.h
@@ -0,0 +1,893 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __AUBase_h__
+#define __AUBase_h__
+
+#include <TargetConditionals.h>
+
+#if TARGET_OS_MAC
+ #include <pthread.h>
+#elif TARGET_OS_WIN32
+ #include <windows.h>
+#else
+ #error Unsupported Operating System
+#endif
+
+#include <vector>
+
+#include "ComponentBase.h"
+#include "AUScopeElement.h"
+#include "AUInputElement.h"
+#include "AUOutputElement.h"
+#include "AUBuffer.h"
+#include "CAMath.h"
+#include "CAThreadSafeList.h"
+#include "CAVectorUnit.h"
+
+#if 0 && DEBUG
+ #include "CATrace.h"
+#else
+ #define CATRACE(code, a, b, c, d)
+#endif
+
+typedef AUElement AUGlobalElement;
+#if !TARGET_OS_IPHONE
+ typedef AUElement AUGroupElement;
+ typedef AUElement AUPartElement;
+#endif
+
+
+
+// ________________________________________________________________________
+// 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 AUDebugDispatcher;
+
+// ________________________________________________________________________
+
+/*! @class AUBase */
+class AUBase : public ComponentBase, public AUElementCreator {
+public:
+
+ /*! @ctor AUBase */
+ AUBase( AudioComponentInstance inInstance,
+ UInt32 numInputElements,
+ UInt32 numOutputElements,
+ UInt32 numGroupElements = 0,
+ UInt32 numPartElements = 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.
+
+ // ________________________________________________________________________
+ // 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);
+
+#if !TARGET_OS_IPHONE
+ /*! @method SetGroupParameter */
+ virtual OSStatus SetGroupParameter( AudioUnitParameterID inID,
+ AudioUnitElement inElement,
+ AudioUnitParameterValue inValue,
+ UInt32 inBufferOffsetInFrames);
+
+ /*! @method GetGroupParameter */
+ virtual OSStatus GetGroupParameter( AudioUnitParameterID inID,
+ AudioUnitElement inElement,
+ AudioUnitParameterValue & outValue);
+#endif
+
+ /*! @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);
+
+
+ // 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.mSampleTime))
+ 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;
+ }
+
+
+ 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);
+
+ /*! @method SaveState */
+ virtual OSStatus SaveState( CFPropertyListRef * 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 GetNumCustomUIComponents */
+ virtual int GetNumCustomUIComponents ();
+#if !TARGET_OS_IPHONE
+ /*! @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 !TARGET_OS_IPHONE
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch( ComponentParameters * params,
+ AUBase * This);
+#endif
+
+ // ________________________________________________________________________
+ // Methods useful for subclasses
+
+ /*! @method GetScope */
+ AUScope & GetScope( AudioUnitScope inScope)
+ {
+ if (inScope >= kNumScopes) COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+ return mScopes[inScope];
+ }
+
+ /*! @method GlobalScope */
+ AUScope & GlobalScope() { return mScopes[kAudioUnitScope_Global]; }
+ /*! @method Inputs */
+ AUScope & Inputs() { return mScopes[kAudioUnitScope_Input]; }
+ /*! @method Outputs */
+ AUScope & Outputs() { return mScopes[kAudioUnitScope_Output]; }
+ /*! @method Groups */
+#if !TARGET_OS_IPHONE
+ AUScope & Groups() { return mScopes[kAudioUnitScope_Group]; }
+ /*! @method Parts */
+ AUScope & Parts() { return mScopes[kAudioUnitScope_Part]; }
+#endif
+ /*! @method Globals */
+ AUElement * Globals() { return mScopes[kAudioUnitScope_Global].GetElement(0); }
+
+ /*! @method SetNumberOfElements */
+ void SetNumberOfElements( AudioUnitScope inScope,
+ UInt32 numElements);
+
+ /*! @method GetElement */
+ AUElement * GetElement( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+ {
+ return GetScope(inScope).GetElement(inElement);
+ }
+
+ /*! @method GetIOElement */
+ AUIOElement * GetIOElement( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+ {
+ return GetScope(inScope).GetIOElement(inElement);
+ }
+
+ /*! @method SafeGetElement */
+ AUElement * SafeGetElement( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+ {
+ return GetScope(inScope).SafeGetElement(inElement);
+ }
+
+ /*! @method GetInput */
+ AUInputElement * GetInput( AudioUnitElement inElement)
+ {
+ return static_cast<AUInputElement *>(Inputs().SafeGetElement(inElement));
+ }
+
+ /*! @method GetOutput */
+ AUOutputElement * GetOutput( AudioUnitElement inElement)
+ {
+ return static_cast<AUOutputElement *>(Outputs().SafeGetElement(inElement));
+ }
+
+#if !TARGET_OS_IPHONE
+ /*! @method GetGroup */
+ AUGroupElement * GetGroup( AudioUnitElement inElement)
+ {
+ return static_cast<AUGroupElement *>(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 GetVectorUnitType */
+ static SInt32 GetVectorUnitType() { return sVectorUnitType; }
+ /*! @method HasVectorUnit */
+ static bool HasVectorUnit() { return sVectorUnitType > 0; }
+ /*! @method HasAltivec */
+ static bool HasAltivec() { return sVectorUnitType == kVecAltivec; }
+ /*! @method HasSSE2 */
+ static bool HasSSE2() { return sVectorUnitType >= kVecSSE2; }
+ /*! @method HasSSE3 */
+ static bool HasSSE3() { return sVectorUnitType == kVecSSE3; }
+
+ /*! @method AudioUnitAPIVersion */
+ UInt8 AudioUnitAPIVersion() const { return mAudioUnitAPIVersion; }
+
+ /*! @method IsRenderThread */
+ bool InRenderThread () const
+ {
+#if TARGET_OS_MAC
+ return (mRenderThreadID ? pthread_equal (mRenderThreadID, pthread_self()) : false);
+#elif TARGET_OS_WIN32
+ return (mRenderThreadID ? mRenderThreadID == GetCurrentThreadId() : false);
+#endif
+ }
+
+ /*! @method HasInput */
+ bool HasInput( AudioUnitElement inElement) {
+ AUInputElement *in = static_cast<AUInputElement *>(Inputs().GetElement(inElement));
+ return in != NULL && in->IsActive();
+ }
+ // says whether an input is connected or has a callback
+
+ /*! @method PropertyChanged */
+ void PropertyChanged( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+#if !TARGET_OS_IPHONE
+ // 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;
+
+protected:
+ // ________________________________________________________________________
+ // AUElementCreator override, may be further overridden by subclasses
+ /*! @method CreateElement */
+ virtual AUElement * CreateElement( AudioUnitScope scope,
+ AudioUnitElement element);
+
+ /*! @method ReallocateBuffers */
+ virtual void ReallocateBuffers();
+ // needs to be called when mMaxFramesPerSlice changes
+
+ /*! @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);
+ CATRACE(kCATrace_AUBaseDoRenderBus, inNumberFrames, (int)theOutput->GetBufferList().mBuffers[0].mData, 0, *(UInt32 *)ioData.mBuffers[0].mData);
+ } else {
+ theOutput->CopyBufferContentsTo(ioData);
+ CATRACE(kCATrace_AUBaseDoRenderBus, inNumberFrames, (int)theOutput->GetBufferList().mBuffers[0].mData, (int)ioData.mBuffers[0].mData, *(UInt32 *)ioData.mBuffers[0].mData);
+ theOutput->InvalidateBufferList();
+ }
+ }
+ return result;
+ }
+
+ /*! @method HasIcon */
+ bool HasIcon ();
+
+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( Float64 inSampleTime)
+ {
+ bool needsToRender = fnotequal(inSampleTime, mLastRenderedSampleTime);
+ mLastRenderedSampleTime = inSampleTime;
+ return needsToRender;
+ }
+
+ // Scheduled parameter implementation:
+
+ typedef std::vector<AudioUnitParameterEvent> ParameterEventList;
+
+ // Usually, you won't override this method. You only need to call this if your DSP code
+ // is prepared to handle scheduled immediate and ramped parameter changes.
+ // Before calling this method, it is assumed you have already called PullInput() on the input busses
+ // for which the DSP code depends. ProcessForScheduledParams() will call (potentially repeatedly)
+ // virtual method ProcessScheduledSlice() to perform the actual DSP for a given sub-division of
+ // the buffer. The job of ProcessForScheduledParams() is to sub-divide the buffer into smaller
+ // pieces according to the scheduled times found in the ParameterEventList (usually coming
+ // directly from a previous call to ScheduleParameter() ), setting the appropriate immediate or
+ // ramped parameter values for the corresponding scopes and elements, then calling ProcessScheduledSlice()
+ // to do the actual DSP for each of these divisions.
+ virtual OSStatus ProcessForScheduledParams( ParameterEventList &inParamList,
+ UInt32 inFramesToProcess,
+ void *inUserData );
+
+ // This method is called (potentially repeatedly) by ProcessForScheduledParams()
+ // in order to perform the actual DSP required for this portion of the entire buffer
+ // being processed. The entire buffer can be divided up into smaller "slices"
+ // according to the timestamps on the scheduled parameters...
+ //
+ // sub-classes wishing to handle scheduled parameter changes should override this method
+ // in order to do the appropriate DSP. AUEffectBase already overrides this for standard
+ // effect AudioUnits.
+ virtual OSStatus ProcessScheduledSlice( void *inUserData,
+ UInt32 inStartFrameInBuffer,
+ UInt32 inSliceFramesToProcess,
+ UInt32 inTotalBufferFrames ) {return noErr;}; // default impl does nothing...
+
+ // ________________________________________________________________________
+ // Private data members to discourage hacking in subclasses
+private:
+ struct RenderCallback {
+ RenderCallback(AURenderCallback proc, void *ref) :
+ mRenderNotify(proc),
+ mRenderNotifyRefCon(ref)
+ { }
+
+ AURenderCallback mRenderNotify;
+ void * mRenderNotifyRefCon;
+
+ bool operator == (const RenderCallback &other) {
+ return this->mRenderNotify == other.mRenderNotify &&
+ this->mRenderNotifyRefCon == other.mRenderNotifyRefCon;
+ }
+ };
+ typedef TThreadSafeList<RenderCallback> RenderCallbackList;
+
+#if TARGET_OS_IPHONE
+ enum { kNumScopes = 3 };
+#else
+ enum { kNumScopes = 5 };
+#endif
+
+ /*! @var mElementsCreated */
+ bool mElementsCreated;
+protected:
+ /*! @var mInitialized */
+ bool mInitialized;
+ /*! @var mHasBegunInitializing */
+ bool mHasBegunInitializing;
+private:
+ /*! @var mAudioUnitAPIVersion */
+ UInt8 mAudioUnitAPIVersion;
+
+ /*! @var mInitNumInputEls */
+ UInt32 mInitNumInputEls;
+ /*! @var mInitNumOutputEls */
+ UInt32 mInitNumOutputEls;
+#if !TARGET_OS_IPHONE
+ /*! @var mInitNumGroupEls */
+ UInt32 mInitNumGroupEls;
+ /*! @var mInitNumPartEls */
+ UInt32 mInitNumPartEls;
+#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 mLastRenderedSampleTime */
+ Float64 mLastRenderedSampleTime;
+
+ /*! @var mMaxFramesPerSlice */
+ UInt32 mMaxFramesPerSlice;
+
+ /*! @var mLastRenderError */
+ OSStatus mLastRenderError;
+ /*! @var mCurrentPreset */
+ AUPreset mCurrentPreset;
+
+protected:
+ struct PropertyListener {
+ AudioUnitPropertyID propertyID;
+ AudioUnitPropertyListenerProc listenerProc;
+ void * listenerRefCon;
+ };
+ typedef std::vector<PropertyListener> PropertyListeners;
+
+ /*! @var mParamList */
+ ParameterEventList mParamList;
+ /*! @var mPropertyListeners */
+ PropertyListeners mPropertyListeners;
+
+ /*! @var mBuffersAllocated */
+ bool mBuffersAllocated;
+
+ /*! @var mLogString */
+ // if this is NOT null, it will contain identifying info about this AU.
+ char* mLogString;
+
+private:
+ /*! @var sVectorUnitType */
+ static SInt32 sVectorUnitType;
+
+#if !TARGET_OS_IPHONE
+protected:
+ /*! @var mHostCallbackInfo */
+ HostCallbackInfo mHostCallbackInfo;
+
+ /*! @var mContextInfo */
+ CFStringRef mContextName;
+
+public:
+ AUDebugDispatcher* mDebugDispatcher;
+#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 !TARGET_OS_IPHONE
+ if (mConnRenderProc != NULL)
+ theResult = reinterpret_cast<AudioUnitRenderProc>(mConnRenderProc)(
+ mConnInstanceStorage, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
+ else
+#endif
+ theResult = AudioUnitRender(
+ mConnection.sourceAudioUnit, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
+ } else {
+ // kFromCallback:
+ theResult = (mInputProc)(
+ mInputProcRefCon, &ioActionFlags, &inTimeStamp, inElement, nFrames, inBufferList);
+ }
+
+ if (mInputType == kNoInput) // defense: the guy upstream could have disconnected
+ // it's a horrible thing to do, but may happen!
+ return kAudioUnitErr_NoConnection;
+
+
+ return theResult;
+}
+
+#endif // __AUBase_h__
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUDispatch.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUDispatch.cpp
new file mode 100755
index 00000000..cd3e4b51
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUDispatch.cpp
@@ -0,0 +1,477 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "AUBase.h"
+#include "CAXException.h"
+
+
+
+#if TARGET_OS_MAC
+ #if __LP64__
+ // comp instance, parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index + 1];
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
+ #endif
+#elif TARGET_OS_WIN32
+ // (no comp instance), parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index];
+#endif
+
+
+#if AU_DEBUG_DISPATCHER
+ #include "AUDebugDispatcher.h"
+
+ #define INIT_DEBUG_DISPATCHER(This) \
+ UInt64 nowTime = 0; \
+ if (This->mDebugDispatcher != NULL) \
+ nowTime = CAHostTimeBase::GetTheCurrentTime();
+#endif
+
+OSStatus AUBase::ComponentEntryDispatch(ComponentParameters *params, AUBase *This)
+{
+ if (This == NULL) return paramErr;
+
+#if AU_DEBUG_DISPATCHER
+ INIT_DEBUG_DISPATCHER(This)
+#endif
+
+ OSStatus result = noErr;
+
+ switch (params->what) {
+ case kComponentCanDoSelect:
+ switch (params->params[0]) {
+ // 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:
+ {
+ result = This->DoInitialize();
+
+ #if AU_DEBUG_DISPATCHER
+ if (This->mDebugDispatcher)
+ This->mDebugDispatcher->Initialize (nowTime, result);
+ #endif
+ }
+ break;
+
+ case kAudioUnitUninitializeSelect:
+ {
+ This->DoCleanup();
+ result = noErr;
+
+ #if AU_DEBUG_DISPATCHER
+ if (This->mDebugDispatcher)
+ This->mDebugDispatcher->Uninitialize (nowTime, result);
+ #endif
+ }
+ break;
+
+ case kAudioUnitGetPropertyInfoSelect:
+ {
+ 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;
+
+ #if AU_DEBUG_DISPATCHER
+ if (This->mDebugDispatcher)
+ This->mDebugDispatcher->GetPropertyInfo (nowTime, result, pinID, pinScope, pinElement,
+ poutDataSize, poutWritable);
+ #endif
+
+
+ }
+ break;
+
+ case kAudioUnitGetPropertySelect:
+ {
+ 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 = paramErr;
+ goto finishGetProperty;
+ }
+ if (poutData == NULL) {
+ UInt32 dataSize;
+ Boolean writable;
+
+ 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 = paramErr;
+ 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)
+ {
+ memcpy(poutData, tempBuffer, clientBufferSize);
+ delete[] tempBuffer;
+ // pioDataSize remains correct, the number of bytes we wrote
+ } else
+ *pioDataSize = actualPropertySize;
+ } else
+ *pioDataSize = 0;
+
+ finishGetProperty:
+
+ #if AU_DEBUG_DISPATCHER
+ if (This->mDebugDispatcher)
+ This->mDebugDispatcher->GetProperty (nowTime, result, pinID, pinScope, pinElement,
+ pioDataSize, poutData);
+ #else
+ ;
+ #endif
+
+ }
+ break;
+
+ case kAudioUnitSetPropertySelect:
+ {
+ 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 = paramErr;
+ goto finishSetProperty;
+ }
+
+ if (pinDataSize == 0) {
+ ca_debug_string("AudioUnitSetProperty: inDataSize == 0");
+ result = paramErr;
+ goto finishSetProperty;
+ }
+ }
+ }
+ finishSetProperty:
+
+ #if AU_DEBUG_DISPATCHER
+ if (This->mDebugDispatcher)
+ This->mDebugDispatcher->SetProperty (nowTime, result, pinID, pinScope, pinElement,
+ pinData, pinDataSize);
+ #else
+ ;
+ #endif
+
+ }
+ break;
+
+ case kAudioUnitAddPropertyListenerSelect:
+ {
+ 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:
+ {
+ PARAM(AudioUnitPropertyID, pinID, 0, 2);
+ PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 2);
+ result = This->RemovePropertyListener(pinID, pinProc, NULL, false);
+ }
+ break;
+#endif
+
+ case kAudioUnitRemovePropertyListenerWithUserDataSelect:
+ {
+ 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:
+ {
+ PARAM(AURenderCallback, pinProc, 0, 2);
+ PARAM(void *, pinProcRefCon, 1, 2);
+ result = This->SetRenderNotification (pinProc, pinProcRefCon);
+ }
+ break;
+
+ case kAudioUnitRemoveRenderNotifySelect:
+ {
+ PARAM(AURenderCallback, pinProc, 0, 2);
+ PARAM(void *, pinProcRefCon, 1, 2);
+ result = This->RemoveRenderNotification (pinProc, pinProcRefCon);
+ }
+ break;
+
+ case kAudioUnitGetParameterSelect:
+ {
+ PARAM(AudioUnitParameterID, pinID, 0, 4);
+ PARAM(AudioUnitScope, pinScope, 1, 4);
+ PARAM(AudioUnitElement, pinElement, 2, 4);
+ PARAM(AudioUnitParameterValue *, poutValue, 3, 4);
+ result = (poutValue == NULL ? paramErr : This->GetParameter(pinID, pinScope, pinElement, *poutValue));
+ }
+ break;
+
+ case kAudioUnitSetParameterSelect:
+ {
+ 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:
+ {
+ 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:
+ {
+ {
+ 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 = paramErr;
+ else {
+ if (pinActionFlags == NULL) {
+ tempFlags = 0;
+ pinActionFlags = &tempFlags;
+ }
+ result = This->DoRender(*pinActionFlags, *pinTimeStamp, pinOutputBusNumber, pinNumberFrames, *pioData);
+ }
+
+ #if AU_DEBUG_DISPATCHER
+ if (This->mDebugDispatcher)
+ This->mDebugDispatcher->Render (nowTime, result, pinActionFlags, pinTimeStamp,
+ pinOutputBusNumber, pinNumberFrames, pioData);
+ #endif
+ }
+ }
+ break;
+
+ case kAudioUnitResetSelect:
+ {
+ PARAM(AudioUnitScope, pinScope, 0, 2);
+ PARAM(AudioUnitElement, pinElement, 1, 2);
+ This->mLastRenderedSampleTime = -1;
+ 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 AudioUnitBaseGetParameter( AUBase * This,
+ AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ float *outValue)
+{
+ OSStatus result = AUBase::noErr;
+
+ try {
+ if (This == NULL || outValue == NULL) return AUBase::paramErr;
+ result = This->GetParameter(inID, inScope, inElement, *outValue);
+ }
+ COMPONENT_CATCH
+
+ return result;
+}
+
+OSStatus AudioUnitBaseSetParameter( AUBase * This,
+ AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ float inValue,
+ UInt32 inBufferOffset)
+{
+ OSStatus result = AUBase::noErr;
+
+ try {
+ if (This == NULL) return AUBase::paramErr;
+ result = This->SetParameter(inID, inScope, inElement, inValue, inBufferOffset);
+ }
+ COMPONENT_CATCH
+
+ return result;
+}
+
+OSStatus AudioUnitBaseRender( AUBase * This,
+ AudioUnitRenderActionFlags *ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList * ioData)
+{
+ if (inTimeStamp == NULL || ioData == NULL) return AUBase::paramErr;
+
+#if AU_DEBUG_DISPATCHER
+ INIT_DEBUG_DISPATCHER(This)
+#endif
+
+ OSStatus result = AUBase::noErr;
+ AudioUnitRenderActionFlags tempFlags;
+
+ try {
+ if (ioActionFlags == NULL) {
+ tempFlags = 0;
+ ioActionFlags = &tempFlags;
+ }
+ result = This->DoRender(*ioActionFlags, *inTimeStamp, inBusNumber, inNumberFrames, *ioData);
+ }
+ COMPONENT_CATCH
+
+ #if AU_DEBUG_DISPATCHER
+ if (This->mDebugDispatcher)
+ This->mDebugDispatcher->Render (nowTime, result, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
+ #endif
+
+ return result;
+}
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUDispatch.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUDispatch.h
new file mode 100755
index 00000000..ac0329d9
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUDispatch.h
@@ -0,0 +1,71 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __AUDispatch_h__
+#define __AUDispatch_h__
+
+// Fast dispatch function prototypes
+
+#include <TargetConditionals.h>
+
+/*! @function AudioUnitBaseGetParameter */
+OSStatus AudioUnitBaseGetParameter( AUBase * This,
+ AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ float * outValue);
+
+/*! @function AudioUnitBaseSetParameter */
+OSStatus AudioUnitBaseSetParameter( AUBase * This,
+ AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ float inValue,
+ UInt32 inBufferOffset);
+
+/*! @function AudioUnitBaseRender */
+OSStatus AudioUnitBaseRender( AUBase * This,
+ AudioUnitRenderActionFlags *ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList * ioData);
+
+#endif // __AUDispatch_h__
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUInputElement.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUInputElement.cpp
new file mode 100755
index 00000000..82085534
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUInputElement.cpp
@@ -0,0 +1,146 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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;
+ mConnRenderProc = NULL;
+ AllocateBuffer();
+
+#if !CA_AU_IS_ONLY_PLUGIN
+ UInt32 size = sizeof(AudioUnitRenderProc);
+ OSStatus result = AudioUnitGetProperty( conn.sourceAudioUnit,
+ kAudioUnitProperty_FastDispatch,
+ kAudioUnitScope_Global,
+ kAudioUnitRenderSelect,
+ &mConnRenderProc,
+ &size);
+ if (result == noErr)
+ mConnInstanceStorage = GetComponentInstanceStorage (conn.sourceAudioUnit);
+ else
+ mConnRenderProc = NULL;
+#else // !TARGET_OS_IPHONE
+ mConnInstanceStorage = NULL;
+ 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/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUInputElement.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUInputElement.h
new file mode 100755
index 00000000..59556b3f
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUInputElement.h
@@ -0,0 +1,111 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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;
+ /*! @var mConnRenderProc */
+ AudioUnitRenderProc mConnRenderProc;
+ /*! @var mConnInstanceStorage */
+ void * mConnInstanceStorage; // for the input component
+};
+
+
+#endif // __AUInput_h__
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp
new file mode 100755
index 00000000..5074c1cb
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp
@@ -0,0 +1,56 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUOutputElement.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUOutputElement.h
new file mode 100755
index 00000000..367064f2
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUOutputElement.h
@@ -0,0 +1,60 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUResources.r b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUResources.r
new file mode 100755
index 00000000..acef631a
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUResources.r
@@ -0,0 +1,134 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUResources.r
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* sample macro definitions -- all of these symbols must be defined
+#define RES_ID kHALOutputResID
+#define COMP_TYPE kAudioUnitComponentType
+#define COMP_SUBTYPE kAudioUnitOutputSubType
+#define COMP_MANUF kAudioUnitAudioHardwareOutputSubSubType
+#define VERSION 0x00010000
+#define NAME "AudioHALOutput"
+#define DESCRIPTION "Audio hardware output AudioUnit"
+#define ENTRY_POINT "AUHALEntry"
+*/
+#define UseExtendedThingResource 1
+
+#include <CoreServices/CoreServices.r>
+
+// this is a define used to indicate that a component has no static data that would mean
+// that no more than one instance could be open at a time - never been true for AUs
+#ifndef cmpThreadSafeOnMac
+#define cmpThreadSafeOnMac 0x10000000
+#endif
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+resource 'STR ' (RES_ID, purgeable) {
+ NAME
+};
+
+resource 'STR ' (RES_ID + 1, purgeable) {
+ DESCRIPTION
+};
+
+resource 'dlle' (RES_ID) {
+ ENTRY_POINT
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+resource 'thng' (RES_ID, NAME) {
+ COMP_TYPE,
+ COMP_SUBTYPE,
+ COMP_MANUF,
+ 0, 0, 0, 0, // no 68K
+ 'STR ', RES_ID,
+ 'STR ', RES_ID + 1,
+ 0, 0, /* icon */
+ VERSION,
+ componentHasMultiplePlatforms | componentDoAutoVersion,
+ 0,
+ {
+ #if defined(ppc_YES)
+ cmpThreadSafeOnMac,
+ 'dlle', RES_ID, platformPowerPCNativeEntryPoint
+ #define NeedLeadingComma 1
+ #endif
+ #if defined(ppc64_YES)
+ #if defined(NeedLeadingComma)
+ ,
+ #endif
+ cmpThreadSafeOnMac,
+ 'dlle', RES_ID, platformPowerPC64NativeEntryPoint
+ #define NeedLeadingComma 1
+ #endif
+ #if defined(i386_YES)
+ #if defined(NeedLeadingComma)
+ ,
+ #endif
+ cmpThreadSafeOnMac,
+ 'dlle', RES_ID, platformIA32NativeEntryPoint
+ #define NeedLeadingComma 1
+ #endif
+ #if defined(x86_64_YES)
+ #if defined(NeedLeadingComma)
+ ,
+ #endif
+ cmpThreadSafeOnMac,
+ 'dlle', RES_ID, 8
+ #define NeedLeadingComma 1
+ #endif
+ }
+};
+
+#undef RES_ID
+#undef COMP_TYPE
+#undef COMP_SUBTYPE
+#undef COMP_MANUF
+#undef VERSION
+#undef NAME
+#undef DESCRIPTION
+#undef ENTRY_POINT
+#undef NeedLeadingComma
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp
new file mode 100755
index 00000000..fe02061f
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp
@@ -0,0 +1,506 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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;
+}
+
+//_____________________________________________________________________________
+//
+// 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 = 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 = 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(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 = GetCreator()->CreateElement(GetScope(), mElements.size());
+ mElements.push_back(elem);
+ }
+ } else
+ while (numElements < mElements.size()) {
+ AUElement *elem = mElements.back();
+ mElements.pop_back();
+ delete elem;
+ }
+}
+
+//_____________________________________________________________________________
+//
+bool AUScope::HasElementWithName () const
+{
+ for (UInt32 i = 0; i < GetNumberOfElements(); ++i) {
+ AUElement * el = const_cast<AUScope*>(this)->GetElement (i);
+ if (el && el->HasName()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+//_____________________________________________________________________________
+//
+
+void AUScope::AddElementNamesToDict (CFMutableDictionaryRef & inNameDict)
+{
+ if (HasElementWithName())
+ {
+ static char string[32];
+ CFMutableDictionaryRef elementDict = CFDictionaryCreateMutable (NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CFStringRef str;
+ for (UInt32 i = 0; i < GetNumberOfElements(); ++i) {
+ AUElement * el = GetElement (i);
+ if (el && el->HasName()) {
+ snprintf (string, sizeof(string), "%d", int(i));
+ str = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
+ CFDictionarySetValue (elementDict, str, el->GetName());
+ CFRelease (str);
+ }
+ }
+
+ snprintf (string, sizeof(string), "%d", int(mScope));
+ str = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
+ CFDictionarySetValue (inNameDict, str, elementDict);
+ CFRelease (str);
+ CFRelease (elementDict);
+ }
+}
+
+//_____________________________________________________________________________
+//
+bool AUScope::RestoreElementNames (CFDictionaryRef& inNameDict)
+{
+ static char string[32];
+
+ //first we have to see if we have enough elements and if not create them
+ bool didAddElements = false;
+ unsigned int maxElNum = 0;
+
+ int dictSize = CFDictionaryGetCount(inNameDict);
+ CFStringRef * keys = (CFStringRef*)CA_malloc (dictSize * sizeof (CFStringRef));
+ CFDictionaryGetKeysAndValues (inNameDict, reinterpret_cast<const void**>(keys), NULL);
+ for (int i = 0; i < dictSize; i++)
+ {
+ unsigned int intKey;
+ CFStringGetCString (keys[i], string, 32, kCFStringEncodingASCII);
+ sscanf (string, "%u", &intKey);
+ if (UInt32(intKey) > maxElNum)
+ maxElNum = intKey;
+ }
+
+ if (maxElNum >= GetNumberOfElements()) {
+ SetNumberOfElements (maxElNum+1);
+ didAddElements = true;
+ }
+
+ // OK, now we have the number of elements that we need - lets restate their names
+ for (int i = 0; i < dictSize; i++)
+ {
+ CFStringRef elName = reinterpret_cast<CFStringRef>(CFDictionaryGetValue (inNameDict, keys[i]));
+ int intKey;
+ CFStringGetCString (keys[i], string, 32, kCFStringEncodingASCII);
+ sscanf (string, "%d", &intKey);
+ GetElement (intKey)->SetName (elName);
+ }
+ free (keys);
+
+ return didAddElements;
+}
+
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.h
new file mode 100755
index 00000000..bb55f763
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.h
@@ -0,0 +1,535 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __AUScopeElement_h__
+#define __AUScopeElement_h__
+
+#include <map>
+#include <vector>
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnit.h>
+#else
+ #include <AudioUnit.h>
+#endif
+#include "ComponentBase.h"
+#include "AUBuffer.h"
+
+
+class AUBase;
+
+// ____________________________________________________________________________
+//
+// represents a parameter's value (either constant or ramped)
+/*! @class ParameterMapEvent */
+class ParameterMapEvent
+{
+public:
+/*! @ctor ParameterMapEvent */
+ ParameterMapEvent()
+ : mEventType(kParameterEvent_Immediate), mBufferOffset(0), mDurationInFrames(0), mValue1(0.0), mValue2(0.0), 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 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 */
+ UInt32 GetNumberOfParameters()
+ {
+ if(mUseIndexedParameters) return mIndexedParameters.size(); else return mParameters.size();
+ }
+/*! @method GetParameterList */
+ void GetParameterList(AudioUnitParameterID *outList);
+
+/*! @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);
+
+protected:
+ inline ParameterMapEvent& GetParamEvent(AudioUnitParameterID paramID);
+
+private:
+ typedef std::map<AudioUnitParameterID, ParameterMapEvent, std::less<AudioUnitParameterID> > ParameterMap;
+
+/*! @var mAudioUnit */
+ AUBase * mAudioUnit;
+/*! @var mParameters */
+ ParameterMap mParameters;
+
+/*! @var mUseIndexedParameters */
+ bool mUseIndexedParameters;
+/*! @var mIndexedParameters */
+ std::vector<ParameterMapEvent> mIndexedParameters;
+
+/*! @var mElementName */
+ CFStringRef mElementName;
+};
+
+
+
+// ____________________________________________________________________________
+//
+/*! @class AUIOElement */
+class AUIOElement : public AUElement {
+public:
+/*! @ctor AUIOElement */
+ AUIOElement(AUBase *audioUnit);
+
+/*! @method GetStreamFormat */
+ const CAStreamBasicDescription &GetStreamFormat() const { return mStreamFormat; }
+
+/*! @method SetStreamFormat */
+ virtual OSStatus SetStreamFormat(const CAStreamBasicDescription &desc);
+
+/*! @method AllocateBuffer */
+ virtual void AllocateBuffer(UInt32 inFramesToAllocate = 0);
+/*! @method DeallocateBuffer */
+ void DeallocateBuffer();
+/*! @method NeedsBufferSpace */
+ virtual bool NeedsBufferSpace() const = 0;
+
+/*! @method DeallocateBuffer */
+ void SetWillAllocateBuffer(bool inFlag) {
+ mWillAllocate = inFlag;
+ }
+/*! @method DeallocateBuffer */
+ bool WillAllocateBuffer() const {
+ return mWillAllocate;
+ }
+
+/*! @method UseExternalBuffer */
+ void UseExternalBuffer(const AudioUnitExternalBuffer &buf) {
+ mIOBuffer.UseExternalBuffer(mStreamFormat, buf);
+ }
+/*! @method PrepareBuffer */
+ AudioBufferList & PrepareBuffer(UInt32 nFrames) {
+ if (mWillAllocate)
+ return mIOBuffer.PrepareBuffer(mStreamFormat, nFrames);
+ throw OSStatus(kAudioUnitErr_InvalidPropertyValue);
+ }
+/*! @method PrepareNullBuffer */
+ AudioBufferList & PrepareNullBuffer(UInt32 nFrames) {
+ return mIOBuffer.PrepareNullBuffer(mStreamFormat, nFrames);
+ }
+/*! @method SetBufferList */
+ AudioBufferList & SetBufferList(AudioBufferList &abl) { return mIOBuffer.SetBufferList(abl); }
+/*! @method SetBuffer */
+ void SetBuffer(UInt32 index, AudioBuffer &ab) { mIOBuffer.SetBuffer(index, ab); }
+/*! @method InvalidateBufferList */
+ void InvalidateBufferList() { mIOBuffer.InvalidateBufferList(); }
+
+/*! @method GetBufferList */
+ AudioBufferList & GetBufferList() const { return mIOBuffer.GetBufferList(); }
+
+/*! @method GetChannelData */
+ AudioUnitSampleType * GetChannelData(int ch) const {
+ if (mStreamFormat.IsInterleaved())
+ return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
+ else
+ return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
+ }
+ SInt16 * GetInt16ChannelData(int ch) const {
+ if (mStreamFormat.IsInterleaved())
+ return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
+ else
+ return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
+ }
+
+/*! @method CopyBufferListTo */
+ void CopyBufferListTo(AudioBufferList &abl) const {
+ mIOBuffer.CopyBufferListTo(abl);
+ }
+/*! @method CopyBufferContentsTo */
+ void CopyBufferContentsTo(AudioBufferList &abl) const {
+ mIOBuffer.CopyBufferContentsTo(abl);
+ }
+
+/* UInt32 BytesToFrames(UInt32 nBytes) { return nBytes / mStreamFormat.mBytesPerFrame; }
+ UInt32 BytesToFrames(AudioBufferList &abl) {
+ return BytesToFrames(abl.mBuffers[0].mDataByteSize);
+ }
+ UInt32 FramesToBytes(UInt32 nFrames) { return nFrames * mStreamFormat.mBytesPerFrame; }*/
+
+/*! @method IsInterleaved */
+ bool IsInterleaved() const { return mStreamFormat.IsInterleaved(); }
+/*! @method NumberChannels */
+ UInt32 NumberChannels() const { return mStreamFormat.NumberChannels(); }
+/*! @method NumberInterleavedChannels */
+ UInt32 NumberInterleavedChannels() const { return mStreamFormat.NumberInterleavedChannels(); }
+
+/*! @method GetChannelMapTags */
+ virtual UInt32 GetChannelLayoutTags (AudioChannelLayoutTag *outLayoutTagsPtr);
+
+/*! @method GetAudioChannelLayout */
+ virtual UInt32 GetAudioChannelLayout (AudioChannelLayout *outMapPtr, Boolean &outWritable);
+
+/*! @method SetAudioChannelLayout */
+ virtual OSStatus SetAudioChannelLayout (const AudioChannelLayout &inData);
+
+/*! @method RemoveAudioChannelLayout */
+ virtual OSStatus RemoveAudioChannelLayout ();
+
+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;
+};
+
+// ____________________________________________________________________________
+//
+/*! @class AUElementCreator */
+class AUElementCreator {
+public:
+/*! @method CreateElement */
+ virtual AUElement * CreateElement(AudioUnitScope scope, AudioUnitElement element) = 0;
+ virtual ~AUElementCreator() { }
+};
+
+// ____________________________________________________________________________
+//
+// 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 */
+ virtual void Initialize( AUElementCreator *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;
+
+ AUElementCreator * GetCreator() const { return mCreator; }
+ AudioUnitScope GetScope() const { return mScope; }
+
+
+private:
+/*! @var mCreator */
+ AUElementCreator * 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(AUElementCreator *creator,
+ AudioUnitScope scope,
+ UInt32 numElements)
+ {
+ if (mDelegate)
+ return mDelegate->Initialize(creator, scope, numElements);
+
+ mCreator = creator;
+ mScope = scope;
+ SetNumberOfElements(numElements);
+ }
+
+/*! @method SetNumberOfElements */
+ void SetNumberOfElements(UInt32 numElements);
+
+/*! @method GetNumberOfElements */
+ UInt32 GetNumberOfElements() const
+ {
+ if (mDelegate)
+ return mDelegate->GetNumberOfElements();
+
+ return 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;
+ #if !CA_NO_RTTI
+ if (element == NULL || (ioel = dynamic_cast<AUIOElement *>(element)) == NULL)
+ COMPONENT_THROW (kAudioUnitErr_InvalidElement);
+ #else
+ if (element == NULL || (ioel = static_cast<AUIOElement *>(element)) == NULL)
+ COMPONENT_THROW (kAudioUnitErr_InvalidElement);
+ #endif
+ return ioel;
+ }
+
+/*! @method HasElementWithName */
+ bool HasElementWithName () const;
+
+/*! @method AddElementNamesToDict */
+ void AddElementNamesToDict (CFMutableDictionaryRef & inNameDict);
+
+ bool RestoreElementNames (CFDictionaryRef& inNameDict);
+
+ AUElementCreator * GetCreator() const { return mCreator; }
+ AudioUnitScope GetScope() const { return mScope; }
+
+ void SetDelegate(AUScopeDelegate* inDelegate) { mDelegate = inDelegate; }
+
+private:
+ typedef std::vector<AUElement *> ElementVector;
+/*! @var mCreator */
+ AUElementCreator * mCreator;
+/*! @var mScope */
+ AudioUnitScope mScope;
+/*! @var mElements */
+ ElementVector mElements;
+/*! @var mDelegate */
+ AUScopeDelegate * mDelegate;
+};
+
+
+
+#endif // __AUScopeElement_h__
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/ComponentBase.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/ComponentBase.cpp
new file mode 100755
index 00000000..38e2f064
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/ComponentBase.cpp
@@ -0,0 +1,189 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "ComponentBase.h"
+#include "CAXException.h"
+
+#if TARGET_OS_MAC
+pthread_mutex_t ComponentInitLocker::sComponentOpenMutex = PTHREAD_MUTEX_INITIALIZER;
+#elif TARGET_OS_WIN32
+CAGuard ComponentInitLocker::sComponentOpenGuard("sComponentOpenGuard");
+#endif
+
+#if CA_DO_NOT_USE_AUDIO_COMPONENT
+ #include <dlfcn.h>
+#endif
+
+ComponentBase::~ComponentBase()
+{
+}
+
+void ComponentBase::PostConstructor()
+{
+}
+
+void ComponentBase::PreDestructor()
+{
+}
+
+#if !TARGET_OS_IPHONE
+OSStatus ComponentBase::Version()
+{
+ return 0x00000001;
+}
+
+OSStatus ComponentBase::ComponentEntryDispatch(ComponentParameters *p, ComponentBase *This)
+{
+ if (This == NULL) return paramErr;
+
+ OSStatus result = noErr;
+
+ switch (p->what) {
+ case kComponentCloseSelect:
+ This->PreDestructor();
+ delete This;
+ break;
+
+ case kComponentVersionSelect:
+ result = This->Version();
+ break;
+
+ case kComponentCanDoSelect:
+ switch (p->params[0]) {
+ case kComponentOpenSelect:
+ case kComponentCloseSelect:
+ case kComponentVersionSelect:
+ case kComponentCanDoSelect:
+ return 1;
+ default:
+ return 0;
+ }
+
+ default:
+ result = badComponentSelector;
+ break;
+ }
+ return result;
+}
+#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;
+
+#if CA_DO_NOT_USE_AUDIO_COMPONENT
+ ca_require_noerr (result = ComponentBase_GetComponentDescription (mComponentInstance, desc), home);
+#else
+ AudioComponent comp = AudioComponentInstanceGetComponent(mComponentInstance);
+ XAssert (comp);
+ if (comp) {
+ ca_require_noerr(result = AudioComponentGetDescription(comp, &desc), home);
+ } else
+ ca_require_noerr(result = -1, home);
+#endif
+
+home:
+ if (result)
+ memset (&desc, 0, sizeof(AudioComponentDescription));
+ return desc;
+}
+
+
+#if CA_DO_NOT_USE_AUDIO_COMPONENT
+OSStatus ComponentBase_GetComponentDescription (const AudioComponentInstance & inInstance, AudioComponentDescription & outDesc)
+{
+ // we prefer to use the new API. If it is not available however, we have to go back to using the ComponentMgr one.
+ typedef AudioComponent (*AudioComponentInstanceGetComponentProc) (AudioComponentInstance);
+ static AudioComponentInstanceGetComponentProc aciGCProc = NULL;
+
+ typedef OSStatus (*AudioComponentGetDescriptionProc)(AudioComponent, AudioComponentDescription *);
+ static AudioComponentGetDescriptionProc acGDProc = NULL;
+
+ typedef OSErr (*GetComponentInfoProc)(Component, ComponentDescription *, void*, void*, void*);
+ static GetComponentInfoProc gciProc = NULL;
+
+ static int doneInit = 0;
+ if (doneInit == 0) {
+ doneInit = 1;
+ bool loadCMgr = true;
+
+ void* theImage = dlopen("/System/Library/Frameworks/AudioUnit.framework/AudioUnit", RTLD_LAZY);
+ if (theImage != NULL)
+ {
+ // we assume that all routine names passed here have a leading underscore which gets shaved
+ // off when passed to dlsym
+ aciGCProc = (AudioComponentInstanceGetComponentProc)dlsym (theImage, "AudioComponentInstanceGetComponent");
+ if (aciGCProc) {
+ acGDProc = (AudioComponentGetDescriptionProc)dlsym (theImage, "AudioComponentGetDescription");
+ if (acGDProc)
+ loadCMgr = false;
+ }
+ }
+ if (loadCMgr) {
+ theImage = dlopen("/System/Library/Frameworks/CoreServices.framework/CoreServices", RTLD_LAZY);
+ if (theImage != NULL)
+ {
+ gciProc = (GetComponentInfoProc)dlsym (theImage, "GetComponentInfo");
+ }
+ }
+ }
+
+ OSStatus result = noErr;
+ if (acGDProc && aciGCProc) {
+ AudioComponent comp = (*aciGCProc)(inInstance);
+ XAssert (comp);
+ if (comp) {
+ ca_require_noerr(result = (*acGDProc)(comp, &outDesc), home);
+ } else
+ ca_require_noerr(result = -1, home);
+
+ } else if (gciProc) {
+ // in this case we know that inInstance is directly castable to a Component
+ ca_require_noerr(result = (*gciProc)((Component)inInstance, (ComponentDescription*)&outDesc, NULL, NULL, NULL), home);
+ }
+home:
+ return result;
+}
+#endif //CA_DO_NOT_USE_AUDIO_COMPONENT
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/ComponentBase.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/ComponentBase.h
new file mode 100755
index 00000000..f60bd3f6
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/ComponentBase.h
@@ -0,0 +1,226 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __ComponentBase_h__
+#define __ComponentBase_h__
+
+#include <new>
+#include "CADebugMacros.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <AudioUnit/AudioUnit.h>
+
+ #if !TARGET_OS_IPHONE
+ #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/Components.h>
+
+ #if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)
+ #define AudioComponentInstance ComponentInstance
+ #define AudioComponentDescription ComponentDescription
+ #define AudioComponent Component
+ #define CA_DO_NOT_USE_AUDIO_COMPONENT 1
+ #endif
+ #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
+
+ #include <pthread.h>
+#else
+ #include "CoreAudioTypes.h"
+ #include "Components.h"
+ #include "AudioUnit.h"
+ #include "CAGuard.h"
+#endif
+
+#ifndef COMPONENT_THROW
+ #if VERBOSE_COMPONENT_THROW
+ #define COMPONENT_THROW(err) \
+ do { DebugMessage(#err); throw static_cast<OSStatus>(err); } while (0)
+ #else
+ #define COMPONENT_THROW(err) \
+ throw static_cast<OSStatus>(err)
+ #endif
+#endif
+
+#define COMPONENT_CATCH \
+ catch (std::bad_alloc &) { result = -108/*memFullErr*/; } \
+ catch (OSStatus err) { result = err; } \
+ catch (OSErr err) { result = err; } \
+ catch (...) { result = -1; }
+
+class ComponentInitLocker
+{
+#if TARGET_OS_MAC
+public:
+ ComponentInitLocker() { pthread_mutex_lock(&sComponentOpenMutex); }
+ ~ComponentInitLocker() { pthread_mutex_unlock(&sComponentOpenMutex); }
+private:
+ static pthread_mutex_t sComponentOpenMutex;
+#elif TARGET_OS_WIN32
+public:
+ bool sNeedsUnlocking;
+ ComponentInitLocker() { sNeedsUnlocking = sComponentOpenGuard.Lock(); }
+ ~ComponentInitLocker() { if(sNeedsUnlocking) { sComponentOpenGuard.Unlock(); } }
+private:
+ static CAGuard sComponentOpenGuard;
+#endif
+};
+
+#if !TARGET_OS_IPHONE
+ /*! @class ComponentEntryPoint */
+template <class Class>
+class ComponentEntryPoint {
+public:
+ /*! @method Dispatch */
+ static OSStatus Dispatch(ComponentParameters *params, Class *obj)
+ {
+ OSStatus result = noErr;
+
+ try {
+ if (params->what == kComponentOpenSelect) {
+ // solve a host of initialization thread safety issues.
+ ComponentInitLocker lock;
+
+ 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
+
+ #if !CA_AU_IS_ONLY_PLUGIN
+ SetComponentInstanceStorage(ci, (Handle)This);
+ #endif
+ } 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;
+ }
+};
+
+#if TARGET_OS_MAC && TARGET_CPU_PPC && !TARGET_RT_MAC_MACHO
+ // for OS 9, a PPC native component's entry point must be a routine descriptor
+ #define COMPONENT_ENTRY(Class) \
+ extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj); \
+ extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj) { \
+ return ComponentEntryPoint<Class>::Dispatch(params, obj); \
+ } \
+ \
+ struct RoutineDescriptor Class##EntryRD = \
+ BUILD_ROUTINE_DESCRIPTOR((kPascalStackBased | RESULT_SIZE (kFourByteCode) | \
+ STACK_ROUTINE_PARAMETER (1, kFourByteCode) | \
+ STACK_ROUTINE_PARAMETER (2, kFourByteCode)), Class##Entry);
+#else
+ #define COMPONENT_ENTRY(Class) \
+ extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj); \
+ extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj) { \
+ return ComponentEntryPoint<Class>::Dispatch(params, obj); \
+ }
+#endif
+
+ /*! @class ComponentRegistrar */
+template <class Class, OSType Type, OSType Subtype, OSType Manufacturer>
+class ComponentRegistrar {
+public:
+ /*! @ctor ComponentRegistrar */
+ ComponentRegistrar() { ComponentEntryPoint<Class>::Register(Type, Subtype, Manufacturer); }
+};
+
+#define COMPONENT_REGISTER(Class,Type,Subtype,Manufacturer) \
+ static ComponentRegistrar<Class, Type, Subtype, Manufacturer> gRegistrar##Class
+#else
+#define COMPONENT_ENTRY(Class)
+#define COMPONENT_REGISTER(Class)
+#endif // !TARGET_OS_IPHONE
+
+
+ /*! @class ComponentBase */
+class ComponentBase {
+public:
+ // classic MacErrors
+ enum { noErr = 0, paramErr = -50, memFullErr = -108 };
+
+ /*! @ctor ComponentBase */
+ ComponentBase(AudioComponentInstance inInstance) : mComponentInstance(inInstance) { }
+ /*! @dtor ~ComponentBase */
+ virtual ~ComponentBase();
+
+ /*! @method PostConstructor */
+ virtual void PostConstructor();
+
+ /*! @method PreDestructor */
+ virtual void PreDestructor();
+
+#if !TARGET_OS_IPHONE
+ /*! @method Version */
+ virtual OSStatus Version();
+
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch(ComponentParameters *p, ComponentBase *This);
+#endif
+
+ /*! @method GetComponentInstance */
+ AudioComponentInstance GetComponentInstance() const { return mComponentInstance; }
+
+ /*! @method GetComponentDescription */
+ AudioComponentDescription GetComponentDescription() const;
+
+protected:
+ /*! @var mComponentInstance */
+ AudioComponentInstance mComponentInstance;
+};
+
+#endif // __ComponentBase_h__
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp
new file mode 100755
index 00000000..55ccf833
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp
@@ -0,0 +1,386 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "AUCarbonViewBase.h"
+#include "AUCarbonViewControl.h"
+#include <algorithm>
+
+AUCarbonViewBase::AUCarbonViewBase(AudioUnitCarbonView inInstance, Float32 inNotificationInterval /* in seconds */) :
+ ComponentBase(inInstance),
+ mEditAudioUnit(0),
+ mParameterListener(NULL),
+#if !__LP64__
+ mEventListener(NULL),
+#endif
+ mTimerRef (NULL),
+ mTimerUPP (NULL),
+ mCarbonWindow(NULL),
+ mCarbonPane(NULL),
+ mXOffset(0),
+ mYOffset(0)
+{
+ AUEventListenerCreate (ParameterListener, this,
+ CFRunLoopGetCurrent(), kCFRunLoopCommonModes,
+ inNotificationInterval, inNotificationInterval,
+ &mParameterListener);
+}
+
+AUCarbonViewBase::~AUCarbonViewBase()
+{
+ if (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);
+}
+
+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)
+{
+ 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;
+}
+
+OSStatus AUCarbonViewBase::CreateUI(Float32 inXOffset, Float32 inYOffset)
+{
+ return noErr;
+}
+
+OSStatus AUCarbonViewBase::EmbedControl(ControlRef ctl)
+{
+ 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);
+}
+
+void AUCarbonViewBase::AddCarbonControl(AUCarbonViewControl::ControlType type, const CAAUParameter &param, ControlRef control)
+{
+ verify_noerr(EmbedControl(control));
+
+ AUCarbonViewControl *auvc = new AUCarbonViewControl(this, mParameterListener, type, param, control);
+ auvc->Bind();
+ AddControl(auvc);
+}
+
+bool AUCarbonViewBase::HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event)
+{
+ 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;
+ }
+
+ return false;
+}
+
+/*! @method TellListener */
+void AUCarbonViewBase::TellListener (const CAAUParameter &auvp, AudioUnitCarbonViewEventID event, void *evpar)
+{
+#if !__LP64__
+ if (mEventListener)
+ (*mEventListener)(mEventListenerUserData, mComponentInstance, &auvp, event, evpar);
+#endif
+
+ AudioUnitEvent auEvent;
+ auEvent.mArgument.mParameter = auvp;
+ if (event == kAudioUnitCarbonViewEvent_MouseDownInControl) {
+ auEvent.mEventType = kAudioUnitEvent_BeginParameterChangeGesture;
+ } else {
+ auEvent.mEventType = kAudioUnitEvent_EndParameterChangeGesture;
+ }
+ AUEventListenerNotify(mParameterListener, this, &auEvent);
+}
+
+
+void AUCarbonViewBase::Update (bool inUIThread)
+{
+ for (ControlList::iterator iter = mControlList.begin(); iter != mControlList.end(); ++iter)
+ {
+ (*iter)->Update(inUIThread);
+ }
+}
+
+pascal void AUCarbonViewBase::TheTimerProc (EventLoopTimerRef inTimer, void *inUserData)
+{
+ AUCarbonViewBase* This = reinterpret_cast<AUCarbonViewBase*>(inUserData);
+ This->RespondToEventTimer (inTimer);
+}
+
+void AUCarbonViewBase::RespondToEventTimer (EventLoopTimerRef inTimer)
+{}
+
+/*
+ THESE are reasonable values for these two times
+ 0.005 // delay
+ 0.050 // interval
+*/
+
+OSStatus AUCarbonViewBase::CreateEventLoopTimer (Float32 inDelay, Float32 inInterval)
+{
+ if (mTimerUPP)
+ return noErr;
+
+ mTimerUPP = NewEventLoopTimerUPP(TheTimerProc);
+
+ EventLoopRef mainEventLoop = GetMainEventLoop();
+
+ //doesn't seem to like too small a value
+ if (inDelay < 0.005)
+ inDelay = 0.005;
+
+ OSStatus timerResult = ::InstallEventLoopTimer(
+ mainEventLoop,
+ inDelay,
+ inInterval,
+ mTimerUPP,
+ this,
+ &mTimerRef);
+ return timerResult;
+}
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h
new file mode 100755
index 00000000..e97ef61b
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h
@@ -0,0 +1,182 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __AUCarbonViewBase_h__
+#define __AUCarbonViewBase_h__
+
+#include <vector>
+#include "AUCarbonViewControl.h"
+#include "ComponentBase.h"
+
+static const Float32 kDefaultNotificationInterval = 0.100;
+
+ /*! @class AUCarbonViewBase */
+class AUCarbonViewBase : public ComponentBase, public CarbonEventHandler
+{
+public:
+ /*! @ctor AUCarbonViewBase */
+ AUCarbonViewBase ( AudioUnitCarbonView inInstance,
+ Float32 inNotificationInterval = kDefaultNotificationInterval /* in seconds */);
+ /*! @dtor ~AUCarbonViewBase */
+ virtual ~AUCarbonViewBase();
+
+ // AUViewBase overrides
+ /*! @method CreateCarbonView */
+ virtual OSStatus CreateCarbonView (AudioUnit inAudioUnit, WindowRef inWindow, ControlRef inParentControl, const Float32Point &inLocation, const Float32Point &inSize, ControlRef &outParentControl);
+
+ // our own virtual methods
+ /*! @method CreateUI */
+ virtual OSStatus CreateUI (Float32 inXOffset, Float32 inYOffset);
+
+ /*! @method HandleEvent */
+ virtual bool HandleEvent (EventHandlerCallRef inHandlerRef, EventRef event);
+
+ /*! @method GetEditAudioUnit */
+ const AudioUnit GetEditAudioUnit () const { return mEditAudioUnit; }
+ //
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch (
+ ComponentParameters * params,
+ AUCarbonViewBase * This);
+
+ /*! @method AddCarbonControl */
+ void AddCarbonControl (
+ AUCarbonViewControl::ControlType type,
+ const CAAUParameter & param,
+ ControlRef control);
+
+ /*! @method GetCarbonWindow */
+ WindowRef GetCarbonWindow () { return mCarbonWindow; }
+ /*! @method GetCarbonPane */
+ ControlRef GetCarbonPane () { return mCarbonPane; }
+ /*! @method EmbedControl */
+ OSStatus EmbedControl (ControlRef ctl);
+
+ /*! @method TellListener */
+ void TellListener (const CAAUParameter &auvp, AudioUnitCarbonViewEventID event, void *evpar);
+
+ // pass in true if wanting an update to the view and you're calling this from a thread
+ // that is safe to do UI in.
+ // If you don't know, pass in false!
+ /*! @method Update */
+ void Update (bool inUIThread);
+
+ /*! @method GetXOffset */
+ Float32 GetXOffset () { return mXOffset; }
+ /*! @method GetYOffset */
+ Float32 GetYOffset () { return mYOffset; }
+
+ /*! @method ClearControls */
+ void ClearControls ();
+
+ /*! @method IsCompositWindow */
+ bool IsCompositWindow () const { return mCompositWindow; }
+
+protected:
+#if !__LP64__
+ /*! @method SetEventListener */
+ void SetEventListener (AudioUnitCarbonViewEventListener listener, void *userData)
+ {
+ mEventListener = listener;
+ mEventListenerUserData = userData;
+ }
+#endif
+
+ /*! @method AddControl */
+ void AddControl (AUCarbonViewControl *control);
+ /*! @method RemoveControl */
+ void RemoveControl (AUCarbonViewControl *control);
+
+ OSStatus CreateEventLoopTimer (Float32 inDelay, Float32 inInterval);
+
+ /*! @method ParameterListener */
+ static void ParameterListener (void * inCallbackRefCon,
+ void * inObject,
+ const AudioUnitEvent * inEvent,
+ UInt64 inEventHostTime,
+ Float32 inParameterValue);
+
+ static pascal void TheTimerProc ( EventLoopTimerRef inTimer,
+ void * inUserData);
+
+ virtual void RespondToEventTimer (EventLoopTimerRef inTimer);
+
+ /*! @var mEditAudioUnit */
+ AudioUnit mEditAudioUnit; // the AU we're controlling
+ /*! @var mParameterListener */
+ AUEventListenerRef mParameterListener;
+
+#if !__LP64__
+ /*! @var mEventListener */
+ AudioUnitCarbonViewEventListener
+ mEventListener;
+#endif
+
+ /*! @var mEventListenerUserData */
+ void * mEventListenerUserData;
+
+private:
+ typedef std::vector<AUCarbonViewControl *> ControlList;
+ /*! @var mControlList */
+ ControlList mControlList;
+
+ EventLoopTimerRef mTimerRef;
+
+ EventLoopTimerUPP mTimerUPP;
+
+protected:
+ /*! @var mCarbonWindow */
+ WindowRef mCarbonWindow;
+ /*! @var mCarbonPane */
+ ControlRef mCarbonPane; // user pane, contains all other controls
+ /*! @var mBottomRight */
+ Point mBottomRight; // largest width and height of child controls
+ /*! @var mXOffset */
+ Float32 mXOffset;
+ /*! @var mYOffset */
+ Float32 mYOffset;
+ /*! @var mCompositWindow */
+ bool mCompositWindow;
+ /*! @var mCurrentScrollPoint */
+ HIPoint mCurrentScrollPoint; // needed for scrolling
+};
+
+
+#endif // __AUCarbonViewBase_h__
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp
new file mode 100755
index 00000000..12e4534b
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp
@@ -0,0 +1,667 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "AUCarbonViewControl.h"
+#include "AUCarbonViewBase.h"
+#include "AUViewLocalizedStringKeys.h"
+
+AUCarbonViewControl::AUCarbonViewControl(AUCarbonViewBase *ownerView, AUParameterListenerRef listener, ControlType type, const CAAUParameter &param, ControlRef control) :
+ mOwnerView(ownerView),
+ mListener(listener),
+ mType(type),
+ mParam(param),
+ mControl(control),
+ mInControlInitialization(0)
+{
+#if __LP64__
+ SetControlReference(control, SRefCon(this));
+#else
+ SetControlReference(control, SInt32(this));
+#endif
+}
+
+AUCarbonViewControl::~AUCarbonViewControl()
+{
+ AUListenerRemoveParameter(mListener, this, &mParam);
+}
+
+AUCarbonViewControl* AUCarbonViewControl::mLastControl = NULL;
+
+void AUCarbonViewControl::Bind()
+{
+ 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
+}
+
+void AUCarbonViewControl::ParameterToControl(Float32 paramValue)
+{
+ ++mInControlInitialization;
+ switch (mType) {
+ case kTypeContinuous:
+ SetValueFract(AUParameterValueToLinear(paramValue, &mParam));
+ break;
+ case kTypeDiscrete:
+ {
+ long value = long(paramValue);
+
+ // special case [1] -- menu parameters
+ if (mParam.HasNamedParams()) {
+ // if we're dealing with menus they behave differently!
+ // becaue setting min and max doesn't work correctly for the control value
+ // first menu item always reports a control value of 1
+ ControlKind ctrlKind;
+ if (GetControlKind(mControl, &ctrlKind) == noErr) {
+ if ((ctrlKind.kind == kControlKindPopupArrow)
+ || (ctrlKind.kind == kControlKindPopupButton))
+ {
+ value = value - long(mParam.ParamInfo().minValue) + 1;
+ }
+ }
+ }
+
+ // special case [2] -- Write-only boolean parameters
+ AudioUnitParameterInfo AUPI = mParam.ParamInfo();
+
+ bool isWriteOnlyBoolParameter = ( (AUPI.unit == kAudioUnitParameterUnit_Boolean) &&
+ (AUPI.flags & kAudioUnitParameterFlag_IsWritable) &&
+ !(AUPI.flags & kAudioUnitParameterFlag_IsReadable) );
+ if (!isWriteOnlyBoolParameter) {
+ SetValue (value);
+ }
+ }
+ break;
+ case kTypeText:
+ {
+ CFStringRef cfstr = mParam.GetStringFromValueCopy(&paramValue);
+
+ if ( !(mParam.ParamInfo().flags & kAudioUnitParameterFlag_IsWritable) //READ ONLY PARAMS
+ && (mParam.ParamInfo().flags & kAudioUnitParameterFlag_IsReadable))
+ {
+ if (mParam.GetParamTag()) {
+ CFMutableStringRef str = CFStringCreateMutableCopy(NULL, 256, cfstr);
+ CFRelease (cfstr);
+ CFStringAppend (str, CFSTR(" "));
+ CFStringAppend (str, mParam.GetParamTag());
+ cfstr = str;
+ }
+ }
+ SetTextValue(cfstr);
+ CFRelease (cfstr);
+ }
+ break;
+ }
+ --mInControlInitialization;
+}
+
+void AUCarbonViewControl::ControlToParameter()
+{
+ 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;
+ }
+}
+
+void AUCarbonViewControl::SetValueFract(double value)
+{
+ 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);
+}
+
+double AUCarbonViewControl::GetValueFract()
+{
+ 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;
+}
+
+void AUCarbonViewControl::SetTextValue(CFStringRef cfstr)
+{
+ verify_noerr(SetControlData(mControl, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), &cfstr));
+}
+
+CFStringRef AUCarbonViewControl::GetTextValue()
+{
+ CFStringRef cfstr;
+ verify_noerr(GetControlData(mControl, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), &cfstr, NULL));
+ return cfstr;
+}
+
+void AUCarbonViewControl::SetValue(long value)
+{
+ SetControl32BitValue(mControl, value);
+}
+
+long AUCarbonViewControl::GetValue()
+{
+ return GetControl32BitValue(mControl);
+}
+
+/* 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)
+{
+ 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();
+ }
+ return kControlKeyFilterBlockKey;
+}
+
+pascal ControlKeyFilterResult AUCarbonViewControl::NumericKeyFilterCallback(ControlRef theControl,
+ SInt16 *keyCode, SInt16 *charCode,
+ EventModifiers *modifiers)
+{
+ 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();
+ }
+ return kControlKeyFilterBlockKey;
+}
+
+Boolean AUCarbonViewControl::SizeControlToFit(ControlRef inControl, SInt16 *outWidth, SInt16 *outHeight)
+{
+ 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;
+
+ 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 ()
+{
+ EventTypeSpec events[] = {
+ { kEventClassControl, kEventControlValueFieldChanged } // N.B. OS X only
+ };
+
+ WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
+}
+
+void AUPropertyControl::EmbedControl (ControlRef theControl)
+{
+ mView->EmbedControl (theControl);
+}
+
+WindowRef AUPropertyControl::GetCarbonWindow()
+{
+ return mView->GetCarbonWindow();
+}
+
+#pragma mark ___AUVPreset
+static CFStringRef kStringFactoryPreset = kAUViewLocalizedStringKey_FactoryPreset;
+static bool sAUVPresetLocalized = false;
+
+AUVPresets::AUVPresets (AUCarbonViewBase* inParentView,
+ CFArrayRef& inPresets,
+ Point inLocation,
+ int nameWidth,
+ int controlWidth,
+ ControlFontStyleRec & inFontStyle)
+ : AUPropertyControl (inParentView),
+ mPresets (inPresets),
+ mView (inParentView)
+{
+ 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;
+
+#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
+
+ EmbedControl (mControl);
+
+ HandlePropertyChange(defaultPreset);
+
+ RegisterEvents();
+}
+
+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 ()
+{
+ 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) );
+ }
+}
+
+void AUVPresets::HandlePropertyChange(AUPreset &preset)
+{
+ // 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);
+}
+
+bool AUVPresets::HandlePropertyChange (const AudioUnitProperty &inProp)
+{
+ if (inProp.mPropertyID == mPropertyID)
+ {
+ UInt32 theSize = sizeof(AUPreset);
+ AUPreset currentPreset;
+
+ OSStatus result = AudioUnitGetProperty(inProp.mAudioUnit,
+ inProp.mPropertyID,
+ inProp.mScope,
+ inProp.mElement, &currentPreset, &theSize);
+
+ if (result == noErr) {
+#ifndef __LP64__
+ if (inProp.mPropertyID == kAudioUnitProperty_CurrentPreset && currentPreset.presetName)
+ CFRetain (currentPreset.presetName);
+#endif
+ HandlePropertyChange(currentPreset);
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h
new file mode 100755
index 00000000..4a7d5d8f
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h
@@ -0,0 +1,224 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __AUCarbonViewControl_h__
+#define __AUCarbonViewControl_h__
+
+#include <Carbon/Carbon.h>
+#include <AudioUnit/AudioUnitCarbonView.h>
+#include <AudioToolbox/AudioUnitUtilities.h>
+#include "CarbonEventHandler.h"
+#include "CAAUParameter.h"
+
+class AUCarbonViewBase;
+
+// ____________________________________________________________________________
+// AUCarbonViewControl
+// Wrapper for a control that is wired to an AudioUnit parameter.
+ /*! @class AUCarbonViewControl */
+class AUCarbonViewControl : public CarbonEventHandler {
+ // note that the controls are never disposed; that's managed by the AUCarbonViewBase's
+ // parent pane which contains all of them ... if we later need to be able to delete
+ // individual controls on the fly, extra work needed
+public:
+ enum ControlType {
+ kTypeContinuous, // e.g. slider
+ kTypeDiscrete, // e.g. pop-up menu
+ kTypeText
+ };
+
+ AUCarbonViewControl(AUCarbonViewBase *ownerView, AUParameterListenerRef listener, ControlType type, const CAAUParameter &param, ControlRef control);
+ ~AUCarbonViewControl();
+
+ /*! @method Bind */
+ virtual void Bind(); // second-stage construction
+
+ /*! @method ControlToParameter */
+ virtual void ControlToParameter();
+ /*! @method ParameterToControl */
+ virtual void ParameterToControl(Float32 newValue);
+
+ /*! @method SetValueFract */
+ virtual void SetValueFract(double value);
+ /*! @method GetValueFract */
+ virtual double GetValueFract();
+ /*! @method SetTextValue */
+ virtual void SetTextValue(CFStringRef str);
+ /*! @method GetTextValue */
+ virtual CFStringRef GetTextValue();
+ /*! @method SetValue */
+ virtual void SetValue(long value);
+ /*! @method GetValue */
+ virtual long GetValue();
+
+ /*! @method GetOwnerView */
+ AUCarbonViewBase * GetOwnerView() {return mOwnerView;}
+
+ /*! @method Update */
+ void Update (bool inUIThread)
+ {
+ if (inUIThread)
+ ParameterToControl (mParam.GetValue());
+ else
+ AUParameterListenerNotify (mListener, this, &mParam);
+ }
+
+
+ // CarbonEventHandler overrides
+ /*! @method HandleEvent */
+ virtual bool HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event);
+
+ /*! @method ControlRef */
+ operator ControlRef() { return mControl; }
+
+ /*! @method SizeControlToFit */
+ static Boolean SizeControlToFit(ControlRef inControl, SInt16 *outWidth = NULL, SInt16 *outHeight = NULL);
+
+ /*! @method SliderTrackProc */
+ static pascal void SliderTrackProc(ControlRef theControl, ControlPartCode partCode);
+ /*! @method NumericKeyFilterCallback */
+ static pascal ControlKeyFilterResult NumericKeyFilterCallback(ControlRef theControl, SInt16 *keyCode, SInt16 *charCode,
+ EventModifiers *modifiers);
+protected:
+ /*! @method ParamInfo */
+ const AudioUnitParameterInfo &ParamInfo() { return mParam.ParamInfo(); }
+
+ /*! @var mOwnerView */
+ AUCarbonViewBase * mOwnerView;
+ /*! @var mListener */
+ AUParameterListenerRef mListener;
+ /*! @var mType */
+ ControlType mType;
+ /*! @var mParam */
+ CAAUParameter mParam;
+
+ /*! @var mControl */
+ ControlRef mControl;
+
+ /*! @method StdKeyFilterCallback */
+ static pascal ControlKeyFilterResult StdKeyFilterCallback(ControlRef theControl, SInt16 *keyCode, SInt16 *charCode,
+ EventModifiers *modifiers);
+ SInt16 mInControlInitialization;
+
+ static AUCarbonViewControl* mLastControl;
+};
+
+ /*! @class AUPropertyControl */
+class AUPropertyControl : public CarbonEventHandler {
+public:
+ /*! @ctor AUPropertyControl */
+ AUPropertyControl (AUCarbonViewBase * inBase) : mControl(0), mView (inBase), mHeight(0) {}
+
+ /*! @method HandleEvent */
+ virtual bool HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event);
+
+ /*! @method HandlePropertyChange */
+ virtual bool HandlePropertyChange (const AudioUnitProperty &inProp) = 0;
+
+ /*! @method AddInterest */
+ virtual void AddInterest (AUEventListenerRef inListener,
+ void * inObject) = 0;
+
+ /*! @method RemoveInterest */
+ virtual void RemoveInterest (AUEventListenerRef inListener,
+ void * inObject) = 0;
+
+ /*! @method GetHeight */
+ int GetHeight() { return mHeight;}
+
+protected:
+ /*! @method HandleControlChange */
+ virtual void HandleControlChange () = 0;
+
+ /*! @method RegisterEvents */
+ void RegisterEvents ();
+
+ /*! @method EmbedControl */
+ void EmbedControl (ControlRef theControl);
+
+ /*! @method GetCarbonWindow */
+ WindowRef GetCarbonWindow();
+
+ /*! @var mControl */
+ ControlRef mControl;
+ /*! @var mView */
+ AUCarbonViewBase* mView;
+ /*! @var mHeight */
+ SInt16 mHeight;
+};
+
+ /*! @class AUVPresets */
+class AUVPresets : public AUPropertyControl {
+public:
+ /*! @ctor HandleControlChange */
+ AUVPresets (AUCarbonViewBase * inBase,
+ CFArrayRef& inPresets,
+ Point inLocation,
+ int nameWidth,
+ int controlWidth,
+ ControlFontStyleRec & inFontStyle);
+
+ virtual ~AUVPresets () { CFRelease (mPresets); }
+
+ /*! @method HandlePropertyChange */
+ virtual bool HandlePropertyChange (const AudioUnitProperty &inProp);
+
+ /*! @method AddInterest */
+ virtual void AddInterest (AUEventListenerRef inListener,
+ void * inObject);
+
+ /*! @method RemoveInterest */
+ virtual void RemoveInterest (AUEventListenerRef inListener,
+ void * inObject);
+
+protected:
+ /*! @method HandleControlChange */
+ virtual void HandleControlChange ();
+
+ /*! @var mPresets */
+ CFArrayRef mPresets;
+ /*! @var mView */
+ AUCarbonViewBase* mView;
+ AudioUnitPropertyID mPropertyID;
+
+ void HandlePropertyChange(AUPreset &preset);
+};
+
+#endif // __AUCarbonViewControl_h__
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp
new file mode 100755
index 00000000..ccba4c93
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp
@@ -0,0 +1,119 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp
new file mode 100755
index 00000000..79da1416
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp
@@ -0,0 +1,343 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <Carbon/Carbon.h>
+#include "AUCarbonViewBase.h"
+#include "AUCarbonViewControl.h"
+#include "AUControlGroup.h"
+#include "AUViewLocalizedStringKeys.h"
+
+#define kSliderThinDimension 10
+#define kLabelAndSliderSpacing 4
+
+static CFStringRef kStringManufacturer = kAUViewLocalizedStringKey_Manufacturer;
+static bool sLocalized = false;
+
+void AUControlGroup::CreateLabelledSlider(
+ AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ Point labelSize,
+ const ControlFontStyleRec & inFontStyle)
+{
+ 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);
+}
+
+void AUControlGroup::CreateLabelledSliderAndEditText(
+ AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ Point labelSize,
+ Point editTextSize,
+ const ControlFontStyleRec & inFontStyle)
+{
+ 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);
+}
+
+void AUControlGroup::CreatePopupMenu (AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ const ControlFontStyleRec & inFontStyle,
+ const bool inSizeToFit)
+{
+ 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);
+}
+
+void AUControlGroup::AddAUInfo ( AUCarbonViewBase * auView,
+ const Point & inLocation,
+ const SInt16 inRightOffset,
+ const SInt16 inTotalWidth)
+{
+ // 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);
+}
+
+
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h
new file mode 100755
index 00000000..9f7ae173
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h
@@ -0,0 +1,84 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __AUControlGroup_h__
+#define __AUControlGroup_h__
+
+#include <Carbon/Carbon.h>
+
+class AUCarbonViewBase;
+class CAAUParameter;
+
+// Utility class to create clusters of controls related to a single parameter
+ /*! @class AUControlGroup */
+class AUControlGroup {
+public:
+ /*! @method CreateLabelledSlider */
+ static void CreateLabelledSlider( AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ Point labelSize,
+ const ControlFontStyleRec & fontStyle);
+
+ /*! @method CreateLabelledSliderAndEditText */
+ static void CreateLabelledSliderAndEditText(
+ AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ Point labelSize,
+ Point editTextSize,
+ const ControlFontStyleRec & fontStyle);
+
+ /*! @method CreatePopupMenu */
+ static void CreatePopupMenu ( AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ const ControlFontStyleRec & inFontStyle,
+ const bool inSizeToFit = false);
+
+ /*! @method AddAUInfo */
+ static void AddAUInfo ( AUCarbonViewBase * auView,
+ const Point & inLocation,
+ const SInt16 inRightOffset,
+ const SInt16 inTotalWidth);
+};
+
+
+#endif // __AUControlGroup_h__
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp
new file mode 100755
index 00000000..15d382aa
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp
@@ -0,0 +1,84 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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 = 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/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h
new file mode 100755
index 00000000..2253ddeb
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h
@@ -0,0 +1,65 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CarbonEventHandler_h__
+#define __CarbonEventHandler_h__
+
+#include <Carbon/Carbon.h>
+
+ /*! @class CarbonEventHandler */
+class CarbonEventHandler {
+public:
+ /*! @ctor CarbonEventHandler */
+ CarbonEventHandler();
+ /*! @dtor ~CarbonEventHandler */
+ virtual ~CarbonEventHandler();
+
+ /*! @method WantEventTypes */
+ virtual void WantEventTypes(EventTargetRef target, UInt32 inNumTypes, const EventTypeSpec *inList);
+
+ /*! @method HandleEvent */
+ virtual bool HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event) = 0;
+
+protected:
+ /*! @var mHandlers */
+ CFMutableDictionaryRef mHandlers;
+};
+
+#endif // __CarbonEventHandler_h__
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp
new file mode 100755
index 00000000..f8bfe39e
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp
@@ -0,0 +1,760 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "AUInstrumentBase.h"
+
+#if DEBUG
+ #define DEBUG_PRINT 0
+ #define DEBUG_PRINT_RENDER 0
+#endif
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const UInt32 kEventQueueSize = 1024;
+
+AUInstrumentBase::AUInstrumentBase(
+ ComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups,
+ UInt32 numParts)
+ : MusicDeviceBase(inInstance, numInputs, numOutputs, numGroups, numParts),
+ mAbsoluteSampleFrame(0),
+ mEventQueue(kEventQueueSize),
+ mNumNotes(0),
+ mNumActiveNotes(0),
+ mMaxActiveNotes(0),
+ mNotes(0),
+ mNoteSize(0)
+{
+#if DEBUG_PRINT
+ printf("new AUInstrumentBase\n");
+#endif
+ mFreeNotes.mState = kNoteState_Free;
+}
+
+
+AUInstrumentBase::~AUInstrumentBase()
+{
+#if DEBUG_PRINT
+ printf("delete AUInstrumentBase\n");
+#endif
+}
+
+AUElement* AUInstrumentBase::CreateElement( AudioUnitScope scope,
+ AudioUnitElement element)
+{
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::CreateElement %d %d\n", scope, element);
+#endif
+ switch (scope)
+ {
+ case kAudioUnitScope_Group :
+ return new SynthGroupElement(this, element);
+ case kAudioUnitScope_Part :
+ return new SynthPartElement(this, element);
+ default :
+ return AUBase::CreateElement(scope, element);
+ }
+}
+
+
+void AUInstrumentBase::SetNotes(UInt32 inNumNotes, UInt32 inMaxActiveNotes, SynthNote* inNotes, UInt32 inNoteDataSize)
+{
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::SetNotes %d %d %08X %d\n", inNumNotes, inMaxActiveNotes, inNotes, inNoteDataSize);
+#endif
+ mNumNotes = inNumNotes;
+ mMaxActiveNotes = inMaxActiveNotes;
+ mNoteSize = inNoteDataSize;
+ mNotes = inNotes;
+
+ for (UInt32 i=0; i<mNumNotes; ++i)
+ {
+ SynthNote *note = GetNote(i);
+ note->Reset();
+ mFreeNotes.AddNote(note);
+ }
+}
+
+UInt32 AUInstrumentBase::CountActiveNotes()
+{
+ // debugging tool.
+ UInt32 sum = 0;
+ for (UInt32 i=0; i<mNumNotes; ++i)
+ {
+ SynthNote *note = GetNote(i);
+ if (note->mState <= kNoteState_Released)
+ sum++;
+ }
+ return sum;
+}
+
+void AUInstrumentBase::AddFreeNote(SynthNote* inNote)
+{
+ if (inNote->mState != kNoteState_FastReleased)
+ DecNumActiveNotes();
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::AddFreeNote mNumActiveNotes %lu\n", 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()
+{
+}
+
+
+OSStatus AUInstrumentBase::Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::Reset\n");
+#endif
+ if (inScope == kAudioUnitScope_Global)
+ {
+ // kill all notes..
+ mFreeNotes.Empty();
+ for (UInt32 i=0; i<mNumNotes; ++i)
+ {
+ SynthNote *note = GetNote(i);
+ if (note->IsSounding())
+ note->Kill(0);
+ note->ListRemove();
+ mFreeNotes.AddNote(note);
+ }
+ mNumActiveNotes = 0;
+ mAbsoluteSampleFrame = 0;
+
+ // empty lists.
+ UInt32 numGroups = Groups().GetNumberOfElements();
+ for (UInt32 j = 0; j < numGroups; ++j)
+ {
+ SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
+ group->Reset();
+ }
+ }
+ return MusicDeviceBase::Reset(inScope, inElement);
+}
+
+void AUInstrumentBase::PerformEvents(const AudioTimeStamp& inTimeStamp)
+{
+#if DEBUG_PRINT_RENDER
+ printf("AUInstrumentBase::PerformEvents\n");
+#endif
+ SynthEvent *event;
+ SynthGroupElement *group;
+
+ while ((event = mEventQueue.ReadItem()) != NULL)
+ {
+#if DEBUG_PRINT_RENDER
+ printf("event %08X %d\n", event, event->GetEventType());
+#endif
+ switch(event->GetEventType())
+ {
+ case SynthEvent::kEventType_NoteOn :
+ RealTimeStartNote(GetElForGroupID (event->GetGroupID()), event->GetNoteID(),
+ event->GetOffsetSampleFrame(), *event->GetParams());
+ break;
+ case SynthEvent::kEventType_NoteOff :
+ RealTimeStopNote(event->GetGroupID(), event->GetNoteID(),
+ event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_SustainOn :
+ group = GetElForGroupID (event->GetGroupID());
+ group->SustainOn(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_SustainOff :
+ group = GetElForGroupID (event->GetGroupID());
+ group->SustainOff(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_SostenutoOn :
+ group = GetElForGroupID (event->GetGroupID());
+ group->SostenutoOn(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_SostenutoOff :
+ group = GetElForGroupID (event->GetGroupID());
+ group->SostenutoOff(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_AllNotesOff :
+ group = GetElForGroupID (event->GetGroupID());
+ group->AllNotesOff(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_AllSoundOff :
+ group = GetElForGroupID (event->GetGroupID());
+ group->AllSoundOff(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_ResetAllControllers :
+ group = GetElForGroupID (event->GetGroupID());
+ group->ResetAllControllers(event->GetOffsetSampleFrame());
+ break;
+ }
+
+ mEventQueue.AdvanceReadPtr();
+ }
+}
+
+
+OSStatus AUInstrumentBase::Render( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames)
+{
+ PerformEvents(inTimeStamp);
+
+ UInt32 numOutputs = Outputs().GetNumberOfElements();
+ for (UInt32 j = 0; j < numOutputs; ++j)
+ {
+ 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(inNumberFrames);
+ 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;
+}
+
+SynthGroupElement * AUInstrumentBase::GetElForGroupID (MusicDeviceGroupID inGroupID)
+{
+ AUScope & groups = Groups();
+ unsigned int numEls = groups.GetNumberOfElements();
+ SynthGroupElement* unassignedEl = NULL;
+
+ for (unsigned int i = 0; i < numEls; ++i) {
+ SynthGroupElement* el = reinterpret_cast<SynthGroupElement*>(groups.GetElement(i));
+ if (el->GroupID() == inGroupID)
+ return el;
+ if (el->GroupID() == SynthGroupElement::kUnassignedGroup) {
+ unassignedEl = el;
+ break; // we fill this up from the start of the group scope vector
+ }
+ }
+ if (unassignedEl) {
+ unassignedEl->SetGroupID(inGroupID);
+ return unassignedEl;
+ }
+ throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement);
+}
+
+OSStatus AUInstrumentBase::RealTimeStopNote(
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame)
+{
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::RealTimeStopNote %d %d\n", inGroupID, inNoteInstanceID);
+#endif
+
+ SynthGroupElement *gp = (inGroupID == kMusicNoteEvent_Unused
+ ? GetElForNoteID (inNoteInstanceID)
+ : GetElForGroupID(inGroupID));
+
+ gp->NoteOff (inNoteInstanceID, inOffsetSampleFrame);
+
+ return noErr;
+}
+
+SynthGroupElement * AUInstrumentBase::GetElForNoteID (NoteInstanceID inNoteID)
+{
+#if DEBUG_PRINT
+ printf("GetElForNoteID id %d\n", (int)inNoteID);
+#endif
+ if (!mNotes) throw std::runtime_error("no notes");
+
+ for (unsigned int i = 0; i < mNumNotes; ++i) {
+ if (inNoteID == mNotes[i].GetNoteID()) {
+ return mNotes[i].GetGroup();
+ }
+ }
+ throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement);
+}
+
+OSStatus AUInstrumentBase::StartNote( MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams)
+{
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::StartNote %d\n", inGroupID);
+#endif
+ OSStatus err = noErr;
+
+ NoteInstanceID noteID;
+ if (outNoteInstanceID) {
+ noteID = NextNoteID();
+ *outNoteInstanceID = noteID;
+ } else
+ noteID = (UInt32)inParams.mPitch;
+
+ 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 %d %d\n", inGroupID, inNoteInstanceID);
+#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);
+ 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)
+{
+ GetControls(inChannel)->mControls[inController] = inValue;
+ 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;
+ }
+ return noErr;
+}
+
+OSStatus AUInstrumentBase::HandlePitchWheel( UInt8 inChannel,
+ UInt8 inPitch1,
+ UInt8 inPitch2,
+ UInt32 inStartFrame)
+{
+ MidiControls* controls = GetControls(inChannel);
+ controls->mPitchBend = (inPitch2 << 7) | inPitch1;
+ controls->mFPitchBend = (float)((SInt16)controls->mPitchBend - 8192) / 8192.;
+ return noErr;
+}
+
+
+OSStatus AUInstrumentBase::HandleChannelPressure(UInt8 inChannel,
+ UInt8 inValue,
+ UInt32 inStartFrame)
+{
+ GetControls(inChannel)->mMonoPressure = inValue;
+ return noErr;
+}
+
+
+OSStatus AUInstrumentBase::HandleProgramChange( UInt8 inChannel,
+ UInt8 inValue)
+{
+ GetControls(inChannel)->mMonoPressure = inValue;
+ return noErr;
+}
+
+
+OSStatus AUInstrumentBase::HandlePolyPressure( UInt8 inChannel,
+ UInt8 inKey,
+ UInt8 inValue,
+ UInt32 inStartFrame)
+{
+ GetControls(inChannel)->mPolyPressure[inKey] = inValue;
+ return noErr;
+}
+
+
+OSStatus AUInstrumentBase::HandleResetAllControllers( UInt8 inChannel)
+{
+ SendPedalEvent (inChannel, SynthEvent::kEventType_ResetAllControllers, 0);
+ return noErr;
+}
+
+
+OSStatus AUInstrumentBase::HandleAllNotesOff( UInt8 inChannel)
+{
+ SendPedalEvent (inChannel, SynthEvent::kEventType_AllNotesOff, 0);
+ return noErr;
+}
+
+
+OSStatus AUInstrumentBase::HandleAllSoundOff( UInt8 inChannel)
+{
+ SendPedalEvent (inChannel, SynthEvent::kEventType_AllSoundOff, 0);
+ return noErr;
+}
+
+SynthNote* AUInstrumentBase::GetAFreeNote(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("GetAFreeNote size %d\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
+ printf("enter voice stealing\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
+ printf(" steal 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
+ printf(" steal group %d size %d\n", j, group->mNoteList[i].Length());
+#endif
+ if (group->mNoteList[i].NotEmpty()) {
+#if DEBUG_PRINT
+ printf("not empty %d %d\n", i, j);
+#endif
+ SynthNote *note = group->mNoteList[i].FindMostQuietNote();
+ if (inKillIt) {
+#if DEBUG_PRINT
+ printf("--=== KILL ===---\n");
+#endif
+ note->mRelativeKillFrame = inFrame;
+ note->Kill(inFrame);
+ group->mNoteList[i].RemoveNote(note);
+ if (i != kNoteState_FastReleased)
+ DecNumActiveNotes();
+ return note;
+ } else {
+#if DEBUG_PRINT
+ printf("--=== 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
+ 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(
+ ComponentInstance 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;
+
+ IncNumActiveNotes();
+ note->AttackNote(NULL, inGroup, inNoteInstanceID,
+ mAbsoluteSampleFrame + inOffsetSampleFrame, inOffsetSampleFrame, inParams);
+
+ inGroup->mNoteList[kNoteState_Attacked].AddNote(note);
+ return noErr;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+OSStatus AUMultitimbralInstrumentBase::GetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus result = noErr;
+
+ switch (inID)
+ {
+ case kMusicDeviceProperty_PartGroup:
+ if (inScope != kAudioUnitScope_Part) return kAudioUnitErr_InvalidScope;
+ outDataSize = sizeof(UInt32);
+ outWritable = true;
+ break;
+
+ 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)
+ {
+ case kMusicDeviceProperty_PartGroup:
+ if (inScope != kAudioUnitScope_Group) return kAudioUnitErr_InvalidScope;
+ // ??
+ return -1; //unimpl
+ break;
+
+ 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)
+ {
+ case kMusicDeviceProperty_PartGroup:
+ if (inScope != kAudioUnitScope_Group) return kAudioUnitErr_InvalidScope;
+ // ??
+ return -1; //unimpl
+ break;
+
+ default:
+ result = MusicDeviceBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
+ }
+
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h
new file mode 100755
index 00000000..8f779cbf
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h
@@ -0,0 +1,246 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __AUInstrumentBase__
+#define __AUInstrumentBase__
+
+#include <vector>
+#include <stdexcept>
+#include <AudioUnit/AudioUnit.h>
+#include <CoreAudio/CoreAudio.h>
+#include "MusicDeviceBase.h"
+#include "LockFreeFIFO.h"
+#include "SynthEvent.h"
+#include "SynthNote.h"
+#include "SynthElement.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+typedef LockFreeFIFOWithFree<SynthEvent> SynthEventQueue;
+
+class AUInstrumentBase : public MusicDeviceBase
+{
+public:
+ AUInstrumentBase(
+ ComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups = 32,
+ UInt32 numParts = 0);
+ virtual ~AUInstrumentBase();
+
+ virtual OSStatus Initialize();
+
+ virtual void Cleanup();
+
+ virtual AUElement* CreateElement( AudioUnitScope scope,
+ AudioUnitElement element);
+
+ 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 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);
+
+ MidiControls* GetControls( MusicDeviceGroupID inChannel)
+ {
+ SynthGroupElement *group = GetElForGroupID(inChannel);
+ return &(group->mMidiControls);
+ }
+
+
+protected:
+
+ UInt32 NextNoteID() { return IncrementAtomic(&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();
+ // this call throws if there's no assigned element for the group ID
+ SynthGroupElement * GetElForGroupID (MusicDeviceGroupID inGroupID);
+ SynthGroupElement * GetElForNoteID (NoteInstanceID inNoteID);
+
+ SInt64 mAbsoluteSampleFrame;
+
+
+private:
+
+ SInt32 mNoteIDCounter;
+
+ SynthEventQueue mEventQueue;
+
+ UInt32 mNumNotes;
+ UInt32 mNumActiveNotes;
+ UInt32 mMaxActiveNotes;
+ SynthNote* mNotes;
+ SynthNoteList mFreeNotes;
+ UInt32 mNoteSize;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class AUMonotimbralInstrumentBase : public AUInstrumentBase
+{
+public:
+ AUMonotimbralInstrumentBase(
+ ComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups = 32,
+ UInt32 numParts = 0);
+
+ 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(
+ ComponentInstance 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/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h
new file mode 100755
index 00000000..50f97771
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h
@@ -0,0 +1,167 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <Carbon/Carbon.h>
+
+
+template <class ITEM>
+class LockFreeFIFOWithFree
+{
+ LockFreeFIFOWithFree(); // private, unimplemented.
+public:
+ LockFreeFIFOWithFree(UInt32 inMaxSize)
+ : mReadIndex(0), mWriteIndex(0), mFreeIndex(0)
+ {
+ //assert(IsPowerOfTwo(inMaxSize));
+ mItems = new ITEM[inMaxSize];
+ mMask = inMaxSize - 1;
+ }
+
+ ~LockFreeFIFOWithFree()
+ {
+ delete [] mItems;
+ }
+
+
+ void Reset()
+ {
+ FreeItems();
+ mReadIndex = 0;
+ mWriteIndex = 0;
+ mFreeIndex = 0;
+ }
+
+ ITEM* WriteItem()
+ {
+ //printf("WriteItem %d %d\n", mReadIndex, mWriteIndex);
+ FreeItems(); // free items on the write thread.
+ UInt32 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];
+ }
+
+ // 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() { CompareAndSwap(mWriteIndex, (mWriteIndex + 1) & mMask, (UInt32*)&mWriteIndex); }
+ void AdvanceReadPtr() { CompareAndSwap(mReadIndex, (mReadIndex + 1) & mMask, (UInt32*)&mReadIndex); }
+
+private:
+ ITEM* FreeItem()
+ {
+ if (mFreeIndex == mReadIndex) return NULL;
+ return &mItems[mFreeIndex];
+ }
+ void AdvanceFreePtr() { CompareAndSwap(mFreeIndex, (mFreeIndex + 1) & mMask, (UInt32*)&mFreeIndex); }
+
+ void FreeItems()
+ {
+ ITEM* item;
+ while ((item = FreeItem()) != NULL)
+ {
+ item->Free();
+ AdvanceFreePtr();
+ }
+ }
+
+ volatile UInt32 mReadIndex, mWriteIndex, mFreeIndex;
+ UInt32 mMask;
+ ITEM *mItems;
+};
+
+
+
+// Same as above but no free.
+
+template <class ITEM>
+class LockFreeFIFO
+{
+ LockFreeFIFO(); // private, unimplemented.
+public:
+ LockFreeFIFO(UInt32 inMaxSize)
+ : mReadIndex(0), mWriteIndex(0)
+ {
+ //assert(IsPowerOfTwo(inMaxSize));
+ mItems = new ITEM[inMaxSize];
+ mMask = inMaxSize - 1;
+ }
+
+ ~LockFreeFIFO()
+ {
+ delete [] mItems;
+ }
+
+ void Reset()
+ {
+ mReadIndex = 0;
+ mWriteIndex = 0;
+ }
+
+ ITEM* WriteItem()
+ {
+ UInt32 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() { CompareAndSwap(mWriteIndex, (mWriteIndex + 1) & mMask, (UInt32*)&mWriteIndex); }
+ void AdvanceReadPtr() { CompareAndSwap(mReadIndex, (mReadIndex + 1) & mMask, (UInt32*)&mReadIndex); }
+
+private:
+
+ volatile UInt32 mReadIndex, mWriteIndex;
+ UInt32 mMask;
+ ITEM *mItems;
+};
+
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp
new file mode 100755
index 00000000..d16f8e87
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp
@@ -0,0 +1,266 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "SynthElement.h"
+#include "AUInstrumentBase.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+MidiControls::MidiControls()
+{
+ Reset();
+}
+
+void MidiControls::Reset()
+{
+ memset(this, 0, sizeof(MidiControls));
+ mControls[kMidiController_Pan] = 64;
+ mControls[kMidiController_Expression] = 127;
+ mPitchBendDepth = 2 << 7;
+ mFPitchBendDepth = 2.;
+}
+
+
+SynthElement::SynthElement(AUInstrumentBase *audioUnit, UInt32 inElement)
+ : AUElement(audioUnit), mName(0), mIndex(inElement)
+{
+}
+
+SynthElement::~SynthElement()
+{
+ if (mName) CFRelease(mName);
+}
+
+SynthGroupElement::SynthGroupElement(AUInstrumentBase *audioUnit, UInt32 inElement)
+ : SynthElement(audioUnit, inElement), mSustainIsOn(false), mSostenutoIsOn(false), mOutputBus(0), mGroupID(kUnassignedGroup)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::SynthGroupElement %d\n", inElement);
+#endif
+ for (UInt32 i=0; i<kNumberOfSoundingNoteStates; ++i)
+ mNoteList[i].mState = i;
+}
+
+void SynthGroupElement::SetGroupID (MusicDeviceGroupID inGroup)
+{
+ // can't re-assign a group once its been assigned
+ if (mGroupID != kUnassignedGroup) throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement);
+ mGroupID = inGroup;
+}
+
+void SynthGroupElement::Reset()
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::Reset\n");
+#endif
+ mMidiControls.Reset();
+ for (UInt32 i=0; i<kNumberOfSoundingNoteStates; ++i)
+ mNoteList[i].Empty();
+}
+
+SynthPartElement::SynthPartElement(AUInstrumentBase *audioUnit, UInt32 inElement)
+ : SynthElement(audioUnit, inElement)
+{
+}
+
+void SynthGroupElement::NoteOff(NoteInstanceID inNoteID, UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::NoteOff %d\n", inNoteID);
+#endif
+ SynthNote *note = mNoteList[kNoteState_Attacked].mHead;
+ // see if this note is attacked.
+ while (note && note->mNoteID != inNoteID)
+ {
+#if DEBUG_PRINT
+ printf(" ? %08X %d\n", note, note->mNoteID);
+#endif
+ note = note->mNext;
+ }
+
+#if DEBUG_PRINT
+ printf(" found %08X\n", note);
+#endif
+ if (note)
+ {
+#if DEBUG_PRINT
+ printf(" old state %d\n", note->mState);
+#endif
+ mNoteList[kNoteState_Attacked].RemoveNote(note);
+ note->Release(inFrame);
+ if (mSustainIsOn) {
+ mNoteList[kNoteState_ReleasedButSustained].AddNote(note);
+ } else {
+ mNoteList[kNoteState_Released].AddNote(note);
+ }
+#if DEBUG_PRINT
+ printf(" new state %d\n", note->mState);
+#endif
+ }
+ else if (mSostenutoIsOn)
+ {
+ // see if this note is sostenutoed.
+ note = mNoteList[kNoteState_Sostenutoed].mHead;
+ while (note && note->mNoteID != inNoteID)
+ note = note->mNext;
+ if (note)
+ {
+ mNoteList[kNoteState_Sostenutoed].RemoveNote(note);
+ mNoteList[kNoteState_ReleasedButSostenutoed].AddNote(note);
+ }
+ }
+}
+
+void SynthGroupElement::NoteEnded(SynthNote *inNote, UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::NoteEnded %d %d\n", inNote->mNoteID, inNote->mState);
+#endif
+ SynthNoteList *list = mNoteList + inNote->mState;
+ list->RemoveNote(inNote);
+
+ GetAUInstrument()->AddFreeNote(inNote);
+}
+
+void SynthGroupElement::SostenutoOn(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::SostenutoOn\n");
+#endif
+ mSostenutoIsOn = true;
+ mNoteList[kNoteState_Sostenutoed].TransferAllFrom(&mNoteList[kNoteState_Attacked], inFrame);
+}
+
+void SynthGroupElement::SostenutoOff(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::SostenutoOff\n");
+#endif
+ 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
+ mSustainIsOn = true;
+}
+
+void SynthGroupElement::SustainOff(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::SustainOff\n");
+#endif
+ 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<kNumberOfActiveNoteStates; ++i)
+ {
+ note = mNoteList[i].mHead;
+ while (note)
+ {
+ SynthNote *nextNote = note->mNext;
+
+ mNoteList[i].RemoveNote(note);
+ note->FastRelease(inFrame);
+ mNoteList[kNoteState_FastReleased].AddNote(note);
+
+ note = nextNote;
+ }
+ }
+}
+
+void SynthGroupElement::AllSoundOff(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::AllSoundOff\n");
+#endif
+ AllNotesOff(inFrame);
+}
+
+void SynthGroupElement::ResetAllControllers(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::ResetAllControllers\n");
+#endif
+ mMidiControls.Reset();
+}
+
+OSStatus SynthGroupElement::Render(UInt32 inNumberFrames)
+{
+ SynthNote *note;
+ AudioBufferList& bufferList = GetAudioUnit()->GetOutput(mOutputBus)->GetBufferList();
+
+ for (UInt32 i=0 ; i<kNumberOfSoundingNoteStates; ++i)
+ {
+ note = mNoteList[i].mHead;
+ while (note)
+ {
+#if DEBUG_PRINT
+ printf(" note %d %08X %d\n", i, note, inNumberFrames);
+#endif
+ SynthNote *nextNote = note->mNext;
+
+ OSStatus err = note->Render(inNumberFrames, bufferList);
+ if (err) return err;
+
+ note = nextNote;
+ }
+ }
+
+ return noErr;
+}
+
+
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h
new file mode 100755
index 00000000..a1170730
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h
@@ -0,0 +1,262 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __SynthElement__
+#define __SynthElement__
+
+#include <Carbon/Carbon.h>
+#include <AudioUnit/AudioUnit.h>
+#include "MusicDeviceBase.h"
+#include "SynthNoteList.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(); }
+
+ CFStringRef GetName() const { return mName; }
+ void SetName(CFStringRef inName)
+ {
+ CFStringRef oldName = mName;
+ mName = inName;
+ CFRetain(mName);
+ if (oldName) CFRelease(oldName);
+ }
+private:
+ CFStringRef mName;
+ UInt32 mIndex;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+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_AllSoundOff = 120,
+ kMidiController_ResetAllControllers = 121,
+ kMidiController_AllNotesOff = 123
+};
+
+struct MidiControls
+{
+ MidiControls();
+ void Reset();
+
+ 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;
+
+ SInt16 GetHiResControl(UInt32 inIndex) const
+ {
+ return ((mControls[inIndex] & 127) << 7) | (mControls[inIndex + 32] & 127);
+ }
+
+ void SetHiResControl(UInt32 inIndex, UInt8 inMSB, UInt8 inLSB)
+ {
+ mControls[inIndex] = inMSB;
+ mControls[inIndex + 32] = inLSB;
+ }
+
+ float GetControl(UInt32 inIndex) const
+ {
+ if (inIndex < 32) {
+ return (float)mControls[inIndex] + (float)mControls[inIndex + 32] / 127.;
+ } else {
+ return (float)mControls[inIndex];
+ }
+ }
+
+ float PitchBend() const { return mFPitchBend * mFPitchBendDepth; }
+
+};
+
+
+class SynthGroupElement : public SynthElement
+{
+public:
+ enum {
+ kUnassignedGroup = 0xFFFFFFFF
+ };
+
+ SynthGroupElement(AUInstrumentBase *audioUnit, UInt32 inElement);
+
+ void NoteOff(NoteInstanceID inNoteID, UInt32 inFrame);
+ void SustainOn(UInt32 inFrame);
+ void SustainOff(UInt32 inFrame);
+ void SostenutoOn(UInt32 inFrame);
+ void SostenutoOff(UInt32 inFrame);
+
+ void NoteEnded(SynthNote *inNote, UInt32 inFrame);
+
+ void AllNotesOff(UInt32 inFrame);
+ void AllSoundOff(UInt32 inFrame);
+ void ResetAllControllers(UInt32 inFrame);
+
+ UInt32 GetOutputBus() const { return mOutputBus; }
+ void SetOutputBus(UInt32 inBus) { mOutputBus = inBus; }
+
+ void Reset();
+
+ virtual OSStatus Render(UInt32 inNumberFrames);
+
+ float GetControl(UInt32 inIndex) const { return mMidiControls.GetControl(inIndex); }
+ float PitchBend() const { return mMidiControls.PitchBend(); }
+
+ MusicDeviceGroupID GroupID () const { return mGroupID; }
+ void SetGroupID (MusicDeviceGroupID inGroup);
+
+private:
+ friend class AUInstrumentBase;
+ friend class AUMonotimbralInstrumentBase;
+ friend class AUMultitimbralInstrumentBase;
+
+ MidiControls mMidiControls;
+
+ bool mSustainIsOn;
+ bool mSostenutoIsOn;
+ UInt32 mOutputBus;
+ MusicDeviceGroupID mGroupID;
+
+
+ SynthNoteList mNoteList[kNumberOfSoundingNoteStates];
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+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;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline AUInstrumentBase* SynthNote::GetAudioUnit() const
+ {
+ return (AUInstrumentBase*)mGroup->GetAudioUnit();
+ }
+
+inline Float32 SynthNote::GetGlobalParameter(AudioUnitParameterID inParamID) const
+ {
+ return mGroup->GetAudioUnit()->Globals()->GetParameter(inParamID);
+ }
+
+inline void SynthNote::NoteEnded(UInt32 inFrame)
+ {
+ mGroup->NoteEnded(this, inFrame);
+ mNoteID = 0xFFFFFFFF;
+ }
+
+inline float SynthNote::PitchBend() const
+ {
+ return mGroup->PitchBend();
+ }
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#endif
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h
new file mode 100755
index 00000000..86a439ad
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h
@@ -0,0 +1,140 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+/* You can either fill in code here or remove this and create or add new files. */
+
+#ifndef __SynthEvent__
+#define __SynthEvent__
+
+#include <Carbon/Carbon.h>
+#include <AudioUnit/AudioUnit.h>
+#include <CoreAudio/CoreAudio.h>
+#include "MusicDeviceBase.h"
+#include <stdexcept>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+class SynthEvent
+{
+public:
+ enum {
+ kEventType_NoteOn = 1,
+ kEventType_NoteOff = 2,
+ kEventType_SustainOn = 3,
+ kEventType_SustainOff = 4,
+ kEventType_SostenutoOn = 5,
+ kEventType_SostenutoOff = 6,
+ kEventType_AllNotesOff = 7,
+ kEventType_AllSoundOff = 8,
+ kEventType_ResetAllControllers = 9
+ };
+
+
+ SynthEvent() {}
+ ~SynthEvent() {}
+
+ void Set(
+ UInt32 inEventType,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams* inNoteParams
+ )
+ {
+ mEventType = inEventType;
+ mGroupID = inGroupID;
+ mNoteID = inNoteID;
+ mOffsetSampleFrame = inOffsetSampleFrame;
+
+ if (inNoteParams)
+ {
+ UInt32 paramSize = offsetof(MusicDeviceNoteParams, mControls) + (inNoteParams->argCount-2)*sizeof(NoteParamsControlValue);
+ mNoteParams = inNoteParams->argCount > 3
+ ? (MusicDeviceNoteParams*)malloc(paramSize)
+ : &mSmallNoteParams;
+ memcpy(mNoteParams, inNoteParams, paramSize);
+ }
+ else
+ mNoteParams = NULL;
+ }
+
+
+ void Free()
+ {
+ if (mNoteParams)
+ {
+ if (mNoteParams->argCount > 3)
+ free(mNoteParams);
+ mNoteParams = NULL;
+ }
+ }
+
+ UInt32 GetEventType() const { return mEventType; }
+ MusicDeviceGroupID GetGroupID() const { return mGroupID; }
+ NoteInstanceID GetNoteID() const { return mNoteID; }
+ UInt32 GetOffsetSampleFrame() const { return mOffsetSampleFrame; }
+
+ MusicDeviceNoteParams* GetParams() const { return mNoteParams; }
+
+ UInt32 GetArgCount() const { return mNoteParams->argCount; }
+ UInt32 NumberParameters() const { return mNoteParams->argCount - 2; }
+
+ Float32 GetNote() const { return mNoteParams->mPitch; }
+ Float32 GetVelocity() const { return mNoteParams->mVelocity; }
+
+ NoteParamsControlValue GetParameter(UInt32 inIndex) const
+ {
+ if (inIndex >= NumberParameters())
+ throw std::runtime_error("index out of range");
+ return mNoteParams->mControls[inIndex];
+ }
+
+private:
+ UInt32 mEventType;
+ MusicDeviceGroupID mGroupID;
+ NoteInstanceID mNoteID;
+ UInt32 mOffsetSampleFrame;
+ MusicDeviceNoteParams* mNoteParams;
+ MusicDeviceNoteParams mSmallNoteParams; // inline a small one to eliminate malloc for the simple case.
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#endif
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp
new file mode 100755
index 00000000..a3c838ca
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp
@@ -0,0 +1,113 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "SynthNote.h"
+#include "SynthElement.h"
+#include "AUInstrumentBase.h"
+
+void SynthNote::AttackNote(
+ SynthPartElement * inPart,
+ SynthGroupElement * inGroup,
+ NoteInstanceID inNoteID,
+ SInt64 inAbsoluteSampleFrame,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams)
+{
+#if DEBUG_PRINT
+ printf("SynthNote::AttackNote %d %d %d\n", inPart, inGroup->GroupID(), inNoteID);
+#endif
+ mPart = inPart;
+ mGroup = inGroup;
+ mNoteID = inNoteID;
+
+ mAbsoluteStartFrame = inAbsoluteSampleFrame;
+ mRelativeStartFrame = inOffsetSampleFrame;
+ mRelativeReleaseFrame = -1;
+ mRelativeKillFrame = -1;
+
+ mPitch = inParams.mPitch;
+ mVelocity = inParams.mVelocity;
+
+
+ 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. + PitchBend()) / 12.);
+}
+
+double SynthNote::SampleRate()
+{
+ return GetAudioUnit()->GetOutput(0)->GetStreamFormat().mSampleRate;
+}
+
+
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h
new file mode 100755
index 00000000..afb1730d
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h
@@ -0,0 +1,170 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __SynthNote__
+#define __SynthNote__
+
+#include <Carbon/Carbon.h>
+#include <AudioUnit/AudioUnit.h>
+#include <CoreAudio/CoreAudio.h>
+#include "MusicDeviceBase.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+enum {
+ 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
+};
+
+/*
+ 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), mState(kNoteState_Free),
+ mRelativeStartFrame(0),
+ mRelativeReleaseFrame(-1),
+ mRelativeKillFrame(-1)
+ {
+ }
+
+ virtual ~SynthNote() {}
+
+ virtual void Reset();
+ virtual void AttackNote(
+ SynthPartElement * inPart,
+ SynthGroupElement * inGroup,
+ NoteInstanceID inNoteID,
+ SInt64 inAbsoluteSampleFrame,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams
+ );
+
+ virtual OSStatus Render(UInt32 inNumFrames, AudioBufferList& inBufferList)=0;
+ virtual void 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; }
+ UInt32 GetState() const { return mState; }
+ Boolean IsSounding() const { return mState < kNumberOfSoundingNoteStates; }
+ Boolean IsActive() const { return mState < kNumberOfActiveNoteStates; }
+ SInt64 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 PitchBend() const;
+ double TuningA() const;
+
+ virtual double Frequency(); // returns the frequency of note + pitch bend.
+ double SampleRate();
+
+//private:
+// friend class NoteList;
+
+ // linked list pointers
+ SynthNote *mPrev;
+ SynthNote *mNext;
+
+ SynthPartElement* mPart;
+ SynthGroupElement* mGroup;
+
+ NoteInstanceID mNoteID;
+ UInt32 mState;
+ SInt64 mAbsoluteStartFrame;
+ SInt32 mRelativeStartFrame;
+ SInt32 mRelativeReleaseFrame;
+ SInt32 mRelativeKillFrame;
+
+ Float32 mPitch;
+ Float32 mVelocity;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#endif
+
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp
new file mode 100755
index 00000000..a5ee505b
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp
@@ -0,0 +1,87 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "SynthNoteList.h"
+#include <stdexcept>
+
+void SynthNoteList::SanityCheck() const
+{
+ if (mState >= kNumberOfNoteStates) {
+ throw std::runtime_error("mState is bad");
+ }
+
+ if (mHead == NULL) {
+ if (mTail != NULL)
+ throw std::runtime_error("mHead is NULL but not mTail");
+ return;
+ }
+ if (mTail == NULL) {
+ throw std::runtime_error("mTail is NULL but not mHead");
+ }
+
+ if (mHead->mPrev) {
+ throw std::runtime_error("mHead has a mPrev");
+ }
+ if (mTail->mNext) {
+ throw std::runtime_error("mTail has a mNext");
+ }
+
+ SynthNote *note = mHead;
+ while (note)
+ {
+ if (note->mState != mState)
+ throw std::runtime_error("note in wrong state");
+ if (note->mNext) {
+ if (note->mNext->mPrev != note)
+ throw std::runtime_error("bad link 1");
+ } else {
+ if (mTail != note)
+ throw std::runtime_error("note->mNext is nil, but mTail != note");
+ }
+ if (note->mPrev) {
+ if (note->mPrev->mNext != note)
+ throw std::runtime_error("bad link 2");
+ } else {
+ if (mHead != note)
+ throw std::runtime_error("note->mPrev is nil, but mHead != note");
+ }
+ note = note->mNext;
+ }
+}
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h
new file mode 100755
index 00000000..5ab7ffa0
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h
@@ -0,0 +1,226 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __SynthNoteList__
+#define __SynthNoteList__
+
+#include "SynthNote.h"
+
+#if DEBUG
+#ifndef DEBUG_PRINT
+ #define DEBUG_PRINT 0
+#endif
+ #define SANITY_CHECK 0
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+struct SynthNoteList
+{
+ SynthNoteList() : mState(0xFFFFFFFF), mHead(0), mTail(0) {}
+
+ bool NotEmpty() const { return mHead != NULL; }
+ bool IsEmpty() const { return mHead == NULL; }
+ void Empty() {
+#if SANITY_CHECK
+ SanityCheck();
+#endif
+ mHead = mTail = NULL;
+ }
+
+ UInt32 Length() const {
+#if 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 %d %08X\n", mState, inNote);
+#endif
+#if SANITY_CHECK
+ SanityCheck();
+#endif
+ inNote->mState = mState;
+ inNote->mNext = mHead;
+ inNote->mPrev = NULL;
+
+ if (mHead) { mHead->mPrev = inNote; mHead = inNote; }
+ else mHead = mTail = inNote;
+#if SANITY_CHECK
+ SanityCheck();
+#endif
+ }
+
+ void RemoveNote(SynthNote *inNote)
+ {
+#if DEBUG_PRINT
+ printf("RemoveNote\n");
+#endif
+#if 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 SANITY_CHECK
+ SanityCheck();
+#endif
+ }
+
+ void TransferAllFrom(SynthNoteList *inNoteList, UInt32 inFrame)
+ {
+#if DEBUG_PRINT
+ printf("TransferAllFrom\n");
+#endif
+#if 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 release %08X\n", note);
+#endif
+ note->mState = mState;
+ note->Release(inFrame);
+ }
+ }
+ else
+ {
+ for (SynthNote* note = inNoteList->mHead; note; note = note->mNext)
+ {
+ note->mState = 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 SANITY_CHECK
+ SanityCheck();
+ inNoteList->SanityCheck();
+#endif
+ }
+
+ SynthNote* FindOldestNote()
+ {
+#if DEBUG_PRINT
+ printf("FindOldestNote\n");
+#endif
+#if SANITY_CHECK
+ SanityCheck();
+#endif
+ SInt64 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 = 1e9;
+ SInt64 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 SANITY_CHECK
+ SanityCheck();
+#endif
+ return mostQuietNote;
+ }
+
+ void SanityCheck() const;
+
+ UInt32 mState;
+ SynthNote *mHead;
+ SynthNote *mTail;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h
new file mode 100755
index 00000000..7f1a8106
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h
@@ -0,0 +1,82 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp
new file mode 100755
index 00000000..1931dd72
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp
@@ -0,0 +1,483 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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)
+{
+}
+
+//_____________________________________________________________________________
+//
+AUEffectBase::~AUEffectBase()
+{
+ Cleanup();
+}
+
+//_____________________________________________________________________________
+//
+void AUEffectBase::Cleanup()
+{
+ for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end(); ++it)
+ delete *it;
+
+ mKernelList.clear();
+}
+
+
+//_____________________________________________________________________________
+//
+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();
+
+
+
+ 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()
+{
+ UInt32 nChannels = GetNumberOfChannels();
+
+ if (mKernelList.size() < nChannels) {
+ mKernelList.reserve(nChannels);
+ for (UInt32 i = mKernelList.size(); i < nChannels; ++i)
+ mKernelList.push_back(NewKernel());
+ } else
+ while (mKernelList.size() > nChannels) {
+ AUKernelBase *kernel = mKernelList.back();
+ delete kernel;
+ mKernelList.pop_back();
+ }
+
+ for(unsigned int i = 0; i < nChannels; 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;
+
+ // 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 * inSliceFramesToProcess * sizeof(AudioUnitSampleType));
+ }
+
+ for(unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
+ outputBufferList.mBuffers[i].mDataByteSize =
+ (outputBufferList.mBuffers[i].mNumberChannels * inSliceFramesToProcess * sizeof(AudioUnitSampleType));
+ }
+ // 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 =
+ (AudioUnitSampleType *)inputBufferList.mBuffers[i].mData + inputBufferList.mBuffers[i].mNumberChannels * inSliceFramesToProcess;
+ }
+
+ for(unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
+ outputBufferList.mBuffers[i].mData =
+ (AudioUnitSampleType *)outputBufferList.mBuffers[i].mData + outputBufferList.mBuffers[i].mNumberChannels * inSliceFramesToProcess;
+ }
+
+ return result;
+}
+
+// ____________________________________________________________________________
+//
+
+OSStatus AUEffectBase::Render( AudioUnitRenderActionFlags &ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 nFrames)
+{
+ if (!HasInput(0))
+ return kAudioUnitErr_NoConnection;
+
+ OSStatus result = noErr;
+ AUOutputElement *theOutput = GetOutput(0); // throws if error
+
+ AUInputElement *theInput = GetInput(0);
+ result = theInput->PullInput(ioActionFlags, inTimeStamp, 0 /* element */, nFrames);
+
+ if (result == noErr)
+ {
+ if(ProcessesInPlace() && theOutput->WillAllocateBuffer())
+ {
+ theOutput->SetBufferList(theInput->GetBufferList() );
+ }
+
+ if (ShouldBypassEffect())
+ {
+ // leave silence bit alone
+
+ if(!ProcessesInPlace() )
+ {
+ theInput->CopyBufferContentsTo (theOutput->GetBufferList());
+ }
+ }
+ else
+ {
+ if(mParamList.size() == 0 )
+ {
+ // this will read/write silence bit
+ result = ProcessBufferLists(ioActionFlags, theInput->GetBufferList(), theOutput->GetBufferList(), nFrames);
+ }
+ else
+ {
+ // deal with scheduled parameters...
+
+ AudioBufferList &inputBufferList = theInput->GetBufferList();
+ AudioBufferList &outputBufferList = theOutput->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
+ for(unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
+ inputBufferList.mBuffers[i].mData =
+ (AudioUnitSampleType *)inputBufferList.mBuffers[i].mData - inputBufferList.mBuffers[i].mNumberChannels * nFrames;
+ inputBufferList.mBuffers[i].mDataByteSize =
+ (inputBufferList.mBuffers[i].mNumberChannels * nFrames * sizeof(AudioUnitSampleType));
+ }
+
+ for(unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
+ outputBufferList.mBuffers[i].mData =
+ (AudioUnitSampleType *)outputBufferList.mBuffers[i].mData - outputBufferList.mBuffers[i].mNumberChannels * nFrames;
+ outputBufferList.mBuffers[i].mDataByteSize =
+ (outputBufferList.mBuffers[i].mNumberChannels * nFrames * sizeof(AudioUnitSampleType));
+ }
+ }
+ }
+
+ if ( (ioActionFlags & kAudioUnitRenderAction_OutputIsSilence) && !ProcessesInPlace() )
+ {
+ AUBufferList::ZeroBuffer(theOutput->GetBufferList() );
+ }
+ }
+
+ return result;
+}
+
+OSStatus AUEffectBase::ProcessBufferLists(
+ 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) {
+ // interleaved (or mono)
+ int channel = 0;
+
+ for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end(); ++it, ++channel) {
+ AUKernelBase *kernel = *it;
+
+ if (kernel != NULL) {
+ ioSilence = silentInput;
+
+ // process each interleaved channel individually
+ kernel->Process(
+ (const AudioUnitSampleType *)inBuffer.mBuffers[0].mData + channel,
+ (AudioUnitSampleType *)outBuffer.mBuffers[0].mData + channel,
+ inFramesToProcess,
+ inBuffer.mBuffers[0].mNumberChannels,
+ ioSilence);
+
+ if (!ioSilence)
+ ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence;
+ }
+ }
+ } else {
+ // deinterleaved
+ const AudioBuffer *srcBuffer = inBuffer.mBuffers;
+ AudioBuffer *destBuffer = outBuffer.mBuffers;
+
+ for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end();
+ ++it, ++srcBuffer, ++destBuffer) {
+ AUKernelBase *kernel = *it;
+
+ if (kernel != NULL) {
+ ioSilence = silentInput;
+
+ kernel->Process(
+ (const AudioUnitSampleType *)srcBuffer->mData,
+ (AudioUnitSampleType *)destBuffer->mData,
+ inFramesToProcess,
+ 1,
+ ioSilence);
+
+ if (!ioSilence)
+ ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence;
+ }
+ }
+ }
+
+ return noErr;
+}
+
+Float64 AUEffectBase::GetSampleRate()
+{
+ return GetOutput(0)->GetStreamFormat().mSampleRate;
+}
+
+UInt32 AUEffectBase::GetNumberOfChannels()
+{
+ return GetOutput(0)->GetStreamFormat().mChannelsPerFrame;
+}
+
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUEffectBase.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUEffectBase.h
new file mode 100755
index 00000000..886963d7
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUEffectBase.h
@@ -0,0 +1,269 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __AUEffectBase_h__
+#define __AUEffectBase_h__
+
+#include "AUBase.h"
+#include "AUSilentTimeout.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 */
+ void SetParameter( AudioUnitParameterID paramID,
+ AudioUnitParameterValue value)
+ {
+ Globals()->SetParameter(paramID, value);
+ }
+
+ /*! @method GetParameter */
+ AudioUnitParameterValue GetParameter( AudioUnitParameterID paramID )
+ {
+ return Globals()->GetParameter(paramID );
+ }
+
+ /*! @method IsBypassEffect */
+ // This is used for the property value - to reflect to the UI if an effect is bypassed
+ bool IsBypassEffect () { return mBypassEffect; }
+
+protected:
+
+ /*! @method MaintainKernels */
+ void MaintainKernels();
+
+ /*! @method ShouldBypassEffect */
+ // This is used in the render call to see if an effect is bypassed
+ // It can return a different status than IsBypassEffect (though it MUST take that into account)
+ virtual bool ShouldBypassEffect () { return IsBypassEffect(); }
+
+public:
+ /*! @method SetBypassEffect */
+ virtual void SetBypassEffect (bool inFlag) { mBypassEffect = inFlag; }
+
+ /*! @method SetParamHasSampleRateDependency */
+ void SetParamHasSampleRateDependency (bool inFlag)
+ {
+ mParamSRDep = inFlag;
+ }
+
+ /*! @method GetParamHasSampleRateDependency */
+ bool GetParamHasSampleRateDependency () const { return mParamSRDep; }
+
+
+ struct ScheduledProcessParams // pointer passed in as void* userData param for ProcessScheduledSlice()
+ {
+ AudioUnitRenderActionFlags *actionFlags;
+ AudioBufferList *inputBufferList;
+ AudioBufferList *outputBufferList;
+ };
+
+ virtual OSStatus ProcessScheduledSlice( void *inUserData,
+ UInt32 inStartFrameInBuffer,
+ UInt32 inSliceFramesToProcess,
+ UInt32 inTotalBufferFrames );
+
+
+ bool ProcessesInPlace() const {return mProcessesInPlace;};
+ void SetProcessesInPlace(bool inProcessesInPlace) {mProcessesInPlace = inProcessesInPlace;};
+
+ typedef std::vector<AUKernelBase *> KernelList;
+
+
+
+protected:
+ /*! @var mKernelList */
+ KernelList mKernelList;
+
+ AUKernelBase* GetKernel(UInt32 index) { return mKernelList[index]; }
+
+ /*! @method IsInputSilent */
+ bool IsInputSilent (AudioUnitRenderActionFlags inActionFlags, UInt32 inFramesToProcess)
+ {
+ bool inputSilent = (inActionFlags & kAudioUnitRenderAction_OutputIsSilence) != 0;
+
+ // take latency and tail time into account when propagating the silent bit
+ UInt32 silentTimeoutFrames = UInt32(GetSampleRate() * (GetLatency() + GetTailTime()));
+ mSilentTimeout.Process (inFramesToProcess, silentTimeoutFrames, inputSilent);
+ return inputSilent;
+ }
+
+private:
+ /*! @var mBypassEffect */
+ bool mBypassEffect;
+ /*! @var mParamSRDep */
+ bool mParamSRDep;
+
+ /*! @var mProcessesInplace */
+ bool mProcessesInPlace;
+
+ /*! @var mSilentTimeout */
+ AUSilentTimeout mSilentTimeout;
+
+
+};
+
+
+// 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 AudioUnitSampleType * inSourceP,
+ AudioUnitSampleType * inDestP,
+ UInt32 inFramesToProcess,
+ UInt32 inNumChannels,
+ bool & ioSilence) = 0;
+
+ /*! @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;
+
+};
+
+
+
+#endif // __AUEffectBase_h__
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp
new file mode 100755
index 00000000..21c0c18c
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp
@@ -0,0 +1,481 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "AUMIDIBase.h"
+#include <CoreMIDI/CoreMIDI.h>
+#include "CAXException.h"
+
+//temporaray location
+enum
+{
+ kMidiMessage_NoteOff = 0x80,
+ kMidiMessage_NoteOn = 0x90,
+ kMidiMessage_PolyPressure = 0xA0,
+ kMidiMessage_ControlChange = 0xB0,
+ kMidiMessage_ProgramChange = 0xC0,
+ kMidiMessage_ChannelPressure = 0xD0,
+ kMidiMessage_PitchWheel = 0xE0,
+
+ kMidiController_AllSoundOff = 120,
+ kMidiController_ResetAllControllers = 121,
+ kMidiController_AllNotesOff = 123
+};
+
+AUMIDIBase::AUMIDIBase(AUBase* inBase)
+ : mAUBaseInstance (*inBase)
+{
+#if CA_AUTO_MIDI_MAP
+ mMapManager = new CAAUMIDIMapManager();
+#endif
+}
+
+AUMIDIBase::~AUMIDIBase()
+{
+#if CA_AUTO_MIDI_MAP
+ if (mMapManager)
+ delete mMapManager;
+#endif
+}
+
+#if TARGET_API_MAC_OSX
+OSStatus AUMIDIBase::DelegateGetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus result = noErr;
+
+ switch (inID) {
+ 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;
+
+#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;
+InvalidScope:
+ return kAudioUnitErr_InvalidScope;
+InvalidElement:
+ return kAudioUnitErr_InvalidElement;
+}
+
+OSStatus AUMIDIBase::DelegateGetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ OSStatus result;
+
+ switch (inID) {
+ case kMusicDeviceProperty_MIDIXMLNames:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ result = GetXMLNames((CFURLRef *)outData);
+ break;
+
+#if CA_AUTO_MIDI_MAP
+ case kAudioUnitProperty_AllParameterMIDIMappings:{
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ AUParameterMIDIMapping* maps = (static_cast<AUParameterMIDIMapping*>(outData));
+ mMapManager->GetMaps(maps);
+// printf ("GETTING MAPS\n");
+// mMapManager->Print();
+ result = noErr;
+ break;
+ }
+
+ case kAudioUnitProperty_HotMapParameterMIDIMapping:{
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ AUParameterMIDIMapping * map = (static_cast<AUParameterMIDIMapping*>(outData));
+ mMapManager->GetHotParameterMap (*map);
+ result = noErr;
+ break;
+ }
+#endif
+
+ default:
+ result = kAudioUnitErr_InvalidProperty;
+ break;
+ }
+ return result;
+InvalidScope:
+ return kAudioUnitErr_InvalidScope;
+InvalidElement:
+ return kAudioUnitErr_InvalidElement;
+}
+
+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], startFrame);
+ // note that we're generating a bogus channel number for system messages (0xF0-FF)
+ }
+ event = NextMIDIEvent(event, packetEnd);
+ }
+ pkt = reinterpret_cast<const MIDIPacket *>(packetEnd);
+ }
+ return noErr;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUMIDIBase::HandleMidiEvent
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+OSStatus AUMIDIBase::HandleMidiEvent(UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
+{
+ if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
+
+#if CA_AUTO_MIDI_MAP
+// you potentially have a choice to make here - if a param mapping matches, do you still want to process the
+// MIDI event or not. The default behaviour is to continue on with the MIDI event.
+ if (mMapManager->HandleHotMapping (status, channel, data1, mAUBaseInstance)) {
+ mAUBaseInstance.PropertyChanged (kAudioUnitProperty_HotMapParameterMIDIMapping, kAudioUnitScope_Global, 0);
+ }
+ else {
+ mMapManager->FindParameterMapEventMatch(status, channel, data1, data2, inStartFrame, mAUBaseInstance);
+ }
+#endif
+
+ OSStatus result = noErr;
+
+ switch(status)
+ {
+ case kMidiMessage_NoteOn:
+ if(data2)
+ {
+ result = HandleNoteOn(channel, data1, data2, inStartFrame);
+ }
+ else
+ {
+ // zero velocity translates to note off
+ result = HandleNoteOff(channel, data1, data2, inStartFrame);
+ }
+ break;
+
+ case kMidiMessage_NoteOff:
+ result = HandleNoteOff(channel, data1, data2, inStartFrame);
+ break;
+
+ default:
+ result = HandleNonNoteEvent (status, channel, data1, data2, inStartFrame);
+ break;
+ }
+
+ return result;
+}
+
+OSStatus AUMIDIBase::HandleNonNoteEvent (UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
+{
+ OSStatus result = noErr;
+
+ switch (status)
+ {
+ case kMidiMessage_PitchWheel:
+ result = HandlePitchWheel(channel, data1, data2, inStartFrame);
+ break;
+
+ case kMidiMessage_ProgramChange:
+ result = HandleProgramChange(channel, data1);
+ break;
+
+ case kMidiMessage_ChannelPressure:
+ result = HandleChannelPressure(channel, data1, inStartFrame);
+ break;
+
+ case kMidiMessage_ControlChange:
+ {
+ switch (data1) {
+ case kMidiController_AllNotesOff:
+ result = HandleAllNotesOff(channel);
+ break;
+
+ case kMidiController_ResetAllControllers:
+ result = HandleResetAllControllers(channel);
+ break;
+
+ case kMidiController_AllSoundOff:
+ result = HandleAllSoundOff(channel);
+ break;
+
+ default:
+ result = HandleControlChange(channel, data1, data2, inStartFrame);
+ break;
+ }
+ break;
+ }
+ case kMidiMessage_PolyPressure:
+ result = HandlePolyPressure (channel, data1, data2, inStartFrame);
+ break;
+ }
+ return result;
+}
+
+OSStatus AUMIDIBase::SysEx (const UInt8 * inData,
+ UInt32 inLength)
+{
+ if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
+
+ return HandleSysEx(inData, inLength );
+}
+
+
+
+#if TARGET_OS_MAC
+ #if __LP64__
+ // comp instance, parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index + 1];
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
+ #endif
+#elif TARGET_OS_WIN32
+ // (no comp instance), parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index];
+#endif
+
+
+OSStatus AUMIDIBase::ComponentEntryDispatch( ComponentParameters * params,
+ AUMIDIBase * This)
+{
+ if (This == NULL) return paramErr;
+
+ 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;
+}
+
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h
new file mode 100755
index 00000000..0b6fe2a5
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h
@@ -0,0 +1,207 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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 */
+ 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 */
+ 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 !TARGET_OS_IPHONE
+ // component dispatcher
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch( ComponentParameters *params,
+ AUMIDIBase *This);
+#endif
+};
+
+#endif // __AUMIDIBase_h__
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp
new file mode 100755
index 00000000..a9087099
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp
@@ -0,0 +1,158 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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_AU_IS_ONLY_PLUGIN
+ if (inID == kAudioUnitProperty_FastDispatch) {
+ if (inElement == kMusicDeviceMIDIEventSelect) {
+ *(TEMP_MusicDeviceMIDIEventProc *)outData = AUMIDIEffectBaseMIDIEvent;
+ return noErr;
+ }
+ return kAudioUnitErr_InvalidElement;
+ }
+#endif
+
+ result = AUEffectBase::GetProperty (inID, inScope, inElement, outData);
+
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = AUMIDIBase::DelegateGetProperty (inID, inScope, inElement, outData);
+
+ return result;
+}
+
+OSStatus AUMIDIEffectBase::SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+
+ OSStatus result = AUEffectBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
+
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = AUMIDIBase::DelegateSetProperty (inID, inScope, inElement, inData, inDataSize);
+
+ return result;
+}
+
+
+#if !TARGET_OS_IPHONE
+OSStatus AUMIDIEffectBase::ComponentEntryDispatch(ComponentParameters * params,
+ AUMIDIEffectBase * This)
+{
+ if (This == NULL) return paramErr;
+
+ OSStatus result;
+
+ switch (params->what) {
+ case kMusicDeviceMIDIEventSelect:
+ case kMusicDeviceSysExSelect:
+ result = AUMIDIBase::ComponentEntryDispatch (params, This);
+ break;
+ default:
+ result = AUEffectBase::ComponentEntryDispatch(params, This);
+ break;
+ }
+
+ return result;
+}
+#endif
+
+// fast dispatch
+static OSStatus AUMIDIEffectBaseMIDIEvent(void * inComponentStorage,
+ UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame)
+{
+ OSStatus result = noErr;
+ try {
+ AUMIDIEffectBase *This = static_cast<AUMIDIEffectBase *>(inComponentStorage);
+ if (This == NULL) return paramErr;
+ result = This->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
+ }
+ COMPONENT_CATCH
+ return result;
+}
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h
new file mode 100755
index 00000000..ce28e55d
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h
@@ -0,0 +1,83 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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 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/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp
new file mode 100755
index 00000000..8203a235
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp
@@ -0,0 +1,105 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "AUOutputBase.h"
+
+#if PRAGMA_STRUCT_ALIGN
+ #pragma options align=mac68k
+#elif PRAGMA_STRUCT_PACKPUSH
+ #pragma pack(push, 2)
+#elif PRAGMA_STRUCT_PACK
+ #pragma pack(2)
+#endif
+
+#if TARGET_API_MAC_OS8 || TARGET_API_MAC_OSX
+struct AudioOutputUnitStartStopGluePB {
+ unsigned char componentFlags;
+ unsigned char componentParamSize;
+ short componentWhat;
+ AudioUnit ci;
+};
+#elif TARGET_OS_WIN32
+struct AudioOutputUnitStartStopGluePB {
+ unsigned char componentFlags;
+ unsigned char componentParamSize;
+ short componentWhat;
+};
+#else
+ #error Platform not supported
+#endif
+
+#if PRAGMA_STRUCT_ALIGN
+ #pragma options align=reset
+#elif PRAGMA_STRUCT_PACKPUSH
+ #pragma pack(pop)
+#elif PRAGMA_STRUCT_PACK
+ #pragma pack()
+#endif
+
+#if !TARGET_OS_IPHONE
+OSStatus AUOutputBase::ComponentEntryDispatch(ComponentParameters *params, AUOutputBase *This)
+{
+ if (This == NULL) return paramErr;
+
+ OSStatus result;
+
+ switch (params->what) {
+ case kAudioOutputUnitStartSelect:
+ {
+ //AudioOutputUnitStartStopGluePB *p = (AudioOutputUnitStartStopGluePB *)params;
+ result = This->Start();
+ }
+ break;
+
+ case kAudioOutputUnitStopSelect:
+ {
+ //AudioOutputUnitStartStopGluePB *p = (AudioOutputUnitStartStopGluePB *)params;
+ result = This->Stop();
+ }
+ break;
+
+ default:
+ result = badComponentSelector;
+ break;
+ }
+
+ return result;
+}
+#endif
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUOutputBase.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUOutputBase.h
new file mode 100755
index 00000000..ea516c84
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUOutputBase.h
@@ -0,0 +1,76 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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 !TARGET_OS_IPHONE
+ // component dispatcher
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch( ComponentParameters * params,
+ AUOutputBase * This);
+#endif
+
+private:
+ /*! @var mAUBaseInstance */
+ AUBase & mAUBaseInstance;
+};
+
+#endif // __AUOutputBase_h__
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp
new file mode 100755
index 00000000..5c0b4858
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp
@@ -0,0 +1,700 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "AUPannerBase.h"
+#include "CABundleLocker.h"
+#include <AudioToolbox/AudioToolbox.h>
+#include <Accelerate/Accelerate.h>
+
+static bool sLocalized = false;
+
+static CFStringRef kPanner_Azimuth_Name = CFSTR("azimuth");
+static CFStringRef kPanner_Elevation_Name = CFSTR("elevation");
+static CFStringRef kPanner_Distance_Name = CFSTR("distance");
+
+static CFStringRef kPanner_CoordScale_Name = CFSTR("coordinate scale");
+static CFStringRef kPanner_RefDistance_Name = CFSTR("reference distance");
+static CFStringRef kPanner_Gain_Name = CFSTR("gain");
+
+static Float32 kPannerParamDefault_Azimuth = 0.;
+static Float32 kPannerParamDefault_Elevation = 0.;
+static Float32 kPannerParamDefault_Distance = 1.;
+
+static Float32 kPannerParamDefault_CoordScale = 10.;
+static Float32 kPannerParamDefault_RefDistance = 1.;
+static Float32 kPannerParamDefault_Gain = 1.;
+
+//_____________________________________________________________________________
+//
+AUPannerBase::AUPannerBase(AudioComponentInstance inAudioUnit)
+ : AUBase(inAudioUnit, 1, 1), mBypassEffect(false)
+{
+ {
+ CABundleLocker lock;
+ if (!sLocalized)
+ {
+ CFBundleRef bundle = CFBundleGetBundleWithIdentifier( CFSTR("com.apple.audio.units.Components") );
+ if (bundle != NULL)
+ {
+ kPanner_Azimuth_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Azimuth_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_Elevation_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Elevation_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_Distance_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Distance_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+
+ kPanner_CoordScale_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_CoordScale_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_RefDistance_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_RefDistance_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_Gain_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Gain_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+
+ }
+
+ sLocalized = true;
+ }
+ }
+
+ CreateElements();
+
+ SetParameter(kPannerParam_Azimuth, kPannerParamDefault_Azimuth);
+ SetParameter(kPannerParam_Elevation, kPannerParamDefault_Elevation);
+ SetParameter(kPannerParam_Distance, kPannerParamDefault_Distance);
+
+ SetParameter(kPannerParam_CoordScale, kPannerParamDefault_CoordScale);
+ SetParameter(kPannerParam_RefDistance, kPannerParamDefault_RefDistance);
+ SetParameter(kPannerParam_Gain, kPannerParamDefault_Gain);
+}
+
+//_____________________________________________________________________________
+//
+AUPannerBase::~AUPannerBase()
+{
+ Cleanup();
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Initialize */
+OSStatus AUPannerBase::Initialize()
+{
+ OSStatus err = noErr;
+ AllocBypassMatrix();
+ err = UpdateBypassMatrix();
+ return err;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method AllocBypassMatrix */
+void AUPannerBase::AllocBypassMatrix()
+{
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ mBypassMatrix.alloc(inChannels * outChannels, true);
+}
+
+static AudioChannelLayoutTag DefaultTagForNumberOfChannels(UInt32 inNumberChannels)
+{
+ switch (inNumberChannels) {
+ case 1: return kAudioChannelLayoutTag_Mono;
+ case 2: return kAudioChannelLayoutTag_Stereo;
+ case 4: return kAudioChannelLayoutTag_Quadraphonic;
+ case 5: return kAudioChannelLayoutTag_AudioUnit_5_0;
+ case 6: return kAudioChannelLayoutTag_AudioUnit_6_0;
+ case 7: return kAudioChannelLayoutTag_AudioUnit_7_0;
+ case 8: return kAudioChannelLayoutTag_AudioUnit_8;
+
+ default: return 0xFFFF0000 | inNumberChannels;
+ }
+}
+
+//_____________________________________________________________________________
+//
+/*! @method UpdateBypassMatrix */
+OSStatus AUPannerBase::SetDefaultChannelLayoutsIfNone()
+{
+ OSStatus err = noErr;
+
+ // if layout has not been set, then guess layout from number of channels
+ UInt32 inChannels = GetNumberOfInputChannels();
+ AudioChannelLayout inputLayoutSubstitute;
+ const AudioChannelLayout* inputLayout = &GetInputLayout();
+ if (inputLayout == NULL || inputLayout->mChannelLayoutTag == 0) {
+ inputLayout = &inputLayoutSubstitute;
+ inputLayoutSubstitute.mNumberChannelDescriptions = 0;
+ inputLayoutSubstitute.mChannelBitmap = 0;
+ inputLayoutSubstitute.mChannelLayoutTag = DefaultTagForNumberOfChannels(inChannels);
+
+ mInputLayout = &inputLayoutSubstitute;
+ err = SetAudioChannelLayout(kAudioUnitScope_Input, 0, &GetInputLayout());
+ if (err) return err;
+ }
+
+ // if layout has not been set, then guess layout from number of channels
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ AudioChannelLayout outputLayoutSubstitute;
+ const AudioChannelLayout* outputLayout = &GetOutputLayout();
+ if (outputLayout == NULL || outputLayout->mChannelLayoutTag == 0) {
+ outputLayout = &outputLayoutSubstitute;
+ outputLayoutSubstitute.mNumberChannelDescriptions = 0;
+ outputLayoutSubstitute.mChannelBitmap = 0;
+ outputLayoutSubstitute.mChannelLayoutTag = DefaultTagForNumberOfChannels(outChannels);
+
+ mOutputLayout = &outputLayoutSubstitute;
+ err = SetAudioChannelLayout(kAudioUnitScope_Output, 0, &GetOutputLayout());
+ if (err) return err;
+ }
+
+ return err;
+}
+
+
+
+OSStatus AUPannerBase::UpdateBypassMatrix()
+{
+ OSStatus err = SetDefaultChannelLayoutsIfNone();
+ if (err) return err;
+
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+
+ const AudioChannelLayout* inoutACL[2];
+
+ inoutACL[0] = &GetInputLayout();
+ inoutACL[1] = &GetOutputLayout();
+
+ mBypassMatrix.alloc(inChannels * outChannels, true);
+
+ UInt32 propSize = inChannels * outChannels * sizeof(Float32);
+
+ err = AudioFormatGetProperty(kAudioFormatProperty_MatrixMixMap, sizeof(inoutACL), inoutACL, &propSize, mBypassMatrix());
+ if (err) {
+ // if there is an error, use a diagonal matrix.
+ Float32* bypass = mBypassMatrix();
+ for (UInt32 chan = 0; chan < std::min(inChannels, outChannels); ++chan)
+ {
+ float *amp = bypass + (chan * outChannels + chan);
+ *amp = 1.;
+ }
+ }
+
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Cleanup */
+void AUPannerBase::Cleanup()
+{
+
+}
+
+
+//_____________________________________________________________________________
+//
+/*! @method Reset */
+OSStatus AUPannerBase::Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ return AUBase::Reset(inScope, inElement);
+}
+
+//_____________________________________________________________________________
+//
+/*! @method GetParameterInfo */
+OSStatus AUPannerBase::GetParameterInfo( AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ AudioUnitParameterInfo &outParameterInfo )
+{
+ OSStatus result = noErr;
+
+ outParameterInfo.flags = kAudioUnitParameterFlag_IsWritable
+ + kAudioUnitParameterFlag_IsReadable;
+
+ if (inScope == kAudioUnitScope_Global) {
+
+ switch(inParameterID)
+ {
+ case kPannerParam_Azimuth:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Azimuth_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Degrees;
+ outParameterInfo.minValue = -180.;
+ outParameterInfo.maxValue = 180;
+ outParameterInfo.defaultValue = kPannerParamDefault_Azimuth;
+ break;
+
+ case kPannerParam_Elevation:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Elevation_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Degrees;
+ outParameterInfo.minValue = -90.;
+ outParameterInfo.maxValue = 90;
+ outParameterInfo.defaultValue = kPannerParamDefault_Elevation;
+ break;
+
+ case kPannerParam_Distance:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Distance_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
+ outParameterInfo.minValue = 0.0;
+ outParameterInfo.maxValue = 1.;
+ outParameterInfo.defaultValue = kPannerParamDefault_Distance;
+ outParameterInfo.flags += kAudioUnitParameterFlag_IsHighResolution;
+ //outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
+ break;
+
+ case kPannerParam_CoordScale:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_CoordScale_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Meters;
+ outParameterInfo.minValue = 0.01;
+ outParameterInfo.maxValue = 1000.;
+ outParameterInfo.defaultValue = kPannerParamDefault_CoordScale;
+ outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
+ break;
+
+ case kPannerParam_RefDistance:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_RefDistance_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Meters;
+ outParameterInfo.minValue = 0.01;
+ outParameterInfo.maxValue = 1000.;
+ outParameterInfo.defaultValue = kPannerParamDefault_RefDistance;
+ outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
+ break;
+
+ case kPannerParam_Gain:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Gain_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
+ outParameterInfo.minValue = 0.;
+ outParameterInfo.maxValue = 1.;
+ outParameterInfo.defaultValue = kPannerParamDefault_Gain;
+ break;
+
+ default:
+ result = kAudioUnitErr_InvalidParameter;
+ break;
+ }
+ } else {
+ result = kAudioUnitErr_InvalidParameter;
+ }
+
+ return result;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::GetParameter( AudioUnitParameterID inParamID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ Float32 & outValue)
+{
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ outValue = Globals()->GetParameter(inParamID);
+
+ return noErr;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::SetParameter( AudioUnitParameterID inParamID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ Float32 inValue,
+ UInt32 inBufferOffsetInFrames)
+{
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ Globals()->SetParameter(inParamID, inValue);
+
+ return noErr;
+}
+
+
+
+//_____________________________________________________________________________
+//
+/*! @method GetPropertyInfo */
+OSStatus AUPannerBase::GetPropertyInfo (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus err = noErr;
+ switch (inID) {
+ case kAudioUnitProperty_BypassEffect:
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ outWritable = true;
+ outDataSize = sizeof (UInt32);
+ break;
+ default:
+ err = AUBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);
+ }
+ return err;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method GetProperty */
+OSStatus AUPannerBase::GetProperty (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ OSStatus err = noErr;
+ switch (inID)
+ {
+ case kAudioUnitProperty_BypassEffect:
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ *((UInt32*)outData) = (IsBypassEffect() ? 1 : 0);
+ break;
+ default:
+ err = AUBase::GetProperty(inID, inScope, inElement, outData);
+ }
+ return err;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method SetProperty */
+OSStatus AUPannerBase::SetProperty(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ switch (inID)
+ {
+ case kAudioUnitProperty_BypassEffect:
+ if (inDataSize < sizeof(UInt32))
+ return kAudioUnitErr_InvalidPropertyValue;
+ bool tempNewSetting = *((UInt32*)inData) != 0;
+ // we're changing the state of bypass
+ if (tempNewSetting != IsBypassEffect())
+ {
+ if (!tempNewSetting && IsBypassEffect() && IsInitialized()) // turning bypass off and we're initialized
+ Reset(0, 0);
+ SetBypassEffect (tempNewSetting);
+ }
+ return noErr;
+ }
+ return AUBase::SetProperty(inID, inScope, inElement, inData, inDataSize);
+}
+
+
+//_____________________________________________________________________________
+//
+/*! @method StreamFormatWritable */
+bool AUPannerBase::StreamFormatWritable (AudioUnitScope scope,
+ AudioUnitElement element)
+{
+ return true;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method ChangeStreamFormat */
+OSStatus AUPannerBase::ChangeStreamFormat (
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inPrevFormat,
+ const CAStreamBasicDescription & inNewFormat)
+{
+ if (inScope == kAudioUnitScope_Input && !InputChannelConfigIsSupported(inNewFormat.NumberChannels()))
+ return kAudioUnitErr_FormatNotSupported;
+
+ if (inScope == kAudioUnitScope_Output && !OutputChannelConfigIsSupported(inNewFormat.NumberChannels()))
+ return kAudioUnitErr_FormatNotSupported;
+
+ if (inNewFormat.NumberChannels() != inPrevFormat.NumberChannels())
+ RemoveAudioChannelLayout(inScope, inElement);
+
+ return AUBase::ChangeStreamFormat(inScope, inElement, inPrevFormat, inNewFormat);
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Render */
+OSStatus AUPannerBase::Render(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames)
+{
+ if (IsBypassEffect())
+ return BypassRender(ioActionFlags, inTimeStamp, inNumberFrames);
+ else
+ return PannerRender(ioActionFlags, inTimeStamp, inNumberFrames);
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Render */
+OSStatus AUPannerBase::BypassRender(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames)
+{
+ AudioUnitRenderActionFlags xflags = 0;
+ OSStatus result = PullInput(0, xflags, inTimeStamp, inNumberFrames);
+ if (result) return false;
+ bool isSilent = xflags & kAudioUnitRenderAction_OutputIsSilence;
+
+ AudioBufferList& outputBufferList = GetOutput(0)->GetBufferList();
+ AUBufferList::ZeroBuffer(outputBufferList);
+
+ if (!isSilent)
+ {
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ Float32* bypass = mBypassMatrix();
+ for (UInt32 outChan = 0; outChan < outChannels; ++outChan)
+ {
+ float* outData = GetOutput(0)->GetChannelData(outChan);
+
+ for (UInt32 inChan = 0; inChan < inChannels; ++inChan)
+ {
+ float* inData = GetInput(0)->GetChannelData(inChan);
+ float *amp = bypass + (inChan * outChannels + outChan);
+ vDSP_vsma(inData, 1, amp, outData, 1, outData, 1, inNumberFrames);
+ }
+ }
+ }
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+UInt32 AUPannerBase::GetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayout * outLayoutPtr,
+ Boolean & outWritable)
+{
+ SetDefaultChannelLayoutsIfNone();
+
+ outWritable = true;
+
+ CAAudioChannelLayout* caacl = NULL;
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ caacl = &mInputLayout;
+ break;
+ case kAudioUnitScope_Output:
+ caacl = &mOutputLayout;
+ break;
+ default:
+ COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+ }
+
+ if (inElement != 0)
+ COMPONENT_THROW(kAudioUnitErr_InvalidElement);
+
+ UInt32 size = caacl->IsValid() ? caacl->Size() : 0;
+ if (size > 0 && outLayoutPtr)
+ memcpy(outLayoutPtr, &caacl->Layout(), size);
+
+ return size;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::RemoveAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ CAAudioChannelLayout* caacl = NULL;
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ caacl = &mInputLayout;
+ break;
+ case kAudioUnitScope_Output:
+ caacl = &mOutputLayout;
+ break;
+ default:
+ return kAudioUnitErr_InvalidScope;
+ }
+
+ if (inElement != 0)
+ return kAudioUnitErr_InvalidElement;
+
+ *caacl = NULL;
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::SetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const AudioChannelLayout * inLayout)
+{
+ if (!inLayout)
+ return RemoveAudioChannelLayout(inScope, inElement);
+
+ if (!ChannelLayoutTagIsSupported(inScope, inElement, inLayout->mChannelLayoutTag))
+ return kAudioUnitErr_FormatNotSupported;
+
+ CAAudioChannelLayout* caacl = NULL;
+ UInt32 currentChannels;
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ caacl = &mInputLayout;
+ currentChannels = GetNumberOfInputChannels();
+ break;
+ case kAudioUnitScope_Output:
+ caacl = &mOutputLayout;
+ currentChannels = GetNumberOfOutputChannels();
+ break;
+ default:
+ return kAudioUnitErr_InvalidScope;
+ }
+
+ if (inElement != 0)
+ return kAudioUnitErr_InvalidElement;
+
+ UInt32 numChannelsInLayout = CAAudioChannelLayout::NumberChannels(*inLayout);
+ if (currentChannels != numChannelsInLayout)
+ return kAudioUnitErr_InvalidPropertyValue;
+
+ *caacl = inLayout;
+ if (IsInitialized())
+ UpdateBypassMatrix();
+
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+UInt32 AUPannerBase::GetChannelLayoutTags( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag* outTags)
+{
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ if (outTags) {
+ outTags[0] = kAudioChannelLayoutTag_Mono;
+ outTags[1] = kAudioChannelLayoutTag_Stereo;
+ outTags[2] = kAudioChannelLayoutTag_Ambisonic_B_Format;
+ }
+ return 3;
+ case kAudioUnitScope_Output:
+ if (outTags) {
+ outTags[0] = kAudioChannelLayoutTag_Stereo;
+ outTags[1] = kAudioChannelLayoutTag_Quadraphonic;
+ outTags[2] = kAudioChannelLayoutTag_AudioUnit_5_0;
+ outTags[3] = kAudioChannelLayoutTag_AudioUnit_6_0;
+ outTags[4] = kAudioChannelLayoutTag_AudioUnit_7_0;
+ outTags[5] = kAudioChannelLayoutTag_AudioUnit_7_0_Front;
+ outTags[6] = kAudioChannelLayoutTag_AudioUnit_8;
+ }
+ return 7;
+ default: {
+ OSStatus err = kAudioUnitErr_InvalidScope;
+ throw err;
+ }
+ }
+}
+
+
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::ChannelConfigIsSupported()
+{
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ const AUChannelInfo* cinfo = NULL;
+ UInt32 numConfigs = SupportedNumChannels(&cinfo);
+ for (UInt32 i = 0; i < numConfigs; ++i)
+ {
+ if (cinfo[i].inChannels == (SInt16)inChannels && cinfo[i].outChannels == (SInt16)outChannels)
+ return true;
+ }
+ return false;
+}
+
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::InputChannelConfigIsSupported(UInt32 inNumberChannels)
+{
+ const AUChannelInfo* cinfo = NULL;
+ UInt32 numConfigs = SupportedNumChannels(&cinfo);
+ for (UInt32 i = 0; i < numConfigs; ++i)
+ {
+ if (cinfo[i].inChannels == (SInt16)inNumberChannels)
+ return true;
+ }
+ return false;
+}
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::OutputChannelConfigIsSupported(UInt32 inNumberChannels)
+{
+ const AUChannelInfo* cinfo = NULL;
+ UInt32 numConfigs = SupportedNumChannels(&cinfo);
+ for (UInt32 i = 0; i < numConfigs; ++i)
+ {
+ if (cinfo[i].outChannels == (SInt16)inNumberChannels)
+ return true;
+ }
+ return false;
+}
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::ChannelLayoutTagIsSupported( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag inTag)
+{
+ UInt32 numTags = GetChannelLayoutTags(inScope, inElement, NULL);
+ CAAutoFree<AudioChannelLayoutTag> tags(numTags);
+ GetChannelLayoutTags(inScope, inElement, tags());
+
+ for (UInt32 i = 0; i < numTags; ++i)
+ {
+ if (tags[i] == inTag)
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUPannerBase.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUPannerBase.h
new file mode 100755
index 00000000..fa2140cc
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUPannerBase.h
@@ -0,0 +1,263 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __AUPannerBase_h__
+#define __AUPannerBase_h__
+
+#include "AUBase.h"
+#include <math.h>
+#include "CAAutoDisposer.h"
+#include "CAAudioChannelLayout.h"
+
+
+/*! @class AUPannerBase */
+class AUPannerBase : public AUBase
+{
+public:
+/*! @ctor AUPannerBase */
+ AUPannerBase(AudioComponentInstance inAudioUnit);
+/*! @dtor ~AUPannerBase */
+ virtual ~AUPannerBase();
+
+ /*! @method Initialize */
+ virtual OSStatus Initialize();
+
+ /*! @method Cleanup */
+ virtual void Cleanup();
+
+
+ /*! @method Reset */
+ virtual OSStatus Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ /*! @method GetParameterInfo */
+ virtual OSStatus GetParameterInfo( AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ AudioUnitParameterInfo &outParameterInfo );
+
+
+ /*! @method GetPropertyInfo */
+ virtual OSStatus GetPropertyInfo (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ /*! @method GetProperty */
+ virtual OSStatus GetProperty (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+
+ /*! @method SetProperty */
+ virtual OSStatus SetProperty(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+
+
+ /*! @method StreamFormatWritable */
+ virtual bool StreamFormatWritable (AudioUnitScope scope,
+ AudioUnitElement element);
+
+ /*! @method ChangeStreamFormat */
+ virtual OSStatus ChangeStreamFormat (
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inPrevFormat,
+ const CAStreamBasicDescription & inNewFormat);
+
+
+ /*! @method IsBypassEffect */
+ // This is used for the property value - to reflect to the UI if an effect is bypassed
+ bool IsBypassEffect () { return mBypassEffect; }
+
+ /*! @method SetBypassEffect */
+ virtual void SetBypassEffect (bool inFlag) { mBypassEffect = inFlag; }
+
+
+ /*! @method Render */
+ virtual OSStatus Render(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames);
+
+ /*! @method Render */
+ virtual OSStatus PannerRender(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames) = 0;
+
+ /*! @method BypassRender */
+ virtual OSStatus BypassRender(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames);
+
+
+ /*! @method GetAudioChannelLayout */
+ virtual UInt32 GetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayout * outLayoutPtr,
+ Boolean & outWritable);
+
+ /*! @method SetAudioChannelLayout */
+ virtual OSStatus SetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const AudioChannelLayout * inLayout);
+
+ /*! @method RemoveAudioChannelLayout */
+ virtual OSStatus RemoveAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ /*! @method GetChannelLayoutTags */
+ virtual UInt32 GetChannelLayoutTags( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag* outTags);
+
+ /*! @method GetNumberOfInputChannels */
+ UInt32 GetNumberOfInputChannels() { return ((AUIOElement*)Inputs().SafeGetElement(0))->NumberChannels(); };
+ /*! @method GetNumberOfOutputChannels */
+ UInt32 GetNumberOfOutputChannels() { return ((AUIOElement*)Outputs().SafeGetElement(0))->NumberChannels(); }
+
+ /*! @method GetParameter */
+ virtual OSStatus GetParameter( AudioUnitParameterID inParamID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ Float32 & outValue);
+
+ /*! @method SetParameter */
+ virtual OSStatus SetParameter( AudioUnitParameterID inParamID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ Float32 inValue,
+ UInt32 inBufferOffsetInFrames);
+
+ // convenience wrappers for accessing parameters in the global scope
+ /*! @method SetParameter */
+ void SetParameter( UInt32 inParamID,
+ Float32 inValue)
+ {
+ OSStatus err = SetParameter(inParamID, kAudioUnitScope_Global, 0, inValue, 0);
+ if (err) throw err;
+ }
+
+ /*! @method GetParameter */
+ Float32 GetParameter( UInt32 inParamID )
+ {
+ Float32 outValue = 0.;
+ OSStatus err = GetParameter(inParamID, kAudioUnitScope_Global, 0, outValue);
+ if (err) throw err;
+ return outValue;
+ }
+
+ /*! @method InputChannelConfigIsSupported */
+ bool InputChannelConfigIsSupported(UInt32 inNumberChannels);
+ /*! @method OutputChannelConfigIsSupported */
+ bool OutputChannelConfigIsSupported(UInt32 inNumberChannels);
+ /*! @method ChannelConfigIsSupported */
+ bool ChannelConfigIsSupported();
+
+ /*! @method SupportsTail */
+ virtual bool SupportsTail () { return true; }
+ /*! @method GetTailTime */
+ virtual Float64 GetTailTime() { return 0; }
+
+
+ /*! @method GetGain */
+ Float32 GetGain() { return GetParameter(kPannerParam_Gain); }
+ /*! @method GetTailTime */
+ Float32 GetAzimuth() { return GetParameter(kPannerParam_Azimuth); }
+ /*! @method GetElevation */
+ Float32 GetElevation() { return GetParameter(kPannerParam_Elevation); }
+ /*! @method GetDistance */
+ Float32 GetDistance() { return GetParameter(kPannerParam_Distance); }
+ /*! @method GetCoordScale */
+ Float32 GetCoordScale() { return GetParameter(kPannerParam_CoordScale); }
+ /*! @method GetRefDistance */
+ Float32 GetRefDistance() { return GetParameter(kPannerParam_RefDistance); }
+
+ /*! @method SetGain */
+ void SetGain(Float32 inValue) { SetParameter(kPannerParam_Gain, inValue); }
+ /*! @method SetAzimuth */
+ void SetAzimuth(Float32 inValue) { SetParameter(kPannerParam_Azimuth, inValue); }
+ /*! @method SetElevation */
+ void SetElevation(Float32 inValue) { SetParameter(kPannerParam_Elevation, inValue); }
+ /*! @method SetDistance */
+ void SetDistance(Float32 inValue) { SetParameter(kPannerParam_Distance, inValue); }
+ /*! @method SetCoordScale */
+ void SetCoordScale(Float32 inValue) { SetParameter(kPannerParam_CoordScale, inValue); }
+ /*! @method SetRefDistance */
+ void SetRefDistance(Float32 inValue) { SetParameter(kPannerParam_RefDistance, inValue); }
+
+protected:
+ /*! @method ShouldBypassEffect */
+ // This is used in the render call to see if an effect is bypassed
+ // It can return a different status than IsBypassEffect (though it MUST take that into account)
+ virtual bool ShouldBypassEffect () { return IsBypassEffect(); }
+
+ /*! @method AllocBypassMatrix */
+ void AllocBypassMatrix();
+
+ /*! @method UpdateBypassMatrix */
+ OSStatus UpdateBypassMatrix();
+
+ /*! @method SetDefaultChannelLayoutsIfNone */
+ OSStatus SetDefaultChannelLayoutsIfNone();
+
+ /*! @method ChannelLayoutTagIsSupported */
+ bool ChannelLayoutTagIsSupported( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag inTag);
+
+ const AudioChannelLayout& GetInputLayout() const { return mInputLayout.Layout(); }
+ const AudioChannelLayout& GetOutputLayout() const { return mOutputLayout.Layout(); }
+
+private:
+
+ /*! @var UpdateBypassMatrix */
+ bool mBypassEffect;
+ /*! @var mBypassMatrix */
+ CAAutoFree<Float32> mBypassMatrix;
+ /*! @var mInputLayout */
+ CAAudioChannelLayout mInputLayout;
+ /*! @var mOutputLayout */
+ CAAudioChannelLayout mOutputLayout;
+};
+
+#endif /* __AUPannerBase_h__ */
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp
new file mode 100755
index 00000000..986d2ca4
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp
@@ -0,0 +1,343 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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);
+
+
+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);
+
+
+
+MusicDeviceBase::MusicDeviceBase(AudioComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups,
+ UInt32 numParts)
+ : AUBase(inInstance, numInputs, numOutputs, numGroups, numParts),
+ AUMIDIBase(this)
+{
+}
+
+OSStatus MusicDeviceBase::GetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus result;
+
+ switch (inID)
+ {
+ case kMusicDeviceProperty_InstrumentCount:
+ if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
+ outDataSize = sizeof(UInt32);
+ outWritable = false;
+ result = noErr;
+ break;
+
+ 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_AU_IS_ONLY_PLUGIN
+ case kAudioUnitProperty_FastDispatch:
+ 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
+
+ case kMusicDeviceProperty_InstrumentCount:
+ if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
+ return GetInstrumentCount (*(UInt32*)outData);
+
+ 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 paramErr;
+
+ if (!IsInitialized()) return kAudioUnitErr_Uninitialized;
+
+ return StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
+}
+
+#if TARGET_OS_MAC
+ #if __LP64__
+ // comp instance, parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index + 1];
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
+ #endif
+#elif TARGET_OS_WIN32
+ // (no comp instance), parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index];
+#endif
+
+#if !TARGET_OS_IPHONE
+OSStatus MusicDeviceBase::ComponentEntryDispatch( ComponentParameters * params,
+ MusicDeviceBase * This)
+{
+ if (This == NULL) return paramErr;
+
+ 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
+
+
+// fast dispatch
+static OSStatus MusicDeviceBaseMIDIEvent(void * inComponentStorage,
+ UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame)
+{
+ OSStatus result = noErr;
+ try {
+ MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
+ if (This == NULL) return paramErr;
+ 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 paramErr;
+ MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
+ if (This == NULL) return paramErr;
+ result = This->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+OSStatus MusicDeviceBaseStopNote(void * inComponentStorage,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame)
+{
+ OSStatus result = noErr;
+ try {
+ MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
+ if (This == NULL) return paramErr;
+ result = This->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h
new file mode 100755
index 00000000..2223dfad
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h
@@ -0,0 +1,123 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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,
+ UInt32 numParts = 0);
+
+ /*! @method PrepareInstrument */
+ virtual OSStatus PrepareInstrument(MusicDeviceInstrumentID inInstrument) { return noErr; }
+
+ /*! @method ReleaseInstrument */
+ virtual OSStatus ReleaseInstrument(MusicDeviceInstrumentID inInstrument) { return noErr; }
+
+ /*! @method StartNote */
+ virtual OSStatus StartNote( MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams) = 0;
+
+ /*! @method StopNote */
+ virtual OSStatus StopNote( MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame) = 0;
+
+ /*! @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 !TARGET_OS_IPHONE
+ // 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/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp
new file mode 100755
index 00000000..9f73c36f
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp
@@ -0,0 +1,128 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "AUBaseHelper.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnitProperties.h>
+#else
+ #include <AudioUnitProperties.h>
+#endif
+
+OSStatus GetFileRefPath (CFDictionaryRef parent, CFStringRef frKey, CFStringRef * fPath)
+{
+ static CFStringRef kFRString = CFSTR (kAUPresetExternalFileRefs);
+
+ const void* frVal = CFDictionaryGetValue(parent, kFRString);
+ if (!frVal) return kAudioUnitErr_InvalidPropertyValue;
+
+ const void* frString = CFDictionaryGetValue ((CFDictionaryRef)frVal, frKey);
+ if (!frString) return kAudioUnitErr_InvalidPropertyValue;
+
+ if (fPath)
+ *fPath = (CFStringRef)frString;
+
+ return noErr;
+}
+
+// write valid samples check, with bool for zapping
+
+UInt32 FindInvalidSamples(Float32 *inSource, UInt32 inFramesToProcess, bool &outHasNonZero, bool zapInvalidSamples)
+{
+ float *sourceP = inSource;
+
+ UInt32 badSamplesDetected = 0;
+ bool hasNonZero = false;
+ for (UInt32 i=0; i < inFramesToProcess; i++)
+ {
+ float input = *(sourceP++);
+
+ if(input > 0)
+ hasNonZero = true;
+
+ float absx = fabs(input);
+
+ // a bad number!
+ if (!(absx < 1e15))
+ {
+ if (!(absx == 0))
+ {
+ //printf("\tbad sample: %f\n", input);
+ badSamplesDetected++;
+ if (zapInvalidSamples)
+ input = 0;
+ }
+ }
+ }
+
+ return badSamplesDetected;
+}
+
+
+CFMutableDictionaryRef CreateFileRefDict (CFStringRef fKey, CFStringRef fPath, CFMutableDictionaryRef fileRefDict)
+{
+ if (!fileRefDict)
+ fileRefDict = CFDictionaryCreateMutable (NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ CFDictionarySetValue (fileRefDict, fKey, fPath);
+
+ return fileRefDict;
+}
+
+#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/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBaseHelper.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBaseHelper.h
new file mode 100755
index 00000000..7bb4618e
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBaseHelper.h
@@ -0,0 +1,74 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __AUBaseHelper_h__
+#define __AUBaseHelper_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CoreFoundation.h>
+ #include <AudioUnit/AUComponent.h>
+#else
+ #include <CoreFoundation.h>
+ #include <AUComponent.h>
+#endif
+
+#include "AUBase.h"
+
+
+UInt32 FindInvalidSamples(Float32 *inSource, UInt32 inFramesToProcess, bool &hasNonZero, bool zapInvalidSamples);
+
+
+// helpers for dealing with the file-references dictionary in an AUPreset
+
+extern "C" 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
+extern "C" CFMutableDictionaryRef
+CreateFileRefDict (CFStringRef fKey, CFStringRef fPath, CFMutableDictionaryRef fileRefDict);
+
+#if DEBUG
+ void PrintAUParamEvent (AudioUnitParameterEvent& event, FILE* f);
+#endif
+
+
+
+#endif // __AUBaseHelper_h__ \ No newline at end of file
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBuffer.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBuffer.cpp
new file mode 100755
index 00000000..67259110
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBuffer.cpp
@@ -0,0 +1,203 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "AUBuffer.h"
+#include <stdlib.h>
+
+AUBufferList::~AUBufferList()
+{
+ Deallocate();
+ if (mPtrs)
+ free(mPtrs);
+}
+
+void AUBufferList::Allocate(const CAStreamBasicDescription &format, UInt32 nFrames)
+{
+ UInt32 nStreams;
+ UInt32 channelsPerStream;
+ if (format.IsInterleaved()) {
+ nStreams = 1;
+ channelsPerStream = format.mChannelsPerFrame;
+ } else {
+ nStreams = format.mChannelsPerFrame;
+ channelsPerStream = 1;
+ }
+
+ // careful -- the I/O thread could be running!
+ if (nStreams > mAllocatedStreams) {
+ mPtrs = (AudioBufferList *)CA_realloc(mPtrs, offsetof(AudioBufferList, mBuffers) + nStreams * sizeof(AudioBuffer));
+ mAllocatedStreams = nStreams;
+ }
+ UInt32 bytesPerStream = (nFrames * format.mBytesPerFrame + 0xF) & ~0xF;
+ UInt32 nBytes = nStreams * bytesPerStream;
+ 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/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBuffer.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBuffer.h
new file mode 100755
index 00000000..3c5bf082
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBuffer.h
@@ -0,0 +1,261 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __AUBuffer_h__
+#define __AUBuffer_h__
+
+#include <TargetConditionals.h>
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnit.h>
+#else
+ #include <AudioUnit.h>
+#endif
+
+#include <string.h>
+#include "CAStreamBasicDescription.h"
+#include "CAAutoDisposer.h"
+#include "CADebugMacros.h"
+
+// make this usable outside the stricter context of AudiUnits
+#ifndef COMPONENT_THROW
+ #define COMPONENT_THROW(err) \
+ do { DebugMessage(#err); throw static_cast<OSStatus>(err); } while (0)
+#endif
+
+
+ /*! @class AUBufferList */
+class AUBufferList {
+ enum EPtrState {
+ kPtrsInvalid,
+ kPtrsToMyMemory,
+ kPtrsToExternalMemory
+ };
+public:
+ /*! @ctor AUBufferList */
+ AUBufferList() : mPtrState(kPtrsInvalid), mExternalMemory(false), mPtrs(NULL), mMemory(NULL),
+ mAllocatedStreams(0), mAllocatedFrames(0), mAllocatedBytes(0) { }
+ /*! @dtor ~AUBufferList */
+ ~AUBufferList();
+
+ /*! @method PrepareBuffer */
+ AudioBufferList & PrepareBuffer(const CAStreamBasicDescription &format, UInt32 nFrames);
+ /*! @method PrepareNullBuffer */
+ AudioBufferList & PrepareNullBuffer(const CAStreamBasicDescription &format, UInt32 nFrames);
+
+ /*! @method SetBufferList */
+ AudioBufferList & SetBufferList(const AudioBufferList &abl) {
+ if (mAllocatedStreams < abl.mNumberBuffers)
+ COMPONENT_THROW(-1);
+ mPtrState = kPtrsToExternalMemory;
+ memcpy(mPtrs, &abl, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl);
+ return *mPtrs;
+ }
+
+ /*! @method SetBuffer */
+ void SetBuffer(UInt32 index, const AudioBuffer &ab) {
+ if (mPtrState == kPtrsInvalid || index >= mPtrs->mNumberBuffers)
+ COMPONENT_THROW(-1);
+ mPtrState = kPtrsToExternalMemory;
+ mPtrs->mBuffers[index] = ab;
+ }
+
+ /*! @method InvalidateBufferList */
+ void InvalidateBufferList() { mPtrState = kPtrsInvalid; }
+
+ /*! @method GetBufferList */
+ AudioBufferList & GetBufferList() const {
+ if (mPtrState == kPtrsInvalid)
+ COMPONENT_THROW(-1);
+ return *mPtrs;
+ }
+
+ /*! @method CopyBufferListTo */
+ void CopyBufferListTo(AudioBufferList &abl) const {
+ if (mPtrState == kPtrsInvalid)
+ COMPONENT_THROW(-1);
+ memcpy(&abl, mPtrs, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl);
+ }
+
+ /*! @method CopyBufferContentsTo */
+ void CopyBufferContentsTo(AudioBufferList &abl) const {
+ if (mPtrState == kPtrsInvalid)
+ COMPONENT_THROW(-1);
+ const AudioBuffer *srcbuf = mPtrs->mBuffers;
+ AudioBuffer *destbuf = abl.mBuffers;
+
+ for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++srcbuf, ++destbuf) {
+ if (i >= mPtrs->mNumberBuffers) // duplicate last source to additional outputs [4341137]
+ --srcbuf;
+ if (destbuf->mData != srcbuf->mData)
+ memmove(destbuf->mData, srcbuf->mData, srcbuf->mDataByteSize);
+ destbuf->mDataByteSize = srcbuf->mDataByteSize;
+ }
+ }
+
+ /*! @method Allocate */
+ void Allocate(const CAStreamBasicDescription &format, UInt32 nFrames);
+ /*! @method Deallocate */
+ void Deallocate();
+
+ /*! @method UseExternalBuffer */
+ void UseExternalBuffer(const CAStreamBasicDescription &format, const AudioUnitExternalBuffer &buf);
+
+ // AudioBufferList utilities
+ /*! @method ZeroBuffer */
+ static void ZeroBuffer(AudioBufferList &abl) {
+ AudioBuffer *buf = abl.mBuffers;
+ for (UInt32 i = abl.mNumberBuffers ; i--; ++buf)
+ memset(buf->mData, 0, buf->mDataByteSize);
+ }
+#if DEBUG
+ /*! @method PrintBuffer */
+ static void PrintBuffer(const char *label, int subscript, const AudioBufferList &abl, UInt32 nFrames = 8, bool asFloats = true);
+#endif
+
+ /*! @method GetAllocatedFrames */
+ UInt32 GetAllocatedFrames() const { return mAllocatedFrames; }
+
+private:
+ /*! @ctor AUBufferList */
+ AUBufferList(AUBufferList &) { } // prohibit copy constructor
+
+ /*! @var mPtrState */
+ EPtrState mPtrState;
+ /*! @var mExternalMemory */
+ bool mExternalMemory;
+ /*! @var mPtrs */
+ AudioBufferList * mPtrs;
+ /*! @var mMemory */
+ Byte * mMemory;
+ /*! @var mAllocatedStreams */
+ UInt32 mAllocatedStreams;
+ /*! @var mAllocatedFrames */
+ UInt32 mAllocatedFrames;
+ /*! @var mAllocatedBytes */
+ UInt32 mAllocatedBytes;
+};
+
+
+// Allocates an array of samples (type T), to be optimally aligned for the processor
+ /*! @class TAUBuffer */
+template <class T>
+class TAUBuffer {
+public:
+ enum {
+ kAlignInterval = 0x10,
+ kAlignMask = kAlignInterval - 1
+ };
+
+ /*! @ctor TAUBuffer.0 */
+ TAUBuffer() : mMemObject(NULL), mAlignedBuffer(NULL), mBufferSizeBytes(0)
+ {
+ }
+
+ /*! @ctor TAUBuffer.1 */
+ TAUBuffer(UInt32 numElems, UInt32 numChannels) : mMemObject(NULL), mAlignedBuffer(NULL),
+ mBufferSizeBytes(0)
+ {
+ Allocate(numElems, numChannels);
+ }
+
+ /*! @dtor ~TAUBuffer */
+ ~TAUBuffer()
+ {
+ Deallocate();
+ }
+
+ /*! @method Allocate */
+ void Allocate(UInt32 numElems) // can also re-allocate
+ {
+ UInt32 reqSize = numElems * sizeof(T);
+
+ if (mMemObject != NULL && reqSize == mBufferSizeBytes)
+ return; // already allocated
+
+ mBufferSizeBytes = reqSize;
+ mMemObject = CA_realloc(mMemObject, reqSize);
+ UInt32 misalign = (uintptr_t)mMemObject & kAlignMask;
+ if (misalign) {
+ mMemObject = CA_realloc(mMemObject, reqSize + kAlignMask);
+ mAlignedBuffer = (T *)((char *)mMemObject + kAlignInterval - misalign);
+ } else
+ mAlignedBuffer = (T *)mMemObject;
+ }
+
+ /*! @method Deallocate */
+ void Deallocate()
+ {
+ if (mMemObject == NULL) return; // so this method has no effect if we're using
+ // an external buffer
+
+ free(mMemObject);
+ mMemObject = NULL;
+ mAlignedBuffer = NULL;
+ mBufferSizeBytes = 0;
+ }
+
+ /*! @method AllocateClear */
+ void AllocateClear(UInt32 numElems) // can also re-allocate
+ {
+ Allocate(numElems);
+ Clear();
+ }
+
+ /*! @method Clear */
+ void Clear()
+ {
+ memset(mAlignedBuffer, 0, mBufferSizeBytes);
+ }
+
+ // accessors
+
+ /*! @method operator T *()@ */
+ operator T *() { return mAlignedBuffer; }
+
+private:
+ /*! @var mMemObject */
+ void * mMemObject; // null when using an external buffer
+ /*! @var mAlignedBuffer */
+ T * mAlignedBuffer; // always valid once allocated
+ /*! @var mBufferSizeBytes */
+ UInt32 mBufferSizeBytes;
+};
+
+#endif // __AUBuffer_h__
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUDebugDispatcher.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUDebugDispatcher.cpp
new file mode 100755
index 00000000..799ce686
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUDebugDispatcher.cpp
@@ -0,0 +1,423 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+ * AUDebugDispatcher.h
+ * CAServices
+
+=============================================================================*/
+
+#if AU_DEBUG_DISPATCHER
+
+#warning "This should * * NOT * * be seen on a Release Version"
+
+
+#include "AUDebugDispatcher.h"
+
+static char* AUErrorStr (OSStatus result);
+
+class AUDD_Locker {
+public:
+ AUDD_Locker (CAMutex &guard) :mGuard (guard) { didLock = mGuard.Lock(); }
+ ~AUDD_Locker () { if (didLock) mGuard.Unlock(); }
+
+private:
+ bool didLock;
+ CAMutex &mGuard;
+};
+
+AUDebugDispatcher::AUDebugDispatcher (AUBase *au, FILE* file)
+ : mAUBase (au),
+ mFile (file),
+ mHaveDoneProperty (false),
+ mPrintMutex ("AU Debug Dispatcher Printer"),
+ mHostCB1_Result (0),
+ mHostCB2_Result (0),
+ mHostCB3_Result (0),
+ mHostCB_WhenToPrint (0),
+ mHostCB_WasPlaying (0)
+{
+ // lets gather some info about this instance...
+ AudioComponentDescription desc = mAUBase->GetComponentDescription();
+ fprintf (mFile, "\nAUBase=0x%X, Type=%4.4s, SubType=%4.4s, Manu=%4.4s\n\n", AU(),
+ (char*)&desc.componentType,
+ (char*)&desc.componentSubType,
+ (char*)&desc.componentManufacturer);
+ mFirstTime = CAHostTimeBase::GetCurrentTime();
+}
+
+
+AUDebugDispatcher::~AUDebugDispatcher()
+{
+ PrintHeaderString (CAHostTimeBase::GetCurrentTime(), (unsigned int)pthread_self(), "Close");
+ fprintf (mFile, "\n");
+}
+
+void AUDebugDispatcher::PrintHeaderString (UInt64 inNowTime, unsigned int inThread, const char* inMethod)
+{
+ double secsSinceStart = SecsSinceStart(inNowTime);
+ fprintf (mFile, "[AUDisp:AUBase = 0x%X, Time = %.6lf secs, Thread = 0x%X, IsInitialized = '%c'] %s()\n",
+ AU(), secsSinceStart, inThread, (mAUBase->IsInitialized() ? 'T' : 'F'), inMethod);
+}
+
+unsigned int AUDebugDispatcher::RecordDispatch (UInt64 inStartTime, OSStatus result, const char* inMethod)
+{
+ UInt64 nowTime = CAHostTimeBase::GetCurrentTime();
+
+ unsigned int theThread = (unsigned int)pthread_self();
+
+ PrintHeaderString (nowTime, theThread, inMethod);
+
+ UInt64 nanos = CAHostTimeBase::ConvertToNanos(nowTime - inStartTime);
+
+ fprintf (mFile, "\t[Time To execute = %.6lf secs", (nanos * 1.0e-9));
+
+ if (result)
+ fprintf (mFile, ", * * * result = %ld, %s * * * ", result, AUErrorStr(result));
+
+ fprintf (mFile, "]\n");
+
+ return theThread;
+}
+
+#pragma mark -
+#pragma mark __AU Dispatch
+#pragma mark -
+
+void AUDebugDispatcher::Initialize (UInt64 nowTime, OSStatus result)
+{
+ AUDD_Locker lock (mPrintMutex);
+ RecordDispatch (nowTime, result, "Initialize");
+}
+
+void AUDebugDispatcher::Uninitialize (UInt64 nowTime, OSStatus result)
+{
+ AUDD_Locker lock (mPrintMutex);
+ RecordDispatch (nowTime, result, "Uninitialize");
+}
+
+void AUDebugDispatcher::GetPropertyInfo (UInt64 nowTime,
+ OSStatus result,
+ AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 *outDataSize,
+ Boolean *outWritable)
+{
+ AUDD_Locker lock (mPrintMutex);
+ RecordDispatch (nowTime, result, "GetPropertyInfo");
+ PrintProperty (inID, inScope, inElement);
+}
+
+void AUDebugDispatcher::GetProperty (UInt64 nowTime,
+ OSStatus result,
+ AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 *ioDataSize,
+ void *outData)
+{
+ //err -> ioDataSize == NULL or 0
+ //outData == NULL -> Dispatches to GetPropertyInfo
+
+ // still should log these as calls to GetProperty...
+ AUDD_Locker lock (mPrintMutex);
+ const char *dispStr = outData != NULL ? "GetProperty" : "GetProperty - Info";
+ RecordDispatch (nowTime, result, dispStr);
+ PrintProperty (inID, inScope, inElement);
+}
+
+void AUDebugDispatcher::SetProperty (UInt64 nowTime,
+ OSStatus result,
+ AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ // inData could be NULL to remove property value...
+ AUDD_Locker lock (mPrintMutex);
+ RecordDispatch (nowTime, result, "SetProperty");
+ PrintProperty (inID, inScope, inElement);
+}
+
+void AUDebugDispatcher::Render ( UInt64 nowTime,
+ OSStatus result,
+ AudioUnitRenderActionFlags * inRenderFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inOutputBusNumber,
+ UInt32 inNumFrames,
+ AudioBufferList * inIOData)
+{
+ if (mHaveDoneProperty) {
+ AUDD_Locker lock (mPrintMutex);
+ RecordDispatch (nowTime, result, "Render");
+ fprintf (mFile, "\t\t[Sample Time = %.0lf, NumFrames = %ld]\n", inTimeStamp->mSampleTime, inNumFrames);
+ mHaveDoneProperty = false;
+ }
+ RenderActions_HostCallbacks ();
+}
+
+#define kBeginLine " "
+
+void AUDebugDispatcher::RenderActions_HostCallbacks ()
+{
+ bool doPrint = !(mHostCB_WhenToPrint++ % 5000);
+
+// (3) Host Transport State callback
+// - this is printed below, but we use the transStateChange to see if we have something to print
+ Boolean isPlaying, transStateChange, isCycling;
+ Float64 currentSample, cycleStartBeat, cycleEndBeat;
+ OSStatus result = mAUBase->CallHostTransportState (&isPlaying, &transStateChange, &currentSample,
+ &isCycling, &cycleStartBeat, &cycleEndBeat);
+ bool newCB3Result = false;
+ if (result != mHostCB3_Result) {
+ mHostCB3_Result = result;
+ newCB3Result = true;
+ }
+
+ if (transStateChange) mHostCB_WhenToPrint = 1;
+
+// Code to test the Host Callbacks
+ Float64 currentBeat, currentTempo;
+
+// (1) Beat and Tempo callback
+ result = mAUBase->CallHostBeatAndTempo (&currentBeat, &currentTempo);
+
+ if (result) {
+ if (result != mHostCB1_Result) {
+ printf ("_HCback_ Error Calling HostBeatAndTempo:%ld\n", result);
+ mHostCB1_Result = result;
+ }
+ } else {
+ if (doPrint || currentBeat < 0 || transStateChange)
+ printf ("_HCback_ Beat and Tempo: Current Beat:%f, Current Tempo:%f\n", currentBeat, currentTempo);
+ }
+
+// (2) Musical Time callback
+ UInt32 deltaSampleOffset, timeSig_Denom;
+ Float32 timeSig_Num;
+ Float64 currentMeasureDownBeat;
+ result = mAUBase->CallHostMusicalTimeLocation (&deltaSampleOffset, &timeSig_Num, &timeSig_Denom, &currentMeasureDownBeat);
+
+ if (result) {
+ if (result != mHostCB2_Result) {
+ printf ("%sError Calling CallHostMusicalTimeLocation:%ld\n", kBeginLine, result);
+ mHostCB2_Result = result;
+ }
+ } else {
+ if (doPrint || currentMeasureDownBeat < 0 || deltaSampleOffset < 0 || transStateChange) {
+ printf ("%sMusical Time: Delta Sample Offset:%ld, Time Sig:Num:%.1f, Time Sig:Denom:%ld, DownBeat:%f\n",
+ kBeginLine, deltaSampleOffset, timeSig_Num, timeSig_Denom, currentMeasureDownBeat);
+ }
+ }
+
+ if (mHostCB3_Result) {
+ if (newCB3Result) {
+ printf ("%sError Calling CallHostTransportState:%ld\n", kBeginLine, mHostCB3_Result);
+ }
+ } else {
+ if (doPrint || (mHostCB_WasPlaying != isPlaying) || transStateChange || currentSample < 0)
+ {
+ printf ("%sTransport State: Was Playing:%d, ", kBeginLine, mHostCB_WasPlaying);
+ mHostCB_WasPlaying = isPlaying;
+ printf ("Is Playing:%d, Transport State Changed:%d", isPlaying, transStateChange);
+ if (isPlaying) {
+ printf (", Current Sample:%.1f", currentSample);
+ if (isCycling)
+ printf (", Is Cycling [Start Beat:%.2f, End Beat:%.2f]", cycleStartBeat, cycleEndBeat);
+ }
+ printf ("\n");
+ }
+ }
+}
+
+#pragma mark -
+#pragma mark __Utilities
+#pragma mark -
+
+static char* AUScopeStr (AudioUnitScope inScope)
+{
+ switch (inScope) {
+ case kAudioUnitScope_Global: return "Global";
+ case kAudioUnitScope_Output: return "Output";
+ case kAudioUnitScope_Input: return "Input";
+ case kAudioUnitScope_Group: return "Group";
+ }
+ return NULL;
+}
+
+static char* AUErrorStr (OSStatus result)
+{
+ switch (result) {
+ case kAudioUnitErr_InvalidProperty: return "Invalid Property";
+ case kAudioUnitErr_InvalidParameter: return "Invalid Parameter";
+ case kAudioUnitErr_InvalidElement: return "Invalid Element";
+ case kAudioUnitErr_NoConnection: return "Invalid Connection";
+ case kAudioUnitErr_FailedInitialization: return "Failed Initialization";
+ case kAudioUnitErr_TooManyFramesToProcess: return "Too Many Frames";
+ case kAudioUnitErr_IllegalInstrument: return "Illegal Instrument";
+ case kAudioUnitErr_InstrumentTypeNotFound: return "Instrument Type Not Found";
+ case kAudioUnitErr_InvalidFile: return "Invalid File";
+ case kAudioUnitErr_UnknownFileType: return "Unknown File Type";
+ case kAudioUnitErr_FileNotSpecified: return "File Not Specified";
+ case kAudioUnitErr_FormatNotSupported: return "Format Not Supported";
+ case kAudioUnitErr_Uninitialized: return "Un Initialized";
+ case kAudioUnitErr_InvalidScope: return "Invalid Scope";
+ case kAudioUnitErr_PropertyNotWritable: return "Property Not Writable";
+ case kAudioUnitErr_InvalidPropertyValue: return "Invalid Property Value";
+ case kAudioUnitErr_PropertyNotInUse: return "Property Not In Use";
+ case kAudioUnitErr_Initialized: return "Initialized";
+
+ // some common system errors
+ case badComponentSelector: return "Bad Component Selector";
+ case paramErr: return "Parameter Error";
+ case badComponentInstance: return "Bad Component Instance";
+ }
+ return "Unknown Error";
+}
+
+static char* AUPropertyStr (AudioUnitPropertyID inID)
+{
+ switch (inID) {
+ case kAudioUnitProperty_ClassInfo: return "Class Info";
+ case kAudioUnitProperty_MakeConnection: return "Connection";
+ case kAudioUnitProperty_SampleRate: return "Sample Rate";
+ case kAudioUnitProperty_ParameterList: return "Parameter List";
+ case kAudioUnitProperty_ParameterInfo: return "Parameter Info";
+ case kAudioUnitProperty_FastDispatch: return "Fast Dispatch";
+ case kAudioUnitProperty_CPULoad: return "CPU Load";
+ case kAudioUnitProperty_StreamFormat: return "Format";
+ case kAudioUnitProperty_ReverbRoomType: return "Reverb Room Type";
+ case kAudioUnitProperty_ElementCount: return "Element Count";
+ case kAudioUnitProperty_Latency: return "Latency";
+ case kAudioUnitProperty_SupportedNumChannels: return "Supported Num Channels";
+ case kAudioUnitProperty_MaximumFramesPerSlice: return "Max Frames Per Slice";
+ case kAudioUnitProperty_SetExternalBuffer: return "Set External Buffer";
+ case kAudioUnitProperty_ParameterValueStrings: return "Parameter Value Strings";
+ case kAudioUnitProperty_GetUIComponentList: return "Carbon UI";
+ case kAudioUnitProperty_AudioChannelLayout: return "Audio Channel Layout";
+ case kAudioUnitProperty_TailTime: return "Tail Time";
+ case kAudioUnitProperty_BypassEffect: return "Bypass Effect";
+ case kAudioUnitProperty_LastRenderError: return "Last Render Error";
+ case kAudioUnitProperty_SetRenderCallback: return "Render Callback";
+ case kAudioUnitProperty_FactoryPresets: return "Factory Preset";
+ case kAudioUnitProperty_ContextName: return "Context Name";
+ case kAudioUnitProperty_RenderQuality: return "Render Quality";
+ case kAudioUnitProperty_HostCallbacks: return "Host Callbacks";
+ case kAudioUnitProperty_InPlaceProcessing: return "In Place Processing";
+ case kAudioUnitProperty_ElementName: return "Element Name";
+ case kAudioUnitProperty_CocoaUI: return "Cocoa UI";
+ case kAudioUnitProperty_SupportedChannelLayoutTags: return "Supported Channel Layout Tags";
+ case kAudioUnitProperty_ParameterStringFromValue: return "Parameter Value Name";
+ case kAudioUnitProperty_UsesInternalReverb: return "Use Internal Reverb";
+ case kAudioUnitProperty_ParameterIDName: return "Parameter ID Name";
+ case kAudioUnitProperty_ParameterClumpName: return "Clump Name";
+ case kAudioUnitProperty_PresentPreset: return "Present Preset";
+
+
+ case kMusicDeviceProperty_InstrumentCount: return "Instrument Count";
+ case kMusicDeviceProperty_InstrumentName: return "Instrument Name";
+ case kMusicDeviceProperty_SoundBankFSRef: return "Sound Bank - File";
+ case kMusicDeviceProperty_InstrumentNumber: return "Instrument Number";
+ case kMusicDeviceProperty_MIDIXMLNames: return "MIDI XML Names";
+ case kMusicDeviceProperty_BankName: return "Bank Name";
+ case kMusicDeviceProperty_SoundBankData: return "Sound Bank - Data";
+
+
+ case kAudioOutputUnitProperty_CurrentDevice: return "Current AudioDevice";
+ case kAudioOutputUnitProperty_IsRunning: return "Is Running";
+ case kAudioOutputUnitProperty_ChannelMap: return "Channel Map";
+ case kAudioOutputUnitProperty_EnableIO: return "Enable I/O";
+ case kAudioOutputUnitProperty_StartTime: return "Start Time";
+ case kAudioOutputUnitProperty_SetInputCallback: return "I/O Input Callback";
+ }
+ return "Unknown";
+}
+
+
+void AUDebugDispatcher::PrintProperty ( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ char* scopeStr = AUScopeStr(inScope);
+ char* propStr = AUPropertyStr (inID);
+
+ if (scopeStr != NULL)
+ fprintf (mFile, "\t\t[ID = %ld, %s, Scope = %s, El = %ld]\n", inID, propStr, scopeStr, inElement);
+ else
+ fprintf (mFile, "\t\t[ID = %ld, %s, Scope = %ld, El = %ld]\n", inID, propStr, inScope , inElement);
+
+ bool iscback = false;
+ bool isInput = false;
+ switch (inID)
+ {
+ case kAudioUnitProperty_SetRenderCallback:
+ iscback = true;
+ case kAudioUnitProperty_MakeConnection:
+ {
+ AUInputElement *el = mAUBase->GetInput (inElement);
+ if (el) {
+ bool hasInput = false;
+ if (iscback)
+ hasInput = el->IsCallback();
+ else
+ hasInput = el->HasConnection();
+ fprintf (mFile, "\t\tHas Input=%c, ", (hasInput ? 'T' : 'F'));
+ isInput = true;
+ }
+ }
+ case kAudioUnitProperty_SampleRate:
+ case kAudioUnitProperty_StreamFormat:
+ {
+ CAStreamBasicDescription desc = mAUBase->GetStreamFormat (inScope, inElement);
+ if (!isInput)
+ fprintf (mFile, "\t\t");
+ desc.Print (mFile);
+ break;
+ }
+ default:
+ break;
+ }
+
+ mHaveDoneProperty = true;
+}
+
+#endif //AU_DEBUG_DISPATCHER
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUDebugDispatcher.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUDebugDispatcher.h
new file mode 100755
index 00000000..4712e730
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUDebugDispatcher.h
@@ -0,0 +1,131 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+ * AUDebugDispatcher.h
+ * CAServices
+
+ =============================================================================*/
+
+#ifndef __AUDebugDispatcher_h__
+#define __AUDebugDispatcher_h__
+
+#if AU_DEBUG_DISPATCHER
+
+#include "CAHostTimeBase.h"
+#include "CAMutex.h"
+#include "AUBase.h"
+
+
+class AUDebugDispatcher {
+public:
+ AUDebugDispatcher (AUBase *au, FILE* file = stdout);
+ ~AUDebugDispatcher();
+
+// these are the AU API calls
+ void Initialize (UInt64 nowTime, OSStatus result);
+
+ void Uninitialize (UInt64 nowTime, OSStatus result);
+
+ void GetPropertyInfo (UInt64 nowTime,
+ OSStatus result,
+ AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 *outDataSize,
+ Boolean *outWritable);
+
+ void GetProperty ( UInt64 nowTime,
+ OSStatus result,
+ AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 *ioDataSize,
+ void *outData);
+
+ void SetProperty ( UInt64 nowTime,
+ OSStatus result,
+ AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+
+ void Render ( UInt64 nowTime,
+ OSStatus result,
+ AudioUnitRenderActionFlags * inRenderFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inOutputBusNumber,
+ UInt32 inNumFrames,
+ AudioBufferList * inIOData);
+
+private:
+ AUBase* mAUBase;
+ UInt64 mFirstTime;
+ FILE* mFile;
+ bool mHaveDoneProperty;
+ CAMutex mPrintMutex;
+
+
+ OSStatus mHostCB1_Result;
+ OSStatus mHostCB2_Result;
+ OSStatus mHostCB3_Result;
+ int mHostCB_WhenToPrint;
+ int mHostCB_WasPlaying;
+
+ double SecsSinceStart(UInt64 inNowTime)
+ {
+ UInt64 nanos = CAHostTimeBase::ConvertToNanos(inNowTime - mFirstTime);
+ return nanos * 1.0e-9;
+ }
+
+ unsigned int RecordDispatch (UInt64 inStartTime, OSStatus result, const char* inMethod);
+
+ void PrintHeaderString (UInt64 inNowTime, unsigned int inThread, const char* inMethod);
+
+ unsigned int AU() const { return (unsigned int)mAUBase->GetComponentInstance(); }
+
+ void PrintProperty (AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement);
+
+ void RenderActions_HostCallbacks ();
+};
+
+#endif // AU_DEBUG_DISPATCHER
+#endif //__AUDebugDispatcher_h__
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h
new file mode 100755
index 00000000..d24801f0
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h
@@ -0,0 +1,149 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUSilentTimeout.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUSilentTimeout.h
new file mode 100755
index 00000000..a1334b16
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUSilentTimeout.h
@@ -0,0 +1,87 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp
new file mode 100755
index 00000000..c3020782
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp
@@ -0,0 +1,185 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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)
+{
+ mRateScalarAdj = rateScalarAdj;
+ mLastOutputTime = mCurrentOutputTime;
+ mCurrentOutputTime = inTimeStamp;
+ if (mBypassed)
+ return;
+ if (mHostTimeDiscontinuityCorrection && !(mCurrentOutputTime.mFlags & kAudioTimeStampHostTimeValid) && (mLastOutputTime.mFlags & kAudioTimeStampHostTimeValid)) {
+ // no host time here but we had one last time, interpolate one
+ double rateScalar = (mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid) ? mCurrentOutputTime.mRateScalar : 1.0;
+ Float64 deltaSamples = mCurrentOutputTime.mSampleTime - mLastOutputTime.mSampleTime;
+ mCurrentOutputTime.mHostTime = mLastOutputTime.mHostTime +
+ UInt64(CAHostTimeBase::GetFrequency() * deltaSamples * rateScalar / outputSampleRate);
+ mCurrentOutputTime.mFlags |= kAudioTimeStampHostTimeValid;
+#if DEBUG
+ if (mVerbosity > 1)
+ printf("synthesized host time: %.3f (%.3f + %.f smp @ %.f Hz, rs %.3f\n", DebugHostTime(mCurrentOutputTime), DebugHostTime(mLastOutputTime), deltaSamples, outputSampleRate, rateScalar);
+#endif
+ }
+ // copy rate scalar
+ if (rateScalarAdj != 1.0) {
+ if (mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid)
+ mCurrentOutputTime.mRateScalar *= rateScalarAdj;
+ else {
+ mCurrentOutputTime.mRateScalar = rateScalarAdj;
+ mCurrentOutputTime.mFlags |= kAudioTimeStampRateScalarValid;
+ }
+ }
+
+ if (mFirstTime) {
+ mFirstTime = false;
+ mDiscontinuous = false;
+ mDiscontinuityDeltaSamples = 0.;
+ if (!mStartInputAtZero)
+ mNextInputSampleTime = mCurrentOutputTime.mSampleTime;
+ } else {
+ mDiscontinuous = fnotequal(mCurrentOutputTime.mSampleTime, mNextOutputSampleTime);
+ mDiscontinuityDeltaSamples = mCurrentOutputTime.mSampleTime - mNextOutputSampleTime;
+ // time should never go backwards...
+ if (mDiscontinuityDeltaSamples < 0.)
+ mDiscontinuityDeltaSamples = 0.;
+#if DEBUG
+ if (mVerbosity > 1)
+ if (mDiscontinuous)
+ printf("%-20.20s: *** DISCONTINUOUS, got "TSGFMT", expected "TSGFMT"\n", mDebugName, (SInt64)mCurrentOutputTime.mSampleTime, (SInt64)mNextOutputSampleTime);
+#endif
+ }
+ mNextOutputSampleTime = mCurrentOutputTime.mSampleTime + expectedDeltaFrames;
+}
+
+const AudioTimeStamp & AUTimestampGenerator::GenerateInputTime(Float64 framesToAdvance, double inputSampleRate)
+{
+ if (mBypassed)
+ return mCurrentOutputTime;
+
+ double inputSampleTime;
+
+ mCurrentInputTime.mFlags = kAudioTimeStampSampleTimeValid;
+ double rateScalar = 1.0;
+
+ // propagate rate scalar
+ if (mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid) {
+ mCurrentInputTime.mFlags |= kAudioTimeStampRateScalarValid;
+ mCurrentInputTime.mRateScalar = rateScalar = mCurrentOutputTime.mRateScalar;
+ }
+
+ // propagate host time and sample time
+ if (mCurrentOutputTime.mFlags & kAudioTimeStampHostTimeValid) {
+ mCurrentInputTime.mFlags |= kAudioTimeStampHostTimeValid;
+ mCurrentInputTime.mHostTime = mCurrentOutputTime.mHostTime;
+ if (mHostTimeDiscontinuityCorrection && mDiscontinuous && (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 = mCurrentOutputTime.mHostTime - mLastOutputTime.mHostTime;
+ double deltaSeconds = double(deltaHostTime) * CAHostTimeBase::GetInverseFrequency();
+ // samples/second * seconds = samples
+ double deltaSamples = floor(inputSampleRate / rateScalar * deltaSeconds + 0.5);
+ double lastInputSampleTime = 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
+ mDiscontinuous = false;
+ } else {
+ inputSampleTime = mNextInputSampleTime;
+ }
+ } else {
+ // we don't know the host time, so we can't do much
+ inputSampleTime = mNextInputSampleTime;
+ }
+
+ if (!mHostTimeDiscontinuityCorrection && fnonzero(mDiscontinuityDeltaSamples))
+ {
+ // we had a discontinuous output time, need to resync by propagating the
+ // detected discontinuity, taking the rate scalar adjustment into account
+ inputSampleTime += floor(mDiscontinuityDeltaSamples / mRateScalarAdj + 0.5);
+
+#if DEBUG
+ if (mVerbosity > 1)
+ printf("%-20.20s: adjusted input time: %.0f -> %.0f (SR=%.3f, rs=%.3f, delta=%.0f)\n", mDebugName, mNextInputSampleTime, inputSampleTime, inputSampleRate, mRateScalarAdj, mDiscontinuityDeltaSamples);
+#endif
+
+ mDiscontinuityDeltaSamples = 0.;
+ }
+
+
+ // propagate word clock
+ if (mCurrentOutputTime.mFlags & kAudioTimeStampWordClockTimeValid) {
+ mCurrentInputTime.mFlags |= kAudioTimeStampWordClockTimeValid;
+ mCurrentInputTime.mWordClockTime = mCurrentOutputTime.mWordClockTime;
+ }
+
+ // propagate SMPTE time
+ if (mCurrentOutputTime.mFlags & kAudioTimeStampSMPTETimeValid) {
+ mCurrentInputTime.mFlags |= kAudioTimeStampSMPTETimeValid;
+ mCurrentInputTime.mSMPTETime = mCurrentOutputTime.mSMPTETime;
+ }
+
+ // store the input sample time and expected next input time
+ mCurrentInputTime.mSampleTime = inputSampleTime;
+ 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)mCurrentOutputTime.mSampleTime, DebugHostTime(mCurrentOutputTime), (SInt64)inputSampleTime, DebugHostTime(mCurrentInputTime), (SInt64)(mCurrentOutputTime.mSampleTime - inputSampleTime), (SInt64)framesToAdvance);
+ }
+#endif
+ return mCurrentInputTime;
+}
diff --git a/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h
new file mode 100755
index 00000000..e08bd86a
--- /dev/null
+++ b/distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h
@@ -0,0 +1,148 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __AUTimestampGenerator_h__
+#define __AUTimestampGenerator_h__
+
+#include <math.h>
+#include "CAHostTimeBase.h"
+#include <stdio.h>
+
+#define TSGFMT "0x%10qx"
+//#define TSGFMT "%10qd"
+
+// This class generates a continuously increasing series of timestamps based
+// on a series of potentially discontinuous timestamps (as can be delivered from
+// CoreAudio in the event of an overload or major engine change).
+// N.B.: "output" = downstream (source) timestamp
+// "input" = upstream (derived) timestamp
+class AUTimestampGenerator {
+public:
+ AUTimestampGenerator(bool hostTimeDiscontinuityCorrection = false) :
+ mStartInputAtZero(true),
+ mBypassed(false),
+ mHostTimeDiscontinuityCorrection(hostTimeDiscontinuityCorrection)
+ {
+#if DEBUG
+ mVerbosity = 0;
+ sprintf(mDebugName, "tsg @ %p", this);
+#endif
+ // CAHostTimeBase should be used instead of the calls in <CoreAudio/HostTime.h>
+ // we make this call here to ensure that this is initialized, otherwise the first time
+ // you do actually call CAHostTimeBase to do work, can be on the render thread, and lead to unwanted VM faults
+ CAHostTimeBase::GetFrequency();
+ Reset();
+ }
+
+ void SetStartInputAtZero(bool b) { mStartInputAtZero = b; }
+ bool GetStartInputAtZero() const { return 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) { mBypassed = b; }
+ bool GetBypassed() const { return mBypassed; }
+
+ // Call this to reset the timeline.
+ void Reset()
+ {
+ mCurrentInputTime.mSampleTime = 0.;
+ mNextInputSampleTime = 0.;
+ mCurrentOutputTime.mSampleTime = 0.;
+ mNextOutputSampleTime = 0.;
+ mLastOutputTime.mFlags = 0;
+ 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);
+
+ // 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)mCurrentInputTime.mSampleTime, (SInt64)framesToAdvance);
+#endif
+ mNextInputSampleTime = mCurrentInputTime.mSampleTime + framesToAdvance;
+ }
+
+
+private:
+ AudioTimeStamp mCurrentInputTime;
+ Float64 mNextInputSampleTime;
+ Float64 mNextOutputSampleTime;
+
+ AudioTimeStamp mLastOutputTime;
+ AudioTimeStamp mCurrentOutputTime;
+
+ bool mFirstTime;
+ 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.
+
+
+#if DEBUG
+public:
+ int mVerbosity;
+ char mDebugName[64];
+#endif
+};
+
+
+#endif // __AUTimestampGenerator_h__
diff --git a/distrho/src/CoreAudio106/PublicUtility/AUOutputBL.cpp b/distrho/src/CoreAudio106/PublicUtility/AUOutputBL.cpp
new file mode 100755
index 00000000..f5ee5a2b
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/AUOutputBL.cpp
@@ -0,0 +1,163 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "AUOutputBL.h"
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AUComponent.h>
+#else
+ #include <AUComponent.h>
+#endif
+/*
+struct AudioBufferList
+{
+ UInt32 mNumberBuffers;
+ AudioBuffer mBuffers[1];
+};
+struct AudioBuffer
+{
+ UInt32 mNumberChannels; // number of interleaved channels in the buffer
+ UInt32 mDataByteSize; // the size of the buffer pointed to by mData
+ void* mData; // the pointer to the buffer
+};
+*/
+
+AUOutputBL::AUOutputBL (const CAStreamBasicDescription &inDesc, UInt32 inDefaultNumFrames)
+ : mFormat (inDesc),
+ mBufferMemory(NULL),
+ mBufferList (NULL),
+ mNumberBuffers (0), // keep this here, so can ensure integrity of ABL
+ mBufferSize (0),
+ mFrames(inDefaultNumFrames)
+{
+ mNumberBuffers = mFormat.IsInterleaved() ? 1 : mFormat.NumberChannels();
+ mBufferList = reinterpret_cast<AudioBufferList*>(new Byte[offsetof(AudioBufferList, mBuffers) + (mNumberBuffers * sizeof(AudioBuffer))]);
+}
+
+AUOutputBL::~AUOutputBL()
+{
+ if (mBufferMemory)
+ delete[] mBufferMemory;
+
+ if (mBufferList)
+ delete [] (Byte *)mBufferList;
+}
+
+void AUOutputBL::Prepare (UInt32 inNumFrames, bool inWantNullBufferIfAllocated)
+{
+ UInt32 channelsPerBuffer = mFormat.IsInterleaved() ? mFormat.NumberChannels() : 1;
+
+ if (mBufferMemory == NULL || inWantNullBufferIfAllocated)
+ {
+ mBufferList->mNumberBuffers = mNumberBuffers;
+ AudioBuffer *buf = &mBufferList->mBuffers[0];
+ for (UInt32 i = 0; i < mNumberBuffers; ++i, ++buf) {
+ buf->mNumberChannels = channelsPerBuffer;
+ buf->mDataByteSize = mFormat.FramesToBytes (inNumFrames);
+ buf->mData = NULL;
+ }
+ }
+ else
+ {
+ UInt32 nBytes = mFormat.FramesToBytes (inNumFrames);
+ if ((nBytes * mNumberBuffers) > AllocatedBytes())
+ throw OSStatus(kAudioUnitErr_TooManyFramesToProcess);
+
+ mBufferList->mNumberBuffers = mNumberBuffers;
+ AudioBuffer *buf = &mBufferList->mBuffers[0];
+ Byte* p = mBufferMemory;
+ for (UInt32 i = 0; i < mNumberBuffers; ++i, ++buf) {
+ buf->mNumberChannels = channelsPerBuffer;
+ buf->mDataByteSize = nBytes;
+ buf->mData = p;
+ p += mBufferSize;
+ }
+ }
+}
+
+
+void AUOutputBL::Allocate (UInt32 inNumFrames)
+{
+ if (inNumFrames)
+ {
+ UInt32 nBytes = mFormat.FramesToBytes (inNumFrames);
+
+ if (nBytes <= AllocatedBytes())
+ return;
+
+ // align successive buffers for Altivec and to take alternating
+ // cache line hits by spacing them by odd multiples of 16
+ if (mNumberBuffers > 1)
+ nBytes = (nBytes + (0x10 - (nBytes & 0xF))) | 0x10;
+
+ mBufferSize = nBytes;
+
+ UInt32 memorySize = mBufferSize * mNumberBuffers;
+ Byte *newMemory = new Byte[memorySize];
+ memset(newMemory, 0, memorySize); // make buffer "hot"
+
+ Byte *oldMemory = mBufferMemory;
+ mBufferMemory = newMemory;
+ delete[] oldMemory;
+
+ mFrames = inNumFrames;
+ }
+ else
+ {
+ if (mBufferMemory) {
+ delete [] mBufferMemory;
+ mBufferMemory = NULL;
+ }
+ mBufferSize = 0;
+ mFrames = 0;
+ }
+}
+
+#if DEBUG
+void AUOutputBL::Print()
+{
+ printf ("AUOutputBL::Print\n");
+ mFormat.Print();
+ printf ("Num Buffers:%d, mFrames:%d, allocatedMemory:%c\n", (int)mBufferList->mNumberBuffers, (int)mFrames, (mBufferMemory != NULL ? 'T' : 'F'));
+ AudioBuffer *buf = &mBufferList->mBuffers[0];
+ for (UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i, ++buf)
+ printf ("\tBuffer:%d, Size:%d, Chans:%d, Buffer:%p\n", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData);
+}
+#endif
+
diff --git a/distrho/src/CoreAudio106/PublicUtility/AUOutputBL.h b/distrho/src/CoreAudio106/PublicUtility/AUOutputBL.h
new file mode 100755
index 00000000..3e7fe0b9
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/AUOutputBL.h
@@ -0,0 +1,112 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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) { return *this; }
+};
+
+#endif // __AUOutputBL_h__
diff --git a/distrho/src/CoreAudio106/PublicUtility/AUParamInfo.cpp b/distrho/src/CoreAudio106/PublicUtility/AUParamInfo.cpp
new file mode 100755
index 00000000..4f4466a0
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/AUParamInfo.cpp
@@ -0,0 +1,133 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "AUParamInfo.h"
+#include "CAXException.h"
+
+AUParamInfo::AUParamInfo (AudioUnit inAU,
+ bool inIncludeExpert,
+ bool inIncludeReadOnly,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement)
+ : mAU (inAU),
+ mNumParams (0),
+ mParamListID(NULL),
+ mScope (inScope),
+ mElement (inElement)
+{
+ UInt32 size;
+ OSStatus result = AudioUnitGetPropertyInfo(mAU, kAudioUnitProperty_ParameterList, inScope, mElement, &size, NULL);
+ if (size == 0 || result) return;
+
+ int nparams = size / sizeof(AudioUnitPropertyID);
+ mParamListID = new AudioUnitParameterID[nparams];
+
+ memset (mParamListID, 0xFF, size);
+
+ AudioUnitParameterID *paramList = new AudioUnitParameterID[nparams];
+
+ result = AudioUnitGetProperty(mAU, kAudioUnitProperty_ParameterList, mScope, mElement, paramList, &size);
+ if (result) {
+ delete [] mParamListID;
+ delete [] paramList;
+ mParamListID = NULL;
+ return;
+ }
+
+ ParameterMap params;
+ for (int i = 0; i < nparams; ++i)
+ {
+ CAAUParameter auvp (mAU, paramList[i], mScope, mElement); // took out only using global scope in CAAUParameter creation
+ const AudioUnitParameterInfo &paramInfo = auvp.ParamInfo();
+
+ // don't include if parameter can't be read or written
+ if (!(paramInfo.flags & kAudioUnitParameterFlag_IsWritable)
+ && !(paramInfo.flags & kAudioUnitParameterFlag_IsReadable))
+ continue;
+
+ // only include if expert params wanted
+ if (!inIncludeExpert && auvp.IsExpert())
+ continue;
+
+ // only include if read only params are wanted
+ if (!(paramInfo.flags & kAudioUnitParameterFlag_IsWritable)
+ && (paramInfo.flags & kAudioUnitParameterFlag_IsReadable))
+ {
+ if (!inIncludeReadOnly)
+ continue;
+ }
+
+ mParamListID[mNumParams] = paramList[i];
+ mNumParams++;
+
+ // ok - if we're here, then we have a parameter we are going to display.
+ UInt32 clump = 0;
+ auvp.GetClumpID (clump);
+ mParams[clump].push_back (auvp);
+ }
+
+ delete [] paramList;
+}
+
+AUParamInfo::~AUParamInfo()
+{
+ delete [] mParamListID;
+}
+
+UInt32 AUParamInfo::NumParamsForClump (UInt32 inClump) const
+{
+ ParameterMap::const_iterator it = mParams.find(inClump);
+ if (it != mParams.end())
+ return (*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/distrho/src/CoreAudio106/PublicUtility/AUParamInfo.h b/distrho/src/CoreAudio106/PublicUtility/AUParamInfo.h
new file mode 100755
index 00000000..866cae2b
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/AUParamInfo.h
@@ -0,0 +1,106 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <map>
+#include <vector>
+#include <AudioUnit/AudioUnit.h>
+#include "CAAUParameter.h"
+
+/*
+ The ParameterMap returned by the Map() method is a map where
+ - the key is the clumpID
+ - the value is a ParameterList (vector<CAAUParameter>)
+
+ If you have parameters on multiple scopes (or elements within a scope), then you should create one of these
+ for each scope-element pair
+*/
+
+class AUParamInfo {
+
+public:
+ typedef std::vector <CAAUParameter> ParameterList;
+ typedef std::map <UInt32, ParameterList, std::less<UInt32> > ParameterMap;
+
+
+
+ AUParamInfo (AudioUnit inAU,
+ bool inIncludeExpert,
+ bool inIncludeReadOnly,
+ AudioUnitScope inScope = kAudioUnitScope_Global,
+ AudioUnitElement inElement = 0);
+
+ ~AUParamInfo();
+
+ const ParameterMap& Map () const { return mParams; }
+
+ // some convenience methods
+ UInt32 NumParams () const { return mNumParams; }
+
+ AudioUnitParameterID ParamID (UInt32 inIndex) const
+ {
+ if (inIndex < mNumParams) return mParamListID[inIndex];
+ return 0xFFFFFFFF;
+ }
+
+ UInt32 NumClumps () const { return 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/distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMap.cpp b/distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMap.cpp
new file mode 100755
index 00000000..b99480e3
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMap.cpp
@@ -0,0 +1,194 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CAAUMIDIMap.h"
+
+
+static MIDILinearTransformer linearTrans;
+static MIDILogTransformer logTrans;
+static MIDIExpTransformer expTrans;
+static MIDISqrtTransformer sqrtTrans;
+static MIDISquareTransformer squareTrans;
+static MIDICubeRtTransformer cubeRtTrans;
+static MIDICubeTransformer cubeTrans;
+
+MIDIValueTransformer * CAAUMIDIMap::GetTransformer (UInt32 inFlags)
+{
+ if (AudioUnitDisplayTypeIsLogarithmic(inFlags))
+ return &logTrans;
+ else if (AudioUnitDisplayTypeIsExponential(inFlags))
+ return &expTrans;
+ else if (AudioUnitDisplayTypeIsSquareRoot(inFlags))
+ return &sqrtTrans;
+ else if (AudioUnitDisplayTypeIsSquared(inFlags))
+ return &squareTrans;
+ else if (AudioUnitDisplayTypeIsCubed(inFlags))
+ return &cubeTrans;
+ else if (AudioUnitDisplayTypeIsCubeRoot(inFlags))
+ return &cubeRtTrans;
+ else
+ return &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/distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMap.h b/distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMap.h
new file mode 100755
index 00000000..d9189ac0
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMap.h
@@ -0,0 +1,535 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAAUMIDIMap_h_
+#define __CAAUMIDIMap_h_
+
+#include <AudioUnit/AudioUnitProperties.h>
+#include <algorithm>
+
+/*
+enum {
+ kAUParameterMIDIMapping_AnyChannelFlag = (1L << 0),
+ // If this flag is set and mStatus is a MIDI channel message, then the MIDI channel number
+ // in the status byte is ignored; the mapping is from the specified MIDI message on ANY channel.
+
+ kAUParameterMIDIMapping_AnyNoteFlag = (1L << 1),
+ // If this flag is set and mStatus is a Note On, Note Off, or Polyphonic Pressure message,
+ // the message's note number is ignored; the mapping is from ANY note number.
+
+ kAUParameterMIDIMapping_SubRange = (1L << 2),
+ // set this flag if the midi control should map only to a sub-range of the parameter's value
+ // then specify that range in the mSubRangeMin and mSubRangeMax members
+
+ kAUParameterMIDIMapping_Toggle = (1L << 3),
+ // this is only useful for boolean typed parameters. When set, it means that the parameter's
+ // value should be toggled (if true, become false and vice versa) when the represented MIDI message
+ // is received
+
+ kAUParameterMIDIMapping_Bipolar = (1L << 4),
+ // this can be set to when mapping a MIDI Controller to indicate that the parameter (typically a boolean
+ // style parameter) will only have its value changed to either the on or off state of a MIDI controller message
+ // (0 < 64 is off, 64 < 127 is on) such as the sustain pedal. The seeting of the next flag
+ // (kAUParameterMIDIMapping_Bipolar_On) determine whether the parameter is mapped to the on or off
+ // state of the controller
+ kAUParameterMIDIMapping_Bipolar_On = (1L << 5)
+ // only a valid flag if kAUParameterMIDIMapping_Bipolar is set
+};
+
+// The reserved fields here are being used to reserve space (as well as align to 64 bit size) for future use
+// When/If these fields are used, the names of the fields will be changed to reflect their functionality
+// so, apps should NOT refer to these reserved fields directly by name
+typedef struct AUParameterMIDIMapping
+{
+ AudioUnitScope mScope;
+ AudioUnitElement mElement;
+ AudioUnitParameterID mParameterID;
+ UInt32 mFlags;
+ Float32 mSubRangeMin;
+ Float32 mSubRangeMax;
+ UInt8 mStatus;
+ UInt8 mData1;
+ UInt8 reserved1; // MUST be set to zero
+ UInt8 reserved2; // MUST be set to zero
+ UInt32 reserved3; // MUST be set to zero
+} AUParameterMIDIMapping;
+*/
+
+/*
+Parameter To MIDI Mapping Properties
+These properties are used to:
+Describe a current set of mappings between MIDI messages and Parameter value setting
+Create a mapping between a parameter and a MIDI message through either:
+- explicitly adding (or removing) the mapping
+- telling the AU to hot-map the next MIDI message to a specified Parameter
+ The same MIDI Message can map to one or more parameters
+ One Parameter can be mapped from multiple MIDI messages
+
+ In general usage, these properties only apply to AU's that implement the MIDI API
+ AU Instruments (type=='aumu') and Music Effects (type == 'aumf')
+
+ These properties are used in the Global scope. The scope and element members of the structure describe
+ the scope and element of the parameter. In all usages, mScope, mElement and mParameterID must be
+ correctly specified.
+
+
+ * The AUParameterMIDIMapping Structure
+
+ Command mStatus mData1
+ Note Off 0x8n Note Num
+ Note On 0x9n Note Num
+ Key Pressure 0xAn Note Num
+ Control Change 0xBn ControllerID
+ Patch Change 0xCn Patch Num
+ Channel Pressure DxDn 0 (Unused)
+ Pitch Bend 0xEn 0 (Unused)
+
+ (where n is 0-0xF to correspond to MIDI channels 1-16)
+
+ Details:
+
+ In general MIDI Commands can be mapped to either a specific channel as specified in the mStatus bit.
+ If the kAUParameterMIDIMapping_AnyChannelFlag bit is set mStatus is a MIDI channel message, then the
+ MIDI channel number in the status byte is ignored; the mapping is from the specified MIDI message on ANY channel.
+
+ For note commands (note on, note off, key pressure), the MIDI message can trigger either with just a specific
+ note number, or any note number if the kAUParameterMIDIMapping_AnyNoteFlag bit is set. In these instances, the
+ note number is used as the trigger value (for instance, a note message could be used to set the
+ cut off frequency of a filter).
+
+ The Properties:
+
+ kAudioUnitProperty_AllParameterMIDIMappings array of AUParameterMIDIMapping (read/write)
+ This property is used to both retreive and set the current mapping state between (some/many/all of) its parameters
+ and MIDI messages. When set, it should replace any previous mapped settings the AU had.
+
+ If this property is implemented by a non-MIDI capable AU (such as an 'aufx' type), then the property is
+ read only, and recommends a suggested set of mappings for the host to perform. In this case, it is the
+ host's responsibility to map MIDI message to the AU parameters. As described previously, there are a set
+ of default mappings (see AudioToolbox/AUMIDIController.h) that the host can recommend to the user
+ in this circumstance.
+
+ This property's size will be very dynamic, depending on the number of mappings currently in affect, so the
+ caller should always get the size of the property first before retrieving it. The AU should return an error
+ if the caller doesn't provide enough space to return all of the current mappings.
+
+ kAudioUnitProperty_AddParameterMIDIMapping array of AUParameterMIDIMapping (write only)
+ This property is used to Add mappings to the existing set of mappings the AU possesses. It does NOT replace
+ any existing mappings.
+
+ kAudioUnitProperty_RemoveParameterMIDIMapping array of AUParameterMIDIMapping (write only)
+ This property is used to remove the specified mappings from the AU. If a mapping is specified that does not
+ currently exist in the AU, then it should just be ignored.
+
+ kAudioUnitProperty_HotMapParameterMIDIMapping AUParameterMIDIMapping (read/write)
+ This property is used in two ways, determined by the value supplied by the caller.
+ (1) If a mapping struct is provided, then that struct provides *all* of the information that the AU should
+ use to map the parameter, *except* for the MIDI message. The AU should then listen for the next MIDI message
+ and associate that MIDI message with the supplied AUParameter mapping. When this MIDI message is received and
+ the mapping made, the AU should also issue a notification on this property
+ (kAudioUnitProperty_HotMapParameterMIDIMapping) to indicate to the host that the mapping has been made. The host
+ can then retrieve the mapping that was made by getting the value of this property.
+
+ To avoid possible confusion, it is recommended that once the host has retrieved this mapping (if it is
+ presenting a UI to describe the mappings for example), that it then clears the mapping state as described next.
+
+ Thus, the only time this property will return a valid value is when the AU has made a mapping. If the AU's mapping
+ state has been cleared (or it has not been asked to make a mapping), then the AU should return
+ kAudioUnitErr_InvalidPropertyValue if the host tries to read this value.
+
+ (2) If the value passed in is NULL, then if the AU had a parameter that it was in the process of mapping, it
+ should disregard that (stop listening to the MIDI messages to create a mapping) and discard the partially
+ mapped struct. If the value is NULL and the AU is not in the process of mapping, the AU can ignore the request.
+
+ At all times, the _AllMappings property will completely describe the current known state of the AU's mappings
+ of MIDI messages to parameters.
+*/
+
+
+/*
+ When mapping, it is recommended that LSB controllers are in general not mapped (ie. the controller range of 32 < 64)
+ as many host parsers will map 14 bit control values. If you know (or can present an option) that the host deals with
+ 7 bit controllers only, then these controller ID's can be mapped of course.
+*/
+
+
+struct MIDIValueTransformer {
+ virtual double tolinear(double) = 0;
+ virtual double fromlinear(double) = 0;
+#if DEBUG
+ // suppress warning
+ virtual ~MIDIValueTransformer() { }
+#endif
+};
+
+struct MIDILinearTransformer : public MIDIValueTransformer {
+ virtual double tolinear(double x) { return x; }
+ virtual double fromlinear(double x) { return x; }
+};
+
+struct MIDILogTransformer : public MIDIValueTransformer {
+ virtual double tolinear(double x) { return log(std::max(x, .00001)); }
+ virtual double fromlinear(double x) { return exp(x); }
+};
+
+struct MIDIExpTransformer : public MIDIValueTransformer {
+ virtual double tolinear(double x) { return exp(x); }
+ virtual double fromlinear(double x) { return log(std::max(x, .00001)); }
+};
+
+struct MIDISqrtTransformer : public MIDIValueTransformer {
+ virtual double tolinear(double x) { return x < 0. ? -(sqrt(-x)) : sqrt(x); }
+ virtual double fromlinear(double x) { return x < 0. ? -(x * x) : x * x; }
+};
+
+struct MIDISquareTransformer : public MIDIValueTransformer {
+ virtual double tolinear(double x) { return x < 0. ? -(x * x) : x * x; }
+ virtual double fromlinear(double x) { return x < 0. ? -(sqrt(-x)) : sqrt(x); }
+};
+
+struct MIDICubeRtTransformer : public MIDIValueTransformer {
+ virtual double tolinear(double x) { return x < 0. ? -(pow(-x, 1./3.)) : pow(x, 1./3.); }
+ virtual double fromlinear(double x) { return x * x * x; }
+};
+
+struct MIDICubeTransformer : public MIDIValueTransformer {
+ virtual double tolinear(double x) { return x * x * x; }
+ virtual double fromlinear(double x) { return x < 0. ? -(pow(-x, 1./3.)) : pow(x, 1./3.); }
+};
+
+
+class CAAUMIDIMap : public AUParameterMIDIMapping {
+
+public:
+// variables for more efficient parsing of MIDI to Param value
+ Float32 mMinValue;
+ Float32 mMaxValue;
+ MIDIValueTransformer *mTransType;
+
+// methods
+ static MIDIValueTransformer *GetTransformer (UInt32 inFlags);
+
+ CAAUMIDIMap() { memset(this, 0, sizeof(CAAUMIDIMap)); }
+ CAAUMIDIMap (const AUParameterMIDIMapping& inMap)
+ {
+ memset(this, 0, sizeof(CAAUMIDIMap));
+ memcpy (this, &inMap, sizeof(inMap));
+ }
+ CAAUMIDIMap (AudioUnitScope inScope, AudioUnitElement inElement, AudioUnitParameterID inParam)
+ {
+ memset(this, 0, sizeof(CAAUMIDIMap));
+ mScope = inScope;
+ mElement = inElement;
+ mParameterID = inParam;
+ }
+
+
+ bool IsValid () const { return mStatus != 0; }
+
+ // returns -1 if any channel bit is set
+ SInt32 Channel () const { return IsAnyChannel() ? -1 : (mStatus & 0xF); }
+ bool IsAnyChannel () const {
+ return mFlags & kAUParameterMIDIMapping_AnyChannelFlag;
+ }
+ // preserves the existing channel info in the status byte
+ // preserves any previously set mFlags value
+ void SetAnyChannel (bool inFlag)
+ {
+ if (inFlag)
+ mFlags |= kAUParameterMIDIMapping_AnyChannelFlag;
+ else
+ mFlags &= ~kAUParameterMIDIMapping_AnyChannelFlag;
+ }
+
+ bool IsAnyNote () const {
+ return (mFlags & kAUParameterMIDIMapping_AnyNoteFlag) != 0;
+ }
+ // preserves the existing key num in the mData1 byte
+ // preserves any previously set mFlags value
+ void SetAnyNote (bool inFlag)
+ {
+ if (inFlag)
+ mFlags |= kAUParameterMIDIMapping_AnyNoteFlag;
+ else
+ mFlags &= ~kAUParameterMIDIMapping_AnyNoteFlag;
+ }
+
+ bool IsToggle() const { return (mFlags & kAUParameterMIDIMapping_Toggle) != 0; }
+ void SetToggle (bool inFlag)
+ {
+ if (inFlag)
+ mFlags |= kAUParameterMIDIMapping_Toggle;
+ else
+ mFlags &= ~kAUParameterMIDIMapping_Toggle;
+ }
+
+ bool IsBipolar() const { return (mFlags & kAUParameterMIDIMapping_Bipolar) != 0; }
+ // inUseOnValue is valid ONLY if inFlag is true
+ void SetBipolar (bool inFlag, bool inUseOnValue = false)
+ {
+ if (inFlag) {
+ mFlags |= kAUParameterMIDIMapping_Bipolar;
+ if (inUseOnValue)
+ mFlags |= kAUParameterMIDIMapping_Bipolar_On;
+ else
+ mFlags &= ~kAUParameterMIDIMapping_Bipolar_On;
+ } else {
+ mFlags &= ~kAUParameterMIDIMapping_Bipolar;
+ mFlags &= ~kAUParameterMIDIMapping_Bipolar_On;
+ }
+ }
+ bool IsBipolar_OnValue () const { return (mFlags & kAUParameterMIDIMapping_Bipolar_On) != 0; }
+
+ bool IsSubRange () const { return (mFlags & kAUParameterMIDIMapping_SubRange) != 0; }
+ void SetSubRange (Float32 inStartValue, Float32 inStopValue)
+ {
+ mFlags |= kAUParameterMIDIMapping_SubRange;
+
+ mSubRangeMin = inStartValue;
+ mSubRangeMax = inStopValue;
+ }
+
+ void SetParamRange(Float32 minValue, Float32 maxValue)
+ {
+ mMinValue = minValue;
+ mMaxValue = maxValue;
+ }
+
+ // this will retain the subrange values previously set.
+ void SetSubRange (bool inFlag)
+ {
+ if (inFlag)
+ mFlags |= kAUParameterMIDIMapping_SubRange;
+ else
+ mFlags &= ~kAUParameterMIDIMapping_SubRange;
+ }
+
+ bool IsAnyValue() const{return !IsBipolar();}
+ bool IsOnValue() const{return IsBipolar_OnValue();}
+ bool IsOffValue() const{return IsBipolar();}
+
+ bool IsNoteOff () const { return ((mStatus & 0xF0) == 0x80); }
+ bool IsNoteOn () const { return ((mStatus & 0xF0) == 0x90); }
+
+ bool IsKeyPressure () const { return ((mStatus & 0xF0) == 0xA0); }
+
+ bool IsKeyEvent () const { return (mStatus > 0x7F) && (mStatus < 0xB0); }
+
+ bool IsPatchChange () const { return ((mStatus & 0xF0) == 0xC0); }
+ bool IsChannelPressure () const { return ((mStatus & 0xF0) == 0xD0); }
+ bool IsPitchBend () const { return ((mStatus & 0xF0) == 0xE0); }
+ bool IsControlChange () const { return ((mStatus & 0xF0) == 0xB0); }
+
+
+ void SetControllerOnValue(){SetBipolar(true,true);}
+ void SetControllerOffValue(){SetBipolar(true,false);}
+ void SetControllerAnyValue(){SetBipolar(false,false);}
+
+ // All of these Set calls will reset the mFlags field based on the
+ // anyChannel param value
+ void SetNoteOff (UInt8 key, SInt8 channel, bool anyChannel = false)
+ {
+ mStatus = 0x80 | (channel & 0xF);
+ mData1 = key;
+ mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+
+ }
+
+ void SetNoteOn (UInt8 key, SInt8 channel, bool anyChannel = false)
+ {
+ mStatus = 0x90 | (channel & 0xF);
+ mData1 = key;
+ mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+ }
+
+ void SetPolyKey (UInt8 key, SInt8 channel, bool anyChannel = false)
+ {
+ mStatus = 0xA0 | (channel & 0xF);
+ mData1 = key;
+ mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+ }
+
+ void SetControlChange (UInt8 controllerID, SInt8 channel, bool anyChannel = false)
+ {
+ mStatus = 0xB0 | (channel & 0xF);
+ mData1 = controllerID;
+ mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+ }
+
+ void SetPatchChange (UInt8 patchChange, SInt8 channel, bool anyChannel = false)
+ {
+ mStatus = 0xC0 | (channel & 0xF);
+ mData1 = patchChange;
+ mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+ }
+
+ void SetChannelPressure (SInt8 channel, bool anyChannel = false)
+ {
+ mStatus = 0xD0 | (channel & 0xF);
+ mData1 = 0;
+ mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+ }
+
+ void SetPitchBend (SInt8 channel, bool anyChannel = false)
+ {
+ mStatus = 0xE0 | (channel & 0xF);
+ mData1 = 0;
+ mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
+ }
+
+
+ Float32 ParamValueFromMIDILinear (Float32 inLinearValue) const
+ {
+ Float32 low, high;
+ if (IsSubRange()){
+ low = mSubRangeMin;
+ high = mSubRangeMax;
+ }
+ else {
+ low = mMinValue;
+ high = mMaxValue;
+ }
+
+
+ // WE ARE ASSUMING YOU HAVE SET THIS UP PROPERLY!!!!! (or this will crash cause it will be NULL)
+ return 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/distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMapManager.cpp b/distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMapManager.cpp
new file mode 100755
index 00000000..95ce3c43
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMapManager.cpp
@@ -0,0 +1,227 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CAAUMIDIMapManager.h"
+#include <AudioToolbox/AudioUnitUtilities.h>
+
+CAAUMIDIMapManager::CAAUMIDIMapManager()
+{
+ hotMapping = false;
+}
+
+static void FillInMap (CAAUMIDIMap &map, AUBase &That)
+{
+ AudioUnitParameterInfo info;
+ That.GetParameterInfo (map.mScope, map.mParameterID, info);
+
+ if (map.IsSubRange()) {
+ map.mMinValue = map.mSubRangeMin;
+ map.mMaxValue = map.mSubRangeMax;
+ } else {
+ map.mMinValue = info.minValue;
+ map.mMaxValue = info.maxValue;
+ }
+
+ map.mTransType = CAAUMIDIMap::GetTransformer(info.flags);
+}
+
+OSStatus CAAUMIDIMapManager::SortedInsertToParamaterMaps (AUParameterMIDIMapping *maps, UInt32 inNumMaps, AUBase &That)
+{
+ for (unsigned int i = 0; i < inNumMaps; ++i)
+ {
+ CAAUMIDIMap map(maps[i]);
+
+ FillInMap (map, That);
+
+ int idx = FindParameterIndex (maps[i]);
+ if (idx > -1)
+ mParameterMaps.erase(mParameterMaps.begin() + idx);
+
+ // least disruptive place to put this is at the end
+ mParameterMaps.push_back(map);
+ }
+
+ std::sort(mParameterMaps.begin(), mParameterMaps.end(), CompareMIDIMap());
+
+ return noErr;
+}
+
+void CAAUMIDIMapManager::GetHotParameterMap(AUParameterMIDIMapping &outMap )
+{
+ outMap = mHotMap;
+}
+
+void CAAUMIDIMapManager::SortedRemoveFromParameterMaps(AUParameterMIDIMapping *maps, UInt32 inNumMaps, bool &outMapDidChange)
+{
+ if (hotMapping) {
+ hotMapping = false;
+ }
+
+ outMapDidChange = false;
+ for (unsigned int i = 0; i < inNumMaps; ++i) {
+ int idx = FindParameterIndex (maps[i]);
+ if (idx > -1) {
+ //mParameterMaps[idx].Print();
+ mParameterMaps.erase(mParameterMaps.begin() + idx);
+ outMapDidChange = true;
+ }
+ }
+}
+
+void CAAUMIDIMapManager::ReplaceAllMaps (AUParameterMIDIMapping* inMappings, UInt32 inNumMaps, AUBase &That)
+{
+ mParameterMaps.clear();
+
+ for (unsigned int i = 0; i < inNumMaps; ++i) {
+ CAAUMIDIMap mapping(inMappings[i]);
+
+ FillInMap (mapping, That);
+ mParameterMaps.push_back (mapping);
+ }
+
+ std::sort(mParameterMaps.begin(),mParameterMaps.end(), CompareMIDIMap());
+}
+
+bool CAAUMIDIMapManager::HandleHotMapping(UInt8 inStatus,
+ UInt8 inChannel,
+ UInt8 inData1,
+ AUBase &That)
+{ //used to set the hot map info
+
+ if (inStatus == 0xf0) return false;
+
+ if (!hotMapping) return false;
+ hotMapping = false;
+
+ mHotMap.mStatus = inStatus | inChannel;
+ mHotMap.mData1 = inData1;
+
+ SortedInsertToParamaterMaps (&mHotMap, 1, That);
+ return true;
+}
+
+#if DEBUG
+
+void CAAUMIDIMapManager::Print()
+{
+ for ( ParameterMaps::iterator i = mParameterMaps.begin(); i < mParameterMaps.end(); ++i) {
+ CAAUMIDIMap* listmap = &(*i);
+ listmap->Print();
+ }
+}
+
+#endif // DEBUG
+
+void CAAUMIDIMapManager::GetMaps(AUParameterMIDIMapping* maps)
+{
+ int i = 0;
+ for ( ParameterMaps::iterator iter = mParameterMaps.begin(); iter < mParameterMaps.end(); ++iter, ++i) {
+ AUParameterMIDIMapping &listmap = (*iter);
+ maps[i] = listmap;
+ }
+}
+
+int CAAUMIDIMapManager::FindParameterIndex (AUParameterMIDIMapping &inMap)
+{
+ //used to get back hot mapping and one at a time maps, for ui
+
+ int idx = 0;
+ for ( ParameterMaps::iterator i = mParameterMaps.begin(); i < mParameterMaps.end(); ++i) {
+ CAAUMIDIMap & listmap = (*i);
+ if ( (listmap.mParameterID == inMap.mParameterID) &&
+ (listmap.mScope == inMap.mScope) &&
+ (listmap.mElement == inMap.mElement) )
+ {
+ return idx;
+ }
+ idx++;
+ }
+ return -1;
+}
+
+bool CAAUMIDIMapManager::FindParameterMapEventMatch( UInt8 inStatus,
+ UInt8 inChannel,
+ UInt8 inData1,
+ UInt8 inData2,
+ UInt32 inBufferOffset,
+ AUBase& inAUBase)
+{
+ bool ret_value = false;
+
+ if (inStatus == 0x90 && !inData2)
+ inStatus = 0x80 | inChannel;
+
+ //used to test for midi matches once map is made
+ CAAUMIDIMap tempMap;
+ tempMap.mStatus = inStatus | inChannel;
+ tempMap.mData1 = inData1;
+
+ CompareMIDIMap compareObj;
+
+ AudioUnitEvent event;
+ event.mEventType = kAudioUnitEvent_ParameterValueChange;
+ event.mArgument.mParameter.mAudioUnit = inAUBase.GetComponentInstance();
+
+ ParameterMaps::iterator lower_iter =
+ std::lower_bound(mParameterMaps.begin(), mParameterMaps.end(), tempMap, compareObj);
+
+ while (lower_iter < mParameterMaps.end())
+ {
+ CAAUMIDIMap & map = (*lower_iter);
+ if (compareObj.Finish(map, tempMap))
+ break;
+
+ Float32 value;
+ if (map.MIDI_Matches(inChannel, inData1, inData2, value))
+ {
+ inAUBase.SetParameter ( map.mParameterID, map.mScope, map.mElement,
+ map.ParamValueFromMIDILinear(value), inBufferOffset);
+
+ event.mArgument.mParameter.mParameterID = map.mParameterID;
+ event.mArgument.mParameter.mScope = map.mScope;
+ event.mArgument.mParameter.mElement = map.mElement;
+
+ AUEventListenerNotify(NULL, NULL, &event);
+ ret_value = true;
+ }
+ ++lower_iter;
+ }
+ return ret_value;
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMapManager.h b/distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMapManager.h
new file mode 100755
index 00000000..c54b0d1f
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMapManager.h
@@ -0,0 +1,96 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAAUMIDIMapManager_h_
+#define __CAAUMIDIMapManager_h_
+
+#include <AUBase.h>
+#include <CAAUMIDIMap.h>
+#include <vector>
+#include <AudioToolbox/AudioUnitUtilities.h>
+
+class CAAUMIDIMapManager {
+
+protected:
+
+ typedef std::vector<CAAUMIDIMap> ParameterMaps;
+ ParameterMaps mParameterMaps;
+
+ bool hotMapping;
+ AUParameterMIDIMapping mHotMap;
+
+public:
+
+ CAAUMIDIMapManager();
+
+ UInt32 NumMaps(){return 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/distrho/src/CoreAudio106/PublicUtility/CAAUParameter.cpp b/distrho/src/CoreAudio106/PublicUtility/CAAUParameter.cpp
new file mode 100755
index 00000000..7d3bf8a3
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAUParameter.cpp
@@ -0,0 +1,394 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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,
+ mParameterID,
+ &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,
+ mParameterID,
+ &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 = 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/distrho/src/CoreAudio106/PublicUtility/CAAUParameter.h b/distrho/src/CoreAudio106/PublicUtility/CAAUParameter.h
new file mode 100755
index 00000000..508dadd3
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAUParameter.h
@@ -0,0 +1,185 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAAUParameter_h__
+#define __CAAUParameter_h__
+
+#include <AudioToolbox/AudioUnitUtilities.h>
+
+// ____________________________________________________________________________
+// CAAUParameter
+// complete parameter specification
+ /*! @class CAAUParameter */
+class CAAUParameter : public AudioUnitParameter {
+public:
+ /*! @ctor CAAUParameter.0 */
+ CAAUParameter();
+ /*! @ctor CAAUParameter.1 */
+ CAAUParameter(AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element);
+ /*! @ctor CAAUParameter.2 */
+ CAAUParameter(AudioUnitParameter &inParam);
+ /*! @ctor CAAUParameter.3 */
+ CAAUParameter(const CAAUParameter &a);
+ /*! @dtor ~CAAUParameter */
+ ~CAAUParameter();
+
+ /*! @method operator <@ */
+ bool operator < (const CAAUParameter &a) const
+ {
+ return memcmp(this, &a, sizeof(AudioUnitParameter)) < 0;
+ }
+
+ /*! @method operator ==@ */
+ bool operator == (const CAAUParameter &a) const
+ {
+ return !memcmp(this, &a, sizeof(AudioUnitParameter));
+ }
+
+ /*! @method operator =@ */
+ CAAUParameter & operator = (const CAAUParameter &a);
+
+ /*! @method GetValue */
+ Float32 GetValue() const;
+ /*! @method SetValue */
+ void SetValue( AUParameterListenerRef inListener,
+ void * inObject,
+ Float32 inValue) const;
+
+ /*! @method GetName */
+ CFStringRef GetName() const { return mParamName; }
+ // borrowed reference!
+
+ /*! @method GetStringFromValueCopy */
+ CFStringRef GetStringFromValueCopy(const Float32 *value = NULL) const;
+ // returns a copy of the name of the current parameter value
+ // or null if there is no name associated
+ // caller must release
+ /*! @method ValuesHaveStrings */
+ bool ValuesHaveStrings () const
+ {
+ return (mParamInfo.flags & kAudioUnitParameterFlag_ValuesHaveStrings) != 0;
+ }
+
+ /*! @method GetValueFromString */
+ Float32 GetValueFromString (CFStringRef str) const;
+ // caller must release
+
+ /*! @method ParamInfo */
+ const AudioUnitParameterInfo &
+ ParamInfo() const { return mParamInfo; }
+
+ /*! @method GetParamTag */
+ CFStringRef GetParamTag() const { return mParamTag; }
+ // this may return null! -
+ // in which case there is no descriptive tag for the parameter
+
+ /*! @method GetParamName */
+ CFStringRef GetParamName (int inIndex) const
+ // this can return null if there is no name for the parameter
+ {
+ return (mNamedParams && inIndex < mNumIndexedParams)
+ ? (CFStringRef) CFArrayGetValueAtIndex(mNamedParams, inIndex)
+ : 0;
+ }
+
+ /*! @method GetNumIndexedParams */
+ int GetNumIndexedParams () const { return mNumIndexedParams; }
+
+ /*! @method IsIndexedParam */
+ bool IsIndexedParam () const { return mNumIndexedParams != 0; }
+
+ /*! @method HasNamedParams */
+ bool HasNamedParams () const { return IsIndexedParam() && mNamedParams; }
+
+ /*! @method GetClumpID */
+ bool GetClumpID (UInt32 &outClumpID) const
+ {
+ if (mParamInfo.flags & kAudioUnitParameterFlag_HasClump) {
+ outClumpID = mParamInfo.clumpID;
+ return true;
+ }
+ return false;
+ }
+
+ /*! @method HasDisplayTransformation */
+ bool HasDisplayTransformation () const
+ {
+ return GetAudioUnitParameterDisplayType (mParamInfo.flags);
+ }
+
+ /*! @method IsExpert */
+ bool IsExpert () const
+ {
+ return mParamInfo.flags & kAudioUnitParameterFlag_ExpertMode;
+ }
+#if DEBUG
+ void Print () const;
+#endif
+
+ // these methods are defined in CAPersistence.cpp
+ // they will persist and restore only the scope, element and param ID's of the AudioUnitParameter
+ // however, this is sufficient to be able to save/restore a CAAUParameter object
+ void Save (CFPropertyListRef &outData) const;
+
+ static void Save (const AudioUnitParameter &inParam, CFPropertyListRef &outData);
+
+ static OSStatus Restore (const CFPropertyListRef inData, AudioUnitParameter &outParam);
+
+protected:
+ // cached parameter info
+ /*! @var mParamInfo */
+ AudioUnitParameterInfo mParamInfo;
+ /*! @var mParamName */
+ CFStringRef mParamName;
+ /*! @var mParamTag */
+ CFStringRef mParamTag;
+ /*! @var mNumIndexedParams */
+ short mNumIndexedParams;
+ /*! @var mNamedParams */
+ CFArrayRef mNamedParams;
+
+private:
+ void Init (AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element);
+
+};
+
+
+
+#endif // __CAAUParameter_h__
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAAtomic.h b/distrho/src/CoreAudio106/PublicUtility/CAAtomic.h
new file mode 100755
index 00000000..8a3a7ed4
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAtomic.h
@@ -0,0 +1,288 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+/*
+ This file implements all Atomic operations using Interlocked functions specified in
+ Winbase.h
+NOTE: According to Microsoft documentation, all Interlocked functions generates a
+full barrier.
+ On Windows:
+ As the Interlocked functions returns the Old value, Extra checks and operations
+ are made after the atomic operation to return value consistent with OSX counterparts.
+*/
+#ifndef __CAAtomic_h__
+#define __CAAtomic_h__
+
+#if TARGET_OS_WIN32
+ #include <windows.h>
+ #include <intrin.h>
+#else
+ #include <CoreFoundation/CFBase.h>
+ #include <libkern/OSAtomic.h>
+#endif
+
+inline void CAMemoryBarrier()
+{
+#if TARGET_OS_WIN32
+ MemoryBarrier();
+#else
+ OSMemoryBarrier();
+#endif
+}
+
+inline SInt32 CAAtomicAdd32Barrier(SInt32 theAmt, volatile SInt32* theValue)
+{
+#if TARGET_OS_WIN32
+ long lRetVal = InterlockedExchangeAdd((volatile long*)theValue, theAmt);
+ // InterlockedExchangeAdd returns the original value which differs from OSX version.
+ // At this point the addition would have occured and hence returning the new value
+ // to keep it sync with OSX.
+ return lRetVal + theAmt;
+#else
+ return OSAtomicAdd32Barrier(theAmt, (volatile int32_t *)theValue);
+#endif
+}
+
+inline SInt32 CAAtomicOr32Barrier(UInt32 theMask, volatile UInt32* theValue)
+{
+#if TARGET_OS_WIN32
+ // InterlockedAnd macro is not defined in x86 platform, and hence using the intrinsic
+ // function instead.
+ long j = _InterlockedOr((volatile long*)theValue, theMask);
+ // _InterlockedOr returns the original value which differs from OSX version.
+ // Returning the new value similar to OSX
+ return (SInt32)(j | theMask);
+#else
+ return OSAtomicOr32Barrier(theMask, (volatile uint32_t *)theValue);
+#endif
+}
+
+inline SInt32 CAAtomicAnd32Barrier(UInt32 theMask, volatile UInt32* theValue)
+{
+#if TARGET_OS_WIN32
+// InterlockedAnd macro is not defined in x86 platform, and hence using the intrinsic
+// function instead.
+ long j = _InterlockedAnd((volatile long*)theValue, theMask);
+ // _InterlockedAnd returns the original value which differs from OSX version.
+ // Returning the new value similar to OSX
+ return (SInt32)(j & theMask);
+#else
+ return OSAtomicAnd32Barrier(theMask, (volatile uint32_t *)theValue);
+#endif
+}
+
+inline bool CAAtomicCompareAndSwap32Barrier(SInt32 oldValue, SInt32 newValue, volatile SInt32 *theValue)
+{
+#if TARGET_OS_WIN32
+ // InterlockedCompareExchange returns the old value. But we need to return bool value.
+ long lRetVal = InterlockedCompareExchange((volatile long*)theValue, newValue, oldValue);
+// Hence we check if the new value is set and if it is we return true else false.
+// If theValue is equal to oldValue then the swap happens. Otherwise swap doesn't happen.
+ return (oldValue == lRetVal);
+#else
+ return OSAtomicCompareAndSwap32Barrier(oldValue, newValue, (volatile int32_t *)theValue);
+#endif
+}
+
+
+inline SInt32 CAAtomicIncrement32(volatile SInt32* theValue)
+{
+#if TARGET_OS_WIN32
+ return (SInt32)InterlockedIncrement((volatile long*)theValue);
+#else
+ return OSAtomicIncrement32((volatile int32_t *)theValue);
+#endif
+}
+
+inline SInt32 CAAtomicDecrement32(volatile SInt32* theValue)
+{
+#if TARGET_OS_WIN32
+ return (SInt32)InterlockedDecrement((volatile long*)theValue);
+#else
+ return OSAtomicDecrement32((volatile int32_t *)theValue);
+#endif
+}
+
+inline SInt32 CAAtomicIncrement32Barrier(volatile SInt32* theValue)
+{
+#if TARGET_OS_WIN32
+ return CAAtomicIncrement32(theValue);
+#else
+ return OSAtomicIncrement32Barrier((volatile int32_t *)theValue);
+#endif
+}
+
+inline SInt32 CAAtomicDecrement32Barrier(volatile SInt32* theValue)
+{
+#if TARGET_OS_WIN32
+ return CAAtomicDecrement32(theValue);
+#else
+ return OSAtomicDecrement32Barrier((volatile int32_t *)theValue);
+#endif
+}
+
+inline bool CAAtomicTestAndClearBarrier(int bitToClear, void* theAddress)
+{
+#if TARGET_OS_WIN32
+ BOOL bOldVal = InterlockedBitTestAndReset((long*)theAddress, bitToClear);
+ return (bOldVal ? true : false);
+#else
+ return OSAtomicTestAndClearBarrier(bitToClear, (volatile void *)theAddress);
+#endif
+}
+
+inline bool CAAtomicTestAndClear(int bitToClear, void* theAddress)
+{
+#if TARGET_OS_WIN32
+ BOOL bOldVal = CAAtomicTestAndClearBarrier(bitToClear, (long*)theAddress);
+ return (bOldVal ? true : false);
+#else
+ return OSAtomicTestAndClear(bitToClear, (volatile void *)theAddress);
+#endif
+}
+
+inline bool CAAtomicTestAndSetBarrier(int bitToSet, void* theAddress)
+{
+#if TARGET_OS_WIN32
+ BOOL bOldVal = InterlockedBitTestAndSet((long*)theAddress, bitToSet);
+ return (bOldVal ? true : false);
+#else
+ return OSAtomicTestAndSetBarrier(bitToSet, (volatile void *)theAddress);
+#endif
+}
+
+// int32_t flavors -- for C++ only since we can't overload in C
+// CFBase.h defines SInt32 as signed int which is similar to int32_t. If CFBase.h is included, then
+// this will generate redefinition error. But on Mac, CFBase.h, still includes MacTypes.h where
+// SInt32 is defined as signed long so this would work there.
+// So in order to fix the redefinition errors, we define these functions only if MacTypes.h is included.
+#if defined(__cplusplus) && defined(__MACTYPES__) && !__LP64__
+inline int32_t CAAtomicAdd32Barrier(int32_t theAmt, volatile int32_t* theValue)
+{
+ return CAAtomicAdd32Barrier(theAmt, (volatile SInt32 *)theValue);
+}
+
+inline int32_t CAAtomicOr32Barrier(uint32_t theMask, volatile uint32_t* theValue)
+{
+ return CAAtomicOr32Barrier(theMask, (volatile UInt32 *)theValue);
+}
+
+inline int32_t CAAtomicAnd32Barrier(uint32_t theMask, volatile uint32_t* theValue)
+{
+ return CAAtomicAnd32Barrier(theMask, (volatile UInt32 *)theValue);
+}
+
+inline bool CAAtomicCompareAndSwap32Barrier(int32_t oldValue, int32_t newValue, volatile int32_t *theValue)
+{
+ return CAAtomicCompareAndSwap32Barrier(oldValue, newValue, (volatile SInt32 *)theValue);
+}
+
+inline int32_t CAAtomicIncrement32(volatile int32_t* theValue)
+{
+ return CAAtomicIncrement32((volatile SInt32 *)theValue);
+}
+
+inline int32_t CAAtomicDecrement32(volatile int32_t* theValue)
+{
+ return CAAtomicDecrement32((volatile SInt32 *)theValue);
+}
+
+inline int32_t CAAtomicIncrement32Barrier(volatile int32_t* theValue)
+{
+ return CAAtomicIncrement32Barrier((volatile SInt32 *)theValue);
+}
+
+inline int32_t CAAtomicDecrement32Barrier(volatile int32_t* theValue)
+{
+ return CAAtomicDecrement32Barrier((volatile SInt32 *)theValue);
+}
+#endif // __cplusplus && !__LP64__
+
+#if __LP64__
+inline bool CAAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue )
+{
+ return OSAtomicCompareAndSwap64Barrier(__oldValue, __newValue, __theValue );
+}
+#endif
+
+/* 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/distrho/src/CoreAudio106/PublicUtility/CAAtomicStack.h b/distrho/src/CoreAudio106/PublicUtility/CAAtomicStack.h
new file mode 100755
index 00000000..84ddae70
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAtomicStack.h
@@ -0,0 +1,209 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __TStack_h__
+#define __TStack_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <libkern/OSAtomic.h>
+#else
+// #include <DriverSynchronization.h>
+#include <CAAtomic.h>
+#endif
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
+ #include <CoreServices/CoreServices.h>
+#endif
+
+// linked list LIFO or FIFO (pop_all_reversed) stack, elements are pushed and popped atomically
+// class T must implement set_next() and get_next()
+template <class T>
+class TAtomicStack {
+public:
+ TAtomicStack() : mHead(NULL) { }
+
+ // non-atomic routines, for use when initializing/deinitializing, operate NON-atomically
+ void push_NA(T *item)
+ {
+ item->set_next(mHead);
+ mHead = item;
+ }
+
+ T * pop_NA()
+ {
+ T *result = mHead;
+ if (result)
+ mHead = result->get_next();
+ return result;
+ }
+
+ bool empty() { return mHead == NULL; }
+
+ T * head() { return mHead; }
+
+ // atomic routines
+ void push_atomic(T *item)
+ {
+ T *head;
+ do {
+ head = mHead;
+ item->set_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->get_next();
+ } while (p);
+ do {
+ head = mHead;
+ tail->set_next(head);
+ } while (!compare_and_swap(head, item, &mHead));
+ }
+
+ T * pop_atomic_single_reader()
+ // this may only be used when only one thread may potentially pop from the stack.
+ // if multiple threads may pop, this suffers from the ABA problem.
+ // <rdar://problem/4606346> TAtomicStack suffers from the ABA problem
+ {
+ T *result;
+ do {
+ if ((result = mHead) == NULL)
+ break;
+ } while (!compare_and_swap(result, result->get_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->get_next();
+ if (next)
+ // push all the remaining items back onto the stack
+ push_multiple_atomic(next);
+ }
+ return result;
+ }
+
+ T * pop_all()
+ {
+ T *result;
+ do {
+ if ((result = mHead) == NULL)
+ break;
+ } while (!compare_and_swap(result, NULL, &mHead));
+ return result;
+ }
+
+ T* pop_all_reversed()
+ {
+ TAtomicStack<T> reversed;
+ T *p = pop_all(), *next;
+ while (p != NULL) {
+ next = p->get_next();
+ reversed.push_NA(p);
+ p = next;
+ }
+ return reversed.mHead;
+ }
+
+ static bool compare_and_swap(T *oldvalue, T *newvalue, T **pvalue)
+ {
+#if TARGET_OS_MAC
+ #if __LP64__
+ return ::OSAtomicCompareAndSwap64Barrier(int64_t(oldvalue), int64_t(newvalue), (int64_t *)pvalue);
+ #elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ return ::OSAtomicCompareAndSwap32Barrier(int32_t(oldvalue), int32_t(newvalue), (int32_t *)pvalue);
+ #else
+ return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue);
+ #endif
+#else
+ //return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue);
+ return CAAtomicCompareAndSwap32Barrier(SInt32(oldvalue), SInt32(newvalue), (SInt32*)pvalue);
+#endif
+ }
+
+protected:
+ T * mHead;
+};
+
+#if ((MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) && !TARGET_OS_WIN32)
+#include <libkern/OSAtomic.h>
+
+class CAAtomicStack {
+public:
+ CAAtomicStack(size_t nextPtrOffset) : mNextPtrOffset(nextPtrOffset) { /*OSQueueHead h = OS_ATOMIC_QUEUE_INIT; mHead = h;*/ mHead.opaque1 = 0; mHead.opaque2 = 0;
+ }
+ // a subset of the above
+ void push_atomic(void *p) { OSAtomicEnqueue(&mHead, p, mNextPtrOffset); }
+ void push_NA(void *p) { push_atomic(p); }
+
+ void * pop_atomic() { return OSAtomicDequeue(&mHead, mNextPtrOffset); }
+ void * pop_atomic_single_reader() { return pop_atomic(); }
+ void * pop_NA() { return pop_atomic(); }
+
+private:
+ OSQueueHead mHead;
+ size_t mNextPtrOffset;
+};
+
+// syntactic sugar
+template <class T>
+class TAtomicStack2 : public CAAtomicStack {
+public:
+ TAtomicStack2(size_t nextPtrOffset) : CAAtomicStack(nextPtrOffset) { }
+
+ T * pop_atomic() { return (T *)CAAtomicStack::pop_atomic(); }
+ T * pop_atomic_single_reader() { return pop_atomic(); }
+ T * pop_NA() { return pop_atomic(); }
+};
+
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED && !TARGET_OS_WIN32
+
+#endif // __TStack_h__
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAAudioBufferList.cpp b/distrho/src/CoreAudio106/PublicUtility/CAAudioBufferList.cpp
new file mode 100755
index 00000000..08e3e37a
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAudioBufferList.cpp
@@ -0,0 +1,225 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CAAudioBufferList.h"
+#include "CADebugMacros.h"
+#include "CALogMacros.h"
+#include <stdlib.h>
+#include <string.h>
+
+//=============================================================================
+// CAAudioBufferList
+//=============================================================================
+
+AudioBufferList* CAAudioBufferList::Create(UInt32 inNumberBuffers)
+{
+ UInt32 theSize = CalculateByteSize(inNumberBuffers);
+ AudioBufferList* theAnswer = static_cast<AudioBufferList*>(calloc(1, theSize));
+ if(theAnswer != NULL)
+ {
+ theAnswer->mNumberBuffers = inNumberBuffers;
+ }
+ return theAnswer;
+}
+
+void CAAudioBufferList::Destroy(AudioBufferList* inBufferList)
+{
+ free(inBufferList);
+}
+
+UInt32 CAAudioBufferList::CalculateByteSize(UInt32 inNumberBuffers)
+{
+ UInt32 theSize = SizeOf32(AudioBufferList) - SizeOf32(AudioBuffer);
+ theSize += inNumberBuffers * SizeOf32(AudioBuffer);
+ return theSize;
+}
+
+UInt32 CAAudioBufferList::GetTotalNumberChannels(const AudioBufferList& inBufferList)
+{
+ UInt32 theAnswer = 0;
+
+ for(UInt32 theIndex = 0; theIndex < inBufferList.mNumberBuffers; ++theIndex)
+ {
+ theAnswer += inBufferList.mBuffers[theIndex].mNumberChannels;
+ }
+
+ return theAnswer;
+}
+
+bool CAAudioBufferList::GetBufferForChannel(const AudioBufferList& inBufferList, UInt32 inChannel, UInt32& outBufferNumber, UInt32& outBufferChannel)
+{
+ bool theAnswer = false;
+ UInt32 theIndex = 0;
+
+ while((theIndex < inBufferList.mNumberBuffers) && (inChannel >= inBufferList.mBuffers[theIndex].mNumberChannels))
+ {
+ inChannel -= inBufferList.mBuffers[theIndex].mNumberChannels;
+ ++theIndex;
+ }
+
+ if(theIndex < inBufferList.mNumberBuffers)
+ {
+ outBufferNumber = theIndex;
+ outBufferChannel = inChannel;
+ theAnswer = true;
+ }
+
+ return theAnswer;
+}
+
+void CAAudioBufferList::Clear(AudioBufferList& outBufferList)
+{
+ // assumes that "0" is actually the 0 value for this stream format
+ for(UInt32 theBufferIndex = 0; theBufferIndex < outBufferList.mNumberBuffers; ++theBufferIndex)
+ {
+ if(outBufferList.mBuffers[theBufferIndex].mData != NULL)
+ {
+ memset(outBufferList.mBuffers[theBufferIndex].mData, 0, outBufferList.mBuffers[theBufferIndex].mDataByteSize);
+ }
+ }
+}
+
+void CAAudioBufferList::Copy(const AudioBufferList& inSource, UInt32 inStartingSourceChannel, AudioBufferList& outDestination, UInt32 inStartingDestinationChannel)
+{
+ // This is a brute force copy method that can handle ABL's that have different buffer layouts
+ // This means that this method is probably not the fastest way to do this for all cases.
+ // This method also assumes that both the source and destination sample formats are Float32
+
+ UInt32 theInputChannel = inStartingSourceChannel;
+ UInt32 theNumberInputChannels = GetTotalNumberChannels(inSource);
+ UInt32 theOutputChannel = inStartingDestinationChannel;
+ UInt32 theNumberOutputChannels = GetTotalNumberChannels(outDestination);
+
+ UInt32 theInputBufferIndex = 0;
+ UInt32 theInputBufferChannel = 0;
+ UInt32 theOutputBufferIndex = 0;
+ UInt32 theOutputBufferChannel = 0;
+ while((theInputChannel < theNumberInputChannels) && (theOutputChannel < theNumberOutputChannels))
+ {
+ GetBufferForChannel(inSource, theInputChannel, theInputBufferIndex, theInputBufferChannel);
+
+ GetBufferForChannel(inSource, theOutputChannel, theOutputBufferIndex, theOutputBufferChannel);
+
+ CopyChannel(inSource.mBuffers[theInputBufferIndex], theInputBufferChannel, outDestination.mBuffers[theOutputBufferIndex], theOutputBufferChannel);
+
+ ++theInputChannel;
+ ++theOutputChannel;
+ }
+}
+
+void CAAudioBufferList::CopyChannel(const AudioBuffer& inSource, UInt32 inSourceChannel, AudioBuffer& outDestination, UInt32 inDestinationChannel)
+{
+ // set up the stuff for the loop
+ UInt32 theNumberFramesToCopy = outDestination.mDataByteSize / (outDestination.mNumberChannels * SizeOf32(Float32));
+ const Float32* theSource = static_cast<const Float32*>(inSource.mData);
+ Float32* theDestination = static_cast<Float32*>(outDestination.mData);
+
+ // loop through the data and copy the samples
+ while(theNumberFramesToCopy > 0)
+ {
+ // copy the data
+ theDestination[inDestinationChannel] = theSource[inSourceChannel];
+
+ // adjust the pointers
+ --theNumberFramesToCopy;
+ theSource += inSource.mNumberChannels;
+ theDestination += outDestination.mNumberChannels;
+ }
+}
+
+void CAAudioBufferList::Sum(const AudioBufferList& inSourceBufferList, AudioBufferList& ioSummedBufferList)
+{
+ // assumes that the buffers are Float32 samples and the listst have the same layout
+ // this is a lame algorithm, by the way. it could at least be unrolled a couple of times
+ for(UInt32 theBufferIndex = 0; theBufferIndex < ioSummedBufferList.mNumberBuffers; ++theBufferIndex)
+ {
+ Float32* theSourceBuffer = static_cast<Float32*>(inSourceBufferList.mBuffers[theBufferIndex].mData);
+ Float32* theSummedBuffer = static_cast<Float32*>(ioSummedBufferList.mBuffers[theBufferIndex].mData);
+ UInt32 theNumberSamplesToMix = ioSummedBufferList.mBuffers[theBufferIndex].mDataByteSize / SizeOf32(Float32);
+ if((theSourceBuffer != NULL) && (theSummedBuffer != NULL) && (theNumberSamplesToMix > 0))
+ {
+ while(theNumberSamplesToMix > 0)
+ {
+ *theSummedBuffer += *theSourceBuffer;
+ ++theSummedBuffer;
+ ++theSourceBuffer;
+ --theNumberSamplesToMix;
+ }
+ }
+ }
+}
+
+bool CAAudioBufferList::HasData(AudioBufferList& inBufferList)
+{
+ bool hasData = false;
+ for(UInt32 theBufferIndex = 0; !hasData && (theBufferIndex < inBufferList.mNumberBuffers); ++theBufferIndex)
+ {
+ if(inBufferList.mBuffers[theBufferIndex].mData != NULL)
+ {
+ UInt32* theBuffer = (UInt32*)inBufferList.mBuffers[theBufferIndex].mData;
+ UInt32 theNumberSamples = inBufferList.mBuffers[theBufferIndex].mDataByteSize / SizeOf32(UInt32);
+ for(UInt32 theSampleIndex = 0; !hasData && (theSampleIndex < theNumberSamples); ++theSampleIndex)
+ {
+ hasData = theBuffer[theSampleIndex] != 0;
+ }
+ }
+ }
+ return hasData;
+}
+
+#if CoreAudio_Debug
+void CAAudioBufferList::PrintToLog(const AudioBufferList& inBufferList)
+{
+ PrintInt(" Number streams: ", inBufferList.mNumberBuffers);
+
+ for(UInt32 theIndex = 0; theIndex < inBufferList.mNumberBuffers; ++theIndex)
+ {
+ PrintIndexedInt(" Channels in stream", theIndex + 1, inBufferList.mBuffers[theIndex].mNumberChannels);
+ PrintIndexedInt(" Buffer size of stream", theIndex + 1, inBufferList.mBuffers[theIndex].mDataByteSize);
+ }
+}
+#endif
+
+AudioBufferList CAAudioBufferList::sEmptyBufferList = { 0, { { 0, 0, NULL } } };
+
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAAudioBufferList.h b/distrho/src/CoreAudio106/PublicUtility/CAAudioBufferList.h
new file mode 100755
index 00000000..db688702
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAudioBufferList.h
@@ -0,0 +1,93 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CAAudioBufferList_h__)
+#define __CAAudioBufferList_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+//=============================================================================
+// 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
+
+// Constants
+public:
+ static AudioBufferList sEmptyBufferList;
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayout.cpp b/distrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayout.cpp
new file mode 100755
index 00000000..db401d17
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayout.cpp
@@ -0,0 +1,142 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+// Self Include
+#include "CAAudioChannelLayout.h"
+#include "CAAutoDisposer.h"
+#include <stdlib.h>
+#include <string.h>
+
+//=============================================================================
+// CAAudioChannelLayout
+//=============================================================================
+
+AudioChannelLayout* CAAudioChannelLayout::Create(UInt32 inNumberChannelDescriptions)
+{
+ UInt32 theSize = CalculateByteSize(inNumberChannelDescriptions);
+ AudioChannelLayout* theAnswer = static_cast<AudioChannelLayout*>(CA_calloc(1, theSize));
+ if(theAnswer != NULL)
+ {
+ SetAllToUnknown(*theAnswer, inNumberChannelDescriptions);
+ }
+ return theAnswer;
+}
+
+void CAAudioChannelLayout::Destroy(AudioChannelLayout* inChannelLayout)
+{
+ free(inChannelLayout);
+}
+
+void CAAudioChannelLayout::SetAllToUnknown(AudioChannelLayout& outChannelLayout, UInt32 inNumberChannelDescriptions)
+{
+ outChannelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
+ outChannelLayout.mChannelBitmap = 0;
+ outChannelLayout.mNumberChannelDescriptions = inNumberChannelDescriptions;
+ for(UInt32 theChannelIndex = 0; theChannelIndex < inNumberChannelDescriptions; ++theChannelIndex)
+ {
+ outChannelLayout.mChannelDescriptions[theChannelIndex].mChannelLabel = kAudioChannelLabel_Unknown;
+ outChannelLayout.mChannelDescriptions[theChannelIndex].mChannelFlags = 0;
+ outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[0] = 0;
+ outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[1] = 0;
+ outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[2] = 0;
+ }
+}
+
+bool operator== (const AudioChannelLayout &x, const AudioChannelLayout &y)
+{
+ // compare based on the number of channel descriptions present
+ // (this may be too strict a comparison if all you care about are matching layout tags)
+ UInt32 theSize1 = CAAudioChannelLayout::CalculateByteSize(x.mNumberChannelDescriptions);
+ UInt32 theSize2 = CAAudioChannelLayout::CalculateByteSize(y.mNumberChannelDescriptions);
+
+ if (theSize1 != theSize2)
+ return false;
+
+ return !memcmp (&x, &y, theSize1);
+}
+
+// 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/distrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayout.h b/distrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayout.h
new file mode 100755
index 00000000..bfca6c30
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayout.h
@@ -0,0 +1,191 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CAAudioChannelLayout_h__)
+#define __CAAudioChannelLayout_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include <CoreAudioTypes.h>
+ #include <CoreFoundation.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "CADebugMacros.h"
+#include "CAAutoDisposer.h"
+
+#if !HAL_Build
+ #include "CAReferenceCounted.h"
+#endif
+
+//=============================================================================
+// CAAudioChannelLayout
+//=============================================================================
+
+bool operator== (const AudioChannelLayout &x, const AudioChannelLayout &y);
+
+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 OffsetOf32(AudioChannelLayout, mChannelDescriptions) + 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;
+
+ 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(size);
+ }
+
+ static RefCountedLayout *CreateWithLayout(const AudioChannelLayout *layout) {
+ size_t size = CAAudioChannelLayout::CalculateByteSize(layout->mNumberChannelDescriptions);
+ RefCountedLayout *acl = new(size) RefCountedLayout(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/distrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayoutObject.cpp b/distrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayoutObject.cpp
new file mode 100755
index 00000000..a5ca17ce
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayoutObject.cpp
@@ -0,0 +1,193 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CAAudioChannelLayout.h"
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioToolbox/AudioFormat.h>
+#else
+ #include <AudioFormat.h>
+#endif
+
+CAAudioChannelLayout::CAAudioChannelLayout ()
+{
+ mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(0);
+}
+
+//=============================================================================
+// CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround)
+{
+ // this chooses default layouts based on the number of channels...
+ AudioChannelLayoutTag tag;
+
+ switch (inNumberChannels)
+ {
+ default:
+ // here we have a "broken" layout, in the sense that we haven't any idea how to lay this out
+ mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(inNumberChannels);
+ SetAllToUnknown(*mLayout->GetLayout(), inNumberChannels);
+ return; // don't fall into the tag case
+ case 1:
+ tag = kAudioChannelLayoutTag_Mono;
+ break;
+ case 2:
+ tag = inChooseSurround ? kAudioChannelLayoutTag_Binaural : kAudioChannelLayoutTag_Stereo;
+ break;
+ case 4:
+ tag = inChooseSurround ? kAudioChannelLayoutTag_Ambisonic_B_Format : kAudioChannelLayoutTag_AudioUnit_4;
+ break;
+ case 5:
+ tag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_5_0 : kAudioChannelLayoutTag_AudioUnit_5;
+ break;
+ case 6:
+ tag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_6_0 : kAudioChannelLayoutTag_AudioUnit_6;
+ break;
+ case 7:
+ tag = kAudioChannelLayoutTag_AudioUnit_7_0;
+ break;
+ case 8:
+ tag = kAudioChannelLayoutTag_AudioUnit_8;
+ break;
+ }
+
+ mLayout = RefCountedLayout::CreateWithLayoutTag(tag);
+}
+
+//=============================================================================
+// CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (AudioChannelLayoutTag inLayoutTag)
+ : mLayout(NULL)
+{
+ SetWithTag(inLayoutTag);
+}
+
+//=============================================================================
+// CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (const CAAudioChannelLayout &c)
+ : mLayout(NULL)
+{
+ *this = c;
+}
+
+
+//=============================================================================
+// CAAudioChannelLayout::AudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout)
+ : mLayout(NULL)
+{
+ *this = inChannelLayout;
+}
+
+//=============================================================================
+// CAAudioChannelLayout::~CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::~CAAudioChannelLayout ()
+{
+ if (mLayout) {
+ mLayout->release();
+ mLayout = NULL;
+ }
+}
+
+//=============================================================================
+// CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout& CAAudioChannelLayout::operator= (const CAAudioChannelLayout &c)
+{
+ if (mLayout != c.mLayout) {
+ if (mLayout)
+ mLayout->release();
+
+ if ((mLayout = c.mLayout) != NULL)
+ mLayout->retain();
+ }
+
+ return *this;
+}
+
+CAAudioChannelLayout& CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout)
+{
+ if (mLayout && &mLayout->Layout() == inChannelLayout)
+ return *this;
+
+ if (mLayout)
+ mLayout->release();
+
+ if (inChannelLayout == NULL)
+ {
+ mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(0);
+ }
+ else
+ {
+ mLayout = RefCountedLayout::CreateWithLayout(inChannelLayout);
+ }
+ return *this;
+}
+
+void CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag)
+{
+ if (mLayout)
+ mLayout->release();
+
+ mLayout = RefCountedLayout::CreateWithLayoutTag(inTag);
+}
+
+//=============================================================================
+// CAAudioChannelLayout::operator==
+//=============================================================================
+bool CAAudioChannelLayout::operator== (const CAAudioChannelLayout &c) const
+{
+ if (mLayout == c.mLayout)
+ return true;
+ return Layout() == c.Layout();
+}
+
+//=============================================================================
+// CAAudioChannelLayout::Print
+//=============================================================================
+void CAAudioChannelLayout::Print (FILE* file) const
+{
+ CAShowAudioChannelLayout (file, &Layout());
+}
+
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAAudioFileFormats.cpp b/distrho/src/CoreAudio106/PublicUtility/CAAudioFileFormats.cpp
new file mode 100755
index 00000000..67f716d3
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAudioFileFormats.cpp
@@ -0,0 +1,415 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CAAudioFileFormats.h"
+#include <algorithm>
+#include <ctype.h>
+
+CAAudioFileFormats *CAAudioFileFormats::sInstance = NULL;
+
+CAAudioFileFormats *CAAudioFileFormats::Instance(bool loadDataFormats)
+{
+ if (sInstance == NULL)
+ sInstance = new CAAudioFileFormats(loadDataFormats);
+ return sInstance;
+}
+
+/*
+class CompareFileFormatNames {
+public:
+ bool operator() (const CAAudioFileFormats::FileFormatInfo &a, const CAAudioFileFormats::FileFormatInfo &b)
+ {
+ return CFStringCompare(a.mFileTypeName, b.mFileTypeName,
+ kCFCompareCaseInsensitive | kCFCompareLocalized) == kCFCompareLessThan;
+ }
+};*/
+
+static int CompareFileFormatNames(const void *va, const void *vb)
+{
+ CAAudioFileFormats::FileFormatInfo *a = (CAAudioFileFormats::FileFormatInfo *)va,
+ *b = (CAAudioFileFormats::FileFormatInfo *)vb;
+ return CFStringCompare(a->mFileTypeName, b->mFileTypeName,
+ kCFCompareCaseInsensitive | kCFCompareLocalized);
+}
+
+CAAudioFileFormats::CAAudioFileFormats(bool loadDataFormats) :
+ mNumFileFormats(0), mFileFormats(NULL)
+{
+ OSStatus err;
+ UInt32 size;
+ UInt32 *fileTypes = NULL;
+
+ // get all file types
+ err = AudioFileGetGlobalInfoSize(kAudioFileGlobalInfo_WritableTypes, 0, NULL, &size);
+ if (err != noErr) goto bail;
+ mNumFileFormats = size / sizeof(UInt32);
+ mFileFormats = new FileFormatInfo[mNumFileFormats];
+ fileTypes = new UInt32[mNumFileFormats];
+ err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_WritableTypes, 0, NULL, &size, fileTypes);
+ if (err != noErr) goto bail;
+
+ // get info for each file type
+ for (int i = 0; i < mNumFileFormats; ++i) {
+ FileFormatInfo *ffi = &mFileFormats[i];
+ OSType filetype = fileTypes[i];
+
+ ffi->mFileTypeID = filetype;
+
+ // file type name
+ ffi->mFileTypeName = NULL;
+ size = sizeof(CFStringRef);
+ err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_FileTypeName, sizeof(UInt32), &filetype, &size, &ffi->mFileTypeName);
+ if (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, OSType t)
+{
+ char *p = buf;
+ char str[4], *q = str;
+ *(UInt32 *)str = CFSwapInt32HostToBig(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 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 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, 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, 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/distrho/src/CoreAudio106/PublicUtility/CAAudioFileFormats.h b/distrho/src/CoreAudio106/PublicUtility/CAAudioFileFormats.h
new file mode 100755
index 00000000..589652e4
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAudioFileFormats.h
@@ -0,0 +1,143 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAAudioFileFormats_h__
+#define __CAAudioFileFormats_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioToolbox/AudioToolbox.h>
+#else
+ #include <AudioToolbox.h>
+#endif
+#include "CAStreamBasicDescription.h"
+
+class CAAudioFileFormats {
+public:
+ enum { noErr = 0 };
+
+ struct DataFormatInfo {
+ DataFormatInfo() : mVariants(NULL) { }
+ ~DataFormatInfo() { delete[] mVariants; }
+
+ UInt32 mFormatID;
+ int mNumVariants;
+ AudioStreamBasicDescription * mVariants;
+ bool mReadable;
+ bool mWritable;
+ bool mEitherEndianPCM;
+
+#if DEBUG
+ void DebugPrint();
+#endif
+ };
+
+ struct FileFormatInfo {
+ FileFormatInfo() : mFileTypeName(NULL), mExtensions(NULL), mDataFormats(NULL) { }
+ ~FileFormatInfo() {
+ delete[] mDataFormats;
+ if (mFileTypeName)
+ CFRelease(mFileTypeName);
+ if (mExtensions)
+ CFRelease(mExtensions);
+ }
+
+ AudioFileTypeID mFileTypeID;
+ CFStringRef mFileTypeName;
+ CFArrayRef mExtensions;
+ int mNumDataFormats;
+ DataFormatInfo * mDataFormats; // NULL until loaded!
+
+ int NumberOfExtensions() { return 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, UInt32 t);
+int StrToOSType(const char *str, UInt32 &t);
+
+#endif // __CAAudioFileFormats_h__
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAAudioTimeStamp.cpp b/distrho/src/CoreAudio106/PublicUtility/CAAudioTimeStamp.cpp
new file mode 100755
index 00000000..c0bfbe4e
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAudioTimeStamp.cpp
@@ -0,0 +1,127 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//=============================================================================
+// 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;
+ 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;
+ isDone = true;
+ }
+ }
+
+ return isEqual;
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAAudioTimeStamp.h b/distrho/src/CoreAudio106/PublicUtility/CAAudioTimeStamp.h
new file mode 100755
index 00000000..18261bcb
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAudioTimeStamp.h
@@ -0,0 +1,90 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CAAudioTimeStamp_h__)
+#define __CAAudioTimeStamp_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+#include <string.h>
+
+//=============================================================================
+// CAAudioTimeStamp
+//=============================================================================
+
+struct CAAudioTimeStamp
+:
+ public AudioTimeStamp
+{
+
+// Construction/Destruction
+public:
+ CAAudioTimeStamp() { memset(this, 0, sizeof(AudioTimeStamp)); }
+ CAAudioTimeStamp(const AudioTimeStamp& v) { memcpy(this, &v, sizeof(AudioTimeStamp)); }
+ CAAudioTimeStamp(Float64 inSampleTime) { memset(this, 0, sizeof(AudioTimeStamp)); mSampleTime = inSampleTime; mFlags = kAudioTimeStampSampleTimeValid; }
+ CAAudioTimeStamp(UInt64 inHostTime) { memset(this, 0, sizeof(AudioTimeStamp)); mHostTime = inHostTime; mFlags = kAudioTimeStampHostTimeValid; }
+ CAAudioTimeStamp(Float64 inSampleTime, UInt64 inHostTime) { memset(this, 0, sizeof(AudioTimeStamp)); mSampleTime = inSampleTime; mHostTime = inHostTime; mFlags = kAudioTimeStampSampleTimeValid | kAudioTimeStampHostTimeValid; }
+
+// 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/distrho/src/CoreAudio106/PublicUtility/CAAudioUnit.cpp b/distrho/src/CoreAudio106/PublicUtility/CAAudioUnit.cpp
new file mode 100755
index 00000000..e4e60d59
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAudioUnit.cpp
@@ -0,0 +1,1257 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CAAudioUnit.h"
+
+#if !TARGET_OS_IPHONE
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/Components.h>
+ #include <AudioUnit/MusicDevice.h>
+ #include <dlfcn.h>
+#else
+ #include <Components.h>
+ #include <MusicDevice.h>
+#endif
+#endif
+
+#include "CAXException.h"
+#include "CAReferenceCounted.h"
+#include "AUOutputBL.h" //this is for the Preroll only
+
+struct StackAUChannelInfo {
+ StackAUChannelInfo (UInt32 inSize) : mChanInfo ((AUChannelInfo*)malloc (inSize)) {}
+ ~StackAUChannelInfo() { free (mChanInfo); }
+
+ AUChannelInfo* mChanInfo;
+};
+
+// is this symbol is not defined then we use the default setting which is that fast dispatch
+// is supported on a desktop environment
+#ifndef CA_AU_USE_FAST_DISPATCH
+ #define CA_AU_USE_FAST_DISPATCH !TARGET_OS_IPHONE
+#endif
+
+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);
+ }
+
+#if !TARGET_OS_IPHONE
+ 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
+ }
+#endif// !TARGET_OS_IPHONE
+
+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 = GetComponentInstanceStorage ( 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&) { return *this; }
+};
+
+
+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)));
+}
+
+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;
+}
+
+bool CheckDynCount (SInt32 inTotalChans, const CAAUChanHelper &inHelper)
+{
+ int totalChans = 0;
+ for (unsigned int i = 0; i < inHelper.mNumEls; ++i)
+ totalChans += inHelper.mChans[i];
+ return (totalChans <= inTotalChans);
+}
+
+bool CAAudioUnit::CheckOneSide (const CAAUChanHelper &inHelper,
+ bool checkOutput,
+ const AUChannelInfo *info,
+ UInt32 numInfo) const
+{
+ // now we can use the wildcard option (see above impl) to see if this matches
+ for (unsigned int el = 0; el < inHelper.mNumEls; ++el) {
+ bool testAlready = false;
+ for (unsigned int i = 0; i < el; ++i) {
+ if (inHelper.mChans[i] == inHelper.mChans[el]) {
+ testAlready = true;
+ break;
+ }
+ }
+ if (!testAlready) {
+ if (checkOutput) {
+ if (!ValidateChannelPair (0, inHelper.mChans[el], info, numInfo)) return false;
+ } else {
+ if (!ValidateChannelPair (inHelper.mChans[el], 0, info, numInfo)) return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool CAAudioUnit::CanDo (const CAAUChanHelper &inputs,
+ const CAAUChanHelper &outputs) const
+
+{
+// first check our state
+ // huh!
+ if (inputs.mNumEls == 0 && outputs.mNumEls == 0) return false;
+
+ UInt32 elCount;
+ if (GetElementCount (kAudioUnitScope_Input, elCount)) { return false; }
+ if (elCount != inputs.mNumEls) return false;
+
+ if (GetElementCount (kAudioUnitScope_Output, elCount)) { return false; }
+ if (elCount != outputs.mNumEls) return false;
+
+// (1) special cases (effects and sources (generators and instruments) only)
+ UInt32 dataSize = 0;
+ if (GetPropertyInfo (kAudioUnitProperty_SupportedNumChannels,
+ kAudioUnitScope_Global, 0, &dataSize, NULL) != noErr)
+ {
+ if (Comp().Desc().IsEffect() || Comp().Desc().IsOffline()) {
+ UInt32 numChan = outputs.mNumEls > 0 ? outputs.mChans[0] : inputs.mChans[0];
+ for (unsigned int in = 0; in < inputs.mNumEls; ++in)
+ if (numChan != inputs.mChans[in]) return false;
+ for (unsigned int out = 0; out < outputs.mNumEls; ++out)
+ if (numChan != outputs.mChans[out]) return false;
+ return true;
+ }
+
+ // in this case, all the channels have to match the current config
+ if (Comp().Desc().IsGenerator() || Comp().Desc().IsMusicDevice()) {
+ for (unsigned int in = 0; in < inputs.mNumEls; ++in) {
+ UInt32 chan;
+ if (NumberChannels (kAudioUnitScope_Input, in, chan)) return false;
+ if (chan != UInt32(inputs.mChans[in])) return false;
+ }
+ for (unsigned int out = 0; out < outputs.mNumEls; ++out) {
+ UInt32 chan;
+ if (NumberChannels (kAudioUnitScope_Output, out, chan)) return false;
+ if (chan != UInt32(outputs.mChans[out])) return false;
+ }
+ return true;
+ }
+
+ // if we get here we can't determine anything about channel capabilities
+ return false;
+ }
+
+ StackAUChannelInfo info (dataSize);
+
+ if (GetProperty (kAudioUnitProperty_SupportedNumChannels,
+ kAudioUnitScope_Global, 0,
+ info.mChanInfo, &dataSize) != noErr)
+ {
+ return false;
+ }
+
+ int numInfo = dataSize / sizeof(AUChannelInfo);
+
+// (2) Test for dynamic capability (or no elements on that scope)
+ SInt32 dynInChans = 0;
+ if (ValidateDynamicScope (kAudioUnitScope_Input, dynInChans, info.mChanInfo, numInfo)) {
+ if (CheckDynCount (dynInChans, inputs) == false) return false;
+ }
+
+ SInt32 dynOutChans = 0;
+ if (ValidateDynamicScope (kAudioUnitScope_Output, dynOutChans, info.mChanInfo, numInfo)) {
+ if (CheckDynCount (dynOutChans, outputs) == false) return false;
+ }
+
+ if (dynOutChans && dynInChans) { return true; }
+
+// (3) Just need to test one side
+ if (dynInChans || (inputs.mNumEls == 0)) {
+ return CheckOneSide (outputs, true, info.mChanInfo, numInfo);
+ }
+
+ if (dynOutChans || (outputs.mNumEls == 0)) {
+ return CheckOneSide (inputs, false, info.mChanInfo, numInfo);
+ }
+
+// (4) - not a dynamic AU, has ins and outs, and has channel constraints so we test every possible pairing
+ for (unsigned int in = 0; in < inputs.mNumEls; ++in)
+ {
+ bool testInAlready = false;
+ for (unsigned int i = 0; i < in; ++i) {
+ if (inputs.mChans[i] == inputs.mChans[in]) {
+ testInAlready = true;
+ break;
+ }
+ }
+ if (!testInAlready) {
+ for (unsigned int out = 0; out < outputs.mNumEls; ++out) {
+ // try to save a little bit and not test the same pairing multiple times...
+ bool testOutAlready = false;
+ for (unsigned int i = 0; i < out; ++i) {
+ if (outputs.mChans[i] == outputs.mChans[out]) {
+ testOutAlready = true;
+ break;
+ }
+ }
+ if (!testOutAlready) {
+ if (!ValidateChannelPair (inputs.mChans[in], outputs.mChans[out],info.mChanInfo, numInfo)) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool CAAudioUnit::SupportsNumChannels () const
+{
+ // this is the default assumption of an audio effect unit
+ Boolean* isWritable = 0;
+ UInt32 dataSize = 0;
+ // lets see if the unit has any channel restrictions
+ OSStatus result = AudioUnitGetPropertyInfo (AU(),
+ kAudioUnitProperty_SupportedNumChannels,
+ kAudioUnitScope_Global, 0,
+ &dataSize, isWritable); //don't care if this is writable
+
+ // if this property is NOT implemented an FX unit
+ // is expected to deal with same channel valance in and out
+ if (result) {
+ if (Comp().Desc().IsEffect() || Comp().Desc().IsOffline())
+ return true;
+ }
+ return result == noErr;
+}
+
+OSStatus CAAudioUnit::GetChannelLayoutTags (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ ChannelTagVector &outChannelVector) const
+{
+ if (HasChannelLayouts (inScope, inEl) == false) return kAudioUnitErr_InvalidProperty;
+
+ UInt32 dataSize;
+ OSStatus result = AudioUnitGetPropertyInfo (AU(),
+ kAudioUnitProperty_SupportedChannelLayoutTags,
+ inScope, inEl,
+ &dataSize, NULL);
+
+ if (result) return result;
+
+ // OK lets get our channel layouts and see if the one we want is present
+ AudioChannelLayoutTag* info = (AudioChannelLayoutTag*)malloc (dataSize);
+ result = AudioUnitGetProperty (AU(),
+ kAudioUnitProperty_SupportedChannelLayoutTags,
+ inScope, inEl,
+ info, &dataSize);
+ if (result) goto home;
+
+ outChannelVector.erase (outChannelVector.begin(), outChannelVector.end());
+ for (unsigned int i = 0; i < (dataSize / sizeof (AudioChannelLayoutTag)); ++i)
+ outChannelVector.push_back (info[i]);
+
+home:
+ free (info);
+ return result;
+}
+
+bool CAAudioUnit::HasChannelLayouts (AudioUnitScope inScope,
+ AudioUnitElement inEl) const
+{
+ OSStatus result = AudioUnitGetPropertyInfo (AU(),
+ kAudioUnitProperty_SupportedChannelLayoutTags,
+ inScope, inEl,
+ NULL, NULL);
+ return !result;
+}
+
+bool CAAudioUnit::HasChannelLayout (AudioUnitScope inScope,
+ AudioUnitElement inEl) const
+{
+ Boolean writable;
+ UInt32 size;
+
+ return AudioUnitGetPropertyInfo (AU(),
+ kAudioUnitProperty_AudioChannelLayout,
+ inScope, inEl,
+ &size, &writable) == noErr;
+}
+
+OSStatus CAAudioUnit::GetChannelLayout (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ CAAudioChannelLayout &outLayout) const
+{
+ UInt32 size;
+ OSStatus result = AudioUnitGetPropertyInfo (AU(), kAudioUnitProperty_AudioChannelLayout,
+ inScope, inEl, &size, NULL);
+ if (result) return result;
+
+ AudioChannelLayout *layout = (AudioChannelLayout*)malloc (size);
+
+ ca_require_noerr (result = AudioUnitGetProperty (AU(), kAudioUnitProperty_AudioChannelLayout,
+ inScope, inEl, layout, &size), home);
+
+ outLayout = CAAudioChannelLayout (layout);
+
+home:
+ free (layout);
+ return result;
+}
+
+OSStatus CAAudioUnit::SetChannelLayout (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ const CAAudioChannelLayout &inLayout)
+{
+ OSStatus result = AudioUnitSetProperty (AU(),
+ kAudioUnitProperty_AudioChannelLayout,
+ inScope, inEl,
+ inLayout, inLayout.Size());
+ return result;
+}
+
+OSStatus CAAudioUnit::SetChannelLayout (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ const AudioChannelLayout &inLayout,
+ UInt32 inSize)
+{
+ OSStatus result = AudioUnitSetProperty (AU(),
+ kAudioUnitProperty_AudioChannelLayout,
+ inScope, inEl,
+ &inLayout, inSize);
+ return result;
+}
+
+OSStatus CAAudioUnit::ClearChannelLayout (AudioUnitScope inScope,
+ AudioUnitElement inEl)
+{
+ return AudioUnitSetProperty (AU(),
+ kAudioUnitProperty_AudioChannelLayout,
+ inScope, inEl, NULL, 0);
+}
+
+OSStatus CAAudioUnit::GetFormat (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ AudioStreamBasicDescription &outFormat) const
+{
+ UInt32 dataSize = sizeof (AudioStreamBasicDescription);
+ return AudioUnitGetProperty (AU(), kAudioUnitProperty_StreamFormat,
+ inScope, inEl,
+ &outFormat, &dataSize);
+}
+
+OSStatus CAAudioUnit::SetFormat (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ const AudioStreamBasicDescription &inFormat)
+{
+ return AudioUnitSetProperty (AU(), kAudioUnitProperty_StreamFormat,
+ inScope, inEl,
+ const_cast<AudioStreamBasicDescription*>(&inFormat),
+ sizeof (AudioStreamBasicDescription));
+}
+
+OSStatus CAAudioUnit::GetSampleRate (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ Float64 &outRate) const
+{
+ UInt32 dataSize = sizeof (Float64);
+ return AudioUnitGetProperty (AU(), kAudioUnitProperty_SampleRate,
+ inScope, inEl,
+ &outRate, &dataSize);
+}
+
+OSStatus CAAudioUnit::SetSampleRate (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ Float64 inRate)
+{
+ AudioStreamBasicDescription desc;
+ OSStatus result = GetFormat (inScope, inEl, desc);
+ if (result) return result;
+ desc.mSampleRate = inRate;
+ return SetFormat (inScope, inEl, desc);
+}
+
+OSStatus CAAudioUnit::SetSampleRate (Float64 inSampleRate)
+{
+ OSStatus result;
+
+ UInt32 elCount;
+ ca_require_noerr (result = GetElementCount(kAudioUnitScope_Input, elCount), home);
+ if (elCount) {
+ for (unsigned int i = 0; i < elCount; ++i) {
+ ca_require_noerr (result = SetSampleRate (kAudioUnitScope_Input, i, inSampleRate), home);
+ }
+ }
+
+ ca_require_noerr (result = GetElementCount(kAudioUnitScope_Output, elCount), home);
+ if (elCount) {
+ for (unsigned int i = 0; i < elCount; ++i) {
+ ca_require_noerr (result = SetSampleRate (kAudioUnitScope_Output, i, inSampleRate), home);
+ }
+ }
+
+home:
+ return result;
+}
+
+OSStatus CAAudioUnit::NumberChannels (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ UInt32 &outChans) const
+{
+ AudioStreamBasicDescription desc;
+ OSStatus result = GetFormat (inScope, inEl, desc);
+ if (!result)
+ outChans = desc.mChannelsPerFrame;
+ return result;
+}
+
+OSStatus CAAudioUnit::SetNumberChannels (AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ UInt32 inChans)
+{
+ // set this as the output of the AU
+ CAStreamBasicDescription desc;
+ OSStatus result = GetFormat (inScope, inEl, desc);
+ if (result) return result;
+ desc.SetAUCanonical (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.SetAUCanonical (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));
+}
+
+#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) : paramErr;
+}
+
+OSStatus CAAudioUnit::SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+ Float32 value, UInt32 bufferOffsetFrames)
+{
+ return mDataPtr ? mDataPtr->SetParameter (inID, scope, element, value, bufferOffsetFrames) : paramErr;
+}
+
+#if !TARGET_OS_IPHONE
+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;
+}
+#endif
+
+
+#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) : paramErr;
+}
+
+#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);
+ }
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAAudioUnit.h b/distrho/src/CoreAudio106/PublicUtility/CAAudioUnit.h
new file mode 100755
index 00000000..c94c795f
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAudioUnit.h
@@ -0,0 +1,417 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAAudioUnit_h__
+#define __CAAudioUnit_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudio.h>
+ #include <AudioUnit/AudioUnit.h>
+ #if !TARGET_OS_IPHONE
+ #include <AudioUnit/MusicDevice.h>
+ #endif
+ #include <AudioToolbox/AUGraph.h>
+#else
+ #include <ConditionalMacros.h>
+ #include <CoreAudioTypes.h>
+ #include <AudioUnit.h>
+ #include <MusicDevice.h>
+ #include <AUGraph.h>
+ #include <MusicDevice.h>
+#endif
+
+#include <vector>
+#include "CAStreamBasicDescription.h"
+#include "CAComponent.h"
+#include "CAAudioChannelLayout.h"
+
+// defined below
+class CAAUChanHelper;
+
+// These constructors will NOT throw exceptions - so "check" after creation if AU IsValid()
+// The destructor will NOT automatically close the AU down
+// This state should be managed by the Caller
+// once closed, the unit represented by this object is no longer valid
+// it is up to the user of this object to ensure its validity is in sync
+// if it is removed from a graph
+
+// methods that can significantly change the state of the AU (like its format) are
+// NOT const whereas those that don't change the externally related state of the AU are not const
+
+class CAAudioUnit {
+ enum {
+ paramErr = -50,
+ badComponentSelector = (long)0x80008002
+ };
+public:
+ typedef std::vector<AudioChannelLayoutTag> ChannelTagVector;
+ typedef ChannelTagVector::iterator ChannelTagVectorIter;
+
+public:
+ CAAudioUnit ()
+ : mDataPtr(0) {}
+
+ CAAudioUnit (const AudioUnit& inUnit);
+
+ CAAudioUnit (const AUNode &inNode, const AudioUnit& inUnit);
+
+ CAAudioUnit (const CAAudioUnit& y)
+ : mDataPtr(0) { *this = y; }
+
+ static OSStatus Open (const CAComponent& inComp, CAAudioUnit &outUnit);
+
+ ~CAAudioUnit ();
+
+ void Close ();
+
+
+ CAAudioUnit& operator= (const CAAudioUnit& y);
+
+ bool operator== (const CAAudioUnit& y) const;
+
+ bool operator== (const AudioUnit& y) const;
+
+#pragma mark __State Management
+ bool IsValid () const;
+
+ AudioUnit AU() const;
+ operator AudioUnit () const { return AU(); }
+
+ const CAComponent& Comp() const { return mComp; }
+
+ 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 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);
+
+#if !TARGET_OS_IPHONE
+// 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);
+#endif
+
+#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;
+
+ 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;
+
+ 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/distrho/src/CoreAudio106/PublicUtility/CAAudioUnitOutputCapturer.h b/distrho/src/CoreAudio106/PublicUtility/CAAudioUnitOutputCapturer.h
new file mode 100755
index 00000000..80c993ee
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAudioUnitOutputCapturer.h
@@ -0,0 +1,137 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAAudioUnitOutputCapturer_h__
+#define __CAAudioUnitOutputCapturer_h__
+
+#include <AudioToolbox/ExtendedAudioFile.h>
+
+/*
+ Class to capture output from an AudioUnit for analysis.
+
+ example:
+
+ CFURL fileurl = CFURLCreateWithFileSystemPath(NULL, CFSTR("/tmp/recording.caf"), kCFURLPOSIXPathStyle, false);
+
+ CAAudioUnitOutputCapturer captor(someAU, fileurl, 'caff', anASBD);
+
+ {
+ captor.Start();
+ ...
+ captor.Stop();
+ } // can repeat
+
+ captor.Close(); // can be omitted; happens automatically from destructor
+*/
+
+class CAAudioUnitOutputCapturer {
+public:
+ enum { noErr = 0 };
+
+ CAAudioUnitOutputCapturer(AudioUnit au, CFURLRef outputFileURL, AudioFileTypeID fileType, const AudioStreamBasicDescription &format, UInt32 busNumber = 0) :
+ mFileOpen(false),
+ mClientFormatSet(false),
+ mAudioUnit(au),
+ mExtAudioFile(NULL),
+ mBusNumber (busNumber)
+ {
+ CFShow(outputFileURL);
+ OSStatus err = ExtAudioFileCreateWithURL(outputFileURL, fileType, &format, NULL, kAudioFileFlags_EraseFile, &mExtAudioFile);
+ if (!err)
+ mFileOpen = true;
+ }
+
+ void Start() {
+ if (mFileOpen) {
+ if (!mClientFormatSet) {
+ AudioStreamBasicDescription clientFormat;
+ UInt32 size = sizeof(clientFormat);
+ AudioUnitGetProperty(mAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, mBusNumber, &clientFormat, &size);
+ ExtAudioFileSetProperty(mExtAudioFile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat);
+ mClientFormatSet = true;
+ }
+ ExtAudioFileWriteAsync(mExtAudioFile, 0, NULL); // initialize async writes
+ AudioUnitAddRenderNotify(mAudioUnit, RenderCallback, this);
+ }
+ }
+
+ void Stop() {
+ if (mFileOpen)
+ AudioUnitRemoveRenderNotify(mAudioUnit, RenderCallback, this);
+ }
+
+ void Close() {
+ if (mExtAudioFile) {
+ ExtAudioFileDispose(mExtAudioFile);
+ mExtAudioFile = NULL;
+ }
+ }
+
+ ~CAAudioUnitOutputCapturer() {
+ Close();
+ }
+
+private:
+ static OSStatus RenderCallback( void * inRefCon,
+ AudioUnitRenderActionFlags * ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList * ioData)
+ {
+ if (*ioActionFlags & kAudioUnitRenderAction_PostRender) {
+ CAAudioUnitOutputCapturer *This = (CAAudioUnitOutputCapturer *)inRefCon;
+ static int TEMP_kAudioUnitRenderAction_PostRenderError = (1 << 8);
+ if (This->mBusNumber == inBusNumber && !(*ioActionFlags & TEMP_kAudioUnitRenderAction_PostRenderError)) {
+ OSStatus result = ExtAudioFileWrite(This->mExtAudioFile, inNumberFrames, ioData);
+ if (result) DebugMessageN1("ERROR WRITING FRAMES: %d\n", result);
+ }
+ }
+ return noErr;
+ }
+
+ bool mFileOpen;
+ bool mClientFormatSet;
+ AudioUnit mAudioUnit;
+ ExtAudioFileRef mExtAudioFile;
+ UInt32 mBusNumber;
+};
+
+#endif // __CAAudioUnitOutputCapturer_h__
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAAudioValueRange.cpp b/distrho/src/CoreAudio106/PublicUtility/CAAudioValueRange.cpp
new file mode 100755
index 00000000..f3374bb5
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAudioValueRange.cpp
@@ -0,0 +1,244 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CAAudioValueRange.h"
+
+// Standard Library
+#include <algorithm>
+
+//==================================================================================================
+// CAAudioValueRange
+//==================================================================================================
+
+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(const AudioValueRange& inRange, const CAAudioValueRangeList& inRangeList, CAAudioValueRangeList& outIntersections)
+{
+ outIntersections.clear();
+ // iterate through the list and compute the intersections
+ CAAudioValueRangeList::const_iterator theIterator = inRangeList.begin();
+ while(theIterator != inRangeList.end())
+ {
+ // figure out if the range intersects
+ AudioValueRange theIntersection;
+ if(CAAudioValueRange::Intersection(inRange, *theIterator, theIntersection))
+ {
+ // it does, so add the intersection to the return list
+ outIntersections.push_back(theIntersection);
+ }
+
+ // go to the next one
+ std::advance(theIterator, 1);
+ }
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAAudioValueRange.h b/distrho/src/CoreAudio106/PublicUtility/CAAudioValueRange.h
new file mode 100755
index 00000000..cbb643e9
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAudioValueRange.h
@@ -0,0 +1,114 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CAAudioValueRange_h__)
+#define __CAAudioValueRange_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+// Standard Library Includes
+#include <functional>
+#include <vector>
+
+//=============================================================================
+// CAAudioValueRange
+//=============================================================================
+
+struct CAAudioValueRange
+:
+ public AudioValueRange
+{
+
+// Construction/Destruction
+public:
+ CAAudioValueRange() { mMinimum = 0.0; mMaximum = 0.0; }
+ CAAudioValueRange(const AudioValueRange& v) { mMinimum = v.mMinimum; mMaximum = v.mMaximum; }
+ CAAudioValueRange(Float64 inMinimum, Float64 inMaximum) { mMinimum = inMinimum; mMaximum = inMaximum; }
+
+// Assignment
+public:
+ CAAudioValueRange& operator=(const AudioValueRange& v) { mMinimum = v.mMinimum; mMaximum = v.mMaximum; return *this; }
+
+// Operations
+public:
+ static bool ContainsValue(const AudioValueRange& inRange, Float64 inValue) { return (inValue >= inRange.mMinimum) && (inValue <= inRange.mMaximum); }
+ static Float64 PickCommonSampleRate(const AudioValueRange& inRange);
+ static bool IsStrictlyLessThan(const AudioValueRange& x, const AudioValueRange& y) { return x.mMaximum < y.mMinimum; }
+ static bool IsStrictlyGreaterThan(const AudioValueRange& x, const AudioValueRange& y) { return x.mMinimum > y.mMaximum; }
+ static bool IsStrictlyContainedBy(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum >= y.mMinimum) && (x.mMaximum <= y.mMaximum); }
+ static bool OverlapsLow(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum < y.mMinimum) && (x.mMaximum >= y.mMinimum) && (x.mMaximum <= y.mMaximum); }
+ static bool OverlapsHigh(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum >= y.mMinimum) && (x.mMinimum <= y.mMaximum) && (x.mMaximum > y.mMaximum); }
+ static bool Intersection(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange);
+ static bool Union(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange);
+
+// STL Helpers
+public:
+ struct LessThan
+ :
+ public std::binary_function<AudioValueRange, AudioValueRange, bool>
+ {
+ bool operator()(const AudioValueRange& x, const AudioValueRange& y) const
+ {
+ return x.mMinimum < y.mMinimum;
+ }
+ };
+
+};
+
+inline bool operator<(const AudioValueRange& x, const AudioValueRange& y) { return x.mMinimum < y.mMinimum; }
+inline bool operator==(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum == y.mMinimum) && (x.mMaximum == y.mMaximum); }
+inline bool operator!=(const AudioValueRange& x, const AudioValueRange& y) { return !(x == y); }
+inline bool operator<=(const AudioValueRange& x, const AudioValueRange& y) { return (x < y) || (x == y); }
+inline bool operator>=(const AudioValueRange& x, const AudioValueRange& y) { return !(x < y); }
+inline bool operator>(const AudioValueRange& x, const AudioValueRange& y) { return !((x < y) || (x == y)); }
+
+typedef std::vector<CAAudioValueRange> CAAudioValueRangeList;
+void CAAudioValueRange_ComputeUnion(const AudioValueRange& inRange, const CAAudioValueRangeList& inRangeList, CAAudioValueRangeList& outUnion);
+void CAAudioValueRange_ComputeIntersection(const AudioValueRange& inRange, const CAAudioValueRangeList& inRangeList, CAAudioValueRangeList& outIntersections);
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAAutoDisposer.h b/distrho/src/CoreAudio106/PublicUtility/CAAutoDisposer.h
new file mode 100755
index 00000000..e060d6fb
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAutoDisposer.h
@@ -0,0 +1,502 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CAPtr_h__)
+#define __CAPtr_h__
+
+#include <stdlib.h> // for malloc
+#include <new> // for bad_alloc
+#include <string.h> // for memset
+
+inline void* CA_malloc(size_t size)
+{
+ void* p = malloc(size);
+ if (!p && size) throw std::bad_alloc();
+ return p;
+}
+
+inline void* CA_realloc(void* old, size_t size)
+{
+#if TARGET_OS_WIN32
+ void* p = realloc(old, size);
+#else
+ void* p = reallocf(old, size); // reallocf ensures the old pointer is freed if memory is full (p is NULL).
+#endif
+ if (!p && size) throw std::bad_alloc();
+ return p;
+}
+
+#ifndef UINTPTR_MAX
+#if __LP64__
+#define UINTPTR_MAX 18446744073709551615ULL
+#else
+#define UINTPTR_MAX 4294967295U
+#endif
+#endif
+
+inline void* CA_calloc(size_t n, size_t size)
+{
+ // ensure that multiplication will not overflow
+ if (n && UINTPTR_MAX / n < size) throw std::bad_alloc();
+
+ size_t nsize = n*size;
+ void* p = malloc(nsize);
+ if (!p && nsize) throw std::bad_alloc();
+
+ memset(p, 0, nsize);
+ return p;
+}
+
+
+// helper class for automatic conversions
+template <typename T>
+struct CAPtrRef
+{
+ T* ptr_;
+
+ explicit CAPtrRef(T* ptr) : ptr_(ptr) {}
+};
+
+template <typename T>
+class CAAutoFree
+{
+private:
+ T* ptr_;
+
+public:
+
+ CAAutoFree() : ptr_(0) {}
+
+ explicit CAAutoFree(T* ptr) : ptr_(ptr) {}
+
+ template<typename U>
+ CAAutoFree(CAAutoFree<U>& that) : ptr_(that.release()) {} // take ownership
+
+ // C++ std says: a template constructor is never a copy constructor
+ CAAutoFree(CAAutoFree<T>& that) : ptr_(that.release()) {} // take ownership
+
+ CAAutoFree(size_t n, bool clear = false)
+ // this becomes an ambiguous call if n == 0
+ : ptr_(0)
+ {
+ size_t maxItems = ~size_t(0) / sizeof(T);
+ if (n > maxItems)
+ throw std::bad_alloc();
+
+ ptr_ = static_cast<T*>(clear ? CA_calloc(n, sizeof(T)) : CA_malloc(n * sizeof(T)));
+ }
+
+ ~CAAutoFree() { free(); }
+
+ void alloc(size_t numItems, bool clear = false)
+ {
+ size_t maxItems = ~size_t(0) / sizeof(T);
+ if (numItems > maxItems) throw std::bad_alloc();
+
+ free();
+ ptr_ = static_cast<T*>(clear ? CA_calloc(numItems, sizeof(T)) : CA_malloc(numItems * sizeof(T)));
+ }
+
+ void allocBytes(size_t numBytes, bool clear = false)
+ {
+ free();
+ ptr_ = static_cast<T*>(clear ? CA_calloc(1, numBytes) : CA_malloc(numBytes));
+ }
+
+ void reallocBytes(size_t numBytes)
+ {
+ ptr_ = static_cast<T*>(CA_realloc(ptr_, numBytes));
+ }
+
+ void reallocItems(size_t numItems)
+ {
+ size_t maxItems = ~size_t(0) / sizeof(T);
+ if (numItems > maxItems) throw std::bad_alloc();
+
+ ptr_ = static_cast<T*>(CA_realloc(ptr_, numItems * sizeof(T)));
+ }
+
+ template <typename U>
+ CAAutoFree& operator=(CAAutoFree<U>& that)
+ {
+ set(that.release()); // take ownership
+ return *this;
+ }
+
+ CAAutoFree& operator=(CAAutoFree& that)
+ {
+ set(that.release()); // take ownership
+ return *this;
+ }
+
+ CAAutoFree& operator=(T* ptr)
+ {
+ set(ptr);
+ return *this;
+ }
+
+ template <typename U>
+ CAAutoFree& operator=(U* ptr)
+ {
+ set(ptr);
+ return *this;
+ }
+
+ T& operator*() const { return *ptr_; }
+ T* operator->() const { return ptr_; }
+
+ T* operator()() const { return ptr_; }
+ T* get() const { return ptr_; }
+ operator T*() const { return ptr_; }
+
+ bool operator==(CAAutoFree const& that) const { return ptr_ == that.ptr_; }
+ bool operator!=(CAAutoFree const& that) const { return ptr_ != that.ptr_; }
+ bool operator==(T* ptr) const { return ptr_ == ptr; }
+ bool operator!=(T* ptr) const { return ptr_ != ptr; }
+
+ T* release()
+ {
+ // release ownership
+ T* result = ptr_;
+ ptr_ = 0;
+ return result;
+ }
+
+ void set(T* ptr)
+ {
+ if (ptr != ptr_)
+ {
+ ::free(ptr_);
+ ptr_ = ptr;
+ }
+ }
+
+ void free()
+ {
+ set(0);
+ }
+
+
+ // automatic conversions to allow assignment from results of functions.
+ // hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
+ CAAutoFree(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }
+
+ CAAutoFree& operator=(CAPtrRef<T> ref)
+ {
+ set(ref.ptr_);
+ return *this;
+ }
+
+ template<typename U>
+ operator CAPtrRef<U>()
+ { return CAPtrRef<U>(release()); }
+
+ template<typename U>
+ operator CAAutoFree<U>()
+ { return CAAutoFree<U>(release()); }
+
+};
+
+
+template <typename T>
+class CAAutoDelete
+{
+private:
+ T* ptr_;
+
+public:
+ CAAutoDelete() : ptr_(0) {}
+
+ explicit CAAutoDelete(T* ptr) : ptr_(ptr) {}
+
+ template<typename U>
+ CAAutoDelete(CAAutoDelete<U>& that) : ptr_(that.release()) {} // take ownership
+
+ // C++ std says: a template constructor is never a copy constructor
+ CAAutoDelete(CAAutoDelete<T>& that) : ptr_(that.release()) {} // take ownership
+
+ ~CAAutoDelete() { free(); }
+
+ template <typename U>
+ CAAutoDelete& operator=(CAAutoDelete<U>& that)
+ {
+ set(that.release()); // take ownership
+ return *this;
+ }
+
+ CAAutoDelete& operator=(CAAutoDelete& that)
+ {
+ set(that.release()); // take ownership
+ return *this;
+ }
+
+ CAAutoDelete& operator=(T* ptr)
+ {
+ set(ptr);
+ return *this;
+ }
+
+ template <typename U>
+ CAAutoDelete& operator=(U* ptr)
+ {
+ set(ptr);
+ return *this;
+ }
+
+ T& operator*() const { return *ptr_; }
+ T* operator->() const { return ptr_; }
+
+ T* operator()() const { return ptr_; }
+ T* get() const { return ptr_; }
+ operator T*() const { return ptr_; }
+
+ bool operator==(CAAutoDelete const& that) const { return ptr_ == that.ptr_; }
+ bool operator!=(CAAutoDelete const& that) const { return ptr_ != that.ptr_; }
+ bool operator==(T* ptr) const { return ptr_ == ptr; }
+ bool operator!=(T* ptr) const { return ptr_ != ptr; }
+
+ T* release()
+ {
+ // release ownership
+ T* result = ptr_;
+ ptr_ = 0;
+ return result;
+ }
+
+ void set(T* ptr)
+ {
+ if (ptr != ptr_)
+ {
+ delete ptr_;
+ ptr_ = ptr;
+ }
+ }
+
+ void free()
+ {
+ set(0);
+ }
+
+
+ // automatic conversions to allow assignment from results of functions.
+ // hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
+ CAAutoDelete(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }
+
+ CAAutoDelete& operator=(CAPtrRef<T> ref)
+ {
+ set(ref.ptr_);
+ return *this;
+ }
+
+ template<typename U>
+ operator CAPtrRef<U>()
+ { return CAPtrRef<U>(release()); }
+
+ template<typename U>
+ operator CAAutoFree<U>()
+ { return CAAutoFree<U>(release()); }
+
+};
+
+
+template <typename T>
+class CAAutoArrayDelete
+{
+private:
+ T* ptr_;
+
+public:
+ CAAutoArrayDelete() : ptr_(0) {}
+
+ explicit CAAutoArrayDelete(T* ptr) : ptr_(ptr) {}
+
+ template<typename U>
+ CAAutoArrayDelete(CAAutoArrayDelete<U>& that) : ptr_(that.release()) {} // take ownership
+
+ // C++ std says: a template constructor is never a copy constructor
+ CAAutoArrayDelete(CAAutoArrayDelete<T>& that) : ptr_(that.release()) {} // take ownership
+
+ // this becomes an ambiguous call if n == 0
+ CAAutoArrayDelete(size_t n) : ptr_(new T[n]) {}
+
+ ~CAAutoArrayDelete() { free(); }
+
+ void alloc(size_t numItems)
+ {
+ free();
+ ptr_ = new T [numItems];
+ }
+
+ template <typename U>
+ CAAutoArrayDelete& operator=(CAAutoArrayDelete<U>& that)
+ {
+ set(that.release()); // take ownership
+ return *this;
+ }
+
+ CAAutoArrayDelete& operator=(CAAutoArrayDelete& that)
+ {
+ set(that.release()); // take ownership
+ return *this;
+ }
+
+ CAAutoArrayDelete& operator=(T* ptr)
+ {
+ set(ptr);
+ return *this;
+ }
+
+ template <typename U>
+ CAAutoArrayDelete& operator=(U* ptr)
+ {
+ set(ptr);
+ return *this;
+ }
+
+ T& operator*() const { return *ptr_; }
+ T* operator->() const { return ptr_; }
+
+ T* operator()() const { return ptr_; }
+ T* get() const { return ptr_; }
+ operator T*() const { return ptr_; }
+
+ bool operator==(CAAutoArrayDelete const& that) const { return ptr_ == that.ptr_; }
+ bool operator!=(CAAutoArrayDelete const& that) const { return ptr_ != that.ptr_; }
+ bool operator==(T* ptr) const { return ptr_ == ptr; }
+ bool operator!=(T* ptr) const { return ptr_ != ptr; }
+
+ T* release()
+ {
+ // release ownership
+ T* result = ptr_;
+ ptr_ = 0;
+ return result;
+ }
+
+ void set(T* ptr)
+ {
+ if (ptr != ptr_)
+ {
+ delete [] ptr_;
+ ptr_ = ptr;
+ }
+ }
+
+ void free()
+ {
+ set(0);
+ }
+
+
+ // automatic conversions to allow assignment from results of functions.
+ // hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
+ CAAutoArrayDelete(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }
+
+ CAAutoArrayDelete& operator=(CAPtrRef<T> ref)
+ {
+ set(ref.ptr_);
+ return *this;
+ }
+
+ template<typename U>
+ operator CAPtrRef<U>()
+ { return CAPtrRef<U>(release()); }
+
+ template<typename U>
+ operator CAAutoArrayDelete<U>()
+ { return CAAutoFree<U>(release()); }
+
+};
+
+
+
+
+
+// convenience function
+template <typename T>
+void free(CAAutoFree<T>& p)
+{
+ p.free();
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#if 0
+// example program showing ownership transfer
+
+CAAutoFree<char> source()
+{
+ // source allocates and returns ownership to the caller.
+ const char* str = "this is a test";
+ size_t size = strlen(str) + 1;
+ CAAutoFree<char> captr(size, false);
+ strlcpy(captr(), str, size);
+ printf("source %08X %08X '%s'\n", &captr, captr(), captr());
+ return captr;
+}
+
+void user(CAAutoFree<char> const& captr)
+{
+ // passed by const reference. user can access the pointer but does not take ownership.
+ printf("user: %08X %08X '%s'\n", &captr, captr(), captr());
+}
+
+void sink(CAAutoFree<char> captr)
+{
+ // passed by value. sink takes ownership and frees the pointer on return.
+ printf("sink: %08X %08X '%s'\n", &captr, captr(), captr());
+}
+
+
+int main (int argc, char * const argv[])
+{
+
+ CAAutoFree<char> captr(source());
+ printf("main captr A %08X %08X\n", &captr, captr());
+ user(captr);
+ sink(captr);
+ printf("main captr B %08X %08X\n", &captr, captr());
+ return 0;
+}
+#endif
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CABitOperations.h b/distrho/src/CoreAudio106/PublicUtility/CABitOperations.h
new file mode 100755
index 00000000..f7be2882
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CABitOperations.h
@@ -0,0 +1,192 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _CABitOperations_h_
+#define _CABitOperations_h_
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ //#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
+ #include <CoreFoundation/CFBase.h>
+#else
+// #include <MacTypes.h>
+ #include "CFBase.h"
+#endif
+#include <TargetConditionals.h>
+
+// return whether a number is a power of two
+inline UInt32 IsPowerOfTwo(UInt32 x)
+{
+ return (x & (x-1)) == 0;
+}
+
+// count the leading zeroes in a word
+#ifdef __MWERKS__
+
+// Metrowerks Codewarrior. powerpc native count leading zeroes instruction:
+#define CountLeadingZeroes(x) ((int)__cntlzw((unsigned int)x))
+
+#elif TARGET_OS_WIN32
+
+static int CountLeadingZeroes( int arg )
+{
+ __asm{
+ bsr eax, arg
+ mov ecx, 63
+ cmovz eax, ecx
+ xor eax, 31
+ }
+ return arg;
+}
+
+#else
+
+static __inline__ int CountLeadingZeroes(int arg) {
+#if TARGET_CPU_PPC || TARGET_CPU_PPC64
+ __asm__ volatile("cntlzw %0, %1" : "=r" (arg) : "r" (arg));
+ return arg;
+#elif TARGET_CPU_X86 || TARGET_CPU_X86_64
+ __asm__ volatile(
+ "bsrl %0, %0\n\t"
+ "movl $63, %%ecx\n\t"
+ "cmove %%ecx, %0\n\t"
+ "xorl $31, %0"
+ : "=r" (arg)
+ : "0" (arg) : "%ecx"
+ );
+ return arg;
+#else
+ if (arg == 0) return 32;
+ return __builtin_clz(arg);
+#endif
+}
+
+#endif
+
+// 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);
+}
+
+// next power of two greater or equal to x
+inline UInt32 NextPowerOfTwo(UInt32 x)
+{
+ return 1L << Log2Ceil(x);
+}
+
+// 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;
+}
+
+// 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 1UL << 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/distrho/src/CoreAudio106/PublicUtility/CABool.h b/distrho/src/CoreAudio106/PublicUtility/CABool.h
new file mode 100755
index 00000000..04c8a2f4
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CABool.h
@@ -0,0 +1,82 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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;
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CABufferList.cpp b/distrho/src/CoreAudio106/PublicUtility/CABufferList.cpp
new file mode 100755
index 00000000..a7963490
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CABufferList.cpp
@@ -0,0 +1,252 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CABufferList.h"
+#include "CAByteOrder.h"
+
+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 + 15) & ~15) | 16;
+ 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 + 15) & ~15) | 16;
+ 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;
+ }
+
+}
+
+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;
+ strcpy(fmtstr, ", BEF");
+ } else {
+ wordSize = -10;
+ strcpy(fmtstr, ", LEF");
+ }
+ }
+ } else {
+ wordSize = fmt.SampleWordSize();
+ if (wordSize > 0) {
+#if CA_PREFER_FIXED_POINT
+ int fracbits = (asbd.mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
+ if (fracbits > 0)
+ sprintf(fmtstr, ", %d.%d-bit", (int)asbd.mBitsPerChannel - fracbits, fracbits);
+ else
+#endif
+ sprintf(fmtstr, ", %d-bit", (int)asbd.mBitsPerChannel);
+
+ if (!(fmt.mFormatFlags & kLinearPCMFormatFlagIsBigEndian)) {
+ wordSize = -wordSize;
+ strcat(fmtstr, " LEI");
+ } else {
+ strcat(fmtstr, " BEI");
+ }
+ }
+ }
+ }
+ 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)) {
+ sum += p[0];
+ sum += p[datasize / sizeof(int) - 1];
+ }
+ }
+ return anyNull | (sum & ~1);
+}
+
diff --git a/distrho/src/CoreAudio106/PublicUtility/CABufferList.h b/distrho/src/CoreAudio106/PublicUtility/CABufferList.h
new file mode 100755
index 00000000..0d3b88b8
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CABufferList.h
@@ -0,0 +1,298 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CABufferList_h__
+#define __CABufferList_h__
+
+#include <stddef.h>
+#include "CAStreamBasicDescription.h"
+#include "CAXException.h"
+
+void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, const AudioStreamBasicDescription &fmt, const char *label=NULL);
+void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label=NULL);
+extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize);
+extern "C" int CrashIfClientProvidedBogusAudioBufferList(const AudioBufferList *abl, bool nullOK=false);
+
+/* ____________________________________________________________________________
+// CABufferList - variable length buffer list
+
+ This class is designed for use in non-simplistic cases. For AudioUnits, AUBufferList
+ is preferred.
+
+ CABufferList can be used in one of two ways:
+ - as mutable pointers into non-owned memory
+ - as an immutable array of buffers (owns its own memory).
+
+ All buffers are assumed to have the same format (number of channels, word size), so that
+ we can assume their mDataByteSizes are all the same.
+____________________________________________________________________________ */
+class CABufferList {
+public:
+ void * operator new(size_t /*size*/, int nBuffers) {
+ return ::operator new(sizeof(CABufferList) + (nBuffers-1) * sizeof(AudioBuffer));
+ }
+ static CABufferList * New(const char *name, const CAStreamBasicDescription &format)
+ {
+ UInt32 numBuffers = format.NumberChannelStreams(), channelsPerBuffer = format.NumberInterleavedChannels();
+ return new(numBuffers) CABufferList(name, numBuffers, channelsPerBuffer);
+ }
+
+protected:
+ CABufferList(const char *name, UInt32 numBuffers, UInt32 channelsPerBuffer) :
+ mName(name),
+ mBufferMemory(NULL)
+ {
+ //XAssert(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 GetNumberBuffers() const { return mNumberBuffers; }
+
+ UInt32 GetNumBytes() const
+ {
+ return mBuffers[0].mDataByteSize;
+ }
+
+ void SetBytes(UInt32 nBytes, void *data)
+ {
+ VerifyNotTrashingOwnedBuffer();
+ XAssert(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) {
+ XAssert(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) {
+ 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 = 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.
+ XAssert(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/distrho/src/CoreAudio106/PublicUtility/CABundleLocker.cpp b/distrho/src/CoreAudio106/PublicUtility/CABundleLocker.cpp
new file mode 100755
index 00000000..43dabd0e
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CABundleLocker.cpp
@@ -0,0 +1,78 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CABundleLocker.h"
+#include <pthread.h>
+
+/*
+some bundle operations are not thread safe, notably CFCopyLocalizedStringFromTableInBundle
+*/
+
+static pthread_mutex_t sCABundleLocker = PTHREAD_MUTEX_INITIALIZER;
+
+#define RECURSIVE_LOCK 0
+
+#if RECURSIVE_LOCK
+static pthread_once_t sOnce = PTHREAD_ONCE_INIT;
+
+static void InitCABundleLocker()
+{
+ // have to do this because OS X lacks PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&sCABundleLocker, &attr);
+ pthread_mutexattr_destroy(&attr);
+}
+#endif
+
+CABundleLocker::CABundleLocker()
+{
+#if RECURSIVE_LOCK
+ pthread_once(&sOnce, InitCABundleLocker);
+#endif
+ pthread_mutex_lock(&sCABundleLocker);
+}
+
+CABundleLocker::~CABundleLocker()
+{
+ pthread_mutex_unlock(&sCABundleLocker);
+}
+
diff --git a/distrho/src/CoreAudio106/PublicUtility/CABundleLocker.h b/distrho/src/CoreAudio106/PublicUtility/CABundleLocker.h
new file mode 100755
index 00000000..0fb1a976
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CABundleLocker.h
@@ -0,0 +1,61 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _CABundleLocker_h_
+#define _CABundleLocker_h_
+
+/*
+some bundle operations are not thread safe, notably CFCopyLocalizedStringFromTableInBundle
+*/
+
+class CABundleLocker
+{
+public:
+
+#if TARGET_OS_MAC
+ CABundleLocker();
+ ~CABundleLocker();
+#else
+ CABundleLocker() {}
+ ~CABundleLocker() {}
+#endif
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAByteOrder.h b/distrho/src/CoreAudio106/PublicUtility/CAByteOrder.h
new file mode 100755
index 00000000..8b65f21e
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAByteOrder.h
@@ -0,0 +1,155 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CAByteOrder_h__)
+#define __CAByteOrder_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include "CoreFoundation.h"
+#endif
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+CF_INLINE Float32 CASwapFloat32 (Float32 arg) {
+ union {
+ Float32 f;
+ UInt32 i;
+ } flip;
+
+ flip.f = arg;
+ flip.i = CFSwapInt32 (flip.i);
+
+ return flip.f;
+}
+
+CF_INLINE Float64 CASwapFloat64 (Float64 arg) {
+ union {
+ Float64 f;
+ UInt64 i;
+ } flip;
+
+ flip.f = arg;
+ flip.i = CFSwapInt64 (flip.i);
+
+ return flip.f;
+}
+
+#pragma mark -Flippers
+
+CF_INLINE Float32 CASwapFloat32BigToHost(Float32 arg) {
+#if defined(__BIG_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat32(arg);
+#endif
+}
+
+CF_INLINE Float64 CASwapFloat64BigToHost(Float64 arg) {
+#if defined(__BIG_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat64(arg);
+#endif
+}
+
+CF_INLINE Float32 CASwapFloat32HostToBig(Float32 arg) {
+#if defined(__BIG_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat32(arg);
+#endif
+}
+
+CF_INLINE Float64 CASwapFloat64HostToBig(Float64 arg) {
+#if defined(__BIG_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat64(arg);
+#endif
+}
+
+CF_INLINE Float32 CASwapFloat32LittleToHost(Float32 arg) {
+#if defined(__LITTLE_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat32(arg);
+#endif
+}
+
+CF_INLINE Float64 CASwapFloat64LittleToHost(Float64 arg) {
+#if defined(__LITTLE_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat64(arg);
+#endif
+}
+
+CF_INLINE Float32 CASwapFloat32HostToLittle(Float32 arg) {
+#if defined(__LITTLE_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat32(arg);
+#endif
+}
+
+CF_INLINE Float64 CASwapFloat64HostToLittle(Float64 arg) {
+#if defined(__LITTLE_ENDIAN__)
+ return arg;
+#else
+ return CASwapFloat64(arg);
+#endif
+}
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif \ No newline at end of file
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFArray.cpp b/distrho/src/CoreAudio106/PublicUtility/CACFArray.cpp
new file mode 100755
index 00000000..b7b6820e
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFArray.cpp
@@ -0,0 +1,788 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+// Self Include
+#include "CACFArray.h"
+
+// PublicUtility Includes
+#include "CACFDictionary.h"
+#include "CACFNumber.h"
+#include "CACFString.h"
+
+//=============================================================================
+// CACFArray
+//=============================================================================
+
+bool CACFArray::HasItem(const void* inItem) const
+{
+ bool theAnswer = false;
+ if(mCFArray != NULL)
+ {
+ CFRange theRange = { 0, CFArrayGetCount(mCFArray)};
+ theAnswer = CFArrayContainsValue(mCFArray, theRange, inItem);
+ }
+ return theAnswer;
+}
+
+bool CACFArray::GetIndexOfItem(const void* inItem, UInt32& outIndex) const
+{
+ bool theAnswer = false;
+ outIndex = 0;
+ if(mCFArray != NULL)
+ {
+ CFRange theRange = { 0, CFArrayGetCount(mCFArray)};
+ CFIndex theIndex = CFArrayGetFirstIndexOfValue(mCFArray, theRange, inItem);
+ if(theIndex != -1)
+ {
+ theAnswer = true;
+ outIndex = ToUInt32(theIndex);
+ }
+ }
+ return theAnswer;
+}
+
+bool CACFArray::GetBool(UInt32 inIndex, bool& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inIndex, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFBooleanGetTypeID()))
+ {
+ outValue = CFBooleanGetValue(static_cast<CFBooleanRef>(theValue));
+ theAnswer = true;
+ }
+ else if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ SInt32 theNumericValue = 0;
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue);
+ outValue = theNumericValue != 0;
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetSInt32(UInt32 inIndex, SInt32& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt32Type, &outItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetUInt32(UInt32 inIndex, UInt32& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt32Type, &outItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetSInt64(UInt32 inIndex, SInt64& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt64Type, &outItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetUInt64(UInt32 inIndex, UInt64& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt64Type, &outItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetFloat32(UInt32 inIndex, Float32& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberFloat32Type, &outItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetFloat64(UInt32 inIndex, Float64& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberFloat64Type, &outItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetString(UInt32 inIndex, CFStringRef& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFStringGetTypeID()))
+ {
+ outItem = static_cast<CFStringRef>(theItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetArray(UInt32 inIndex, CFArrayRef& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFArrayGetTypeID()))
+ {
+ outItem = static_cast<CFArrayRef>(theItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetDictionary(UInt32 inIndex, CFDictionaryRef& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFDictionaryGetTypeID()))
+ {
+ outItem = static_cast<CFDictionaryRef>(theItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetData(UInt32 inIndex, CFDataRef& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFDataGetTypeID()))
+ {
+ outItem = static_cast<CFDataRef>(theItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetUUID(UInt32 inIndex, CFUUIDRef& outItem) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFUUIDGetTypeID()))
+ {
+ outItem = static_cast<CFUUIDRef>(theItem);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::GetCFType(UInt32 inIndex, CFTypeRef& outItem) const
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && (inIndex < GetNumberItems()))
+ {
+ outItem = CFArrayGetValueAtIndex(mCFArray, inIndex);
+ theAnswer = outItem != NULL;
+ }
+
+ return theAnswer;
+}
+
+void CACFArray::GetCACFString(UInt32 inIndex, CACFString& outItem) const
+{
+ outItem = static_cast<CFStringRef>(NULL);
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFStringGetTypeID()))
+ {
+ outItem = static_cast<CFStringRef>(theItem);
+ }
+ }
+}
+
+void CACFArray::GetCACFArray(UInt32 inIndex, CACFArray& outItem) const
+{
+ outItem = static_cast<CFArrayRef>(NULL);
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFArrayGetTypeID()))
+ {
+ outItem = static_cast<CFArrayRef>(theItem);
+ }
+ }
+}
+
+void CACFArray::GetCACFDictionary(UInt32 inIndex, CACFDictionary& outItem) const
+{
+ outItem = static_cast<CFDictionaryRef>(NULL);
+ CFTypeRef theItem = NULL;
+ if(GetCFType(inIndex, theItem))
+ {
+ if((theItem != NULL) && (CFGetTypeID(theItem) == CFDictionaryGetTypeID()))
+ {
+ outItem = static_cast<CFDictionaryRef>(theItem);
+ }
+ }
+}
+
+bool CACFArray::AppendBool(bool inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFBoolean theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = AppendCFType(theItem.GetCFBoolean());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::AppendSInt32(SInt32 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = AppendCFType(theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::AppendUInt32(UInt32 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = AppendCFType(theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::AppendSInt64(SInt64 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = AppendCFType(theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::AppendUInt64(UInt64 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = AppendCFType(theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::AppendFloat32(Float32 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = AppendCFType(theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::AppendFloat64(Float64 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = AppendCFType(theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::AppendString(const CFStringRef inItem)
+{
+ return AppendCFType(inItem);
+}
+
+bool CACFArray::AppendArray(const CFArrayRef inItem)
+{
+ return AppendCFType(inItem);
+}
+
+bool CACFArray::AppendDictionary(const CFDictionaryRef inItem)
+{
+ return AppendCFType(inItem);
+}
+
+bool CACFArray::AppendData(const CFDataRef inItem)
+{
+ return AppendCFType(inItem);
+}
+
+bool CACFArray::AppendCFType(const CFTypeRef inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CFArrayAppendValue(mCFArray, inItem);
+ theAnswer = true;
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertBool(UInt32 inIndex, bool inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFBoolean theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = InsertCFType(inIndex, theItem.GetCFBoolean());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertSInt32(UInt32 inIndex, SInt32 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertUInt32(UInt32 inIndex, UInt32 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertSInt64(UInt32 inIndex, SInt64 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertUInt64(UInt32 inIndex, UInt64 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertFloat32(UInt32 inIndex, Float32 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertFloat64(UInt32 inIndex, Float64 inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ CACFNumber theItem(inItem);
+ if(theItem.IsValid())
+ {
+ theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFArray::InsertString(UInt32 inIndex, const CFStringRef inItem)
+{
+ return InsertCFType(inIndex, inItem);
+}
+
+bool CACFArray::InsertArray(UInt32 inIndex, const CFArrayRef inItem)
+{
+ return InsertCFType(inIndex, inItem);
+}
+
+bool CACFArray::InsertDictionary(UInt32 inIndex, const CFDictionaryRef inItem)
+{
+ return InsertCFType(inIndex, inItem);
+}
+
+bool CACFArray::InsertData(UInt32 inIndex, const CFDataRef inItem)
+{
+ return InsertCFType(inIndex, inItem);
+}
+
+bool CACFArray::InsertCFType(UInt32 inIndex, const CFTypeRef inItem)
+{
+ bool theAnswer = false;
+
+ if((mCFArray != NULL) && mMutable)
+ {
+ if(inIndex < GetNumberItems())
+ {
+ CFArrayInsertValueAtIndex(mCFArray, 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, inIndex, inItem);
+ theAnswer = true;
+ }
+
+ return theAnswer;
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFArray.h b/distrho/src/CoreAudio106/PublicUtility/CACFArray.h
new file mode 100755
index 00000000..252b3e45
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFArray.h
@@ -0,0 +1,186 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CACFArray_h__)
+#define __CACFArray_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include <CoreAudioTypes.h>
+ #include <CoreFoundation.h>
+#endif
+
+#include "CADebugMacros.h"
+
+//=============================================================================
+// Types
+//=============================================================================
+
+class CACFDictionary;
+class CACFString;
+
+//=============================================================================
+// CACFArray
+//=============================================================================
+
+class CACFArray
+{
+
+// Construction/Destruction
+public:
+ CACFArray(bool inRelease = true) : mCFArray(CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)), mRelease(inRelease), mMutable(true) {}
+ CACFArray(UInt32 inMaxNumberItems, bool inRelease) : mCFArray(CFArrayCreateMutable(NULL, inMaxNumberItems, &kCFTypeArrayCallBacks)), mRelease(inRelease), mMutable(true) {}
+ CACFArray(CFArrayRef inCFArray, bool inRelease) : mCFArray(const_cast<CFMutableArrayRef>(inCFArray)), mRelease(inRelease), mMutable(false) {}
+ CACFArray(CFMutableArrayRef inCFArray, bool inRelease) : mCFArray(inCFArray), mRelease(inRelease), mMutable(true) {}
+ CACFArray(const CACFArray& inArray) : mCFArray(inArray.mCFArray), mRelease(inArray.mRelease), mMutable(inArray.mMutable) { Retain(); }
+ CACFArray& operator=(const CACFArray& inArray) { Release(); mCFArray = inArray.mCFArray; mRelease = inArray.mRelease; mMutable = inArray.mMutable; Retain(); return *this; }
+ CACFArray& operator=(CFArrayRef inCFArray) { Release(); mCFArray = const_cast<CFMutableArrayRef>(inCFArray); mMutable = false; Retain(); return *this; }
+ CACFArray& operator=(CFMutableArrayRef inCFArray) { Release(); mCFArray = inCFArray; mMutable = true; Retain(); return *this; }
+ ~CACFArray() { Release(); }
+
+private:
+ void Retain() { if(mRelease && (mCFArray != NULL)) { CFRetain(mCFArray); } }
+ void Release() { if(mRelease && (mCFArray != NULL)) { CFRelease(mCFArray); } }
+
+// Attributes
+public:
+ bool IsValid() const { return mCFArray != NULL; }
+ bool IsMutable() const { return mMutable; }
+ bool CanModify() const { return mMutable && (mCFArray != NULL); }
+
+ bool WillRelease() const { return mRelease; }
+ void ShouldRelease(bool inRelease) { mRelease = inRelease; }
+
+ CFTypeID GetTypeID() const { return CFGetTypeID(mCFArray); }
+
+ CFArrayRef GetCFArray() const { return mCFArray; }
+ CFArrayRef CopyCFArray() const { if(mCFArray != NULL) { CFRetain(mCFArray); } return mCFArray; }
+
+ CFMutableArrayRef GetCFMutableArray() const { return mCFArray; }
+ CFMutableArrayRef CopyCFMutableArray() const { if(mCFArray != NULL) { CFRetain(mCFArray); } return mCFArray; }
+ CFPropertyListRef AsPropertyList() const { return mCFArray; }
+
+ void SetCFMutableArrayFromCopy(CFArrayRef inArray, bool inRelease = true) { Release(); mCFArray = CFArrayCreateMutableCopy(NULL, 0, inArray); mMutable = true; mRelease = inRelease; }
+
+// Item Operations
+public:
+ UInt32 GetNumberItems() const { UInt32 theAnswer = 0; if(mCFArray != NULL) { theAnswer = ToUInt32(CFArrayGetCount(mCFArray)); } return theAnswer; }
+ bool HasItem(const void* inItem) const;
+ void RemoveItem(const void* inItem) { UInt32 theIndex; if(CanModify() && GetIndexOfItem(inItem, theIndex)) { RemoveItemAtIndex(theIndex); } }
+ bool GetIndexOfItem(const void* inItem, UInt32& outIndex) const;
+ void RemoveItemAtIndex(UInt32 inIndex) { if(CanModify()) { CFArrayRemoveValueAtIndex(mCFArray, 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 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;
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFData.h b/distrho/src/CoreAudio106/PublicUtility/CACFData.h
new file mode 100755
index 00000000..6178a869
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFData.h
@@ -0,0 +1,101 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CACFData_h__)
+#define __CACFData_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <CoreFoundation/CFData.h>
+#else
+ #include <CoreAudioTypes.h>
+ #include <CFData.h>
+#endif
+
+#include "CADebugMacros.h"
+
+//=============================================================================
+// CACFData
+//=============================================================================
+
+class CACFData
+{
+
+// Construction/Destruction
+public:
+ CACFData(CFDataRef inCFData, bool inWillRelease = true) : mCFData(inCFData), mWillRelease(inWillRelease) {}
+ CACFData(const void* inData, UInt32 inDataSize) : mCFData(NULL), mWillRelease(true) { mCFData = CFDataCreate(NULL, static_cast<const UInt8*>(inData), 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 = { inStartOffset, inDataSize }; CFDataGetBytes(mCFData, theRange, static_cast<UInt8*>(outData)); }
+
+ SInt32 GetSInt32() const { SInt32 theAnswer = 0; CopyData(0, &theAnswer, SizeOf32(SInt32)); return theAnswer; }
+ Float32 GetFloat32() const { Float32 theAnswer = 0; CopyData(0, &theAnswer, SizeOf32(Float32)); return theAnswer; }
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFDictionary.cpp b/distrho/src/CoreAudio106/PublicUtility/CACFDictionary.cpp
new file mode 100755
index 00000000..5f9406f9
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFDictionary.cpp
@@ -0,0 +1,561 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//=============================================================================
+// 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 ToUInt32(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<CFBooleanRef>(theValue));
+ theAnswer = true;
+ }
+ else if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ SInt32 theNumericValue = 0;
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue);
+ outValue = theNumericValue != 0;
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetSInt32(const CFStringRef inKey, SInt32& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetUInt32(const CFStringRef inKey, UInt32& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetSInt64(const CFStringRef inKey, SInt64& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetUInt64(const CFStringRef inKey, UInt64& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetFloat32(const CFStringRef inKey, Float32& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat32Type, &outValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetFloat64(const CFStringRef inKey, Float64& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat64Type, &outValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetFixed64(const CFStringRef inKey, Float64& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+ {
+ SInt64 theFixed64 = 0;
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &theFixed64);
+ outValue = static_cast<Float64>(theFixed64 >> 32);
+ outValue += static_cast<Float64>(theFixed64 & 0x00000000FFFFFFFFLL) / static_cast<Float64>(0x0000000100000000LL);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetString(const CFStringRef inKey, CFStringRef& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
+ {
+ outValue = static_cast<CFStringRef>(theValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetArray(const CFStringRef inKey, CFArrayRef& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFArrayGetTypeID()))
+ {
+ outValue = static_cast<CFArrayRef>(theValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetDictionary(const CFStringRef inKey, CFDictionaryRef& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFDictionaryGetTypeID()))
+ {
+ outValue = static_cast<CFDictionaryRef>(theValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetData(const CFStringRef inKey, CFDataRef& outValue) const
+{
+ bool theAnswer = false;
+
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFDataGetTypeID()))
+ {
+ outValue = static_cast<CFDataRef>(theValue);
+ theAnswer = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetCFType(const CFStringRef inKey, CFTypeRef& outValue) const
+{
+ bool theAnswer = false;
+
+ if(mCFDictionary != NULL)
+ {
+ outValue = CFDictionaryGetValue(mCFDictionary, inKey);
+ theAnswer = (outValue != NULL);
+ }
+
+ return theAnswer;
+}
+
+bool CACFDictionary::GetCFTypeWithCStringKey(const char* inKey, CFTypeRef& outValue) const
+{
+ bool theAnswer = false;
+
+ if(mCFDictionary != NULL)
+ {
+ CACFString theKey(inKey);
+ if(theKey.IsValid())
+ {
+ theAnswer = GetCFType(theKey.GetCFString(), outValue);
+ }
+ }
+
+ return theAnswer;
+}
+
+void CACFDictionary::GetCACFString(const CFStringRef inKey, CACFString& outValue) const
+{
+ outValue = static_cast<CFStringRef>(NULL);
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
+ {
+ outValue = static_cast<CFStringRef>(theValue);
+ }
+ }
+}
+
+void CACFDictionary::GetCACFArray(const CFStringRef inKey, CACFArray& outValue) const
+{
+ outValue = static_cast<CFArrayRef>(NULL);
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFArrayGetTypeID()))
+ {
+ outValue = static_cast<CFArrayRef>(theValue);
+ }
+ }
+}
+
+void CACFDictionary::GetCACFDictionary(const CFStringRef inKey, CACFDictionary& outValue) const
+{
+ outValue = static_cast<CFDictionaryRef>(NULL);
+ CFTypeRef theValue = NULL;
+ if(GetCFType(inKey, theValue))
+ {
+ if((theValue != NULL) && (CFGetTypeID(theValue) == CFDictionaryGetTypeID()))
+ {
+ outValue = static_cast<CFDictionaryRef>(theValue);
+ }
+ }
+}
+
+bool CACFDictionary::AddBool(const CFStringRef inKey, bool inValue)
+{
+ bool theAnswer = false;
+
+ if(mMutable && (mCFDictionary != NULL))
+ {
+ CACFBoolean theValue(inValue);
+ theAnswer = AddCFType(inKey, theValue.GetCFBoolean());
+ }
+
+ 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::AddURL(const CFStringRef inKey, const CFURLRef 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/distrho/src/CoreAudio106/PublicUtility/CACFDictionary.h b/distrho/src/CoreAudio106/PublicUtility/CACFDictionary.h
new file mode 100755
index 00000000..92aeabf6
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFDictionary.h
@@ -0,0 +1,162 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CACFDictionary_h__)
+#define __CACFDictionary_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include <CoreFoundation.h>
+#endif
+
+//=============================================================================
+// Types
+//=============================================================================
+
+class CACFArray;
+class CACFString;
+
+//=============================================================================
+// CACFDictionary
+//=============================================================================
+
+class CACFDictionary
+{
+
+// Construction/Destruction
+public:
+ CACFDictionary(bool inRelease = true) : mCFDictionary(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)), mRelease(inRelease), mMutable(true) {}
+ CACFDictionary(CFDictionaryRef inCFDictionary, bool inRelease) : mCFDictionary(const_cast<CFMutableDictionaryRef>(inCFDictionary)), mRelease(inRelease), mMutable(false) {}
+ CACFDictionary(CFMutableDictionaryRef inCFDictionary, bool inRelease) : mCFDictionary(inCFDictionary), mRelease(inRelease), mMutable(true) {}
+ CACFDictionary(const CACFDictionary& inDictionary) : mCFDictionary(inDictionary.mCFDictionary), mRelease(inDictionary.mRelease), mMutable(inDictionary.mMutable) { Retain(); }
+ CACFDictionary& operator=(const CACFDictionary& inDictionary) { Release(); mCFDictionary = inDictionary.mCFDictionary; mRelease = inDictionary.mRelease; mMutable = inDictionary.mMutable; Retain(); return *this; }
+ CACFDictionary& operator=(CFDictionaryRef inDictionary) { Release(); mCFDictionary = const_cast<CFMutableDictionaryRef>(inDictionary); mMutable = false; Retain(); return *this; }
+ CACFDictionary& operator=(CFMutableDictionaryRef inDictionary) { Release(); mCFDictionary = inDictionary; mMutable = true; Retain(); return *this; }
+ ~CACFDictionary() { Release(); }
+
+private:
+ void Retain() { if(mRelease && (mCFDictionary != NULL)) { CFRetain(mCFDictionary); } }
+ void Release() { if(mRelease && (mCFDictionary != NULL)) { CFRelease(mCFDictionary); } }
+
+// Attributes
+public:
+ bool IsValid() const { return mCFDictionary != NULL; }
+ bool IsMutable() const { return mMutable;}
+ bool CanModify() const { return mMutable && (mCFDictionary != NULL); }
+
+ bool WillRelease() const { return mRelease; }
+ void ShouldRelease(bool inRelease) { mRelease = inRelease; }
+
+ CFDictionaryRef GetDict() const { return mCFDictionary; }
+ CFDictionaryRef GetCFDictionary() const { return mCFDictionary; }
+ CFDictionaryRef CopyCFDictionary() const { if(mCFDictionary != NULL) { CFRetain(mCFDictionary); } return mCFDictionary; }
+
+ CFMutableDictionaryRef GetMutableDict() { return mCFDictionary; }
+ CFMutableDictionaryRef GetCFMutableDictionary() const { return mCFDictionary; }
+ CFMutableDictionaryRef CopyCFMutableDictionary() const { if(mCFDictionary != NULL) { CFRetain(mCFDictionary); } return mCFDictionary; }
+ void SetCFMutableDictionaryFromCopy(CFDictionaryRef inDictionary, bool inRelease = true) { Release(); mCFDictionary = CFDictionaryCreateMutableCopy(NULL, 0, inDictionary); mMutable = true; mRelease = inRelease; }
+ void SetCFMutableDictionaryToEmpty(bool inRelease = true) { Release(); mCFDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); mMutable = true; mRelease = inRelease; }
+
+ CFPropertyListRef AsPropertyList() const { return mCFDictionary; }
+ OSStatus GetDictIfMutable(CFMutableDictionaryRef& outDict) const { OSStatus theAnswer = -1; if(mMutable) { outDict = mCFDictionary; theAnswer = 0; } return theAnswer; }
+
+// Item Operations
+public:
+ bool HasKey(const CFStringRef inKey) const;
+ UInt32 Size() const;
+ void GetKeys(const void** keys) const;
+
+ 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 GetFixed64(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;
+
+ 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;
+};
+
+#endif //__CACFDictionary_h__
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFDistributedNotification.cpp b/distrho/src/CoreAudio106/PublicUtility/CACFDistributedNotification.cpp
new file mode 100755
index 00000000..7a6840a5
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFDistributedNotification.cpp
@@ -0,0 +1,100 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//==================================================================================================
+// 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
+ CFNotificationCenterRef theCenter = CFNotificationCenterGetDarwinNotifyCenter();
+ CFNotificationSuspensionBehavior theSuspensionBehavior = 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/distrho/src/CoreAudio106/PublicUtility/CACFDistributedNotification.h b/distrho/src/CoreAudio106/PublicUtility/CACFDistributedNotification.h
new file mode 100755
index 00000000..a3eabb3f
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFDistributedNotification.h
@@ -0,0 +1,67 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CACFDistributedNotification_h__)
+#define __CACFDistributedNotification_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// System Includes
+#include <CoreAudio/CoreAudioTypes.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+//==================================================================================================
+// CACFDistributedNotification
+//==================================================================================================
+
+class CACFDistributedNotification
+{
+
+// Operations
+public:
+ static void AddObserver(const void* inObserver, CFNotificationCallback inCallback, CFStringRef inName, CFNotificationSuspensionBehavior inSuspensionBehavior = CFNotificationSuspensionBehaviorCoalesce);
+ static void RemoveObserver(const void* inObserver, CFStringRef inName);
+ static void PostNotification(CFStringRef inName, CFDictionaryRef inUserInfo, bool inPostToAllSessions);
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFMachPort.cpp b/distrho/src/CoreAudio106/PublicUtility/CACFMachPort.cpp
new file mode 100755
index 00000000..3732af88
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFMachPort.cpp
@@ -0,0 +1,138 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//==================================================================================================
+// 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);
+ }
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFMachPort.h b/distrho/src/CoreAudio106/PublicUtility/CACFMachPort.h
new file mode 100755
index 00000000..00d9523c
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFMachPort.h
@@ -0,0 +1,83 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CACFMachPort_h__)
+#define __CACFMachPort_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+#include <CoreFoundation/CFMachPort.h>
+
+//==================================================================================================
+// CACFMachPort
+//
+// This class wraps a CFMachPort.
+//
+// Note that when you create a CFMachPort object, CF will attach the run loop source for the the
+// Mach Port that handles Port Death notifications (aka the Invalidation Callback) to the current
+// thread's run loop. This is something over which there is no control, so be sure to create the
+// CFMachPort on the thread on which you want to handle Port Death notificaitons on.
+//==================================================================================================
+
+class CACFMachPort
+{
+
+// Construction/Destruction
+public:
+ CACFMachPort(CFMachPortCallBack inCallBack, void* inUserData = NULL);
+ CACFMachPort(mach_port_t inMachPort, CFMachPortCallBack inCallBack, CFMachPortInvalidationCallBack inInvalidationCallBack, void* inUserData);
+ virtual ~CACFMachPort();
+
+// Attributes
+public:
+ CFMachPortRef GetMachPortRef() const { return mMachPort; }
+ mach_port_t GetMachPort() const { return CFMachPortGetPort(mMachPort); }
+ CFRunLoopSourceRef GetRunLoopSource() const { return mRunLoopSource; }
+
+// Implementation
+protected:
+ CFMachPortRef mMachPort;
+ CFRunLoopSourceRef mRunLoopSource;
+ bool mOwnsPort;
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFMessagePort.cpp b/distrho/src/CoreAudio106/PublicUtility/CACFMessagePort.cpp
new file mode 100755
index 00000000..0907658b
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFMessagePort.cpp
@@ -0,0 +1,129 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//=============================================================================
+// 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)
+{
+ // 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);
+ }
+
+ // get the run loop source
+ mRunLoopSource = CFMessagePortCreateRunLoopSource(NULL, mMessagePort, 0);
+ }
+}
+
+CACFLocalMessagePort::~CACFLocalMessagePort()
+{
+ if(mMessagePort != NULL)
+ {
+ CFMessagePortInvalidate(mMessagePort);
+ CFRelease(mMessagePort);
+ }
+
+ if(mRunLoopSource != NULL)
+ {
+ CFRelease(mRunLoopSource);
+ }
+}
+
+//=============================================================================
+// CACFRemoteMessagePort
+//=============================================================================
+
+CACFRemoteMessagePort::CACFRemoteMessagePort(CFStringRef inName, CFMessagePortInvalidationCallBack inInvalidationCallBack)
+:
+ mMessagePort(NULL),
+ mRunLoopSource(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);
+ }
+
+ // get the run loop source
+ mRunLoopSource = CFMessagePortCreateRunLoopSource(NULL, mMessagePort, 0);
+ }
+}
+
+CACFRemoteMessagePort::~CACFRemoteMessagePort()
+{
+ if(mMessagePort != NULL)
+ {
+ //CFMessagePortInvalidate(mMessagePort);
+ CFRelease(mMessagePort);
+ }
+
+ if(mRunLoopSource != NULL)
+ {
+ CFRelease(mRunLoopSource);
+ }
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFMessagePort.h b/distrho/src/CoreAudio106/PublicUtility/CACFMessagePort.h
new file mode 100755
index 00000000..808cca41
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFMessagePort.h
@@ -0,0 +1,109 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CACFMessagePort_h__)
+#define __CACFMessagePort_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CFMessagePort.h>
+#else
+ #include <CFMessagePort.h>
+#endif
+
+//=============================================================================
+// CACFLocalMessagePort
+//=============================================================================
+
+class CACFLocalMessagePort
+{
+
+// Construction/Destruction
+public:
+ CACFLocalMessagePort(CFStringRef inName, CFMessagePortCallBack inPortCallBack, CFMessagePortInvalidationCallBack inInvalidationCallBack, void* inUserData = NULL);
+ virtual ~CACFLocalMessagePort();
+
+// Attributes
+public:
+ bool IsValid() const { return mMessagePort != NULL; }
+ CFMessagePortRef GetMessagePortRef() const { return mMessagePort; }
+ CFRunLoopSourceRef GetRunLoopSource() const { return mRunLoopSource; }
+
+// Implementation
+protected:
+ CFMessagePortRef mMessagePort;
+ CFRunLoopSourceRef mRunLoopSource;
+
+};
+
+//=============================================================================
+// 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 { return mRunLoopSource; }
+
+// 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;
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFNumber.cpp b/distrho/src/CoreAudio106/PublicUtility/CACFNumber.cpp
new file mode 100755
index 00000000..f0ba17af
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFNumber.cpp
@@ -0,0 +1,77 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//=============================================================================
+// 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/distrho/src/CoreAudio106/PublicUtility/CACFNumber.h b/distrho/src/CoreAudio106/PublicUtility/CACFNumber.h
new file mode 100755
index 00000000..7c16f20b
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFNumber.h
@@ -0,0 +1,140 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CACFNumber_h__)
+#define __CACFNumber_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <CoreFoundation/CFNumber.h>
+#else
+ #include <CoreAudioTypes.h>
+ #include <CFNumber.h>
+#endif
+
+//=============================================================================
+// CACFBoolean
+//=============================================================================
+
+class CACFBoolean
+{
+// Construction/Destruction
+public:
+ CACFBoolean(CFBooleanRef inCFBoolean, bool inWillRelease = true) : mCFBoolean(inCFBoolean), mWillRelease(inWillRelease) {}
+ 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; }
+
+};
+
+//=============================================================================
+// 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; }
+ 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; }
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFObject.h b/distrho/src/CoreAudio106/PublicUtility/CACFObject.h
new file mode 100755
index 00000000..8ac07058
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFObject.h
@@ -0,0 +1,100 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CACFObject_h__)
+#define __CACFObject_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include <CoreAudioTypes.h>
+ #include <CoreFoundation.h>
+#endif
+
+//=============================================================================
+// CACFObject
+//=============================================================================
+
+template <class CFObjectType>
+class CACFObject
+{
+
+// Construction/Destruction
+public:
+ CACFObject() : mCFObject(NULL), mWillRelease(true) {}
+ CACFObject(CFObjectType inCFObject, bool inWillRelease = true) : 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; return *this; }
+
+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; }
+
+};
+
+typedef CACFObject<CFBundleRef> CACFBundle;
+typedef CACFObject<CFTypeRef> CACFType;
+typedef CACFObject<CFUUIDRef> CACFUUID;
+typedef CACFObject<CFURLRef> CACFURL;
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFPlugIn.h b/distrho/src/CoreAudio106/PublicUtility/CACFPlugIn.h
new file mode 100755
index 00000000..37d82e74
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFPlugIn.h
@@ -0,0 +1,95 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CACFPlugIn_h__)
+#define __CACFPlugIn_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// System Includes
+#include <CoreAudio/CoreAudioTypes.h>
+#include <CoreFoundation/CFPlugIn.h>
+
+//==================================================================================================
+// CACFPlugIn
+//==================================================================================================
+
+class CACFPlugIn
+{
+
+// Construction/Destruction
+public:
+ CACFPlugIn() : mCFPlugIn(NULL), mWillRelease(true) {}
+ CACFPlugIn(CFPlugInRef inCFPlugIn, bool inWillRelease = true) : mCFPlugIn(inCFPlugIn), mWillRelease(inWillRelease) {}
+ CACFPlugIn(CFURLRef inURL, bool inWillRelease = true) : mCFPlugIn(CFPlugInCreate(NULL, inURL)), mWillRelease(inWillRelease) {}
+ ~CACFPlugIn() { Release(); }
+ CACFPlugIn(const CACFPlugIn& inObject) : mCFPlugIn(inObject.mCFPlugIn), mWillRelease(inObject.mWillRelease) { Retain(); }
+ CACFPlugIn& operator=(const CACFPlugIn& inObject) { Release(); mCFPlugIn = inObject.mCFPlugIn; mWillRelease = inObject.mWillRelease; Retain(); return *this; }
+ CACFPlugIn& operator=(CFPlugInRef inCFPlugIn) { Release(); mCFPlugIn = inCFPlugIn; mWillRelease = true; return *this; }
+
+private:
+ void Retain() { if(mWillRelease && (mCFPlugIn != NULL)) { CFRetain(mCFPlugIn); } }
+ void Release() { if(mWillRelease && (mCFPlugIn != NULL)) { CFRelease(mCFPlugIn); mCFPlugIn = NULL; } }
+
+ CFPlugInRef mCFPlugIn;
+ bool mWillRelease;
+
+// Operations
+public:
+ void AllowRelease() { mWillRelease = true; }
+ void DontAllowRelease() { mWillRelease = false; }
+ bool IsValid() const { return mCFPlugIn != NULL; }
+
+ CFBundleRef GetBundle() const { CFBundleRef theAnswer = NULL; if(IsValid()) { theAnswer = CFPlugInGetBundle(mCFPlugIn); } return theAnswer; }
+ CFStringRef CopyBundleID() const { CFStringRef theAnswer = NULL; CFBundleRef theBundle = GetBundle(); if(IsValid() && (theBundle != NULL)) { theAnswer = CFBundleGetIdentifier(theBundle); if(theAnswer != NULL) { CFRetain(theAnswer); } } return theAnswer; }
+ UInt32 GetBundleVersion() const { UInt32 theAnswer = 0; CFBundleRef theBundle = GetBundle(); if(IsValid() && (theBundle != NULL)) { theAnswer = CFBundleGetVersionNumber(theBundle); } return theAnswer; }
+ CFDictionaryRef CopyBundleInfo() const { CFDictionaryRef theAnswer = NULL; CFBundleRef theBundle = GetBundle(); if(IsValid() && (theBundle != NULL)) { theAnswer = CFBundleGetInfoDictionary(theBundle); if(theAnswer != NULL) { CFRetain(theAnswer); } } return theAnswer; }
+ CFArrayRef FindFactoriesForType(CFUUIDRef inTypeUUID) const { CFArrayRef theAnswer = NULL; if(IsValid()) { theAnswer = CFPlugInFindFactoriesForPlugInTypeInPlugIn(inTypeUUID, mCFPlugIn); } return theAnswer; }
+
+// Value Access
+public:
+ CFPlugInRef GetCFPlugIn() const { return mCFPlugIn; }
+ CFPlugInRef CopyCFPlugIn() const { if(mCFPlugIn != NULL) { CFRetain(mCFPlugIn); } return mCFPlugIn; }
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFPreferences.cpp b/distrho/src/CoreAudio106/PublicUtility/CACFPreferences.cpp
new file mode 100755
index 00000000..41e87dce
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFPreferences.cpp
@@ -0,0 +1,281 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CACFPreferences.h"
+
+// PublicUtility Includes
+#include "CACFDistributedNotification.h"
+#include "CADebugMacros.h"
+
+//==================================================================================================
+// CACFPreferences
+//==================================================================================================
+
+CFPropertyListRef CACFPreferences::CopyValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost)
+{
+ // synchronize to make sure that what's in memory matches what's on disk
+ Synchronize(inCurrentUser, inCurrentHost, false);
+
+ CFPropertyListRef theAnswer = NULL;
+ CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
+ CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost;
+
+ theAnswer = CFPreferencesCopyValue(inKey, kCFPreferencesAnyApplication, theUser, theHost);
+
+ return theAnswer;
+}
+
+CFStringRef CACFPreferences::CopyStringValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost)
+{
+ CFStringRef theAnswer = NULL;
+
+ // get the raw value
+ CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost);
+
+ if(theRawValue != NULL)
+ {
+ // get it's type ID and make sure it's a CFString
+ CFTypeID theTypeID = CFGetTypeID(theRawValue);
+ if(theTypeID == CFStringGetTypeID())
+ {
+ // cast the value
+ theAnswer = static_cast<CFStringRef>(theRawValue);
+ }
+ else
+ {
+ CFRelease(theRawValue);
+ DebugMessage("CACFPreferences::CopyStringValue: not a CFString");
+ }
+ }
+
+ return theAnswer;
+}
+
+CFNumberRef CACFPreferences::CopyNumberValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost)
+{
+ CFNumberRef theAnswer = NULL;
+
+ // get the raw value
+ CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost);
+
+ if(theRawValue != NULL)
+ {
+ // get it's type ID and make sure it's a CFNumber
+ CFTypeID theTypeID = CFGetTypeID(theRawValue);
+ if(theTypeID == CFNumberGetTypeID())
+ {
+ // cast the value
+ theAnswer = static_cast<CFNumberRef>(theRawValue);
+ }
+ else
+ {
+ CFRelease(theRawValue);
+ DebugMessage("CACFPreferences::CopyNumberValue: not a CFNumber");
+ }
+ }
+
+ return theAnswer;
+}
+
+CFArrayRef CACFPreferences::CopyArrayValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost)
+{
+ CFArrayRef theAnswer = NULL;
+
+ // get the raw value
+ CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost);
+
+ if(theRawValue != NULL)
+ {
+ // get it's type ID and make sure it's a CFArray
+ CFTypeID theTypeID = CFGetTypeID(theRawValue);
+ if(theTypeID == CFArrayGetTypeID())
+ {
+ // cast the value
+ theAnswer = static_cast<CFArrayRef>(theRawValue);
+ }
+ else
+ {
+ CFRelease(theRawValue);
+ DebugMessage("CACFPreferences::CopyArrayValue: not a CFArray");
+ }
+ }
+
+ return theAnswer;
+}
+
+CFDictionaryRef CACFPreferences::CopyDictionaryValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost)
+{
+ CFDictionaryRef theAnswer = NULL;
+
+ // get the raw value
+ CFPropertyListRef theRawValue = CopyValue(inKey, inCurrentUser, inCurrentHost);
+
+ if(theRawValue != NULL)
+ {
+ // get it's type ID and make sure it's a CFDictionary
+ CFTypeID theTypeID = CFGetTypeID(theRawValue);
+ if(theTypeID == CFDictionaryGetTypeID())
+ {
+ // cast the value
+ theAnswer = static_cast<CFDictionaryRef>(theRawValue);
+ }
+ else
+ {
+ CFRelease(theRawValue);
+ DebugMessage("CACFPreferences::CopyDictionaryValue: not a CFDictionary");
+ }
+ }
+
+ return theAnswer;
+}
+
+void CACFPreferences::SetValue(CFStringRef inKey, CFPropertyListRef inValue, bool inCurrentUser, bool inCurrentHost, bool inSynchronize)
+{
+ CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
+ CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost;
+ CFPreferencesSetValue(inKey, inValue, kCFPreferencesAnyApplication, theUser, theHost);
+
+ if(inSynchronize)
+ {
+ Synchronize(inCurrentUser, inCurrentHost, true);
+ }
+}
+
+void CACFPreferences::DeleteValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost, bool inSynchronize)
+{
+ CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
+ CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost;
+ CFPreferencesSetValue(inKey, NULL, kCFPreferencesAnyApplication, theUser, theHost);
+
+ if(inSynchronize)
+ {
+ Synchronize(theUser, inCurrentHost, true);
+ }
+}
+
+void CACFPreferences::Synchronize(bool inCurrentUser, bool inCurrentHost, bool inForce)
+{
+ if(inForce || ArePrefsOutOfDate(inCurrentUser, inCurrentHost))
+ {
+ CFStringRef theUser = inCurrentUser ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
+ CFStringRef theHost = inCurrentHost ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost;
+ CFPreferencesSynchronize(kCFPreferencesAnyApplication, theUser, theHost);
+ MarkPrefsClean(inCurrentUser, inCurrentHost);
+ }
+}
+
+void CACFPreferences::MarkPrefsOutOfDate(bool inCurrentUser, bool inCurrentHost)
+{
+ if(!inCurrentUser && !inCurrentHost)
+ {
+ sAnyUserAnyHostPrefsOutOfDate = true;
+ }
+ else if(!inCurrentUser && inCurrentHost)
+ {
+ sAnyUserCurrentHostPrefsOutOfDate = true;
+ }
+ else if(inCurrentUser && !inCurrentHost)
+ {
+ sCurrentUserAnyHostPrefsOutOfDate = true;
+ }
+ else if(inCurrentUser && inCurrentHost)
+ {
+ sCurrentUserCurrentHostPrefsOutOfDate = true;
+ }
+}
+
+void CACFPreferences::MarkPrefsClean(bool inCurrentUser, bool inCurrentHost)
+{
+ if(!inCurrentUser && !inCurrentHost)
+ {
+ sAnyUserAnyHostPrefsOutOfDate = false;
+ }
+ else if(!inCurrentUser && inCurrentHost)
+ {
+ sAnyUserCurrentHostPrefsOutOfDate = false;
+ }
+ else if(inCurrentUser && !inCurrentHost)
+ {
+ sCurrentUserAnyHostPrefsOutOfDate = false;
+ }
+ else if(inCurrentUser && inCurrentHost)
+ {
+ sCurrentUserCurrentHostPrefsOutOfDate = false;
+ }
+}
+
+void CACFPreferences::SendNotification(CFStringRef inName)
+{
+ CACFDistributedNotification::PostNotification(inName, NULL, true);
+}
+
+bool CACFPreferences::ArePrefsOutOfDate(bool inCurrentUser, bool inCurrentHost)
+{
+ bool theAnswer = false;
+
+ if(!inCurrentUser && !inCurrentHost)
+ {
+ theAnswer = sAnyUserAnyHostPrefsOutOfDate;
+ }
+ else if(!inCurrentUser && inCurrentHost)
+ {
+ theAnswer = sAnyUserCurrentHostPrefsOutOfDate;
+ }
+ else if(inCurrentUser && !inCurrentHost)
+ {
+ theAnswer = sCurrentUserAnyHostPrefsOutOfDate;
+ }
+ else if(inCurrentUser && inCurrentHost)
+ {
+ theAnswer = sCurrentUserCurrentHostPrefsOutOfDate;
+ }
+
+ return theAnswer;
+}
+
+bool CACFPreferences::sAnyUserAnyHostPrefsOutOfDate = false;
+bool CACFPreferences::sAnyUserCurrentHostPrefsOutOfDate = false;
+bool CACFPreferences::sCurrentUserAnyHostPrefsOutOfDate = false;
+bool CACFPreferences::sCurrentUserCurrentHostPrefsOutOfDate = false;
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFPreferences.h b/distrho/src/CoreAudio106/PublicUtility/CACFPreferences.h
new file mode 100755
index 00000000..f4549bc2
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFPreferences.h
@@ -0,0 +1,86 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CACFPreferences_h__)
+#define __CACFPreferences_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include <CoreFoundation.h>
+#endif
+
+//==================================================================================================
+// CACFPreferences
+//==================================================================================================
+
+class CACFPreferences
+{
+
+// Operations
+public:
+ static CFPropertyListRef CopyValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost);
+ static CFStringRef CopyStringValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost);
+ static CFNumberRef CopyNumberValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost);
+ static CFArrayRef CopyArrayValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost);
+ static CFDictionaryRef CopyDictionaryValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost);
+ static void SetValue(CFStringRef inKey, CFPropertyListRef inValue, bool inCurrentUser, bool inCurrentHost, bool inSynchronize);
+ static void DeleteValue(CFStringRef inKey, bool inCurrentUser, bool inCurrentHost, bool inSynchronize);
+ static void Synchronize(bool inCurrentUser, bool inCurrentHost, bool inForce);
+ static void MarkPrefsOutOfDate(bool inCurrentUser, bool inCurrentHost);
+ static void MarkPrefsClean(bool inCurrentUser, bool inCurrentHost);
+ static void SendNotification(CFStringRef inName);
+
+private:
+ static bool ArePrefsOutOfDate(bool inCurrentUser, bool inCurrentHost);
+
+ static bool sAnyUserAnyHostPrefsOutOfDate;
+ static bool sAnyUserCurrentHostPrefsOutOfDate;
+ static bool sCurrentUserAnyHostPrefsOutOfDate;
+ static bool sCurrentUserCurrentHostPrefsOutOfDate;
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFString.cpp b/distrho/src/CoreAudio106/PublicUtility/CACFString.cpp
new file mode 100755
index 00000000..ce167012
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFString.cpp
@@ -0,0 +1,104 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//=============================================================================
+// 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, ioStringSize - 1, &theLength);
+ outString[theLength] = 0;
+ ioStringSize = ToUInt32(theLength) + 1;
+ }
+ else
+ {
+ outString[0] = 0;
+ ioStringSize = 1;
+ }
+ }
+}
+
+void CACFString::GetUnicodeString(CFStringRef inCFString, UInt16* outString, UInt32& ioStringSize)
+{
+ if(ioStringSize > 0)
+ {
+ if(inCFString != NULL)
+ {
+ CFRange theStringRange = { 0, CFStringGetLength(inCFString) };
+ if(static_cast<UInt32>(theStringRange.length) > ioStringSize)
+ {
+ theStringRange.length = ioStringSize;
+ }
+ CFStringGetCharacters(inCFString, theStringRange, outString);
+ ioStringSize = ToUInt32(theStringRange.length);
+ }
+ else
+ {
+ outString[0] = 0;
+ ioStringSize = 0;
+ }
+ }
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CACFString.h b/distrho/src/CoreAudio106/PublicUtility/CACFString.h
new file mode 100755
index 00000000..1523d696
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CACFString.h
@@ -0,0 +1,163 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CACFString_h__)
+#define __CACFString_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CADebugMacros.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <CoreFoundation/CFString.h>
+#else
+ #include <CoreAudioTypes.h>
+ #include <CFString.h>
+#endif
+
+//=============================================================================
+// CACFString
+//=============================================================================
+
+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 = 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 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)); }
+
+//=============================================================================
+// 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 = 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/distrho/src/CoreAudio106/PublicUtility/CAComponent.cpp b/distrho/src/CoreAudio106/PublicUtility/CAComponent.cpp
new file mode 100755
index 00000000..0a3574ac
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAComponent.cpp
@@ -0,0 +1,176 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CAComponent.h"
+#include "CAComponentDescription.h"
+#include "CACFDictionary.h"
+#include <stdlib.h>
+#include "CAAutoDisposer.h"
+
+CAComponent::CAComponent (const AudioComponentDescription& inDesc, CAComponent* next)
+ : mManuName(0), mAUName(0), mCompName(0)
+{
+ mComp = AudioComponentFindNext ((next ? next->Comp() : NULL), &inDesc);
+ if (mComp)
+ AudioComponentGetDescription(Comp(), &mDesc);
+ else
+ memcpy (&mDesc, &inDesc, sizeof(AudioComponentDescription));
+}
+
+CAComponent::CAComponent (const AudioComponent& comp)
+ : mComp (comp),
+ mManuName(0),
+ mAUName(0),
+ mCompName(0)
+{
+ AudioComponentGetDescription (Comp(), &mDesc);
+}
+
+CAComponent::CAComponent (const AudioComponentInstance& compInst)
+ : mComp (NULL),
+ mManuName(0),
+ mAUName(0),
+ mCompName(0)
+{
+ mComp = AudioComponentInstanceGetComponent (compInst);
+ AudioComponentGetDescription (Comp(), &mDesc);
+}
+
+CAComponent::CAComponent (OSType inType, OSType inSubtype, OSType inManu)
+ : mDesc (inType, inSubtype, inManu),
+ mManuName(0), mAUName(0), mCompName(0)
+{
+ mComp = AudioComponentFindNext (NULL, &mDesc);
+ AudioComponentGetDescription (Comp(), &mDesc);
+}
+
+CAComponent::~CAComponent ()
+{
+ Clear();
+}
+
+OSStatus CAComponent::GetVersion (UInt32 &outVersion) const
+{
+ return AudioComponentGetVersion (mComp, &outVersion);
+}
+
+void CAComponent::Clear ()
+{
+ if (mManuName) { CFRelease (mManuName); mManuName = 0; }
+ if (mAUName) { CFRelease (mAUName); mAUName = 0; }
+ if (mCompName) { CFRelease (mCompName); mCompName = 0; }
+}
+
+CAComponent& CAComponent::operator= (const CAComponent& y)
+{
+ Clear();
+
+ mComp = y.mComp;
+ mDesc = y.mDesc;
+
+ if (y.mManuName) { mManuName = y.mManuName; CFRetain (mManuName); }
+ if (y.mAUName) { mAUName = y.mAUName; CFRetain (mAUName); }
+ if (y.mCompName) { mCompName = y.mCompName; CFRetain (mCompName); }
+
+ return *this;
+}
+
+void CAComponent::SetCompNames () const
+{
+ if (!mCompName) {
+
+ CFStringRef compName;
+ OSStatus result = AudioComponentCopyName (Comp(), &compName);
+ if (result) return;
+
+ const_cast<CAComponent*>(this)->mCompName = compName;
+ if (compName)
+ {
+ CFArrayRef splitStrArray = CFStringCreateArrayBySeparatingStrings(NULL, compName, CFSTR(":"));
+
+ // we need to retain these values so the strings are not lost when the array is released
+ CFRetain(CFArrayGetValueAtIndex(splitStrArray, 0));
+ const_cast<CAComponent*>(this)->mManuName = (CFStringRef)CFArrayGetValueAtIndex(splitStrArray, 0);
+ if (CFArrayGetCount(splitStrArray) > 1)
+ {
+ CFStringRef str = (CFStringRef)CFArrayGetValueAtIndex(splitStrArray, 1);
+
+ CFMutableStringRef mstr = CFStringCreateMutableCopy (NULL, CFStringGetLength(str), str);
+
+ // this needs to trim out white space:
+
+ CFStringTrimWhitespace (mstr);
+
+ const_cast<CAComponent*>(this)->mAUName = mstr;
+ } else
+ const_cast<CAComponent*>(this)->mAUName = NULL;
+
+ CFRelease(splitStrArray);
+ }
+ }
+}
+
+static void _ShowCF (FILE* file, CFStringRef str)
+{
+ if (CFGetTypeID(str) != CFStringGetTypeID()) {
+ CFShow(str);
+ return;
+ }
+
+ UInt32 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/distrho/src/CoreAudio106/PublicUtility/CAComponent.h b/distrho/src/CoreAudio106/PublicUtility/CAComponent.h
new file mode 100755
index 00000000..c0ca63e4
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAComponent.h
@@ -0,0 +1,115 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAComponent_h__
+#define __CAComponent_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+#else
+ #include <ConditionalMacros.h>
+#endif
+
+#include "CAComponentDescription.h"
+
+class CAComponent
+{
+public:
+ CAComponent ()
+ : mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0) {}
+
+ // if next is specifed that is used to find the next component after that one
+ CAComponent (const AudioComponentDescription& inDesc, CAComponent* next = 0);
+
+ CAComponent (const CAComponent& y)
+ : mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0) { *this = y; }
+
+ CAComponent (const AudioComponent& comp);
+
+ CAComponent (const AudioComponentInstance& compInst);
+
+ CAComponent (OSType inType, OSType inSubtype = 0, OSType inManu = 0);
+
+ ~CAComponent ();
+
+ CAComponent& operator= (const CAComponent& y);
+
+ // returns true if this object references a valid component
+ bool IsValid () const { return Comp() != 0; }
+
+ bool HasAUStrings() const { SetCompNames (); return mManuName != 0; }
+
+ // CFStringRef should be retained by caller if needed beyond lifetime of this object
+
+ // Can return NULL if component doesn't follow AU naming conventions
+ CFStringRef GetAUManu () const { SetCompNames (); return mManuName; }
+ CFStringRef GetAUName () const { SetCompNames (); return mAUName ? mAUName : mCompName; }
+
+ // Return value of NULL indicates a problem getting that information from the component
+ CFStringRef GetCompName () const { SetCompNames(); return mCompName; }
+
+ const CAComponentDescription& Desc () const { return mDesc; }
+
+ OSStatus Open (AudioComponentInstance& outInst) const
+ {
+ return AudioComponentInstanceNew (Comp(), &outInst);
+ }
+
+ OSStatus GetVersion (UInt32 &outVersion) const;
+
+ const AudioComponent& Comp() const { return mComp; }
+
+ void Print(FILE* file = stdout) const;
+
+ OSStatus Save (CFPropertyListRef *outData) const;
+
+ OSStatus Restore (CFPropertyListRef &inData);
+
+private:
+ AudioComponent mComp;
+ CAComponentDescription mDesc;
+
+ CFStringRef mManuName, mAUName, mCompName;
+
+ void SetCompNames () const;
+ void SetCompInfo () const;
+ void Clear ();
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAComponentDescription.cpp b/distrho/src/CoreAudio106/PublicUtility/CAComponentDescription.cpp
new file mode 100755
index 00000000..24108d1b
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAComponentDescription.cpp
@@ -0,0 +1,104 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CAComponentDescription.h"
+#include "CAStreamBasicDescription.h"
+#include <ctype.h>
+
+void CAShowComponentDescription(const AudioComponentDescription *desc)
+{
+ CAComponentDescription::_CAShowComponentDescription (desc, stdout);
+}
+
+void CAComponentDescription::_CAShowComponentDescription(const AudioComponentDescription *desc, FILE* file)
+{
+ if (desc)
+ {
+ char str[24];
+ fprintf (file, "AudioComponentDescription: %s - ", CAStringForOSType(desc->componentType, str));
+ fprintf (file, "%s - ", CAStringForOSType(desc->componentSubType, str));
+ fprintf (file, "%s", CAStringForOSType(desc->componentManufacturer, 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/distrho/src/CoreAudio106/PublicUtility/CAComponentDescription.h b/distrho/src/CoreAudio106/PublicUtility/CAComponentDescription.h
new file mode 100755
index 00000000..7254dbe5
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAComponentDescription.h
@@ -0,0 +1,135 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAComponentDescription_h__
+#define __CAComponentDescription_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnit.h>
+#else
+ #include <ConditionalMacros.h>
+ #include <AudioUnit.h>
+#endif
+
+#include "CACFDictionary.h"
+#include <stdio.h>
+#include <string.h>
+
+void CAShowComponentDescription(const AudioComponentDescription *desc);
+
+// ____________________________________________________________________________
+//
+// CAComponentDescription
+class CAComponentDescription : public AudioComponentDescription {
+public:
+ CAComponentDescription() { memset (this, 0, sizeof (AudioComponentDescription)); }
+
+ CAComponentDescription (OSType inType, OSType inSubtype = 0, OSType inManu = 0);
+
+ CAComponentDescription(const AudioComponentDescription& desc) { memcpy (this, &desc, sizeof (AudioComponentDescription)); }
+
+ // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ //
+ // interrogation
+
+ bool IsAU () const;
+
+ bool IsAUFX() const { return componentType == kAudioUnitType_Effect; }
+ bool IsAUFM() const { return componentType == kAudioUnitType_MusicEffect; }
+
+ bool 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 AudioComponentCount(const_cast<CAComponentDescription*>(this)); }
+
+ // does a semantic match where "wild card" values for type, subtype, manu will match
+ bool Matches (const AudioComponentDescription &desc) const;
+
+ // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ //
+ // other
+
+ void Print(FILE* file = stdout) const { _CAShowComponentDescription (this, file); }
+
+ OSStatus Save (CFPropertyListRef *outData) const;
+ OSStatus Restore (CFPropertyListRef &inData);
+
+private:
+ static void _CAShowComponentDescription (const AudioComponentDescription *desc, FILE* file);
+ friend void CAShowComponentDescription (const AudioComponentDescription *desc);
+};
+
+inline bool operator< (const AudioComponentDescription& x, const AudioComponentDescription& y)
+{
+ return memcmp (&x, &y, offsetof (AudioComponentDescription, componentFlags)) < 0;
+}
+
+inline bool operator== (const AudioComponentDescription& x, const AudioComponentDescription& y)
+{
+ return !memcmp (&x, &y, offsetof (AudioComponentDescription, componentFlags));
+}
+
+inline bool operator!= (const AudioComponentDescription& x, const AudioComponentDescription& y)
+{
+ return !(x == y);
+}
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CADebugMacros.cpp b/distrho/src/CoreAudio106/PublicUtility/CADebugMacros.cpp
new file mode 100755
index 00000000..345cab8c
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CADebugMacros.cpp
@@ -0,0 +1,82 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CADebugMacros.h"
+#include <stdio.h>
+#include <stdarg.h>
+#if TARGET_API_MAC_OSX
+ #include <syslog.h>
+#endif
+
+#if DEBUG
+#include <stdio.h>
+
+void DebugPrint(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+}
+#endif // DEBUG
+
+#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/distrho/src/CoreAudio106/PublicUtility/CADebugMacros.h b/distrho/src/CoreAudio106/PublicUtility/CADebugMacros.h
new file mode 100755
index 00000000..8ce8af88
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CADebugMacros.h
@@ -0,0 +1,448 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CADebugMacros_h__)
+#define __CADebugMacros_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include "CoreAudioTypes.h"
+#endif
+
+//=============================================================================
+// CADebugMacros
+//=============================================================================
+
+//#define CoreAudio_StopOnFailure 1
+//#define CoreAudio_TimeStampMessages 1
+//#define CoreAudio_ThreadStampMessages 1
+//#define CoreAudio_FlushDebugMessages 1
+
+#if TARGET_RT_BIG_ENDIAN
+ #define CA4CCToCString(the4CC) { ((char*)&the4CC)[0], ((char*)&the4CC)[1], ((char*)&the4CC)[2], ((char*)&the4CC)[3], 0 }
+ #define CACopy4CCToCString(theCString, the4CC) { theCString[0] = ((char*)&the4CC)[0]; theCString[1] = ((char*)&the4CC)[1]; theCString[2] = ((char*)&the4CC)[2]; theCString[3] = ((char*)&the4CC)[3]; theCString[4] = 0; }
+#else
+ #define CA4CCToCString(the4CC) { ((char*)&the4CC)[3], ((char*)&the4CC)[2], ((char*)&the4CC)[1], ((char*)&the4CC)[0], 0 }
+ #define CACopy4CCToCString(theCString, the4CC) { theCString[0] = ((char*)&the4CC)[3]; theCString[1] = ((char*)&the4CC)[2]; theCString[2] = ((char*)&the4CC)[1]; theCString[3] = ((char*)&the4CC)[0]; theCString[4] = 0; }
+#endif
+
+// This is a macro that does a sizeof and casts the result to a UInt32. This is useful for all the
+// places where -wshorten64-32 catches assigning a sizeof expression to a UInt32.
+// For want of a better place to park this, we'll park it here.
+#define SizeOf32(X) ((UInt32)sizeof(X))
+
+// This is a macro that does a offsetof and casts the result to a UInt32. This is useful for all the
+// places where -wshorten64-32 catches assigning an offsetof expression to a UInt32.
+// For want of a better place to park this, we'll park it here.
+#define OffsetOf32(X, Y) ((UInt32)offsetof(X, Y))
+
+// This macro casts the expression to a UInt32. It is called out specially to allow us to track casts
+// that have been added purely to avert -wshorten64-32 warnings on 64 bit platforms.
+// For want of a better place to park this, we'll park it here.
+#define ToUInt32(X) ((UInt32)(X))
+
+#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 void DebugStr(const unsigned char* debuggerMsg);
+ #define DebugMessage(msg) DebugStr("\p"msg)
+ #define DebugMessageN1(msg, N1)
+ #define DebugMessageN2(msg, N1, N2)
+ #define DebugMessageN3(msg, N1, N2, N3)
+ #else
+ #include "CADebugPrintf.h"
+
+ #if (CoreAudio_FlushDebugMessages && !CoreAudio_UseSysLog) || defined(CoreAudio_UseSideFile)
+ #define FlushRtn ,fflush(DebugPrintfFile)
+ #else
+ #define FlushRtn
+ #endif
+
+ #if CoreAudio_ThreadStampMessages
+ #include <pthread.h>
+ #include "CAHostTimeBase.h"
+ #define DebugMessage(msg) DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: %s"DebugPrintfLineEnding, pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), msg) FlushRtn
+ #define DebugMessageN1(msg, N1) DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1) FlushRtn
+ #define DebugMessageN2(msg, N1, N2) DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2) FlushRtn
+ #define DebugMessageN3(msg, N1, N2, N3) DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3) FlushRtn
+ #define DebugMessageN4(msg, N1, N2, N3, N4) DebugPrintfRtn(DebugPrintfFileComma "%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(DebugPrintfFileComma "%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(DebugPrintfFileComma "%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(DebugPrintfFileComma "%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(DebugPrintfFileComma "%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(DebugPrintfFileComma "%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(DebugPrintfFileComma "%.4f: %s"DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), msg) FlushRtn
+ #define DebugMessageN1(msg, N1) DebugPrintfRtn(DebugPrintfFileComma "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1) FlushRtn
+ #define DebugMessageN2(msg, N1, N2) DebugPrintfRtn(DebugPrintfFileComma "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2) FlushRtn
+ #define DebugMessageN3(msg, N1, N2, N3) DebugPrintfRtn(DebugPrintfFileComma "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3) FlushRtn
+ #define DebugMessageN4(msg, N1, N2, N3, N4) DebugPrintfRtn(DebugPrintfFileComma "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4) FlushRtn
+ #define DebugMessageN5(msg, N1, N2, N3, N4, N5) DebugPrintfRtn(DebugPrintfFileComma "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5) FlushRtn
+ #define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) DebugPrintfRtn(DebugPrintfFileComma "%.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(DebugPrintfFileComma "%.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(DebugPrintfFileComma "%.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(DebugPrintfFileComma "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8, N9) FlushRtn
+ #else
+ #define DebugMessage(msg) DebugPrintfRtn(DebugPrintfFileComma "%s"DebugPrintfLineEnding, msg) FlushRtn
+ #define DebugMessageN1(msg, N1) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1) FlushRtn
+ #define DebugMessageN2(msg, N1, N2) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2) FlushRtn
+ #define DebugMessageN3(msg, N1, N2, N3) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2, N3) FlushRtn
+ #define DebugMessageN4(msg, N1, N2, N3, N4) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2, N3, N4) FlushRtn
+ #define DebugMessageN5(msg, N1, N2, N3, N4, N5) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2, N3, N4, N5) FlushRtn
+ #define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6) FlushRtn
+ #define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6, N7) FlushRtn
+ #define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6, N7, N8) FlushRtn
+ #define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6, N7, N8, N9) 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
+
+ #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)
+ #ifndef DEBUGPRINT
+ #define DEBUGPRINT(msg)
+ #endif
+ #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: %d (%s)", (int)__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, 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)", __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) \
+ { \
+ unsigned 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)) \
+ { \
+ 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, inAction, inHandler, inMessage) \
+ if((inKernelError) != 0) \
+ { \
+ STOP; \
+ { inAction; } \
+ goto inHandler; \
+ }
+
+#define FailIfError(inError, inAction, inHandler, 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) \
+ { \
+ unsigned 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/distrho/src/CoreAudio106/PublicUtility/CADebugPrintf.cpp b/distrho/src/CoreAudio106/PublicUtility/CADebugPrintf.cpp
new file mode 100755
index 00000000..3e77fac3
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CADebugPrintf.cpp
@@ -0,0 +1,83 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CADebugPrintf.h"
+
+#if DEBUG || CoreAudio_Debug
+
+ #if TARGET_OS_WIN32
+ #include <stdarg.h>
+ #include <stdio.h>
+ #include <Windows.h>
+ extern "C"
+ int CAWin32DebugPrintf(char* inFormat, ...)
+ {
+ char theMessage[1024];
+ va_list theArguments;
+ va_start(theArguments, inFormat);
+ _vsnprintf(theMessage, 1024, inFormat, theArguments);
+ va_end(theArguments);
+ OutputDebugString(theMessage);
+ return 0;
+ }
+ #endif
+
+ #if defined(CoreAudio_UseSideFile)
+ #include <unistd.h>
+ FILE* sDebugPrintfSideFile = NULL;
+ extern "C"
+ void OpenDebugPrintfSideFile()
+ {
+ if(sDebugPrintfSideFile == NULL)
+ {
+ char theFileName[1024];
+ snprintf(theFileName, sizeof(theFileName), CoreAudio_UseSideFile, getpid());
+ sDebugPrintfSideFile = fopen(theFileName, "a+");
+ DebugPrintfRtn(DebugPrintfFileComma "\n------------------------------\n");
+ }
+ }
+ #endif
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CADebugPrintf.h b/distrho/src/CoreAudio106/PublicUtility/CADebugPrintf.h
new file mode 100755
index 00000000..98d611f6
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CADebugPrintf.h
@@ -0,0 +1,107 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CADebugPrintf_h__)
+#define __CADebugPrintf_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include "CoreAudioTypes.h"
+#endif
+
+//=============================================================================
+// Macros to redirect debugging output to various logging services
+//=============================================================================
+
+//#define CoreAudio_UseSysLog 1
+//#define CoreAudio_UseSideFile "/CoreAudio-%d.txt"
+
+#if DEBUG || CoreAudio_Debug
+
+ #if TARGET_OS_WIN32
+ #if defined(__cplusplus)
+ extern "C"
+ #endif
+ extern int CAWin32DebugPrintf(char* inFormat, ...);
+ #define DebugPrintfRtn CAWin32DebugPrintf
+ #define DebugPrintfFile
+ #define DebugPrintfLineEnding "\n"
+ #define DebugPrintfFileComma
+ #else
+ #if CoreAudio_UseSysLog
+ #include <sys/syslog.h>
+ #define DebugPrintfRtn syslog
+ #define DebugPrintfFile LOG_NOTICE
+ #define DebugPrintfLineEnding ""
+ #define DebugPrintfFileComma DebugPrintfFile,
+ #elif defined(CoreAudio_UseSideFile)
+ #include <stdio.h>
+ #if defined(__cplusplus)
+ extern "C"
+ #endif
+ void OpenDebugPrintfSideFile();
+ extern FILE* sDebugPrintfSideFile;
+ #define DebugPrintfRtn fprintf
+ #define DebugPrintfFile ((sDebugPrintfSideFile != NULL) ? sDebugPrintfSideFile : stderr)
+ #define DebugPrintfLineEnding "\n"
+ #define DebugPrintfFileComma DebugPrintfFile,
+ #else
+ #include <stdio.h>
+ #define DebugPrintfRtn fprintf
+ #define DebugPrintfFile stderr
+ #define DebugPrintfLineEnding "\n"
+ #define DebugPrintfFileComma DebugPrintfFile,
+ #endif
+ #endif
+
+#else
+ #define DebugPrintfRtn
+ #define DebugPrintfFile
+ #define DebugPrintfLineEnding
+ #define DebugPrintfFileComma
+#endif
+
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CADebugger.cpp b/distrho/src/CoreAudio106/PublicUtility/CADebugger.cpp
new file mode 100755
index 00000000..7f4831e1
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CADebugger.cpp
@@ -0,0 +1,71 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CADebugger.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+// on X, use the Unix routine, otherwise use Debugger()
+#if TARGET_API_MAC_OSX
+ #include <signal.h>
+#endif
+
+//=============================================================================
+// CADebugger
+//=============================================================================
+
+void CADebuggerStop()
+{
+ #if CoreAudio_Debug
+ #if TARGET_API_MAC_OSX
+ raise(SIGINT);
+ #else
+ __debugbreak();
+ #endif
+ #endif
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CADebugger.h b/distrho/src/CoreAudio106/PublicUtility/CADebugger.h
new file mode 100755
index 00000000..42fcb270
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CADebugger.h
@@ -0,0 +1,50 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CADebugger_h__)
+#define __CADebugger_h__
+
+//=============================================================================
+// CADebugger
+//=============================================================================
+
+extern void CADebuggerStop();
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAException.h b/distrho/src/CoreAudio106/PublicUtility/CAException.h
new file mode 100755
index 00000000..e53fc7db
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAException.h
@@ -0,0 +1,77 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CAException_h__)
+#define __CAException_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include "CoreAudioTypes.h"
+#endif
+
+//=============================================================================
+// CAException
+//=============================================================================
+
+class CAException
+{
+
+public:
+ CAException(OSStatus inError) : mError(inError) {}
+ CAException(const CAException& inException) : mError(inException.mError) {}
+ CAException& operator=(const CAException& inException) { mError = inException.mError; return *this; }
+ ~CAException() {}
+
+ OSStatus GetError() const { return mError; }
+
+protected:
+ OSStatus mError;
+};
+
+#define CATry try{
+#define CACatch }catch(const CAException& inException) {} catch(...) {}
+#define CASwallowException(inExpression) try { inExpression; } catch(...) {}
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAFilePathUtils.cpp b/distrho/src/CoreAudio106/PublicUtility/CAFilePathUtils.cpp
new file mode 100755
index 00000000..0150a92d
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAFilePathUtils.cpp
@@ -0,0 +1,180 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CAFilePathUtils.h"
+#include <string.h>
+
+#if !CA_NO_CORE_SERVICES
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreServices/CoreServices.h> // FSRef
+#else
+ #include <CoreServices.h>
+#endif
+
+OSStatus PosixPathToParentFSRefAndName(const char *path, FSRef &outParentDir, CFStringRef &outFileName)
+{
+ // convert C string to CFString
+#if !TARGET_OS_WIN32
+ CFStringRef cfFullPath = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8);
+#else
+ CFStringRef cfFullPath = CFStringCreateWithCString(NULL, path, kCFStringEncodingWindowsLatin1);
+#endif
+ // convert CF string to URL
+ CFURLRef fullurl = CFURLCreateWithFileSystemPath(NULL, cfFullPath, TARGET_OS_WIN32 ? kCFURLWindowsPathStyle : kCFURLPOSIXPathStyle, false);
+ CFRelease(cfFullPath);
+ // get the directory portion of the URL
+ CFURLRef dirurl = CFURLCreateCopyDeletingLastPathComponent(NULL, fullurl);
+ // get the directory's FSSpec
+ OSStatus err = CFURLGetFSRef(dirurl, &outParentDir) ? OSStatus(noErr) : OSStatus(fnfErr);
+ 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
+ strcpy(sAnswer, inPath);
+
+ // 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
+ strcpy(sAnswer, inPath);
+
+ // 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/distrho/src/CoreAudio106/PublicUtility/CAFilePathUtils.h b/distrho/src/CoreAudio106/PublicUtility/CAFilePathUtils.h
new file mode 100755
index 00000000..d0bb3d52
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAFilePathUtils.h
@@ -0,0 +1,62 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAFilePathUtils_h__
+#define __CAFilePathUtils_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include <TargetConditionals.h>
+ #include <CoreFoundation.h>
+#endif
+
+struct FSRef;
+
+OSStatus PosixPathToParentFSRefAndName(const char *path, FSRef &outParentDir, CFStringRef &outFileName);
+
+#if !TARGET_OS_WIN32
+ #include <libgen.h>
+#else
+ char* dirname(const char* inPath);
+ char* basename(const char* inPath);
+#endif
+
+#endif // __CAFilePathUtils_h__
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAGuard.cpp b/distrho/src/CoreAudio106/PublicUtility/CAGuard.cpp
new file mode 100755
index 00000000..c4ebec84
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAGuard.cpp
@@ -0,0 +1,333 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CAGuard.h"
+
+#if TARGET_OS_MAC
+ #include <errno.h>
+#endif
+
+// PublicUtility Inludes
+#include "CADebugMacros.h"
+#include "CAException.h"
+#include "CAHostTimeBase.h"
+
+//==================================================================================================
+// Logging
+//==================================================================================================
+
+#if CoreAudio_Debug
+// #define Log_Ownership 1
+// #define Log_WaitOwnership 1
+// #define Log_TimedWaits 1
+// #define Log_Latency 1
+// #define Log_Errors 1
+#endif
+
+//#warning Need a try-based Locker too
+//==================================================================================================
+// CAGuard
+//==================================================================================================
+
+CAGuard::CAGuard(const char* inName)
+:
+ CAMutex(inName)
+#if Log_Average_Latency
+ ,mAverageLatencyAccumulator(0.0),
+ mAverageLatencyCount(0)
+#endif
+{
+#if TARGET_OS_MAC
+ OSStatus theError = pthread_cond_init(&mCondVar, NULL);
+ ThrowIf(theError != 0, CAException(theError), "CAGuard::CAGuard: Could not init the cond var");
+#elif TARGET_OS_WIN32
+ mEvent = CreateEvent(NULL, true, false, NULL);
+ ThrowIfNULL(mEvent, CAException(GetLastError()), "CAGuard::CAGuard: Could not create the event");
+#endif
+}
+
+CAGuard::~CAGuard()
+{
+#if TARGET_OS_MAC
+ pthread_cond_destroy(&mCondVar);
+#elif TARGET_OS_WIN32
+ if(mEvent != NULL)
+ {
+ CloseHandle(mEvent);
+ }
+#endif
+}
+
+void CAGuard::Wait()
+{
+#if TARGET_OS_MAC
+ ThrowIf(!pthread_equal(pthread_self(), mOwner), CAException(1), "CAGuard::Wait: A thread has to have locked a guard before it can wait");
+
+ mOwner = 0;
+
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::Wait: thread %p is waiting on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+
+ OSStatus theError = pthread_cond_wait(&mCondVar, &mMutex);
+ ThrowIf(theError != 0, CAException(theError), "CAGuard::Wait: Could not wait for a signal");
+ mOwner = pthread_self();
+
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::Wait: thread %p waited on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+#elif TARGET_OS_WIN32
+ ThrowIf(GetCurrentThreadId() != mOwner, CAException(1), "CAGuard::Wait: A thread has to have locked a guard before it can wait");
+
+ mOwner = 0;
+
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::Wait: thread %lu is waiting on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+
+ ReleaseMutex(mMutex);
+ HANDLE theHandles[] = { mMutex, mEvent };
+ OSStatus theError = WaitForMultipleObjects(2, theHandles, true, INFINITE);
+ ThrowIfError(theError, CAException(GetLastError()), "CAGuard::Wait: Could not wait for the signal");
+ mOwner = GetCurrentThreadId();
+ ResetEvent(mEvent);
+
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::Wait: thread %lu waited on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+#endif
+}
+
+bool CAGuard::WaitFor(UInt64 inNanos)
+{
+ bool theAnswer = false;
+
+#if TARGET_OS_MAC
+ ThrowIf(!pthread_equal(pthread_self(), mOwner), CAException(1), "CAGuard::WaitFor: A thread has to have locked a guard be for it can wait");
+
+ #if Log_TimedWaits
+ DebugMessageN1("CAGuard::WaitFor: waiting %.0f", (Float64)inNanos);
+ #endif
+
+ struct timespec theTimeSpec;
+ static const UInt64 kNanosPerSecond = 1000000000ULL;
+ if(inNanos >= kNanosPerSecond)
+ {
+ theTimeSpec.tv_sec = static_cast<UInt32>(inNanos / kNanosPerSecond);
+ theTimeSpec.tv_nsec = static_cast<UInt32>(inNanos % kNanosPerSecond);
+ }
+ else
+ {
+ theTimeSpec.tv_sec = 0;
+ theTimeSpec.tv_nsec = static_cast<UInt32>(inNanos);
+ }
+
+ #if Log_TimedWaits || Log_Latency || Log_Average_Latency
+ UInt64 theStartNanos = CAHostTimeBase::GetCurrentTimeInNanos();
+ #endif
+
+ mOwner = 0;
+
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::WaitFor: thread %p is waiting on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+
+ OSStatus theError = pthread_cond_timedwait_relative_np(&mCondVar, &mMutex, &theTimeSpec);
+ ThrowIf((theError != 0) && (theError != ETIMEDOUT), CAException(theError), "CAGuard::WaitFor: Wait got an error");
+ mOwner = pthread_self();
+
+ #if Log_TimedWaits || Log_Latency || Log_Average_Latency
+ UInt64 theEndNanos = CAHostTimeBase::GetCurrentTimeInNanos();
+ #endif
+
+ #if Log_TimedWaits
+ DebugMessageN1("CAGuard::WaitFor: waited %.0f", (Float64)(theEndNanos - theStartNanos));
+ #endif
+
+ #if Log_Latency
+ DebugMessageN1("CAGuard::WaitFor: latency %.0f", (Float64)((theEndNanos - theStartNanos) - inNanos));
+ #endif
+
+ #if Log_Average_Latency
+ ++mAverageLatencyCount;
+ mAverageLatencyAccumulator += (theEndNanos - theStartNanos) - inNanos;
+ if(mAverageLatencyCount >= 50)
+ {
+ DebugMessageN2("CAGuard::WaitFor: average latency %.3f ns over %ld waits", mAverageLatencyAccumulator / mAverageLatencyCount, mAverageLatencyCount);
+ mAverageLatencyCount = 0;
+ mAverageLatencyAccumulator = 0.0;
+ }
+ #endif
+
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAGuard::WaitFor: thread %p waited on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+
+ theAnswer = theError == ETIMEDOUT;
+#elif TARGET_OS_WIN32
+ ThrowIf(GetCurrentThreadId() != mOwner, CAException(1), "CAGuard::WaitFor: A thread has to have locked a guard be for it can wait");
+
+ #if Log_TimedWaits
+ DebugMessageN1("CAGuard::WaitFor: waiting %.0f", (Float64)inNanos);
+ #endif
+
+ // the time out is specified in milliseconds(!)
+ UInt32 theWaitTime = static_cast<UInt32>(inNanos / 1000000ULL);
+
+ #if Log_TimedWaits || Log_Latency || Log_Average_Latency
+ UInt64 theStartNanos = CAHostTimeBase::GetCurrentTimeInNanos();
+ #endif
+
+ mOwner = 0;
+
+ #if Log_WaitOwnership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAGuard::WaitFor: thread %lu is waiting on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+
+ ReleaseMutex(mMutex);
+ HANDLE theHandles[] = { mMutex, mEvent };
+ OSStatus theError = WaitForMultipleObjects(2, theHandles, true, theWaitTime);
+ ThrowIf((theError != WAIT_OBJECT_0) && (theError != WAIT_TIMEOUT), CAException(GetLastError()), "CAGuard::WaitFor: Wait got an error");
+ mOwner = GetCurrentThreadId();
+ ResetEvent(mEvent);
+
+ #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/distrho/src/CoreAudio106/PublicUtility/CAGuard.h b/distrho/src/CoreAudio106/PublicUtility/CAGuard.h
new file mode 100755
index 00000000..c9e384cb
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAGuard.h
@@ -0,0 +1,127 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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/distrho/src/CoreAudio106/PublicUtility/CAHALAudioDevice.cpp b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioDevice.cpp
new file mode 100755
index 00000000..13e2be67
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioDevice.cpp
@@ -0,0 +1,1151 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CAHALAudioDevice.h"
+
+// PublicUtility Includes
+#include "CAAutoDisposer.h"
+#include "CADebugMacros.h"
+#include "CAException.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 = OffsetOf32(AudioChannelLayout, mChannelDescriptions) + 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 = OffsetOf32(AudioChannelLayout, mChannelDescriptions) + 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 /= sizeof(AudioObjectID);
+ }
+ return theAnswer;
+}
+
+void CAHALAudioDevice::GetRelatedAudioDevices(UInt32& ioNumberRelatedDevices, AudioObjectID* outRelatedDevices) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyRelatedDevices);
+ if(HasProperty(theAddress))
+ {
+ UInt32 theSize = ioNumberRelatedDevices * sizeof(AudioObjectID);
+ GetPropertyData(theAddress, 0, NULL, theSize, outRelatedDevices);
+ ioNumberRelatedDevices = theSize / sizeof(AudioObjectID);
+ }
+ else
+ {
+ UInt32 theSize = ioNumberRelatedDevices * sizeof(AudioObjectID);
+ memset(outRelatedDevices, 0, theSize);
+ ioNumberRelatedDevices = 0;
+ }
+}
+
+AudioObjectID CAHALAudioDevice::GetRelatedAudioDeviceByIndex(UInt32 inIndex) const
+{
+ AudioObjectID theAnswer = kAudioObjectUnknown;
+ UInt32 theNumberRelatedDevices = GetNumberRelatedAudioDevices();
+ if((theNumberRelatedDevices > 0) && (inIndex < theNumberRelatedDevices))
+ {
+ CAAutoArrayDelete<AudioObjectID> theRelatedDeviceList(theNumberRelatedDevices);
+ GetRelatedAudioDevices(theNumberRelatedDevices, theRelatedDeviceList);
+ if((theNumberRelatedDevices > 0) && (inIndex < theNumberRelatedDevices))
+ {
+ theAnswer = theRelatedDeviceList[inIndex];
+ }
+ }
+ return theAnswer;
+}
+
+UInt32 CAHALAudioDevice::GetNumberStreams(bool inIsInput) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyStreams, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ UInt32 theAnswer = GetPropertyDataSize(theAddress, 0, NULL);
+ theAnswer /= sizeof(AudioObjectID);
+ return theAnswer;
+}
+
+void CAHALAudioDevice::GetStreams(bool inIsInput, UInt32& ioNumberStreams, AudioObjectID* outStreamList) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyStreams, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ UInt32 theSize = ioNumberStreams * sizeof(AudioObjectID);
+ GetPropertyData(theAddress, 0, NULL, theSize, outStreamList);
+ ioNumberStreams = theSize / sizeof(AudioObjectID);
+}
+
+AudioObjectID CAHALAudioDevice::GetStreamByIndex(bool inIsInput, UInt32 inIndex) const
+{
+ AudioObjectID theAnswer = kAudioObjectUnknown;
+ UInt32 theNumberStreams = GetNumberStreams(inIsInput);
+ if((theNumberStreams > 0) && (inIndex < theNumberStreams))
+ {
+ CAAutoArrayDelete<AudioObjectID> theStreamList(theNumberStreams);
+ GetStreams(inIsInput, theNumberStreams, theStreamList);
+ if((theNumberStreams > 0) && (inIndex < theNumberStreams))
+ {
+ theAnswer = theStreamList[inIndex];
+ }
+ }
+ return theAnswer;
+}
+
+UInt32 CAHALAudioDevice::GetTotalNumberChannels(bool inIsInput) const
+{
+ UInt32 theAnswer = 0;
+ CAPropertyAddress theAddress(kAudioDevicePropertyStreamConfiguration, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL);
+ CAAutoFree<AudioBufferList> theBufferList(theSize);
+ GetPropertyData(theAddress, 0, NULL, theSize, theBufferList);
+ for(UInt32 theIndex = 0; theIndex < theBufferList->mNumberBuffers; ++theIndex)
+ {
+ theAnswer += theBufferList->mBuffers[theIndex].mNumberChannels;
+ }
+ return theAnswer;
+}
+
+void CAHALAudioDevice::GetCurrentVirtualFormats(bool inIsInput, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const
+{
+ ioNumberStreams = std::min(ioNumberStreams, GetNumberStreams(inIsInput));
+ for(UInt32 theIndex = 0; theIndex < ioNumberStreams; ++theIndex)
+ {
+ CAHALAudioStream theStream(GetStreamByIndex(inIsInput, theIndex));
+ theStream.GetCurrentVirtualFormat(outFormats[theIndex]);
+ }
+}
+
+void CAHALAudioDevice::GetCurrentPhysicalFormats(bool inIsInput, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const
+{
+ ioNumberStreams = std::min(ioNumberStreams, GetNumberStreams(inIsInput));
+ for(UInt32 theIndex = 0; theIndex < ioNumberStreams; ++theIndex)
+ {
+ CAHALAudioStream theStream(GetStreamByIndex(inIsInput, theIndex));
+ theStream.GetCurrentPhysicalFormat(outFormats[theIndex]);
+ }
+}
+
+bool CAHALAudioDevice::IsRunning() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDeviceIsRunning);
+ UInt32 theAnswer = GetPropertyData_UInt32(theAddress, 0, NULL);
+ return theAnswer != 0;
+}
+
+bool CAHALAudioDevice::IsRunningSomewhere() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDeviceIsRunningSomewhere);
+ UInt32 theAnswer = 0;
+ if(HasProperty(theAddress))
+ {
+ theAnswer = GetPropertyData_UInt32(theAddress, 0, NULL);
+ }
+ return theAnswer != 0;
+}
+
+UInt32 CAHALAudioDevice::GetLatency(bool inIsInput) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyLatency, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+UInt32 CAHALAudioDevice::GetSafetyOffset(bool inIsInput) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySafetyOffset, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+bool CAHALAudioDevice::HasClockDomain() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockDomain);
+ return HasProperty(theAddress);
+}
+
+UInt32 CAHALAudioDevice::GetClockDomain() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockDomain);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+Float64 CAHALAudioDevice::GetActualSampleRate() const
+{
+ Float64 theAnswer = 0;
+ CAPropertyAddress theAddress(kAudioDevicePropertyActualSampleRate);
+ if(HasProperty(theAddress))
+ {
+ UInt32 theSize = sizeof(Float64);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ }
+ else
+ {
+ theAnswer = GetNominalSampleRate();
+ }
+ return theAnswer;
+}
+
+Float64 CAHALAudioDevice::GetNominalSampleRate() const
+{
+ Float64 theAnswer = 0;
+ CAPropertyAddress theAddress(kAudioDevicePropertyNominalSampleRate);
+ UInt32 theSize = sizeof(Float64);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ return theAnswer;
+}
+
+void CAHALAudioDevice::SetNominalSampleRate(Float64 inSampleRate)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyNominalSampleRate);
+ SetPropertyData(theAddress, 0, NULL, sizeof(Float64), &inSampleRate);
+}
+
+UInt32 CAHALAudioDevice::GetNumberAvailableNominalSampleRateRanges() const
+{
+ UInt32 theAnswer = 0;
+ CAPropertyAddress theAddress(kAudioDevicePropertyAvailableNominalSampleRates);
+ if(HasProperty(theAddress))
+ {
+ UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL);
+ theAnswer = theSize / sizeof(AudioValueRange);
+ }
+ return theAnswer;
+}
+
+void CAHALAudioDevice::GetAvailableNominalSampleRateRanges(UInt32& ioNumberRanges, AudioValueRange* outRanges) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyAvailableNominalSampleRates);
+ if(HasProperty(theAddress))
+ {
+ UInt32 theSize = ioNumberRanges * sizeof(AudioValueRange);
+ GetPropertyData(theAddress, 0, NULL, theSize, outRanges);
+ ioNumberRanges = theSize / sizeof(AudioValueRange);
+ }
+ else
+ {
+ ioNumberRanges = 0;
+ }
+}
+
+void CAHALAudioDevice::GetAvailableNominalSampleRateRangeByIndex(UInt32 inIndex, Float64& outMinimum, Float64& outMaximum) const
+{
+ UInt32 theNumberRanges = GetNumberAvailableNominalSampleRateRanges();
+ ThrowIf(inIndex >= theNumberRanges, CAException(kAudioHardwareIllegalOperationError), "CAHALAudioDevice::GetAvailableNominalSampleRateRangeByIndex: index out of range");
+ CAAutoArrayDelete<AudioValueRange> theRanges(theNumberRanges);
+ GetAvailableNominalSampleRateRanges(theNumberRanges, theRanges);
+ outMinimum = theRanges[inIndex].mMinimum;
+ outMaximum = theRanges[inIndex].mMaximum;
+}
+
+bool CAHALAudioDevice::IsValidNominalSampleRate(Float64 inSampleRate) const
+{
+ bool theAnswer = false;
+ UInt32 theNumberRanges = GetNumberAvailableNominalSampleRateRanges();
+ CAAutoArrayDelete<AudioValueRange> theRanges(theNumberRanges);
+ GetAvailableNominalSampleRateRanges(theNumberRanges, theRanges);
+ for(UInt32 theIndex = 0; !theAnswer && (theIndex < theNumberRanges); ++theIndex)
+ {
+ theAnswer = (inSampleRate >= theRanges[theIndex].mMinimum) && (inSampleRate <= theRanges[theIndex].mMinimum);
+ }
+ return theAnswer;
+}
+
+bool CAHALAudioDevice::IsIOBufferSizeSettable() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSize);
+ return IsPropertySettable(theAddress);
+}
+
+UInt32 CAHALAudioDevice::GetIOBufferSize() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSize);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+void CAHALAudioDevice::SetIOBufferSize(UInt32 inBufferSize)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSize);
+ SetPropertyData(theAddress, 0, NULL, sizeof(UInt32), &inBufferSize);
+}
+
+bool CAHALAudioDevice::UsesVariableIOBufferSizes() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyUsesVariableBufferFrameSizes);
+ return HasProperty(theAddress);
+}
+
+UInt32 CAHALAudioDevice::GetMaximumVariableIOBufferSize() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyUsesVariableBufferFrameSizes);
+ return GetPropertyData_UInt32(theAddress, 0, NULL);
+}
+
+bool CAHALAudioDevice::HasIOBufferSizeRange() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSizeRange);
+ return HasProperty(theAddress);
+}
+
+void CAHALAudioDevice::GetIOBufferSizeRange(UInt32& outMinimum, UInt32& outMaximum) const
+{
+ AudioValueRange theAnswer = { 0, 0 };
+ CAPropertyAddress theAddress(kAudioDevicePropertyBufferFrameSizeRange);
+ UInt32 theSize = sizeof(AudioValueRange);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ outMinimum = static_cast<UInt32>(theAnswer.mMinimum);
+ outMaximum = static_cast<UInt32>(theAnswer.mMaximum);
+}
+
+AudioDeviceIOProcID CAHALAudioDevice::CreateIOProcID(AudioDeviceIOProc inIOProc, void* inClientData)
+{
+ AudioDeviceIOProcID theAnswer = NULL;
+ OSStatus theError = AudioDeviceCreateIOProcID(mObjectID, inIOProc, inClientData, &theAnswer);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::CreateIOProcID: got an error creating the IOProc ID");
+ return theAnswer;
+}
+
+void CAHALAudioDevice::DestroyIOProcID(AudioDeviceIOProcID inIOProcID)
+{
+ OSStatus theError = AudioDeviceDestroyIOProcID(mObjectID, inIOProcID);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::DestroyIOProcID: got an error destroying the IOProc ID");
+}
+
+void CAHALAudioDevice::StartIOProc(AudioDeviceIOProcID inIOProcID)
+{
+ OSStatus theError = AudioDeviceStart(mObjectID, inIOProcID);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::StartIOProc: got an error starting an IOProc");
+}
+
+void CAHALAudioDevice::StartIOProcAtTime(AudioDeviceIOProcID inIOProcID, AudioTimeStamp& ioStartTime, bool inIsInput, bool inIgnoreHardware)
+{
+ UInt32 theFlags = 0;
+ if(inIsInput)
+ {
+ theFlags |= kAudioDeviceStartTimeIsInputFlag;
+ }
+ if(inIgnoreHardware)
+ {
+ theFlags |= kAudioDeviceStartTimeDontConsultDeviceFlag;
+ }
+
+ OSStatus theError = AudioDeviceStartAtTime(mObjectID, inIOProcID, &ioStartTime, theFlags);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::StartIOProcAtTime: got an error starting an IOProc");
+}
+
+void CAHALAudioDevice::StopIOProc(AudioDeviceIOProcID inIOProcID)
+{
+ OSStatus theError = AudioDeviceStop(mObjectID, inIOProcID);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::StopIOProc: got an error stopping an IOProc");
+}
+
+void CAHALAudioDevice::GetIOProcStreamUsage(AudioDeviceIOProcID inIOProcID, bool inIsInput, bool* outStreamUsage) const
+{
+ // make an AudioHardwareIOProcStreamUsage the right size
+ UInt32 theNumberStreams = GetNumberStreams(inIsInput);
+ UInt32 theSize = sizeof(void*) + sizeof(UInt32) + (theNumberStreams * sizeof(UInt32));
+ CAAutoFree<AudioHardwareIOProcStreamUsage> theStreamUsage(theSize);
+
+ // set it up
+ theStreamUsage->mIOProc = reinterpret_cast<void*>(inIOProcID);
+ theStreamUsage->mNumberStreams = theNumberStreams;
+
+ // get the property
+ CAPropertyAddress theAddress(kAudioDevicePropertyIOProcStreamUsage, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ GetPropertyData(theAddress, 0, NULL, theSize, theStreamUsage);
+
+ // fill out the return value
+ for(UInt32 theIndex = 0; theIndex < theNumberStreams; ++theIndex)
+ {
+ outStreamUsage[theIndex] = (theStreamUsage->mStreamIsOn[theIndex] != 0);
+ }
+}
+
+void CAHALAudioDevice::SetIOProcStreamUsage(AudioDeviceIOProcID inIOProcID, bool inIsInput, const bool* inStreamUsage)
+{
+ // make an AudioHardwareIOProcStreamUsage the right size
+ UInt32 theNumberStreams = GetNumberStreams(inIsInput);
+ UInt32 theSize = sizeof(void*) + sizeof(UInt32) + (theNumberStreams * sizeof(UInt32));
+ CAAutoFree<AudioHardwareIOProcStreamUsage> theStreamUsage(theSize);
+
+ // set it up
+ theStreamUsage->mIOProc = reinterpret_cast<void*>(inIOProcID);
+ theStreamUsage->mNumberStreams = theNumberStreams;
+ for(UInt32 theIndex = 0; theIndex < theNumberStreams; ++theIndex)
+ {
+ theStreamUsage->mStreamIsOn[theIndex] = (inStreamUsage[theIndex] ? 1 : 0);
+ }
+
+ // set the property
+ CAPropertyAddress theAddress(kAudioDevicePropertyIOProcStreamUsage, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
+ SetPropertyData(theAddress, 0, NULL, theSize, theStreamUsage);
+}
+
+Float32 CAHALAudioDevice::GetIOCycleUsage() const
+{
+ Float32 theAnswer = 0;
+ CAPropertyAddress theAddress(kAudioDevicePropertyIOCycleUsage);
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ return theAnswer;
+}
+
+void CAHALAudioDevice::SetIOCycleUsage(Float32 inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyIOCycleUsage);
+ SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue);
+}
+
+void CAHALAudioDevice::GetCurrentTime(AudioTimeStamp& outTime)
+{
+ OSStatus theError = AudioDeviceGetCurrentTime(mObjectID, &outTime);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::GetCurrentTime: got an error getting the current time");
+}
+
+void CAHALAudioDevice::TranslateTime(const AudioTimeStamp& inTime, AudioTimeStamp& outTime)
+{
+ OSStatus theError = AudioDeviceTranslateTime(mObjectID, &inTime, &outTime);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::TranslateTime: got an error translating time");
+}
+
+void CAHALAudioDevice::GetNearestStartTime(AudioTimeStamp& ioTime, bool inIsInput, bool inIgnoreHardware)
+{
+ UInt32 theFlags = 0;
+ if(inIsInput)
+ {
+ theFlags |= kAudioDeviceStartTimeIsInputFlag;
+ }
+ if(inIgnoreHardware)
+ {
+ theFlags |= kAudioDeviceStartTimeDontConsultDeviceFlag;
+ }
+
+ OSStatus theError = AudioDeviceGetNearestStartTime(mObjectID, &ioTime, theFlags);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioDevice::GetNearestStartTime: got an error getting the start time");
+}
+
+bool CAHALAudioDevice::HasVolumeControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::VolumeControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel);
+ return IsPropertySettable(theAddress);
+}
+
+Float32 CAHALAudioDevice::GetVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel);
+ Float32 theValue = 0.0f;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+Float32 CAHALAudioDevice::GetVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeDecibels, inScope, inChannel);
+ Float32 theValue = 0.0f;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+void CAHALAudioDevice::SetVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalar, inScope, inChannel);
+ SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue);
+}
+
+void CAHALAudioDevice::SetVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeDecibels, inScope, inChannel);
+ SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue);
+}
+
+Float32 CAHALAudioDevice::GetVolumeControlScalarForDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeDecibelsToScalar, inScope, inChannel);
+ Float32 theValue = inValue;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+Float32 CAHALAudioDevice::GetVolumeControlDecibelForScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyVolumeScalarToDecibels, inScope, inChannel);
+ Float32 theValue = inValue;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+bool CAHALAudioDevice::HasSubVolumeControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::SubVolumeControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel);
+ return IsPropertySettable(theAddress);
+}
+
+Float32 CAHALAudioDevice::GetSubVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel);
+ Float32 theValue = 0.0f;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+Float32 CAHALAudioDevice::GetSubVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeDecibels, inScope, inChannel);
+ Float32 theValue = 0.0f;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+void CAHALAudioDevice::SetSubVolumeControlScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalar, inScope, inChannel);
+ SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue);
+}
+
+void CAHALAudioDevice::SetSubVolumeControlDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeDecibels, inScope, inChannel);
+ SetPropertyData(theAddress, 0, NULL, sizeof(Float32), &inValue);
+}
+
+Float32 CAHALAudioDevice::GetSubVolumeControlScalarForDecibelValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeDecibelsToScalar, inScope, inChannel);
+ Float32 theValue = inValue;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+Float32 CAHALAudioDevice::GetSubVolumeControlDecibelForScalarValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySubVolumeScalarToDecibels, inScope, inChannel);
+ Float32 theValue = inValue;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+bool CAHALAudioDevice::HasMuteControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::MuteControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel);
+ return IsPropertySettable(theAddress);
+}
+
+bool CAHALAudioDevice::GetMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel);
+ UInt32 theValue = 0;
+ UInt32 theSize = sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue != 0;
+}
+
+void CAHALAudioDevice::SetMuteControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyMute, inScope, inChannel);
+ UInt32 theValue = (inValue ? 1 : 0);
+ UInt32 theSize = sizeof(UInt32);
+ SetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+}
+
+bool CAHALAudioDevice::HasSoloControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::SoloControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel);
+ return IsPropertySettable(theAddress);
+}
+
+bool CAHALAudioDevice::GetSoloControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel);
+ UInt32 theValue = 0;
+ UInt32 theSize = sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue != 0;
+}
+
+void CAHALAudioDevice::SetSoloControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, bool inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertySolo, inScope, inChannel);
+ UInt32 theValue = (inValue ? 1 : 0);
+ UInt32 theSize = sizeof(UInt32);
+ SetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+}
+
+bool CAHALAudioDevice::HasStereoPanControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::StereoPanControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel);
+ return IsPropertySettable(theAddress);
+}
+
+Float32 CAHALAudioDevice::GetStereoPanControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel);
+ Float32 theValue = 0.0f;
+ UInt32 theSize = sizeof(Float32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theValue;
+}
+
+void CAHALAudioDevice::SetStereoPanControlValue(AudioObjectPropertyScope inScope, UInt32 inChannel, Float32 inValue)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, inScope, inChannel);
+ UInt32 theSize = sizeof(Float32);
+ SetPropertyData(theAddress, 0, NULL, theSize, &inValue);
+}
+
+void CAHALAudioDevice::GetStereoPanControlChannels(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32& outLeftChannel, UInt32& outRightChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyStereoPan, 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 / sizeof(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 * sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, outSources);
+ ioNumberSources = theSize / sizeof(UInt32);
+}
+
+UInt32 CAHALAudioDevice::GetAvailableDataSourceByIndex(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inIndex) const
+{
+ AudioStreamID theAnswer = 0;
+ UInt32 theNumberSources = GetNumberAvailableDataSources(inScope, inChannel);
+ if((theNumberSources > 0) && (inIndex < theNumberSources))
+ {
+ CAAutoArrayDelete<UInt32> theSourceList(theNumberSources);
+ GetAvailableDataSources(inScope, inChannel, theNumberSources, theSourceList);
+ theAnswer = theSourceList[inIndex];
+ }
+ return theAnswer;
+}
+
+CFStringRef CAHALAudioDevice::CopyDataSourceNameForID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyDataSourceNameForIDCFString, inScope, inChannel);
+ CFStringRef theAnswer = NULL;
+ AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(CFStringRef) };
+ UInt32 theSize = sizeof(AudioValueTranslation);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theTranslation);
+ return theAnswer;
+}
+
+bool CAHALAudioDevice::HasDataDestinationControl(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::DataDestinationControlIsSettable(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel);
+ return IsPropertySettable(theAddress);
+}
+
+UInt32 CAHALAudioDevice::GetCurrentDataDestinationID(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel);
+ UInt32 theAnswer = 0;
+ UInt32 theSize = sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ return theAnswer;
+}
+
+void CAHALAudioDevice::SetCurrentDataDestinationByID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestination, inScope, inChannel);
+ UInt32 theSize = sizeof(UInt32);
+ SetPropertyData(theAddress, 0, NULL, theSize, &inID);
+}
+
+UInt32 CAHALAudioDevice::GetNumberAvailableDataDestinations(AudioObjectPropertyScope inScope, UInt32 inChannel) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestinations, inScope, inChannel);
+ UInt32 theAnswer = 0;
+ if(HasProperty(theAddress))
+ {
+ UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL);
+ theAnswer = theSize / sizeof(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 * sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, outDestinations);
+ ioNumberDestinations = theSize / sizeof(UInt32);
+}
+
+UInt32 CAHALAudioDevice::GetAvailableDataDestinationByIndex(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inIndex) const
+{
+ AudioStreamID theAnswer = 0;
+ UInt32 theNumberDestinations = GetNumberAvailableDataDestinations(inScope, inChannel);
+ if((theNumberDestinations > 0) && (inIndex < theNumberDestinations))
+ {
+ CAAutoArrayDelete<UInt32> theDestinationList(theNumberDestinations);
+ GetAvailableDataDestinations(inScope, inChannel, theNumberDestinations, theDestinationList);
+ theAnswer = theDestinationList[inIndex];
+ }
+ return theAnswer;
+}
+
+CFStringRef CAHALAudioDevice::CopyDataDestinationNameForID(AudioObjectPropertyScope inScope, UInt32 inChannel, UInt32 inID) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyPlayThruDestinationNameForIDCFString, inScope, inChannel);
+ CFStringRef theAnswer = NULL;
+ AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(CFStringRef) };
+ UInt32 theSize = sizeof(AudioValueTranslation);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theTranslation);
+ return theAnswer;
+}
+
+bool CAHALAudioDevice::HasClockSourceControl() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSource);
+ return HasProperty(theAddress);
+}
+
+bool CAHALAudioDevice::ClockSourceControlIsSettable() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSource);
+ return IsPropertySettable(theAddress);
+}
+
+UInt32 CAHALAudioDevice::GetCurrentClockSourceID() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSource);
+ UInt32 theAnswer = 0;
+ UInt32 theSize = sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ return theAnswer;
+}
+
+void CAHALAudioDevice::SetCurrentClockSourceByID(UInt32 inID)
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSource);
+ UInt32 theSize = sizeof(UInt32);
+ SetPropertyData(theAddress, 0, NULL, theSize, &inID);
+}
+
+UInt32 CAHALAudioDevice::GetNumberAvailableClockSources() const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSources);
+ UInt32 theAnswer = 0;
+ if(HasProperty(theAddress))
+ {
+ UInt32 theSize = GetPropertyDataSize(theAddress, 0, NULL);
+ theAnswer = theSize / sizeof(UInt32);
+ }
+ return theAnswer;
+}
+
+void CAHALAudioDevice::GetAvailableClockSources(UInt32& ioNumberSources, UInt32* outSources) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSources);
+ UInt32 theNumberSources = std::min(GetNumberAvailableClockSources(), ioNumberSources);
+ UInt32 theSize = theNumberSources * sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, outSources);
+ ioNumberSources = theSize / sizeof(UInt32);
+}
+
+UInt32 CAHALAudioDevice::GetAvailableClockSourceByIndex(UInt32 inIndex) const
+{
+ AudioStreamID theAnswer = 0;
+ UInt32 theNumberSources = GetNumberAvailableClockSources();
+ if((theNumberSources > 0) && (inIndex < theNumberSources))
+ {
+ CAAutoArrayDelete<UInt32> theSourceList(theNumberSources);
+ GetAvailableClockSources(theNumberSources, theSourceList);
+ theAnswer = theSourceList[inIndex];
+ }
+ return theAnswer;
+}
+
+CFStringRef CAHALAudioDevice::CopyClockSourceNameForID(UInt32 inID) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSourceNameForIDCFString);
+ CFStringRef theAnswer = NULL;
+ AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(CFStringRef) };
+ UInt32 theSize = sizeof(AudioValueTranslation);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theTranslation);
+ return theAnswer;
+}
+
+UInt32 CAHALAudioDevice::GetClockSourceKindForID(UInt32 inID) const
+{
+ CAPropertyAddress theAddress(kAudioDevicePropertyClockSourceKindForID);
+ UInt32 theAnswer = inID;
+ UInt32 theSize = sizeof(UInt32);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
+ return theAnswer;
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAHALAudioDevice.h b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioDevice.h
new file mode 100755
index 00000000..ef75e4f2
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioDevice.h
@@ -0,0 +1,219 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CAHALAudioDevice_h__)
+#define __CAHALAudioDevice_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Super Class Includes
+#include "CAHALAudioObject.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);
+ 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;
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAHALAudioObject.cpp b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioObject.cpp
new file mode 100755
index 00000000..703b79be
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioObject.cpp
@@ -0,0 +1,357 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//==================================================================================================
+// 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;
+}
+
+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 /= sizeof(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 * sizeof(AudioClassID);
+ GetPropertyData(theAddress, theQualifierSize, theQualifierData, theDataSize, ioObjectIDs);
+
+ // set the number of object IDs being returned
+ ioNumberObjects = theDataSize / sizeof(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 / sizeof(AudioObjectID);
+
+ // set up the return value
+ AudioObjectID theAnswer = 0;
+
+ // maker sure the index is in range
+ if(inIndex < theNumberObjectIDs)
+ {
+ // allocate it
+ CAAutoArrayDelete<AudioObjectID> theObjectList(theDataSize / sizeof(AudioObjectID));
+
+ // get the property data
+ GetPropertyData(theAddress, theQualifierSize, theQualifierData, theDataSize, theObjectList);
+
+ // get the return value
+ theAnswer = theObjectList[inIndex];
+ }
+
+ return theAnswer;
+}
+
+bool CAHALAudioObject::HasProperty(const AudioObjectPropertyAddress& inAddress) const
+{
+ return AudioObjectHasProperty(mObjectID, &inAddress);
+}
+
+bool CAHALAudioObject::IsPropertySettable(const AudioObjectPropertyAddress& inAddress) const
+{
+ Boolean isSettable = false;
+ OSStatus theError = AudioObjectIsPropertySettable(mObjectID, &inAddress, &isSettable);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioObject::IsPropertySettable: got an error getting info about a property");
+ return isSettable != 0;
+}
+
+UInt32 CAHALAudioObject::GetPropertyDataSize(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData) const
+{
+ UInt32 theDataSize = 0;
+ OSStatus theError = AudioObjectGetPropertyDataSize(mObjectID, &inAddress, inQualifierDataSize, inQualifierData, &theDataSize);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioObject::GetPropertyDataSize: got an error getting the property data size");
+ return theDataSize;
+}
+
+void CAHALAudioObject::GetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32& ioDataSize, void* outData) const
+{
+ OSStatus theError = AudioObjectGetPropertyData(mObjectID, &inAddress, inQualifierDataSize, inQualifierData, &ioDataSize, outData);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioObject::GetPropertyData: got an error getting the property data");
+}
+
+void CAHALAudioObject::SetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32 inDataSize, const void* inData)
+{
+ OSStatus theError = AudioObjectSetPropertyData(mObjectID, &inAddress, inQualifierDataSize, inQualifierData, inDataSize, inData);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioObject::SetPropertyData: got an error setting the property data");
+}
+
+void CAHALAudioObject::AddPropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData)
+{
+ OSStatus theError = AudioObjectAddPropertyListener(mObjectID, &inAddress, inListenerProc, inClientData);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioObject::AddPropertyListener: got an error adding a property listener");
+}
+
+void CAHALAudioObject::RemovePropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData)
+{
+ OSStatus theError = AudioObjectRemovePropertyListener(mObjectID, &inAddress, inListenerProc, inClientData);
+ ThrowIfError(theError, CAException(theError), "CAHALAudioObject::RemovePropertyListener: got an error removing a property listener");
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAHALAudioObject.h b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioObject.h
new file mode 100755
index 00000000..314734d6
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioObject.h
@@ -0,0 +1,131 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CAHALAudioObject_h__)
+#define __CAHALAudioObject_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// PublicUtility Includes
+#include "CADebugMacros.h"
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudio.h>
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include <CoreAudio.h>
+ #include <CoreFoundation.h>
+#endif
+
+//==================================================================================================
+// CAHALAudioObject
+//==================================================================================================
+
+class CAHALAudioObject
+{
+
+// Construction/Destruction
+public:
+ CAHALAudioObject(AudioObjectID inObjectID);
+ virtual ~CAHALAudioObject();
+
+// Attributes
+public:
+ AudioObjectID GetObjectID() const;
+ void SetObjectID(AudioObjectID inObjectID);
+ AudioClassID GetClassID() const;
+ AudioObjectID GetOwnerObjectID() const;
+ CFStringRef CopyOwningPlugInBundleID() const;
+ CFStringRef CopyName() const;
+ CFStringRef CopyManufacturer() const;
+ CFStringRef CopyNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const;
+ CFStringRef CopyCategoryNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const;
+ CFStringRef CopyNumberNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const;
+
+// 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, UInt32 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, UInt32 inValue, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(CFStringRef), &inValue); }
+
+ template <class T> void GetPropertyData_Struct(const AudioObjectPropertyAddress& inAddress, T& outStruct, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { UInt32 theDataSize = SizeOf32(T); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, &outStruct); }
+ template <class T> void SetPropertyData_Struct(const AudioObjectPropertyAddress& inAddress, T& inStruct, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, SizeOf32(T), &inStruct); }
+
+ template <class T> UInt32 GetPropertyData_ArraySize(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { return GetPropertyDataSize(inAddress, inQualifierDataSize, inQualifierData) / SizeOf32(T); }
+ template <class T> void GetPropertyData_Array(const AudioObjectPropertyAddress& inAddress, UInt32& ioNumberItems, T* outArray, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) const { UInt32 theDataSize = ioNumberItems * SizeOf32(T); GetPropertyData(inAddress, inQualifierDataSize, inQualifierData, theDataSize, outArray); ioNumberItems = theDataSize / SizeOf32(T); }
+ template <class T> void SetPropertyData_Array(const AudioObjectPropertyAddress& inAddress, UInt32 inNumberItems, T* inArray, UInt32 inQualifierDataSize = 0, const void* inQualifierData = NULL) { SetPropertyData(inAddress, inQualifierDataSize, inQualifierData, inNumberItems * SizeOf32(T), inArray); }
+
+ void AddPropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData);
+ void RemovePropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData);
+
+// Implementation
+protected:
+ AudioObjectID mObjectID;
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAHALAudioStream.cpp b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioStream.cpp
new file mode 100755
index 00000000..28ae4dfa
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioStream.cpp
@@ -0,0 +1,176 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//==================================================================================================
+// 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 /= sizeof(AudioStreamRangedDescription);
+ return theAnswer;
+}
+
+void CAHALAudioStream::GetAvailableVirtualFormats(UInt32& ioNumberFormats, AudioStreamRangedDescription* outFormats) const
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyAvailableVirtualFormats);
+ UInt32 theSize = ioNumberFormats * sizeof(AudioStreamRangedDescription);
+ GetPropertyData(theAddress, 0, NULL, theSize, outFormats);
+ ioNumberFormats = theSize / sizeof(AudioStreamRangedDescription);
+}
+
+void CAHALAudioStream::GetAvailableVirtualFormatByIndex(UInt32 inIndex, AudioStreamRangedDescription& outFormat) const
+{
+ UInt32 theNumberFormats = GetNumberAvailableVirtualFormats();
+ if((theNumberFormats > 0) && (inIndex < theNumberFormats))
+ {
+ CAAutoArrayDelete<AudioStreamRangedDescription> theFormats(theNumberFormats);
+ GetAvailableVirtualFormats(theNumberFormats, theFormats);
+ if((theNumberFormats > 0) && (inIndex < theNumberFormats))
+ {
+ outFormat = theFormats[inIndex];
+ }
+ }
+}
+
+void CAHALAudioStream::GetCurrentPhysicalFormat(AudioStreamBasicDescription& outFormat) const
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyPhysicalFormat);
+ UInt32 theSize = sizeof(AudioStreamBasicDescription);
+ GetPropertyData(theAddress, 0, NULL, theSize, &outFormat);
+}
+
+void CAHALAudioStream::SetCurrentPhysicalFormat(const AudioStreamBasicDescription& inFormat)
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyPhysicalFormat);
+ SetPropertyData(theAddress, 0, NULL, sizeof(AudioStreamBasicDescription), &inFormat);
+}
+
+UInt32 CAHALAudioStream::GetNumberAvailablePhysicalFormats() const
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyAvailablePhysicalFormats);
+ UInt32 theAnswer = GetPropertyDataSize(theAddress, 0, NULL);
+ theAnswer /= sizeof(AudioStreamRangedDescription);
+ return theAnswer;
+}
+
+void CAHALAudioStream::GetAvailablePhysicalFormats(UInt32& ioNumberFormats, AudioStreamRangedDescription* outFormats) const
+{
+ CAPropertyAddress theAddress(kAudioStreamPropertyAvailablePhysicalFormats);
+ UInt32 theSize = ioNumberFormats * sizeof(AudioStreamRangedDescription);
+ GetPropertyData(theAddress, 0, NULL, theSize, outFormats);
+ ioNumberFormats = theSize / sizeof(AudioStreamRangedDescription);
+}
+
+void CAHALAudioStream::GetAvailablePhysicalFormatByIndex(UInt32 inIndex, AudioStreamRangedDescription& outFormat) const
+{
+ UInt32 theNumberFormats = GetNumberAvailablePhysicalFormats();
+ if((theNumberFormats > 0) && (inIndex < theNumberFormats))
+ {
+ CAAutoArrayDelete<AudioStreamRangedDescription> theFormats(theNumberFormats);
+ GetAvailablePhysicalFormats(theNumberFormats, theFormats);
+ if((theNumberFormats > 0) && (inIndex < theNumberFormats))
+ {
+ outFormat = theFormats[inIndex];
+ }
+ }
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAHALAudioStream.h b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioStream.h
new file mode 100755
index 00000000..e07c7834
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioStream.h
@@ -0,0 +1,88 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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/distrho/src/CoreAudio106/PublicUtility/CAHALAudioSystemObject.cpp b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioSystemObject.cpp
new file mode 100755
index 00000000..f92c8cb6
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioSystemObject.cpp
@@ -0,0 +1,146 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CAHALAudioSystemObject.h"
+
+// PublicUtility Includes
+#include "CAAutoDisposer.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 /= sizeof(AudioObjectID);
+ return theAnswer;
+}
+
+void CAHALAudioSystemObject::GetAudioDevices(UInt32& ioNumberAudioDevices, AudioObjectID* outAudioDevices) const
+{
+ CAPropertyAddress theAddress(kAudioHardwarePropertyDevices);
+ UInt32 theSize = ioNumberAudioDevices * sizeof(AudioObjectID);
+ GetPropertyData(theAddress, 0, NULL, theSize, outAudioDevices);
+ ioNumberAudioDevices = theSize / sizeof(AudioObjectID);
+}
+
+AudioObjectID CAHALAudioSystemObject::GetAudioDeviceAtIndex(UInt32 inIndex) const
+{
+ AudioObjectID theAnswer = kAudioObjectUnknown;
+ UInt32 theNumberDevices = GetNumberAudioDevices();
+ if((theNumberDevices > 0) && (inIndex < theNumberDevices))
+ {
+ CAAutoArrayDelete<AudioObjectID> theDeviceList(theNumberDevices);
+ GetAudioDevices(theNumberDevices, theDeviceList);
+ if((theNumberDevices > 0) && (inIndex < theNumberDevices))
+ {
+ theAnswer = theDeviceList[inIndex];
+ }
+ }
+ return theAnswer;
+}
+
+AudioObjectID CAHALAudioSystemObject::GetAudioDeviceForUID(CFStringRef inUID) const
+{
+ AudioObjectID theAnswer = kAudioObjectUnknown;
+ AudioValueTranslation theValue = { &inUID, sizeof(CFStringRef), &theAnswer, sizeof(AudioObjectID) };
+ CAPropertyAddress theAddress(kAudioHardwarePropertyDeviceForUID);
+ UInt32 theSize = sizeof(AudioValueTranslation);
+ GetPropertyData(theAddress, 0, NULL, theSize, &theValue);
+ return theAnswer;
+}
+
+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/distrho/src/CoreAudio106/PublicUtility/CAHALAudioSystemObject.h b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioSystemObject.h
new file mode 100755
index 00000000..8f6b2717
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAHALAudioSystemObject.h
@@ -0,0 +1,83 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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;
+
+// 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/distrho/src/CoreAudio106/PublicUtility/CAHostTimeBase.cpp b/distrho/src/CoreAudio106/PublicUtility/CAHostTimeBase.cpp
new file mode 100755
index 00000000..c5c70b98
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAHostTimeBase.cpp
@@ -0,0 +1,104 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CAHostTimeBase.h"
+
+Float64 CAHostTimeBase::sFrequency = 0;
+Float64 CAHostTimeBase::sInverseFrequency = 0;
+UInt32 CAHostTimeBase::sMinDelta = 0;
+UInt32 CAHostTimeBase::sToNanosNumerator = 0;
+UInt32 CAHostTimeBase::sToNanosDenominator = 0;
+UInt32 CAHostTimeBase::sFromNanosNumerator = 0;
+UInt32 CAHostTimeBase::sFromNanosDenominator = 0;
+bool CAHostTimeBase::sUseMicroseconds = false;
+bool CAHostTimeBase::sIsInited = false;
+#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;
+ sFromNanosNumerator = sToNanosDenominator;
+ sFromNanosDenominator = sToNanosNumerator;
+
+ // the frequency of that clock is: (sToNanosDenominator / sToNanosNumerator) * 10^9
+ sFrequency = static_cast<Float64>(sToNanosDenominator) / static_cast<Float64>(sToNanosNumerator);
+ sFrequency *= 1000000000.0;
+ #elif TARGET_OS_WIN32
+ LARGE_INTEGER theFrequency;
+ QueryPerformanceFrequency(&theFrequency);
+ sMinDelta = 1;
+ sToNanosNumerator = 1000000000ULL;
+ sToNanosDenominator = *((UInt64*)&theFrequency);
+ sFromNanosNumerator = sToNanosDenominator;
+ sFromNanosDenominator = sToNanosNumerator;
+ sFrequency = static_cast<Float64>(*((UInt64*)&theFrequency));
+ #endif
+ sInverseFrequency = 1.0 / sFrequency;
+
+ #if Log_Host_Time_Base_Parameters
+ DebugMessage( "Host Time Base Parameters");
+ DebugMessageN1(" Minimum Delta: %lu", sMinDelta);
+ DebugMessageN1(" Frequency: %f", sFrequency);
+ DebugMessageN1(" To Nanos Numerator: %lu", sToNanosNumerator);
+ DebugMessageN1(" To Nanos Denominator: %lu", sToNanosDenominator);
+ DebugMessageN1(" From Nanos Numerator: %lu", sFromNanosNumerator);
+ DebugMessageN1(" From Nanos Denominator: %lu", sFromNanosDenominator);
+ #endif
+
+ sIsInited = true;
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAHostTimeBase.h b/distrho/src/CoreAudio106/PublicUtility/CAHostTimeBase.h
new file mode 100755
index 00000000..ffdafbda
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAHostTimeBase.h
@@ -0,0 +1,225 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CAHostTimeBase_h__)
+#define __CAHostTimeBase_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+#if TARGET_OS_MAC
+ #include <mach/mach_time.h>
+#elif TARGET_OS_WIN32
+ #include <windows.h>
+#else
+ #error Unsupported operating system
+#endif
+
+#include "CADebugMacros.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() { if(!sIsInited) { Initialize(); } return sFrequency; }
+ static Float64 GetInverseFrequency() { if(!sIsInited) { Initialize(); } return sInverseFrequency; }
+ static UInt32 GetMinimumDelta() { if(!sIsInited) { Initialize(); } return sMinDelta; }
+
+ static UInt64 AbsoluteHostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime);
+ static SInt64 HostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime);
+
+private:
+ static void Initialize();
+
+ static bool sIsInited;
+
+ static Float64 sFrequency;
+ static Float64 sInverseFrequency;
+ static UInt32 sMinDelta;
+ static UInt32 sToNanosNumerator;
+ static UInt32 sToNanosDenominator;
+ static UInt32 sFromNanosNumerator;
+ static UInt32 sFromNanosDenominator;
+ static bool sUseMicroseconds;
+#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)
+ {
+ DebugMessageN2("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)
+{
+ if(!sIsInited)
+ {
+ Initialize();
+ }
+
+ Float64 theNumerator = static_cast<Float64>(sToNanosNumerator);
+ Float64 theDenominator = static_cast<Float64>(sToNanosDenominator);
+ Float64 theHostTime = static_cast<Float64>(inHostTime);
+
+ Float64 thePartialAnswer = theHostTime / theDenominator;
+ Float64 theFloatAnswer = thePartialAnswer * theNumerator;
+ UInt64 theAnswer = static_cast<UInt64>(theFloatAnswer);
+
+ //Assert(!((theNumerator > theDenominator) && (theAnswer < inHostTime)), "CAHostTimeBase::ConvertToNanos: The conversion wrapped");
+ //Assert(!((theDenominator > theNumerator) && (theAnswer > inHostTime)), "CAHostTimeBase::ConvertToNanos: The conversion wrapped");
+
+ return theAnswer;
+}
+
+inline UInt64 CAHostTimeBase::ConvertFromNanos(UInt64 inNanos)
+{
+ if(!sIsInited)
+ {
+ Initialize();
+ }
+
+ Float64 theNumerator = static_cast<Float64>(sToNanosNumerator);
+ Float64 theDenominator = static_cast<Float64>(sToNanosDenominator);
+ Float64 theNanos = static_cast<Float64>(inNanos);
+
+ Float64 thePartialAnswer = theNanos / theNumerator;
+ Float64 theFloatAnswer = thePartialAnswer * theDenominator;
+ UInt64 theAnswer = static_cast<UInt64>(theFloatAnswer);
+
+ //Assert(!((theDenominator > theNumerator) && (theAnswer < inNanos)), "CAHostTimeBase::ConvertToNanos: The conversion wrapped");
+ //Assert(!((theNumerator > theDenominator) && (theAnswer > inNanos)), "CAHostTimeBase::ConvertToNanos: The conversion wrapped");
+
+ 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 = inEndTime - inStartTime;
+ }
+ else
+ {
+ theAnswer = inStartTime - inEndTime;
+ theSign = -1;
+ }
+
+ return theSign * ConvertToNanos(theAnswer);
+}
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CALogMacros.h b/distrho/src/CoreAudio106/PublicUtility/CALogMacros.h
new file mode 100755
index 00000000..7f7c69dc
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CALogMacros.h
@@ -0,0 +1,134 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CALogMacros_h__)
+#define __CALogMacros_h__
+
+//=============================================================================
+// Log Macros
+//=============================================================================
+
+#if CoreAudio_Debug
+
+ #include "CADebugMacros.h"
+ #include "CADebugPrintf.h"
+ #include <stdio.h>
+ #include <string.h>
+
+ #define PrintLine(msg) DebugPrintfRtn(DebugPrintfFileComma "%s\n", (msg))
+
+ #define PrintBool(msg, b) DebugPrintfRtn(DebugPrintfFileComma "%s%s\n", (msg), (b) ? "true" : "false")
+ #define PrintIndexedBool(msg, i, b) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %s\n", (msg), (long)(i), (b) ? "true" : "false")
+
+ #define PrintToggle(msg, b) DebugPrintfRtn(DebugPrintfFileComma "%s%s\n", (msg), (b) ? "on" : "off")
+ #define PrintIndexedToggle(msg, i, b) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %s\n", (msg), (long)(i), (b) ? "on" : "off")
+
+ #define PrintInt(msg, n) DebugPrintfRtn(DebugPrintfFileComma "%s%ld\n", (msg), (long)(n))
+ #define PrintIndexedInt(msg, i, n) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %ld\n", (msg), (long)(i), (long)(n))
+
+ #define PrintHex(msg, n) DebugPrintfRtn(DebugPrintfFileComma "%s0x%lX\n", (msg), (unsigned long)(n))
+ #define PrintIndexedHex(msg, i, n) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: 0x%lX\n", (msg), (long)(i), (unsigned long)(n))
+
+ #define PrintFloat(msg, f) DebugPrintfRtn(DebugPrintfFileComma "%s%.6f\n", (msg), (f))
+ #define PrintIndexedFloat(msg, i, f) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %.6f\n", (msg), (long)(i), (f))
+ #define PrintFloatIndexedFloat(msg, i, f) DebugPrintfRtn(DebugPrintfFileComma " %s %.6f: %.6f\n", (msg), (i), (f))
+
+ #define PrintString(msg, s) DebugPrintfRtn(DebugPrintfFileComma "%s%s\n", (msg), (s))
+ #define PrintIndexedString(msg, i, s) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %s\n", (msg), (long)(i), (s))
+
+ #define PrintPointer(msg, p) DebugPrintfRtn(DebugPrintfFileComma "%s%p\n", (msg), (p))
+ #define PrintIndexedPointer(msg, i, p) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %p\n", (msg), (long)(i), (p))
+
+ #define Print4CharCode(msg, c) { \
+ UInt32 __4CC_number = (c); \
+ char __4CC_string[5] = CA4CCToCString(__4CC_number); \
+ DebugPrintfRtn(DebugPrintfFileComma "%s'%s'\n", (msg), __4CC_string); \
+ }
+ #define PrintIndexed4CharCode(msg, i, c) { \
+ UInt32 __4CC_number = (c); \
+ char __4CC_string[5] = CA4CCToCString(__4CC_number); \
+ DebugPrintfRtn(DebugPrintfFileComma " %s %ld: '%s'\n", (msg), (long)(i), __4CC_string); \
+ }
+
+ #define ErrorLine(s) DebugPrintfRtn(DebugPrintfFileComma "%s\n", (s))
+ #define OSErrorLine(s, e) { \
+ OSStatus __err_number = (e); \
+ char __err_string[5] = CA4CCToCString(__err_number); \
+ DebugPrintfRtn(DebugPrintfFileComma "%s, OSStatus code: %s\n", (s), __err_string); \
+ }
+
+ #define MessageIfOSError(e, s) if((e) != 0) { OSErrorLine(s, e); }
+ #define MessageIfNULL(p, s) if((p) == 0) { ErrorLine(s); }
+
+#else
+
+ #define PrintLine(msg)
+
+ #define PrintBool(msg, b) (b)
+ #define PrintIndexedBool(msg, i, b) (b)
+
+ #define PrintInt(msg, n) (n)
+ #define PrintIndexedInt(msg, i, n) (n)
+
+ #define PrintHex(msg, n) (n)
+ #define PrintIndexedHex(msg, i, n) (n)
+
+ #define PrintFloat(msg, f) (f)
+ #define PrintIndexedFloat(msg, i, f) (f)
+ #define PrintFloatIndexedFloat(msg, i, f) (f)
+
+ #define PrintString(msg, s) (s)
+ #define PrintIndexedString(msg, i, s) (s)
+
+ #define PrintPointer(msg, p) (p)
+ #define PrintIndexedPointer(msg, i, p) (p)
+
+ #define Print4CharCode(msg, c) (c)
+ #define PrintIndexed4CharCode(msg, i, c) (c)
+
+ #define ErrorLine(s) (s)
+ #define OSErrorLine(s, e) (e)
+
+ #define MessageIfOSError(e, s) (e)
+ #define MessageIfNULL(p, s) (p)
+
+#endif // CoreAudio_Debug
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAMath.h b/distrho/src/CoreAudio106/PublicUtility/CAMath.h
new file mode 100755
index 00000000..3fb0a1e4
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAMath.h
@@ -0,0 +1,62 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAMath_h__
+#define __CAMath_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+inline bool fiszero(Float64 f) { return (f == 0.); }
+inline bool fiszero(Float32 f) { return (f == 0.f); }
+
+inline bool fnonzero(Float64 f) { return !fiszero(f); }
+inline bool fnonzero(Float32 f) { return !fiszero(f); }
+
+inline bool fequal(const Float64 &a, const Float64 &b) { return a == b; }
+inline bool fequal(const Float32 &a, const Float32 &b) { return a == b; }
+
+inline bool fnotequal(const Float64 &a, const Float64 &b) { return !fequal(a, b); }
+inline bool fnotequal(const Float32 &a, const Float32 &b) { return !fequal(a, b); }
+
+#endif // __CAMath_h__
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAMixMap.h b/distrho/src/CoreAudio106/PublicUtility/CAMixMap.h
new file mode 100755
index 00000000..2bb2a252
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAMixMap.h
@@ -0,0 +1,121 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#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()) {
+ 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); }
+
+ 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 \ No newline at end of file
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAMutex.cpp b/distrho/src/CoreAudio106/PublicUtility/CAMutex.cpp
new file mode 100755
index 00000000..c6ce0761
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAMutex.cpp
@@ -0,0 +1,320 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CAMutex.h"
+
+#if TARGET_OS_MAC
+ #include <errno.h>
+#endif
+
+// PublicUtility Includes
+#include "CADebugMacros.h"
+#include "CAException.h"
+#include "CAHostTimeBase.h"
+
+//==================================================================================================
+// Logging
+//==================================================================================================
+
+#if CoreAudio_Debug
+// #define Log_Ownership 1
+// #define Log_Errors 1
+// #define Log_LongLatencies 1
+// #define LongLatencyThreshholdNS 1000000ULL // nanoseconds
+#endif
+
+//==================================================================================================
+// CAMutex
+//==================================================================================================
+
+CAMutex::CAMutex(const char* inName)
+:
+ mName(inName),
+ mOwner(0)
+{
+#if TARGET_OS_MAC
+ OSStatus theError = pthread_mutex_init(&mMutex, NULL);
+ ThrowIf(theError != 0, CAException(theError), "CAMutex::CAMutex: Could not init the mutex");
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::CAMutex: creating %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
+ #endif
+#elif TARGET_OS_WIN32
+ mMutex = CreateMutex(NULL, false, NULL);
+ ThrowIfNULL(mMutex, CAException(GetLastError()), "CAMutex::CAMutex: could not create the mutex.");
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::CAMutex: creating %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
+ #endif
+#endif
+}
+
+CAMutex::~CAMutex()
+{
+#if TARGET_OS_MAC
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::~CAMutex: destroying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
+ #endif
+ pthread_mutex_destroy(&mMutex);
+#elif TARGET_OS_WIN32
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::~CAMutex: destroying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
+ #endif
+ if(mMutex != NULL)
+ {
+ CloseHandle(mMutex);
+ }
+#endif
+}
+
+bool CAMutex::Lock()
+{
+ bool theAnswer = false;
+
+#if TARGET_OS_MAC
+ pthread_t theCurrentThread = pthread_self();
+ if(!pthread_equal(theCurrentThread, mOwner))
+ {
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Lock: thread %p is locking %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
+ #endif
+
+ #if Log_LongLatencies
+ UInt64 lockTryTime = CAHostTimeBase::GetCurrentTimeInNanos();
+ #endif
+
+ OSStatus theError = pthread_mutex_lock(&mMutex);
+ ThrowIf(theError != 0, CAException(theError), "CAMutex::Lock: Could not lock the mutex");
+ mOwner = theCurrentThread;
+ theAnswer = true;
+
+ #if Log_LongLatencies
+ UInt64 lockAcquireTime = CAHostTimeBase::GetCurrentTimeInNanos();
+ if (lockAcquireTime - lockTryTime >= LongLatencyThresholdNS)
+ DebugPrintfRtn(DebugPrintfFileComma "Thread %p took %.6fs to acquire the lock %s\n", theCurrentThread, (lockAcquireTime - lockTryTime) * 1.0e-9 /* nanos to seconds */, mName);
+ #endif
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Lock: thread %p has locked %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+ }
+#elif TARGET_OS_WIN32
+ if(mOwner != GetCurrentThreadId())
+ {
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Lock: thread %lu is locking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+
+ OSStatus theError = WaitForSingleObject(mMutex, INFINITE);
+ ThrowIfError(theError, CAException(theError), "CAMutex::Lock: could not lock the mutex");
+ mOwner = GetCurrentThreadId();
+ theAnswer = true;
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Lock: thread %lu has locked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+ }
+#endif
+
+ return theAnswer;
+}
+
+void CAMutex::Unlock()
+{
+#if TARGET_OS_MAC
+ if(pthread_equal(pthread_self(), mOwner))
+ {
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Unlock: thread %p is unlocking %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+
+ mOwner = 0;
+ OSStatus theError = pthread_mutex_unlock(&mMutex);
+ ThrowIf(theError != 0, CAException(theError), "CAMutex::Unlock: Could not unlock the mutex");
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Unlock: thread %p has unlocked %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
+ #endif
+ }
+ else
+ {
+ DebugMessage("CAMutex::Unlock: A thread is attempting to unlock a Mutex it doesn't own");
+ }
+#elif TARGET_OS_WIN32
+ if(mOwner == GetCurrentThreadId())
+ {
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Unlock: thread %lu is unlocking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+
+ mOwner = 0;
+ bool wasReleased = ReleaseMutex(mMutex);
+ ThrowIf(!wasReleased, CAException(GetLastError()), "CAMutex::Unlock: Could not unlock the mutex");
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Unlock: thread %lu has unlocked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+ }
+ else
+ {
+ DebugMessage("CAMutex::Unlock: A thread is attempting to unlock a Mutex it doesn't own");
+ }
+#endif
+}
+
+bool CAMutex::Try(bool& outWasLocked)
+{
+ bool theAnswer = false;
+ outWasLocked = false;
+
+#if TARGET_OS_MAC
+ pthread_t theCurrentThread = pthread_self();
+ if(!pthread_equal(theCurrentThread, mOwner))
+ {
+ // this means the current thread doesn't already own the lock
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p is try-locking %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
+ #endif
+
+ // go ahead and call trylock to see if we can lock it.
+ int theError = pthread_mutex_trylock(&mMutex);
+ if(theError == 0)
+ {
+ // return value of 0 means we successfully locked the lock
+ mOwner = theCurrentThread;
+ theAnswer = true;
+ outWasLocked = true;
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p has locked %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
+ #endif
+ }
+ else if(theError == EBUSY)
+ {
+ // return value of EBUSY means that the lock was already locked by another thread
+ theAnswer = false;
+ outWasLocked = false;
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p failed to lock %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
+ #endif
+ }
+ else
+ {
+ // any other return value means something really bad happenned
+ ThrowIfError(theError, CAException(theError), "CAMutex::Try: call to pthread_mutex_trylock failed");
+ }
+ }
+ else
+ {
+ // this means the current thread already owns the lock
+ theAnswer = true;
+ outWasLocked = false;
+ }
+#elif TARGET_OS_WIN32
+ if(mOwner != GetCurrentThreadId())
+ {
+ // this means the current thread doesn't own the lock
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu is try-locking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+
+ // try to acquire the mutex
+ OSStatus theError = WaitForSingleObject(mMutex, 0);
+ if(theError == WAIT_OBJECT_0)
+ {
+ // this means we successfully locked the lock
+ mOwner = GetCurrentThreadId();
+ theAnswer = true;
+ outWasLocked = true;
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu has locked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+ }
+ else if(theError == WAIT_TIMEOUT)
+ {
+ // this means that the lock was already locked by another thread
+ theAnswer = false;
+ outWasLocked = false;
+
+ #if Log_Ownership
+ DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu failed to lock %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
+ #endif
+ }
+ else
+ {
+ // any other return value means something really bad happenned
+ ThrowIfError(theError, CAException(GetLastError()), "CAMutex::Try: call to lock the mutex failed");
+ }
+ }
+ else
+ {
+ // this means the current thread already owns the lock
+ theAnswer = true;
+ outWasLocked = false;
+ }
+#endif
+
+ return theAnswer;
+}
+
+bool CAMutex::IsFree() const
+{
+ return mOwner == 0;
+}
+
+bool CAMutex::IsOwnedByCurrentThread() const
+{
+ bool theAnswer = true;
+
+#if TARGET_OS_MAC
+ theAnswer = pthread_equal(pthread_self(), mOwner);
+#elif TARGET_OS_WIN32
+ theAnswer = (mOwner == GetCurrentThreadId());
+#endif
+
+ return theAnswer;
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAMutex.h b/distrho/src/CoreAudio106/PublicUtility/CAMutex.h
new file mode 100755
index 00000000..c014f395
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAMutex.h
@@ -0,0 +1,138 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAMutex_h__
+#define __CAMutex_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+#if TARGET_OS_MAC
+ #include <pthread.h>
+#elif TARGET_OS_WIN32
+ #include <windows.h>
+#else
+ #error Unsupported operating system
+#endif
+
+//==================================================================================================
+// A recursive mutex.
+//==================================================================================================
+
+class CAMutex
+{
+// Construction/Destruction
+public:
+ CAMutex(const char* inName);
+ virtual ~CAMutex();
+
+// Actions
+public:
+ virtual bool Lock();
+ virtual void Unlock();
+ virtual bool Try(bool& outWasLocked); // returns true if lock is free, false if not
+
+ virtual bool IsFree() const;
+ virtual bool IsOwnedByCurrentThread() const;
+
+// Implementation
+protected:
+ const char* mName;
+#if TARGET_OS_MAC
+ pthread_t mOwner;
+ pthread_mutex_t mMutex;
+#elif TARGET_OS_WIN32
+ UInt32 mOwner;
+ HANDLE mMutex;
+#endif
+
+// Helper class to manage taking and releasing recursively
+public:
+ class Locker
+ {
+
+ // Construction/Destruction
+ public:
+ Locker(CAMutex& inMutex) : mMutex(inMutex), mNeedsRelease(false) { mNeedsRelease = mMutex.Lock(); }
+ ~Locker() { if(mNeedsRelease) { mMutex.Unlock(); } }
+
+ private:
+ Locker(const Locker&);
+ Locker& operator=(const Locker&);
+
+ // Implementation
+ private:
+ CAMutex& mMutex;
+ bool mNeedsRelease;
+
+ };
+
+ // 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/distrho/src/CoreAudio106/PublicUtility/CAPThread.cpp b/distrho/src/CoreAudio106/PublicUtility/CAPThread.cpp
new file mode 100755
index 00000000..6c5563a2
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAPThread.cpp
@@ -0,0 +1,375 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+// Self Include
+#include "CAPThread.h"
+
+// PublicUtility Includes
+#include "CADebugMacros.h"
+#include "CAException.h"
+
+// System Includes
+#if TARGET_OS_MAC
+ #include <mach/mach.h>
+#endif
+
+// Standard Library Includes
+#include <stdio.h>
+
+//==================================================================================================
+// CAPThread
+//==================================================================================================
+
+// returns the thread's priority as it was last set by the API
+#define CAPTHREAD_SET_PRIORITY 0
+// returns the thread's priority as it was last scheduled by the Kernel
+#define CAPTHREAD_SCHEDULED_PRIORITY 1
+
+//#define Log_SetPriority 1
+
+CAPThread::CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPriority, bool inFixedPriority, bool inAutoDelete)
+:
+#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)
+{
+}
+
+CAPThread::CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible, bool inAutoDelete)
+:
+#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)
+{
+}
+
+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
+}
+
+void CAPThread::SetPriority(UInt32 inPriority, bool inFixedPriority)
+{
+ mPriority = inPriority;
+ mTimeConstraintSet = false;
+ mFixedPriority = inFixedPriority;
+#if TARGET_OS_MAC
+ if(mPThread != 0)
+ {
+ kern_return_t theError = 0;
+
+ // set whether or not this is a fixed priority thread
+ if (mFixedPriority)
+ {
+ thread_extended_policy_data_t theFixedPolicy = { false };
+ theError = thread_policy_set(pthread_mach_thread_np(mPThread), 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 = { mPriority - theCurrentThreadPriority };
+ theError = thread_policy_set(pthread_mach_thread_np(mPThread), 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(mThreadHandle != NULL)
+ {
+ SetThreadPriority(mThreadHandle, mPriority);
+ }
+#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;
+
+ 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 thePolicyInfo.ts.cur_priority;
+ }
+ return 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 thePolicyInfo.fifo.depress_priority;
+ }
+ return 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 thePolicyInfo.rr.depress_priority;
+ }
+ return thePolicyInfo.rr.base_priority;
+ break;
+ }
+
+ return 0;
+}
+
+#elif TARGET_OS_WIN32
+
+UInt32 WINAPI CAPThread::Entry(CAPThread* inCAPThread)
+{
+ UInt32 theAnswer = 0;
+
+ try
+ {
+ if(inCAPThread->mTimeConstraintSet)
+ {
+ inCAPThread->SetTimeConstraints(inCAPThread->mPeriod, inCAPThread->mComputation, inCAPThread->mConstraint, inCAPThread->mIsPreemptible);
+ }
+ else
+ {
+ inCAPThread->SetPriority(inCAPThread->mPriority, inCAPThread->mFixedPriority);
+ }
+
+ if(inCAPThread->mThreadRoutine != NULL)
+ {
+ theAnswer = reinterpret_cast<UInt32>(inCAPThread->mThreadRoutine(inCAPThread->mThreadParameter));
+ }
+ inCAPThread->mThreadID = 0;
+ }
+ catch (...)
+ {
+ // what should be done here?
+ }
+ CloseHandle(inCAPThread->mThreadHandle);
+ inCAPThread->mThreadHandle = NULL;
+ if (inCAPThread->mAutoDelete)
+ delete inCAPThread;
+ return theAnswer;
+}
+
+extern "C"
+Boolean CompareAndSwap(UInt32 inOldValue, UInt32 inNewValue, UInt32* inOldValuePtr)
+{
+ return InterlockedCompareExchange((volatile LONG*)inOldValuePtr, inNewValue, inOldValue) == inOldValue;
+}
+
+#endif
+
+#if CoreAudio_Debug
+void CAPThread::DebugPriority(const char *label)
+{
+#if !TARGET_OS_WIN32
+ if (mTimeConstraintSet)
+ printf("CAPThread::%s %p: pri=<time constraint>, spawning pri=%d, scheduled pri=%d\n", label, this,
+ (int)mSpawningThreadPriority, (mPThread != NULL) ? (int)GetScheduledPriority() : -1);
+ else
+ printf("CAPThread::%s %p: pri=%d%s, spawning pri=%d, scheduled pri=%d\n", label, this, (int)mPriority, mFixedPriority ? " fixed" : "",
+ (int)mSpawningThreadPriority, (mPThread != NULL) ? (int)GetScheduledPriority() : -1);
+#else
+ if (mTimeConstraintSet)
+ {
+ printf("CAPThread::%s %p: pri=<time constraint>, spawning pri=%d, scheduled pri=%d\n", label, this,
+ (int)mPriority, (mThreadHandle != NULL) ? (int)GetScheduledPriority() : -1);
+ }
+ else
+ {
+ printf("CAPThread::%s %p: pri=%d%s, spawning pri=%d, scheduled pri=%d\n", label, this, (int)mPriority, mFixedPriority ? " fixed" : "",
+ (int)mPriority, (mThreadHandle != NULL) ? (int)GetScheduledPriority() : -1);
+ }
+#endif
+}
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAPThread.h b/distrho/src/CoreAudio106/PublicUtility/CAPThread.h
new file mode 100755
index 00000000..d3780ba8
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAPThread.h
@@ -0,0 +1,178 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CAPThread_h__)
+#define __CAPThread_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CFBase.h>
+#else
+ #include <CFBase.h>
+#endif
+
+#if TARGET_OS_MAC
+ #include <pthread.h>
+ #include <unistd.h>
+#elif TARGET_OS_WIN32
+ #include <windows.h>
+#else
+ #error Unsupported operating system
+#endif
+
+//==================================================================================================
+// CAPThread
+//
+// This class wraps a pthread and a Win32 thread.
+// caution: long-running fixed priority threads can make the system unresponsive
+//==================================================================================================
+
+class CAPThread
+{
+
+// Types
+public:
+ typedef void* (*ThreadRoutine)(void* inParameter);
+
+// Constants
+public:
+ enum
+ {
+#if TARGET_OS_MAC
+ kMinThreadPriority = 1,
+ kMaxThreadPriority = 63,
+ kDefaultThreadPriority = 31
+#elif TARGET_OS_WIN32
+ kMinThreadPriority = 1,
+ kMaxThreadPriority = 31,
+ kDefaultThreadPriority = THREAD_PRIORITY_NORMAL
+#endif
+ };
+
+// Construction/Destruction
+public:
+ CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPriority = kDefaultThreadPriority, bool inFixedPriority=false, bool inAutoDelete=false);
+ CAPThread(ThreadRoutine inThreadRoutine, void* inParameter, UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible, bool inAutoDelete=false);
+ virtual ~CAPThread();
+
+// Properties
+public:
+#if TARGET_OS_MAC
+ typedef pthread_t NativeThread;
+
+ NativeThread GetNativeThread() { return mPThread; }
+ static NativeThread GetCurrentThread() { return pthread_self(); }
+ static bool IsNativeThreadsEqual(NativeThread a, NativeThread b) { return (a==b); }
+
+ bool operator==(NativeThread b) { return pthread_equal(mPThread,b); }
+
+ pthread_t GetPThread() const { return mPThread; }
+ bool IsCurrentThread() const { return (0 != mPThread) && (pthread_self() == mPThread); }
+ bool IsRunning() const { return 0 != mPThread; }
+#elif TARGET_OS_WIN32
+ typedef unsigned long NativeThread;
+
+ NativeThread GetNativeThread() { return mThreadID; }
+ static NativeThread GetCurrentThread() { return GetCurrentThreadId(); }
+ static bool IsNativeThreadsEqual(NativeThread a, NativeThread b) { return (a==b); }
+
+ bool operator ==(NativeThread b) { return (mThreadID==b); }
+
+ HANDLE GetThreadHandle() const { return mThreadHandle; }
+ UInt32 GetThreadID() const { return mThreadID; }
+ bool IsCurrentThread() const { return (0 != mThreadID) && (GetCurrentThreadId() == mThreadID); }
+ bool IsRunning() const { return 0 != mThreadID; }
+#endif
+
+ bool IsTimeShareThread() const { return !mTimeConstraintSet; }
+ bool IsTimeConstraintThread() const { return mTimeConstraintSet; }
+
+ UInt32 GetPriority() const { return mPriority; }
+ UInt32 GetScheduledPriority();
+ void SetPriority(UInt32 inPriority, bool inFixedPriority=false);
+
+ void GetTimeConstraints(UInt32& outPeriod, UInt32& outComputation, UInt32& outConstraint, bool& outIsPreemptible) const { outPeriod = mPeriod; outComputation = mComputation; outConstraint = mConstraint; outIsPreemptible = mIsPreemptible; }
+ void SetTimeConstraints(UInt32 inPeriod, UInt32 inComputation, UInt32 inConstraint, bool inIsPreemptible);
+ void ClearTimeConstraints() { SetPriority(mPriority); }
+
+ bool WillAutoDelete() const { return mAutoDelete; }
+ void SetAutoDelete(bool b) { mAutoDelete = b; }
+
+#if CoreAudio_Debug
+ void DebugPriority(const char *label);
+#endif
+
+// Actions
+public:
+ virtual void Start();
+
+// Implementation
+protected:
+#if TARGET_OS_MAC
+ static void* Entry(CAPThread* inCAPThread);
+ static UInt32 getScheduledPriority(pthread_t inThread, int inPriorityKind);
+#elif TARGET_OS_WIN32
+ static UInt32 WINAPI Entry(CAPThread* inCAPThread);
+#endif
+
+#if TARGET_OS_MAC
+ pthread_t mPThread;
+ UInt32 mSpawningThreadPriority;
+#elif TARGET_OS_WIN32
+ HANDLE mThreadHandle;
+ unsigned long mThreadID;
+#endif
+ ThreadRoutine mThreadRoutine;
+ void* mThreadParameter;
+ SInt32 mPriority;
+ UInt32 mPeriod;
+ UInt32 mComputation;
+ UInt32 mConstraint;
+ bool mIsPreemptible;
+ bool mTimeConstraintSet;
+ bool mFixedPriority;
+ bool mAutoDelete; // delete self when thread terminates
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAPersistence.cpp b/distrho/src/CoreAudio106/PublicUtility/CAPersistence.cpp
new file mode 100755
index 00000000..dab99cb9
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAPersistence.cpp
@@ -0,0 +1,462 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CACFArray.h"
+#include "CACFDictionary.h"
+
+#include "CAAudioUnit.h"
+#include "CACFString.h"
+#include "CAAudioChannelLayout.h"
+#include "CAAUParameter.h"
+#include "CAAUMIDIMap.h"
+
+#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
+
+#pragma mark __CAStreamBasicDescription
+
+static const CFStringRef kSampleRate = CFSTR("sample rate");
+static const CFStringRef kFormat = CFSTR("format");
+static const CFStringRef kFormatFlags = CFSTR("format flags");
+static const CFStringRef kPacketBytes = CFSTR("packet bytes");
+static const CFStringRef kFramePackets = CFSTR("frame packets");
+static const CFStringRef kFrameBytes = CFSTR("frame bytes");
+static const CFStringRef kFrameChannels = CFSTR("frame channels");
+static const CFStringRef kChannelBits = CFSTR("channel bits");
+
+ // This will return a value that should be used as the key for this struct
+ // and a CFData object that contains the current state of this object
+OSStatus CAStreamBasicDescription::Save (CFPropertyListRef *outData) const
+{
+ CACFDictionary dict(false);
+
+ if (!dict.AddFloat64 (kSampleRate, mSampleRate)) goto error;
+ if (!dict.AddUInt32 (kFormat, mFormatID)) goto error;
+ if (!dict.AddUInt32 (kFormatFlags, mFormatFlags)) goto error;
+ if (!dict.AddUInt32 (kPacketBytes, mBytesPerPacket)) goto error;
+ if (!dict.AddUInt32 (kFramePackets, mFramesPerPacket)) goto error;
+ if (!dict.AddUInt32 (kFrameBytes, mBytesPerFrame)) goto error;
+ if (!dict.AddUInt32 (kFrameChannels, mChannelsPerFrame)) goto error;
+ if (!dict.AddUInt32 (kChannelBits, mBitsPerChannel)) goto error;
+
+ *outData = dict.GetDict();
+
+ return noErr;
+
+error:
+ dict.ShouldRelease (true);
+ return paramErr;
+}
+
+
+ // Given a CFData object generated by the save command, this will re-establish
+ // the CAStreamBasicDescription
+OSStatus CAStreamBasicDescription::Restore (CFPropertyListRef& inData)
+{
+ if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
+ CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
+
+ if (!dict.GetFloat64 (kSampleRate, mSampleRate)) return paramErr;
+ if (!dict.GetUInt32 (kFormat, mFormatID)) return paramErr;
+ if (!dict.GetUInt32 (kFormatFlags, mFormatFlags)) return paramErr;
+ if (!dict.GetUInt32 (kPacketBytes, mBytesPerPacket)) return paramErr;
+ if (!dict.GetUInt32 (kFramePackets, mFramesPerPacket)) return paramErr;
+ if (!dict.GetUInt32 (kFrameBytes, mBytesPerFrame)) return paramErr;
+ if (!dict.GetUInt32 (kFrameChannels, mChannelsPerFrame)) return paramErr;
+ if (!dict.GetUInt32 (kChannelBits, mBitsPerChannel)) return paramErr;
+
+ return noErr;
+}
+
+#pragma mark __CAComponentDescription
+
+static const CFStringRef kType = CFSTR("type");
+static const CFStringRef kSubType = CFSTR("subtype");
+static const CFStringRef kManu = CFSTR("manufacturer");
+
+OSStatus CAComponentDescription::Save (CFPropertyListRef *outData) const
+{
+ CACFDictionary dict(false);
+ if (!dict.AddUInt32 (kType, componentType)) goto error;
+ if (!dict.AddUInt32 (kSubType, componentSubType)) goto error;
+ if (!dict.AddUInt32 (kManu, componentManufacturer)) goto error;
+
+ *outData = dict.GetDict();
+
+ return 0;
+error:
+ dict.ShouldRelease (true);
+ return paramErr;
+}
+
+OSStatus CAComponentDescription::Restore (CFPropertyListRef &inData)
+{
+ if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
+ CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
+
+ if (!dict.GetUInt32 (kType, componentType)) return paramErr;
+ if (!dict.GetUInt32 (kSubType, componentSubType)) return paramErr;
+ if (!dict.GetUInt32 (kManu, componentManufacturer)) return paramErr;
+
+ componentFlags = 0;
+ componentFlagsMask = 0;
+
+ return 0;
+}
+
+#pragma mark __CAComponent
+
+OSStatus CAComponent::Save (CFPropertyListRef *outData) const
+{
+ OSStatus result = mDesc.Save (outData);
+ if (result) return result;
+
+ //add the name string of the component for a human readable name...
+ // this name string is *not* restored when restoring the component
+ CFStringRef name = GetCompName ();
+ if (name && *outData)
+ CFDictionarySetValue ((CFMutableDictionaryRef)(*outData), CFSTR("name"), name);
+
+ return noErr;
+}
+
+OSStatus CAComponent::Restore (CFPropertyListRef &inData)
+{
+ if (mDesc.Restore (inData)) return paramErr;
+
+ Clear();
+
+ mComp = AudioComponentFindNext (NULL, &mDesc);
+ // this will restore the current flags...
+ if (mComp)
+ AudioComponentGetDescription (Comp(), &mDesc);
+
+ return noErr;
+}
+
+
+#pragma mark __CAAudioChannelLayout
+
+static const CFStringRef kACLTagKey = CFSTR("acl tag");
+static const CFStringRef kACLBitmapKey = CFSTR("chan bitmap");
+static const CFStringRef kACLLabelKey = CFSTR("label");
+static const CFStringRef kACLFlagsKey = CFSTR("flags");
+static const CFStringRef kACLCoords0Key = CFSTR("coords 0");
+static const CFStringRef kACLCoords1Key = CFSTR("coords 1");
+static const CFStringRef kACLCoords2Key = CFSTR("coords 2");
+static const CFStringRef kACLDescsKey = CFSTR("descriptions");
+
+OSStatus CAAudioChannelLayout::Save (CFPropertyListRef *outData) const
+{
+ const AudioChannelLayout& layout = Layout();
+
+ CACFDictionary dict (false);
+ if (!dict.AddUInt32 (kACLTagKey, layout.mChannelLayoutTag))
+ goto badadd;
+ if (layout.mChannelBitmap && !dict.AddUInt32 (kACLBitmapKey, layout.mChannelBitmap))
+ goto badadd;
+
+ if (layout.mNumberChannelDescriptions)
+ {
+ CFMutableArrayRef descs = CFArrayCreateMutable (NULL, layout.mNumberChannelDescriptions, &kCFTypeArrayCallBacks);
+
+ const AudioChannelDescription *desc = layout.mChannelDescriptions;
+ for (unsigned int i = 0; i < layout.mNumberChannelDescriptions; ++i, ++desc)
+ {
+ CACFDictionary descDict (true);
+ if (!descDict.AddUInt32 (kACLLabelKey, desc->mChannelLabel))
+ { CFRelease (descs); goto badadd; }
+ if (!descDict.AddUInt32 (kACLFlagsKey, desc->mChannelFlags))
+ { CFRelease (descs); goto badadd; }
+ if (!descDict.AddFloat32 (kACLCoords0Key, desc->mCoordinates[0]))
+ { CFRelease (descs); goto badadd; }
+ if (!descDict.AddFloat32 (kACLCoords1Key, desc->mCoordinates[1]))
+ { CFRelease (descs); goto badadd; }
+ if (!descDict.AddFloat32 (kACLCoords2Key, desc->mCoordinates[2]))
+ { CFRelease (descs); goto badadd; }
+
+ CFArrayAppendValue (descs, descDict.AsPropertyList());
+ }
+ dict.AddArray (kACLDescsKey, descs);
+
+ CFRelease (descs);
+ }
+
+ *outData = dict.GetDict();
+
+ return noErr;
+
+badadd:
+ dict.ShouldRelease(true);
+ return paramErr;
+}
+
+OSStatus CAAudioChannelLayout::Restore (CFPropertyListRef &inData)
+{
+ if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
+ CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
+
+ RefCountedLayout *temp = NULL;
+ AudioChannelLayout* layout;
+
+ CFArrayRef descs = NULL;
+ UInt32 numDescs = 0;
+
+ if (dict.GetArray (kACLDescsKey, descs)) {
+ numDescs = CFArrayGetCount (descs);
+ }
+
+ temp = RefCountedLayout::CreateWithNumberChannelDescriptions(numDescs);
+ layout = temp->GetLayout();
+
+ if (!dict.GetUInt32 (kACLTagKey, layout->mChannelLayoutTag))
+ goto badget;
+ if (dict.HasKey (kACLBitmapKey)) {
+ if (!dict.GetUInt32 (kACLBitmapKey, layout->mChannelBitmap))
+ goto badget;
+ } else
+ layout->mChannelBitmap = 0;
+
+ layout->mNumberChannelDescriptions = numDescs;
+
+ if (numDescs)
+ {
+ AudioChannelDescription *desc = layout->mChannelDescriptions;
+ for (unsigned int i = 0; i < numDescs; ++i, ++desc)
+ {
+ CFDictionaryRef descDict = (CFDictionaryRef)CFArrayGetValueAtIndex (descs, i);
+ CACFDictionary theDesc (descDict, false);
+
+ if (!theDesc.GetUInt32 (kACLLabelKey, desc->mChannelLabel))
+ goto badget;
+ if (!theDesc.GetUInt32 (kACLFlagsKey, desc->mChannelFlags))
+ goto badget;
+ if (!theDesc.GetFloat32 (kACLCoords0Key, desc->mCoordinates[0]))
+ goto badget;
+ if (!theDesc.GetFloat32 (kACLCoords1Key, desc->mCoordinates[1]))
+ goto badget;
+ if (!theDesc.GetFloat32 (kACLCoords2Key, desc->mCoordinates[2]))
+ goto badget;
+ }
+ }
+ if (mLayout)
+ mLayout->release();
+
+ mLayout = temp;
+
+ return noErr;
+
+badget:
+ delete temp;
+ return paramErr;
+}
+
+#pragma mark __AudioUnitParameter
+
+static const CFStringRef kAUScopeStr = CFSTR("scope");
+static const CFStringRef kAUElementIDStr = CFSTR("element ID");
+static const CFStringRef kAUParameterIDStr = CFSTR("paramID");
+
+void CAAUParameter::Save (CFPropertyListRef &outData) const
+{
+ return CAAUParameter::Save (*this, outData);
+}
+
+// static functions to save/restore AudioUnitParameter
+void CAAUParameter::Save (const AudioUnitParameter &inParam, CFPropertyListRef &outData)
+{
+ CACFDictionary dict(false);
+ dict.AddUInt32 (kAUScopeStr, inParam.mScope);
+ dict.AddUInt32 (kAUElementIDStr, inParam.mElement);
+ dict.AddUInt32 (kAUParameterIDStr, inParam.mParameterID);
+
+ outData = dict.AsPropertyList();
+}
+
+OSStatus CAAUParameter::Restore (const CFPropertyListRef inData, AudioUnitParameter &outParam)
+{
+ if (CFGetTypeID (inData) != CFDictionaryGetTypeID()) return paramErr;
+ CACFDictionary dict(static_cast<CFDictionaryRef>(inData), false);
+
+ if (!dict.GetUInt32 (kAUScopeStr, outParam.mScope)) return paramErr;
+ if (!dict.GetUInt32 (kAUElementIDStr, outParam.mElement)) return paramErr;
+ if (!dict.GetUInt32 (kAUParameterIDStr, outParam.mParameterID)) return paramErr;
+ return noErr;
+}
+
+
+#pragma mark __MIDIMap
+
+const CFStringRef kParamMIDIStr = CFSTR("param maps");
+
+const CFStringRef kMIDIFlagsStr = CFSTR("flags");
+const CFStringRef kMIDISubMinStr = CFSTR("sub min");
+const CFStringRef kMIDISubMaxStr = CFSTR("sub max");
+const CFStringRef kMIDIStatusStr = CFSTR("midi status byte");
+const CFStringRef kMIDIDataByteStr = CFSTR("midi data1 byte");
+const CFStringRef kAUStr = CFSTR("unit");
+
+static const CFStringRef kLocalElementIDStr = CFSTR("element ID");
+static const CFStringRef kLocalScopeStr = CFSTR("scope");
+static const CFStringRef kLocalParameterIDStr = CFSTR("paramID");
+
+void CAAUMIDIMap::Save(CFPropertyListRef &outData) const
+{
+ CACFDictionary paramDict(false);
+
+ paramDict.AddUInt32 (kLocalScopeStr, mScope);
+ paramDict.AddUInt32 (kLocalElementIDStr, mElement);
+ paramDict.AddUInt32 (kLocalParameterIDStr, mParameterID);
+ paramDict.AddUInt32 (kMIDIFlagsStr, mFlags);
+ paramDict.AddFloat32 (kMIDISubMinStr, mSubRangeMin);
+ paramDict.AddFloat32 (kMIDISubMaxStr, mSubRangeMax);
+
+ UInt32 data = mStatus;
+ paramDict.AddUInt32 (kMIDIStatusStr, data);
+
+ data = mData1;
+ paramDict.AddUInt32 (kMIDIDataByteStr, data);
+
+ outData = paramDict.GetCFDictionary();
+}
+
+void CAAUMIDIMap::Restore(CFDictionaryRef inData)
+{
+ CACFDictionary paramDict (inData, false);
+
+ if (!paramDict.GetUInt32 (kLocalScopeStr, mScope)) return;
+ if (!paramDict.GetUInt32 (kLocalElementIDStr, mElement)) return;
+ if (!paramDict.GetUInt32 (kLocalParameterIDStr, mParameterID)) return;
+ if (!paramDict.GetUInt32 (kMIDIFlagsStr, mFlags)) return;
+ if (!paramDict.GetFloat32 (kMIDISubMinStr, mSubRangeMin)) return;
+ if (!paramDict.GetFloat32 (kMIDISubMaxStr, mSubRangeMax)) return;
+ UInt32 data;
+ if (!paramDict.GetUInt32 (kMIDIStatusStr, data)) return;
+ mStatus = data;
+ if (!paramDict.GetUInt32 (kMIDIDataByteStr, data)) return;
+ mData1 = data;
+}
+
+void CAAUMIDIMap::SaveAsMapPList (AudioUnit inUnit, const AUParameterMIDIMapping* inMappings, UInt32 inNumMappings, CFPropertyListRef &outData, CFStringRef inName)
+{
+
+ CACFDictionary mappingDict (false);
+ CACFArray maps (true);
+
+ for (UInt32 i = 0; i< inNumMappings; ++i)
+ {
+ CFPropertyListRef data;
+ CAAUMIDIMap paramMap(inMappings[i]);
+ paramMap.Save (data);
+ if (data)
+ {
+ maps.AppendCFType (data);
+ CFRelease(data);
+ }
+ }
+
+ if (maps.GetNumberItems()) {
+ mappingDict.AddCFType (kParamMIDIStr, maps.GetCFArray());
+
+ // Add the AU info here - where this map came from
+ CAAudioUnit au (inUnit);
+ CFPropertyListRef data;
+ au.Comp().Save (&data);
+
+ mappingDict.AddCFType (kAUStr, data);
+ CFRelease(data);
+
+ if (!inName) inName = CFSTR("Untitled");
+ mappingDict.AddString (CFSTR("name"), inName);
+
+ mappingDict.AddUInt32 (CFSTR("version"), 1);
+
+ outData = mappingDict.AsPropertyList();
+ } else {
+ mappingDict.ShouldRelease(true);
+ outData = NULL;
+ }
+}
+
+UInt32 CAAUMIDIMap::NumberOfMaps (const CFDictionaryRef inData)
+{
+ CACFDictionary dict (inData, false);
+
+ if (dict.HasKey (kParamMIDIStr))
+ {
+ CFArrayRef cfArray;
+ dict.GetArray (kParamMIDIStr, cfArray);
+
+ CACFArray array (cfArray, false);
+
+ return array.GetNumberItems();
+ }
+ return 0;
+}
+
+void CAAUMIDIMap::RestoreFromMapPList (const CFDictionaryRef inData, AUParameterMIDIMapping* outMappings, UInt32 inNumMappings)
+{
+
+ CACFDictionary dict (inData, false);
+
+ if (dict.HasKey (kParamMIDIStr))
+ {
+ CFArrayRef cfArray;
+ dict.GetArray (kParamMIDIStr, cfArray);
+
+ CACFArray array (cfArray, false);
+
+ UInt32 count = array.GetNumberItems();
+ if (count > inNumMappings)
+ count = inNumMappings;
+
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ CFDictionaryRef paramsDictRef;
+ if (!array.GetDictionary(i, paramsDictRef))
+ return;
+
+ CAAUMIDIMap parameterMap;
+ parameterMap.Restore(paramsDictRef);
+ outMappings[i] = parameterMap;
+ }
+ }
+}
+
+
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAProcess.cpp b/distrho/src/CoreAudio106/PublicUtility/CAProcess.cpp
new file mode 100755
index 00000000..d9b5095c
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAProcess.cpp
@@ -0,0 +1,79 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CAProcess.h"
+#include <signal.h>
+#include <unistd.h>
+
+//=============================================================================
+// CAProcess
+//=============================================================================
+
+bool CAProcess::ProcessExists(pid_t inPID)
+{
+ // pids <= 0 are reserved for special purposes and -1 is
+ // used as a sentinel value by the HAL.
+ bool theAnswer = inPID > 0;
+
+ if(theAnswer)
+ {
+ // according to kill(2), the process exists if kill(pid, 0) returns 0
+ theAnswer = kill(inPID, 0) == 0;
+ }
+
+
+ return theAnswer;
+}
+
+pid_t CAProcess::GetPID()
+{
+ if(sPID == -1)
+ {
+ sPID = getpid();
+ }
+
+ return sPID;
+}
+
+pid_t CAProcess::sPID = -1;
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAProcess.h b/distrho/src/CoreAudio106/PublicUtility/CAProcess.h
new file mode 100755
index 00000000..e1928881
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAProcess.h
@@ -0,0 +1,69 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CAProcess_h__)
+#define __CAProcess_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include <sys/types.h>
+
+//=============================================================================
+// CAProcess
+//
+// Wrapper for utilities for dealing with Unix Processes.
+//=============================================================================
+
+class CAProcess
+{
+
+// operations
+public:
+ static bool ProcessExists(pid_t inPID);
+ static pid_t GetPID();
+
+private:
+ static pid_t sPID;
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAPropertyAddress.h b/distrho/src/CoreAudio106/PublicUtility/CAPropertyAddress.h
new file mode 100755
index 00000000..acc1a152
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAPropertyAddress.h
@@ -0,0 +1,161 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CAPropertyAddress_h__)
+#define __CAPropertyAddress_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// PublicUtility Includes
+#include "CADebugMacros.h"
+
+// System Includes
+#include <CoreAudio/AudioHardware.h>
+
+// Standard Library Includes
+#include <algorithm>
+#include <functional>
+#include <vector>
+
+//==================================================================================================
+// CAPropertyAddress
+//
+// CAPropertyAddress extends the AudioObjectPropertyAddress structure to C++ including constructors
+// and other utility operations. Note that there is no defined operator< or operator== because the
+// presence of wildcards for the fields make comparisons ambiguous without specifying whether or
+// not to take the wildcards into account. Consequently, if you want to use this struct in an STL
+// data structure, you'll need to specify the approriate function object explicitly in the template
+// declaration.
+//==================================================================================================
+
+struct CAPropertyAddress
+:
+ public AudioObjectPropertyAddress
+{
+
+// Construction/Destruction
+public:
+ CAPropertyAddress() : AudioObjectPropertyAddress() { mSelector = 0; mScope = kAudioObjectPropertyScopeGlobal; mElement = kAudioObjectPropertyElementMaster; }
+ CAPropertyAddress(AudioObjectPropertySelector inSelector) : AudioObjectPropertyAddress() { mSelector = inSelector; mScope = kAudioObjectPropertyScopeGlobal; mElement = kAudioObjectPropertyElementMaster; }
+ CAPropertyAddress(AudioObjectPropertySelector inSelector, AudioObjectPropertyScope inScope) : AudioObjectPropertyAddress() { mSelector = inSelector; mScope = inScope; mElement = kAudioObjectPropertyElementMaster; }
+ CAPropertyAddress(AudioObjectPropertySelector inSelector, AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) : AudioObjectPropertyAddress() { mSelector = inSelector; mScope = inScope; mElement = inElement; }
+ CAPropertyAddress(const AudioObjectPropertyAddress& inAddress) : AudioObjectPropertyAddress(inAddress){}
+ CAPropertyAddress(const CAPropertyAddress& inAddress) : AudioObjectPropertyAddress(inAddress){}
+ CAPropertyAddress& operator=(const AudioObjectPropertyAddress& inAddress) { AudioObjectPropertyAddress::operator=(inAddress); return *this; }
+ CAPropertyAddress& operator=(const CAPropertyAddress& inAddress) { AudioObjectPropertyAddress::operator=(inAddress); return *this; }
+
+// Operations
+public:
+ static bool IsSameAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) { return (inAddress1.mScope == inAddress2.mScope) && (inAddress1.mSelector == inAddress2.mSelector) && (inAddress1.mElement == inAddress2.mElement); }
+ static bool IsCongruentSelector(AudioObjectPropertySelector inSelector1, AudioObjectPropertySelector inSelector2) { return (inSelector1 == inSelector2) || (inSelector1 == kAudioObjectPropertySelectorWildcard) || (inSelector2 == kAudioObjectPropertySelectorWildcard); }
+ static bool IsCongruentScope(AudioObjectPropertyScope inScope1, AudioObjectPropertyScope inScope2) { return (inScope1 == inScope2) || (inScope1 == kAudioObjectPropertyScopeWildcard) || (inScope2 == kAudioObjectPropertyScopeWildcard); }
+ static bool IsCongruentElement(AudioObjectPropertyElement inElement1, AudioObjectPropertyElement inElement2) { return (inElement1 == inElement2) || (inElement1 == kAudioObjectPropertyElementWildcard) || (inElement2 == kAudioObjectPropertyElementWildcard); }
+ static bool IsCongruentAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) { return IsCongruentScope(inAddress1.mScope, inAddress2.mScope) && IsCongruentSelector(inAddress1.mSelector, inAddress2.mSelector) && IsCongruentElement(inAddress1.mElement, inAddress2.mElement); }
+
+// STL Helpers
+public:
+ struct EqualTo : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
+ {
+ bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { return IsSameAddress(inAddress1, inAddress2); }
+ };
+
+ struct LessThan : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
+ {
+ bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { bool theAnswer = false; if(inAddress1.mScope != inAddress2.mScope) { theAnswer = inAddress1.mScope < inAddress2.mScope; } else if(inAddress1.mSelector != inAddress2.mSelector) { theAnswer = inAddress1.mSelector < inAddress2.mSelector; } else { theAnswer = inAddress1.mElement < inAddress2.mElement; } return theAnswer; }
+ };
+
+ struct CongruentEqualTo : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
+ {
+ bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { return IsCongruentAddress(inAddress1, inAddress2); }
+ };
+
+ struct CongruentLessThan : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
+ {
+ bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { bool theAnswer = false; if(!IsCongruentScope(inAddress1.mScope, inAddress2.mScope)) { theAnswer = inAddress1.mScope < inAddress2.mScope; } else if(!IsCongruentSelector(inAddress1.mSelector, inAddress2.mSelector)) { theAnswer = inAddress1.mSelector < inAddress2.mSelector; } else if(!IsCongruentElement(inAddress1.mElement, inAddress2.mElement)) { theAnswer = inAddress1.mElement < inAddress2.mElement; } return theAnswer; }
+ };
+
+};
+
+//==================================================================================================
+// CAPropertyAddressList
+//
+// An auto-resizing array of CAPropertyAddress structures.
+//==================================================================================================
+
+class CAPropertyAddressList
+{
+
+// Construction/Destruction
+public:
+ CAPropertyAddressList() : mAddressList() {}
+ CAPropertyAddressList(const CAPropertyAddressList& inAddressList) : mAddressList(inAddressList.mAddressList) {}
+ CAPropertyAddressList& operator=(const CAPropertyAddressList& inAddressList) { mAddressList = inAddressList.mAddressList; return *this; }
+ ~CAPropertyAddressList() {}
+
+// Operations
+public:
+ bool IsEmpty() const { return mAddressList.empty(); }
+ UInt32 GetNumberItems() const { return ToUInt32(mAddressList.size()); }
+ void GetItemByIndex(UInt32 inIndex, AudioObjectPropertyAddress& outAddress) const { if(inIndex < mAddressList.size()) { outAddress = mAddressList.at(inIndex); } }
+ const AudioObjectPropertyAddress* GetItems() const { return &(*mAddressList.begin()); }
+ AudioObjectPropertyAddress* GetItems() { return &(*mAddressList.begin()); }
+
+ bool HasItem(const AudioObjectPropertyAddress& inAddress) const { AddressList::const_iterator theIterator = std::find_if(mAddressList.begin(), mAddressList.end(), std::bind1st(CAPropertyAddress::CongruentEqualTo(), inAddress)); return theIterator != mAddressList.end(); }
+ bool HasExactItem(const AudioObjectPropertyAddress& inAddress) const { AddressList::const_iterator theIterator = std::find_if(mAddressList.begin(), mAddressList.end(), std::bind1st(CAPropertyAddress::EqualTo(), inAddress)); return theIterator != mAddressList.end(); }
+
+ void AppendItem(const AudioObjectPropertyAddress& inAddress) { mAddressList.push_back(inAddress); }
+ void AppendUniqueItem(const AudioObjectPropertyAddress& inAddress) { if(!HasItem(inAddress)) { mAddressList.push_back(inAddress); } }
+ void AppendUniqueExactItem(const AudioObjectPropertyAddress& inAddress) { if(!HasExactItem(inAddress)) { mAddressList.push_back(inAddress); } }
+ void InsertItemAtIndex(UInt32 inIndex, const AudioObjectPropertyAddress& inAddress) { if(inIndex < mAddressList.size()) { AddressList::iterator theIterator = mAddressList.begin(); std::advance(theIterator, inIndex); mAddressList.insert(theIterator, inAddress); } else { mAddressList.push_back(inAddress); } }
+ void EraseExactItem(const AudioObjectPropertyAddress& inAddress) { AddressList::iterator theIterator = std::find_if(mAddressList.begin(), mAddressList.end(), std::bind1st(CAPropertyAddress::EqualTo(), inAddress)); if(theIterator != mAddressList.end()) { mAddressList.erase(theIterator); } }
+ void EraseItemAtIndex(UInt32 inIndex) { if(inIndex < mAddressList.size()) { AddressList::iterator theIterator = mAddressList.begin(); std::advance(theIterator, inIndex); mAddressList.erase(theIterator); } }
+ void EraseAllItems() { mAddressList.clear(); }
+
+// Implementation
+private:
+ typedef std::vector<CAPropertyAddress> AddressList;
+
+ AddressList mAddressList;
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAReferenceCounted.h b/distrho/src/CoreAudio106/PublicUtility/CAReferenceCounted.h
new file mode 100755
index 00000000..88ea6a36
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAReferenceCounted.h
@@ -0,0 +1,78 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAReferenceCounted_h__
+#define __CAReferenceCounted_h__
+
+#include "CAAtomic.h"
+
+// base class for reference-counted objects
+class CAReferenceCounted {
+public:
+ CAReferenceCounted() : mRefCount(1) {}
+
+ void retain() { CAAtomicIncrement32(&mRefCount); }
+
+ void release()
+ {
+ SInt32 rc = CAAtomicDecrement32 (&mRefCount);
+ if (rc == 0) {
+ releaseObject();
+ }
+ }
+
+protected:
+ virtual ~CAReferenceCounted() { }
+
+ virtual void releaseObject ()
+ {
+ delete this;
+ }
+
+ SInt32 GetReferenceCount() const { return mRefCount; }
+private:
+ SInt32 mRefCount;
+
+ CAReferenceCounted(const CAReferenceCounted &a) : mRefCount(0) { }
+ CAReferenceCounted &operator=(const CAReferenceCounted &a) { return *this; }
+};
+
+
+#endif // __CAReferenceCounted_h__
diff --git a/distrho/src/CoreAudio106/PublicUtility/CARingBuffer.cpp b/distrho/src/CoreAudio106/PublicUtility/CARingBuffer.cpp
new file mode 100755
index 00000000..b237a8a9
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CARingBuffer.cpp
@@ -0,0 +1,328 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CARingBuffer.h"
+#include "CABitOperations.h"
+#include "CAAutoDisposer.h"
+#include "CAAtomic.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <libkern/OSAtomic.h>
+
+CARingBuffer::CARingBuffer() :
+ mBuffers(NULL), mNumberChannels(0), mCapacityFrames(0), mCapacityBytes(0)
+{
+
+}
+
+CARingBuffer::~CARingBuffer()
+{
+ Deallocate();
+}
+
+
+void CARingBuffer::Allocate(int nChannels, UInt32 bytesPerFrame, UInt32 capacityFrames)
+{
+ Deallocate();
+
+ //capacityFrames = NextPowerOfTwo(capacityFrames);
+
+ mNumberChannels = nChannels;
+ mBytesPerFrame = bytesPerFrame;
+ mCapacityFrames = capacityFrames;
+ //mCapacityFramesMask = capacityFrames - 1;
+ mCapacityBytes = bytesPerFrame * capacityFrames;
+
+ // put everything in one memory allocation, first the pointers, then the deinterleaved channels
+ UInt32 allocSize = (mCapacityBytes + sizeof(Byte *)) * nChannels;
+ Byte *p = (Byte *)CA_malloc(allocSize);
+ memset(p, 0, allocSize);
+ mBuffers = (Byte **)p;
+ p += nChannels * sizeof(Byte *);
+ for (int i = 0; i < nChannels; ++i) {
+ mBuffers[i] = p;
+ p += mCapacityBytes;
+ }
+
+ for (UInt32 i = 0; i<kGeneralRingTimeBoundsQueueSize; ++i)
+ {
+ mTimeBoundsQueue[i].mStartTime = 0;
+ mTimeBoundsQueue[i].mEndTime = 0;
+ mTimeBoundsQueue[i].mUpdateCounter = 0;
+ }
+ mTimeBoundsQueuePtr = 0;
+}
+
+void CARingBuffer::Deallocate()
+{
+ if (mBuffers) {
+ free(mBuffers);
+ mBuffers = NULL;
+ }
+ mNumberChannels = 0;
+ mCapacityBytes = 0;
+ mCapacityFrames = 0;
+}
+
+inline void ZeroRange(Byte **buffers, int nchannels, int offset, int nbytes)
+{
+ while (--nchannels >= 0) {
+ memset(*buffers + offset, 0, nbytes);
+ ++buffers;
+ }
+}
+
+inline void StoreABL(Byte **buffers, int destOffset, const AudioBufferList *abl, int srcOffset, int nbytes)
+{
+ int nchannels = abl->mNumberBuffers;
+ const AudioBuffer *src = abl->mBuffers;
+ while (--nchannels >= 0) {
+ memcpy(*buffers + destOffset, (Byte *)src->mData + srcOffset, nbytes);
+ ++buffers;
+ ++src;
+ }
+}
+
+inline void FetchABL(AudioBufferList *abl, int destOffset, Byte **buffers, int srcOffset, int nbytes)
+{
+ int nchannels = abl->mNumberBuffers;
+ AudioBuffer *dest = abl->mBuffers;
+ while (--nchannels >= 0) {
+ memcpy((Byte *)dest->mData + destOffset, *buffers + srcOffset, nbytes);
+ ++buffers;
+ ++dest;
+ }
+}
+
+inline void ZeroABL(AudioBufferList *abl, int destOffset, int nbytes)
+{
+ int nBuffers = abl->mNumberBuffers;
+ AudioBuffer *dest = abl->mBuffers;
+ while (--nBuffers >= 0) {
+ memset((Byte *)dest->mData + destOffset, 0, nbytes);
+ ++dest;
+ }
+}
+
+
+CARingBufferError CARingBuffer::Store(const AudioBufferList *abl, UInt32 framesToWrite, SampleTime startWrite)
+{
+ if (framesToWrite > mCapacityFrames)
+ return kCARingBufferError_TooMuch; // too big!
+
+ SampleTime endWrite = startWrite + framesToWrite;
+
+ if (startWrite < EndTime()) {
+ // going backwards, throw everything out
+ SetTimeBounds(startWrite, startWrite);
+ } else if (endWrite - StartTime() <= mCapacityFrames) {
+ // the buffer has not yet wrapped and will not need to
+ } else {
+ // advance the start time past the region we are about to overwrite
+ SampleTime newStart = endWrite - mCapacityFrames; // one buffer of time behind where we're writing
+ SampleTime newEnd = std::max(newStart, EndTime());
+ SetTimeBounds(newStart, newEnd);
+ }
+
+ // write the new frames
+ Byte **buffers = mBuffers;
+ int nchannels = mNumberChannels;
+ int offset0, offset1, nbytes;
+ SampleTime curEnd = EndTime();
+
+ if (startWrite > curEnd) {
+ // we are skipping some samples, so zero the range we are skipping
+ offset0 = FrameOffset(curEnd);
+ offset1 = FrameOffset(startWrite);
+ if (offset0 < offset1)
+ ZeroRange(buffers, nchannels, offset0, offset1 - offset0);
+ else {
+ ZeroRange(buffers, nchannels, offset0, mCapacityBytes - offset0);
+ ZeroRange(buffers, nchannels, 0, offset1);
+ }
+ offset0 = offset1;
+ } else {
+ offset0 = FrameOffset(startWrite);
+ }
+
+ offset1 = FrameOffset(endWrite);
+ if (offset0 < offset1)
+ StoreABL(buffers, offset0, abl, 0, offset1 - offset0);
+ else {
+ nbytes = mCapacityBytes - offset0;
+ StoreABL(buffers, offset0, abl, 0, nbytes);
+ StoreABL(buffers, 0, abl, nbytes, offset1);
+ }
+
+ // now update the end time
+ SetTimeBounds(StartTime(), endWrite);
+
+ return kCARingBufferError_OK; // success
+}
+
+void CARingBuffer::SetTimeBounds(SampleTime startTime, SampleTime endTime)
+{
+ UInt32 nextPtr = mTimeBoundsQueuePtr + 1;
+ UInt32 index = nextPtr & kGeneralRingTimeBoundsQueueMask;
+
+ mTimeBoundsQueue[index].mStartTime = startTime;
+ mTimeBoundsQueue[index].mEndTime = endTime;
+ mTimeBoundsQueue[index].mUpdateCounter = nextPtr;
+ CAAtomicCompareAndSwap32Barrier(mTimeBoundsQueuePtr, mTimeBoundsQueuePtr + 1, (SInt32*)&mTimeBoundsQueuePtr);
+}
+
+CARingBufferError CARingBuffer::GetTimeBounds(SampleTime &startTime, SampleTime &endTime)
+{
+ for (int i=0; i<8; ++i) // fail after a few tries.
+ {
+ UInt32 curPtr = mTimeBoundsQueuePtr;
+ UInt32 index = curPtr & kGeneralRingTimeBoundsQueueMask;
+ CARingBuffer::TimeBounds* bounds = mTimeBoundsQueue + index;
+
+ startTime = bounds->mStartTime;
+ endTime = bounds->mEndTime;
+ UInt32 newPtr = bounds->mUpdateCounter;
+
+ if (newPtr == curPtr)
+ return kCARingBufferError_OK;
+ }
+ return kCARingBufferError_CPUOverload;
+}
+
+CARingBufferError CARingBuffer::CheckTimeBounds(SampleTime& startRead, SampleTime& endRead)
+{
+ SampleTime startTime, endTime;
+
+ CARingBufferError err = GetTimeBounds(startTime, endTime);
+ if (err) return err;
+
+ startRead = std::max(startRead, startTime);
+ endRead = std::min(endRead, endTime);
+
+ if (startRead < startTime)
+ {
+ if (endRead > endTime)
+ return kCARingBufferError_TooMuch;
+
+ if (endRead < startTime)
+ return kCARingBufferError_WayBehind;
+ else
+ return kCARingBufferError_SlightlyBehind;
+ }
+
+ if (endRead > endTime) // we are going to read chunks of zeros its okay
+ {
+ if (startRead > endTime)
+ return kCARingBufferError_WayAhead;
+ else
+ return kCARingBufferError_SlightlyAhead;
+ }
+
+ return kCARingBufferError_OK; // success
+}
+
+CARingBufferError worse(CARingBufferError a, CARingBufferError b)
+{
+ // return the worst error.
+ CARingBufferError aa = a < 0 ? -a : a;
+ CARingBufferError bb = b < 0 ? -b : b;
+ if (aa > bb) return a;
+ return b;
+}
+
+CARingBufferError CARingBuffer::Fetch(AudioBufferList *abl, UInt32 nFrames, SampleTime startRead, bool outOfBoundsOK)
+{
+ SampleTime endRead = startRead + nFrames;
+
+ SampleTime startRead0 = startRead;
+ SampleTime endRead0 = endRead;
+ SampleTime size;
+
+ CARingBufferError err = CheckTimeBounds(startRead, endRead);
+ size = endRead - startRead;
+ if (err) {
+ if (!outOfBoundsOK) return err;
+ if (size <= 0) return err; // there is nothing to read
+ }
+
+ SInt32 destStartOffset = startRead - startRead0;
+ if (destStartOffset > 0) {
+ ZeroABL(abl, 0, destStartOffset * mBytesPerFrame);
+ }
+
+ SInt32 destEndSize = endRead0 - endRead;
+ if (destEndSize > 0) {
+ ZeroABL(abl, destStartOffset + size, destEndSize * mBytesPerFrame);
+ }
+
+ Byte **buffers = mBuffers;
+ int offset0 = FrameOffset(startRead);
+ int offset1 = FrameOffset(endRead);
+ int nbytes;
+
+ if (offset0 < offset1) {
+ FetchABL(abl, destStartOffset, buffers, offset0, nbytes = offset1 - offset0);
+ } else {
+ nbytes = mCapacityBytes - offset0;
+ FetchABL(abl, destStartOffset, buffers, offset0, nbytes);
+ FetchABL(abl, destStartOffset + nbytes, buffers, 0, offset1);
+ nbytes += offset1;
+ }
+
+ int nchannels = abl->mNumberBuffers;
+ AudioBuffer *dest = abl->mBuffers;
+ while (--nchannels >= 0)
+ {
+ dest->mDataByteSize = nbytes;
+ dest++;
+ }
+
+ // have to check bounds again because the data may have been overwritten before we could finish reading it.
+ OSStatus err2 = CheckTimeBounds(startRead, endRead);
+ err2 = worse(err, err2);
+ size = endRead - startRead;
+ if (err2) {
+ if (!outOfBoundsOK) return err2;
+ if (size <= 0) return err2; // there is nothing to read
+ }
+ return err2;
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CARingBuffer.h b/distrho/src/CoreAudio106/PublicUtility/CARingBuffer.h
new file mode 100755
index 00000000..1e662f6f
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CARingBuffer.h
@@ -0,0 +1,124 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+
+#ifndef CARingBuffer_Header
+#define CARingBuffer_Header
+
+enum {
+ kCARingBufferError_WayBehind = -2, // both fetch times are earlier than buffer start time
+ kCARingBufferError_SlightlyBehind = -1, // fetch start time is earlier than buffer start time (fetch end time OK)
+ kCARingBufferError_OK = 0,
+ kCARingBufferError_SlightlyAhead = 1, // fetch end time is later than buffer end time (fetch start time OK)
+ kCARingBufferError_WayAhead = 2, // both fetch times are later than buffer end time
+ kCARingBufferError_TooMuch = 3, // fetch start time is earlier than buffer start time and fetch end time is later than buffer end time
+ kCARingBufferError_CPUOverload = 4 // the reader is unable to get enough CPU cycles to capture a consistent snapshot of the time bounds
+};
+
+typedef SInt32 CARingBufferError;
+
+const UInt32 kGeneralRingTimeBoundsQueueSize = 32;
+const UInt32 kGeneralRingTimeBoundsQueueMask = kGeneralRingTimeBoundsQueueSize - 1;
+
+class CARingBuffer {
+public:
+ typedef SInt64 SampleTime;
+
+ CARingBuffer();
+ ~CARingBuffer();
+
+ void Allocate(int nChannels, UInt32 bytesPerFrame, UInt32 capacityFrames);
+ // capacityFrames will be rounded up to a power of 2
+ void Deallocate();
+
+ CARingBufferError Store(const AudioBufferList *abl, UInt32 nFrames, SampleTime frameNumber);
+ // Copy nFrames of data into the ring buffer at the specified sample time.
+ // The sample time should normally increase sequentially, though gaps
+ // are filled with zeroes. A sufficiently large gap effectively empties
+ // the buffer before storing the new data.
+
+ // If frameNumber is less than the previous frame number, the behavior is undefined.
+
+ // Return false for failure (buffer not large enough).
+
+ CARingBufferError Fetch(AudioBufferList *abl, UInt32 nFrames, SampleTime frameNumber, bool aheadOK);
+ // will alter mNumDataBytes of the buffers
+
+ CARingBufferError GetTimeBounds(SampleTime &startTime, SampleTime &endTime);
+
+protected:
+
+ int FrameOffset(SampleTime frameNumber) { return (frameNumber % mCapacityFrames) * mBytesPerFrame; }
+
+ CARingBufferError CheckTimeBounds(SampleTime& startRead, SampleTime& endRead);
+
+ // these should only be called from Store.
+ SampleTime StartTime() const { return mTimeBoundsQueue[mTimeBoundsQueuePtr & kGeneralRingTimeBoundsQueueMask].mStartTime; }
+ SampleTime EndTime() const { return mTimeBoundsQueue[mTimeBoundsQueuePtr & kGeneralRingTimeBoundsQueueMask].mEndTime; }
+ void SetTimeBounds(SampleTime startTime, SampleTime endTime);
+
+protected:
+ Byte ** mBuffers; // allocated in one chunk of memory
+ int mNumberChannels;
+ UInt32 mBytesPerFrame; // within one deinterleaved channel
+ UInt32 mCapacityFrames; // per channel, must be a power of 2
+ //UInt32 mCapacityFramesMask;
+ UInt32 mCapacityBytes; // per channel
+
+ // range of valid sample time in the buffer
+ typedef struct {
+ volatile SampleTime mStartTime;
+ volatile SampleTime mEndTime;
+ volatile UInt32 mUpdateCounter;
+ } TimeBounds;
+
+ CARingBuffer::TimeBounds mTimeBoundsQueue[kGeneralRingTimeBoundsQueueSize];
+ UInt32 mTimeBoundsQueuePtr;
+};
+
+
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CASettingsStorage.cpp b/distrho/src/CoreAudio106/PublicUtility/CASettingsStorage.cpp
new file mode 100755
index 00000000..c88d8756
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CASettingsStorage.cpp
@@ -0,0 +1,686 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CASettingsStorage.h"
+
+// PublicUtility Includes
+#include "CAAutoDisposer.h"
+#include "CACFData.h"
+#include "CACFDistributedNotification.h"
+#include "CACFNumber.h"
+
+// Stamdard Library Includes
+#include <string.h>
+#include <sys/fcntl.h>
+
+//==================================================================================================
+// CASettingsStorage
+//==================================================================================================
+
+CASettingsStorage::CASettingsStorage(const char* inSettingsFilePath, mode_t inSettingsFileAccessMode)
+{
+ size_t theLength = strlen(inSettingsFilePath);
+ mSettingsFilePath = new char[theLength + 2];
+ strlcpy(mSettingsFilePath, inSettingsFilePath, theLength + 2);
+
+ mSettingsFileAccessMode = inSettingsFileAccessMode;
+
+ mSettingsCache = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ mSettingsCacheTime.tv_sec = 0;
+ mSettingsCacheTime.tv_nsec = 0;
+
+ mSettingsCacheForceRefresh = true;
+}
+
+CASettingsStorage::~CASettingsStorage()
+{
+ delete[] mSettingsFilePath;
+
+ if(mSettingsCache != NULL)
+ {
+ CFRelease(mSettingsCache);
+ }
+}
+
+void CASettingsStorage::CopyBoolValue(CFStringRef inKey, bool& outValue, bool inDefaultValue) const
+{
+ // initialize the return value
+ outValue = inDefaultValue;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, NULL);
+
+ // for this type, NULL is an invalid value
+ if(theValue != NULL)
+ {
+ // bools can be made from either CFBooleans or CFNumbers
+ if(CFGetTypeID(theValue) == CFBooleanGetTypeID())
+ {
+ // get the return value from the CF object
+ outValue = CFBooleanGetValue(static_cast<CFBooleanRef>(theValue));
+ }
+ else if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // get the numeric value
+ SInt32 theNumericValue = 0;
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue);
+
+ // non-zero indicates true
+ outValue = theNumericValue != 0;
+ }
+
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+ }
+}
+
+void CASettingsStorage::CopySInt32Value(CFStringRef inKey, SInt32& outValue, SInt32 inDefaultValue) const
+{
+ // initialize the return value
+ outValue = inDefaultValue;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, NULL);
+
+ // for this type, NULL is an invalid value
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // get the return value from the CF object
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+ }
+
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+ }
+}
+
+void CASettingsStorage::CopyUInt32Value(CFStringRef inKey, UInt32& outValue, UInt32 inDefaultValue) const
+{
+ // initialize the return value
+ outValue = inDefaultValue;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, NULL);
+
+ // for this type, NULL is an invalid value
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // get the return value from the CF object
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+ }
+
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+ }
+}
+
+void CASettingsStorage::CopySInt64Value(CFStringRef inKey, SInt64& outValue, SInt64 inDefaultValue) const
+{
+ // initialize the return value
+ outValue = inDefaultValue;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, NULL);
+
+ // for this type, NULL is an invalid value
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // get the return value from the CF object
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
+ }
+
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+ }
+}
+
+void CASettingsStorage::CopyUInt64Value(CFStringRef inKey, UInt64& outValue, UInt64 inDefaultValue) const
+{
+ // initialize the return value
+ outValue = inDefaultValue;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, NULL);
+
+ // for this type, NULL is an invalid value
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // get the return value from the CF object
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
+ }
+
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+ }
+}
+
+void CASettingsStorage::CopyFloat32Value(CFStringRef inKey, Float32& outValue, Float32 inDefaultValue) const
+{
+ // initialize the return value
+ outValue = inDefaultValue;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, NULL);
+
+ // for this type, NULL is an invalid value
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // get the return value from the CF object
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat32Type, &outValue);
+ }
+
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+ }
+}
+
+void CASettingsStorage::CopyFloat64Value(CFStringRef inKey, Float64& outValue, Float64 inDefaultValue) const
+{
+ // initialize the return value
+ outValue = inDefaultValue;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, NULL);
+
+ // for this type, NULL is an invalid value
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // get the return value from the CF object
+ CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat64Type, &outValue);
+ }
+
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+ }
+}
+
+void CASettingsStorage::CopyNumberValue(CFStringRef inKey, CFNumberRef& outValue, CFNumberRef inDefaultValue) const
+{
+ // initialize the return value
+ outValue = NULL;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, inDefaultValue);
+
+ // for this type, NULL is a valid value, but requires less work
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFNumberGetTypeID())
+ {
+ // set the return value to the CF object we are returning
+ outValue = static_cast<CFNumberRef>(theValue);
+ }
+ else
+ {
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+
+ // set the return value to the default value
+ outValue = inDefaultValue;
+
+ // and retain it
+ CFRetain(outValue);
+ }
+ }
+}
+
+void CASettingsStorage::CopyStringValue(CFStringRef inKey, CFStringRef& outValue, CFStringRef inDefaultValue) const
+{
+ // initialize the return value
+ outValue = NULL;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, inDefaultValue);
+
+ // for this type, NULL is a valid value, but requires less work
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFStringGetTypeID())
+ {
+ // set the return value to the CF object we are returning
+ outValue = static_cast<CFStringRef>(theValue);
+ }
+ else
+ {
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+
+ // set the return value to the default value
+ outValue = inDefaultValue;
+
+ // and retain it
+ CFRetain(outValue);
+ }
+ }
+}
+
+void CASettingsStorage::CopyArrayValue(CFStringRef inKey, CFArrayRef& outValue, CFArrayRef inDefaultValue) const
+{
+ // initialize the return value
+ outValue = NULL;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, inDefaultValue);
+
+ // for this type, NULL is a valid value, but requires less work
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFArrayGetTypeID())
+ {
+ // set the return value to the CF object we are returning
+ outValue = static_cast<CFArrayRef>(theValue);
+ }
+ else
+ {
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+
+ // set the return value to the default value
+ outValue = inDefaultValue;
+
+ // and retain it
+ CFRetain(outValue);
+ }
+ }
+}
+
+void CASettingsStorage::CopyDictionaryValue(CFStringRef inKey, CFDictionaryRef& outValue, CFDictionaryRef inDefaultValue) const
+{
+ // initialize the return value
+ outValue = NULL;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, inDefaultValue);
+
+ // for this type, NULL is a valid value, but requires less work
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFDictionaryGetTypeID())
+ {
+ // set the return value to the CF object we are returning
+ outValue = static_cast<CFDictionaryRef>(theValue);
+ }
+ else
+ {
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+
+ // set the return value to the default value
+ outValue = inDefaultValue;
+
+ // and retain it
+ CFRetain(outValue);
+ }
+ }
+}
+
+void CASettingsStorage::CopyDataValue(CFStringRef inKey, CFDataRef& outValue, CFDataRef inDefaultValue) const
+{
+ // initialize the return value
+ outValue = NULL;
+
+ // get the raw value
+ CFTypeRef theValue = NULL;
+ CopyCFTypeValue(inKey, theValue, inDefaultValue);
+
+ // for this type, NULL is a valid value, but requires less work
+ if(theValue != NULL)
+ {
+ // make sure we are dealing with the right kind of CF object
+ if(CFGetTypeID(theValue) == CFDataGetTypeID())
+ {
+ // set the return value to the CF object we are returning
+ outValue = static_cast<CFDataRef>(theValue);
+ }
+ else
+ {
+ // release the value since we aren't returning it
+ CFRelease(theValue);
+
+ // set the return value to the default value
+ outValue = inDefaultValue;
+
+ // and retain it
+ CFRetain(outValue);
+ }
+ }
+}
+
+void CASettingsStorage::CopyCFTypeValue(CFStringRef inKey, CFTypeRef& outValue, CFTypeRef inDefaultValue) const
+{
+ // make sure our cache is up to date
+ const_cast<CASettingsStorage*>(this)->RefreshSettings();
+
+ // check to see if we have a value for the given key
+ if(!CFDictionaryGetValueIfPresent(mSettingsCache, inKey, &outValue))
+ {
+ // the key wasn't in the cache, so return the default value
+ outValue = inDefaultValue;
+ }
+
+ // make sure we retain the return value
+ if(outValue != NULL)
+ {
+ CFRetain(outValue);
+ }
+}
+
+void CASettingsStorage::SetSInt32Value(CFStringRef inKey, SInt32 inValue)
+{
+ CACFNumber theValue(inValue);
+ SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void CASettingsStorage::SetUInt32Value(CFStringRef inKey, UInt32 inValue)
+{
+ CACFNumber theValue(inValue);
+ SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void CASettingsStorage::SetSInt64Value(CFStringRef inKey, SInt64 inValue)
+{
+ CACFNumber theValue(inValue);
+ SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void CASettingsStorage::SetUInt64Value(CFStringRef inKey, UInt64 inValue)
+{
+ CACFNumber theValue(inValue);
+ SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void CASettingsStorage::SetFloat32Value(CFStringRef inKey, Float32 inValue)
+{
+ CACFNumber theValue(inValue);
+ SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void CASettingsStorage::SetFloat64Value(CFStringRef inKey, Float64 inValue)
+{
+ CACFNumber theValue(inValue);
+ SetCFTypeValue(inKey, theValue.GetCFNumber());
+}
+
+void CASettingsStorage::SetNumberValue(CFStringRef inKey, CFNumberRef inValue)
+{
+ SetCFTypeValue(inKey, inValue);
+}
+
+void CASettingsStorage::SetStringValue(CFStringRef inKey, CFStringRef inValue)
+{
+ SetCFTypeValue(inKey, inValue);
+}
+
+void CASettingsStorage::SetArrayValue(CFStringRef inKey, CFArrayRef inValue)
+{
+ SetCFTypeValue(inKey, inValue);
+}
+
+void CASettingsStorage::SetDictionaryValue(CFStringRef inKey, CFDictionaryRef inValue)
+{
+ SetCFTypeValue(inKey, inValue);
+}
+
+void CASettingsStorage::SetDataValue(CFStringRef inKey, CFDataRef inValue)
+{
+ SetCFTypeValue(inKey, inValue);
+}
+
+void CASettingsStorage::SetCFTypeValue(CFStringRef inKey, CFTypeRef inValue)
+{
+ // make sure our cache is up to date
+ RefreshSettings();
+
+ // add the new key/value to the dictionary
+ CFDictionarySetValue(mSettingsCache, inKey, inValue);
+
+ // write the settings to the file
+ SaveSettings();
+}
+
+void CASettingsStorage::RemoveValue(CFStringRef inKey)
+{
+ // make sure our cache is up to date
+ RefreshSettings();
+
+ // remove the given key
+ CFDictionaryRemoveValue(mSettingsCache, inKey);
+
+ // write the settings to the file
+ SaveSettings();
+}
+
+void CASettingsStorage::RemoveAllValues()
+{
+ // make sure our cache is up to date
+ RefreshSettings();
+
+ // remove the given key
+ CFDictionaryRemoveAllValues(mSettingsCache);
+
+ // write the settings to the file
+ SaveSettings();
+}
+
+void CASettingsStorage::SendNotification(CFStringRef inName, CFDictionaryRef inData, bool inPostToAllSessions) const
+{
+ CACFDistributedNotification::PostNotification(inName, inData, inPostToAllSessions);
+}
+
+void CASettingsStorage::ForceRefresh()
+{
+ mSettingsCacheForceRefresh = true;
+}
+
+inline bool operator<(const struct timespec& inX, const struct timespec& inY)
+{
+ return ((inX.tv_sec < inY.tv_sec) || ((inX.tv_sec == inY.tv_sec) && (inX.tv_nsec < inY.tv_nsec)));
+}
+
+void CASettingsStorage::RefreshSettings()
+{
+ // first, we need to stat the file to check the mod date, this has the side effect of also
+ // telling us if the file exisits
+ struct stat theFileInfo;
+ int theStatError = stat(mSettingsFilePath, &theFileInfo);
+
+ // we use this boolean to make error recovery easier since we need a case for when there's no file anyway
+ bool theSettingsWereCached = false;
+
+ if(theStatError == 0)
+ {
+ // stat says there is something there, only have to do work if we either don't have a cache or the cache is out of date
+ if((mSettingsCache == NULL) || (mSettingsCacheTime < theFileInfo.st_mtimespec) || mSettingsCacheForceRefresh)
+ {
+ // open the file
+ FILE* theFile = fopen(mSettingsFilePath, "r");
+ if(theFile != NULL)
+ {
+ // lock the file (this call blocks until the lock is taken)
+ int theError = flock(fileno(theFile), LOCK_EX);
+ if(theError == 0)
+ {
+ // get the length of the file
+ fseek(theFile, 0, SEEK_END);
+ size_t theFileLength = ftell(theFile);
+ fseek(theFile, 0, SEEK_SET);
+
+ if(theFileLength > 0)
+ {
+ // allocate a block of memory to hold the data in the file
+ CAAutoFree<Byte> theRawFileData(theFileLength);
+
+ // read all the data in
+ fread(static_cast<Byte*>(theRawFileData), theFileLength, 1, theFile);
+
+ // release the lock
+ flock(fileno(theFile), LOCK_UN);
+
+ // put it into a CFData object
+ CACFData theRawFileDataCFData(static_cast<Byte*>(theRawFileData), static_cast<UInt32>(theFileLength));
+
+ // get rid of the existing cache
+ if(mSettingsCache != NULL)
+ {
+ CFRelease(mSettingsCache);
+ mSettingsCache = NULL;
+ }
+
+ // parse the data as a property list
+ mSettingsCache = (CFMutableDictionaryRef)CFPropertyListCreateFromXMLData(NULL, theRawFileDataCFData.GetCFData(), kCFPropertyListMutableContainersAndLeaves, NULL);
+
+ // save the date of the cache
+ mSettingsCacheTime = theFileInfo.st_mtimespec;
+
+ // mark that we're done
+ theSettingsWereCached = true;
+ }
+ }
+
+ // close the file
+ fclose(theFile);
+ mSettingsCacheForceRefresh = false;
+ }
+ }
+ }
+
+ if((theStatError != 0) || (!theSettingsWereCached && (theFileInfo.st_mtimespec < mSettingsCacheTime)))
+ {
+ // we get here if either there isn't a file or something wacky happenned while parsing it
+ // all we do here is make sure that the member variables are set to their initial values
+ if(mSettingsCache != NULL)
+ {
+ CFRelease(mSettingsCache);
+ mSettingsCache = NULL;
+ }
+ mSettingsCache = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ mSettingsCacheTime.tv_sec = 0;
+ mSettingsCacheTime.tv_nsec = 0;
+ }
+}
+
+void CASettingsStorage::SaveSettings()
+{
+ if(mSettingsCache != NULL)
+ {
+ // make a CFData that contains the new settings
+ CACFData theNewRawPrefsCFData(CFPropertyListCreateXMLData(NULL, (CFPropertyListRef)mSettingsCache), true);
+
+ // open the file for writing
+ FILE* theFile = fopen(mSettingsFilePath, "w+");
+ if(theFile != NULL)
+ {
+ // lock the file (this call blocks until the lock is taken)
+ int theError = flock(fileno(theFile), LOCK_EX);
+ if(theError == 0)
+ {
+ // set the file access mode if necessary
+ if(mSettingsFileAccessMode != 0)
+ {
+ fchmod(fileno(theFile), mSettingsFileAccessMode);
+ }
+
+ // write the data
+ fwrite(theNewRawPrefsCFData.GetDataPtr(), theNewRawPrefsCFData.GetSize(), 1, theFile);
+
+ // flush the file to be sure it is all on disk
+ fflush(theFile);
+
+ // release the lock
+ flock(fileno(theFile), LOCK_UN);
+
+ // close the file
+ fclose(theFile);
+
+ // stat the file to get the mod date
+ struct stat theFileInfo;
+ stat(mSettingsFilePath, &theFileInfo);
+
+ // save the mod date
+ mSettingsCacheTime = theFileInfo.st_mtimespec;
+ }
+ else
+ {
+ // close the file
+ fclose(theFile);
+ }
+ }
+ }
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CASettingsStorage.h b/distrho/src/CoreAudio106/PublicUtility/CASettingsStorage.h
new file mode 100755
index 00000000..1ff9106a
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CASettingsStorage.h
@@ -0,0 +1,116 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CASettingsStorage_h__)
+#define __CASettingsStorage_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// System Includes
+#include <CoreAudio/CoreAudioTypes.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+// Stamdard Library Includes
+#include <stdio.h>
+#include <sys/stat.h>
+
+//==================================================================================================
+// CASettingsStorage
+//==================================================================================================
+
+class CASettingsStorage
+{
+
+// Construction/Destruction
+public:
+ CASettingsStorage(const char* inSettingsFilePath, mode_t inSettingsFileAccessMode = 0);
+ ~CASettingsStorage();
+
+// Operations
+public:
+ void CopyBoolValue(const CFStringRef inKey, bool& outValue, bool inDefaultValue = false) const;
+ void CopySInt32Value(const CFStringRef inKey, SInt32& outValue, SInt32 inDefaultValue = 0) const;
+ void CopyUInt32Value(const CFStringRef inKey, UInt32& outValue, UInt32 inDefaultValue = 0) const;
+ void CopySInt64Value(const CFStringRef inKey, SInt64& outValue, SInt64 inDefaultValue = 0) const;
+ void CopyUInt64Value(const CFStringRef inKey, UInt64& outValue, UInt64 inDefaultValue = 0) const;
+ void CopyFloat32Value(const CFStringRef inKey, Float32& outValue, Float32 inDefaultValue = 0) const;
+ void CopyFloat64Value(const CFStringRef inKey, Float64& outValue, Float64 inDefaultValue = 0) const;
+ void CopyNumberValue(const CFStringRef inKey, CFNumberRef& outValue, CFNumberRef inDefaultValue = NULL) const;
+ void CopyStringValue(const CFStringRef inKey, CFStringRef& outValue, CFStringRef inDefaultValue = NULL) const;
+ void CopyArrayValue(const CFStringRef inKey, CFArrayRef& outValue, CFArrayRef inDefaultValue = NULL) const;
+ void CopyDictionaryValue(const CFStringRef inKey, CFDictionaryRef& outValue, CFDictionaryRef inDefaultValue = NULL) const;
+ void CopyDataValue(const CFStringRef inKey, CFDataRef& outValue, CFDataRef inDefaultValue = NULL) const;
+ void CopyCFTypeValue(const CFStringRef inKey, CFTypeRef& outValue, CFTypeRef inDefaultValue = NULL) const;
+
+ void SetSInt32Value(const CFStringRef inKey, SInt32 inValue);
+ void SetUInt32Value(const CFStringRef inKey, UInt32 inValue);
+ void SetSInt64Value(const CFStringRef inKey, SInt64 inValue);
+ void SetUInt64Value(const CFStringRef inKey, UInt64 inValue);
+ void SetFloat32Value(const CFStringRef inKey, Float32 inValue);
+ void SetFloat64Value(const CFStringRef inKey, Float64 inValue);
+ void SetNumberValue(const CFStringRef inKey, const CFNumberRef inValue);
+ void SetStringValue(const CFStringRef inKey, const CFStringRef inValue);
+ void SetArrayValue(const CFStringRef inKey, const CFArrayRef inValue);
+ void SetDictionaryValue(const CFStringRef inKey, const CFDictionaryRef inValue);
+ void SetDataValue(const CFStringRef inKey, const CFDataRef inValue);
+ void SetCFTypeValue(const CFStringRef inKey, const CFTypeRef inValue);
+
+ void RemoveValue(const CFStringRef inKey);
+ void RemoveAllValues();
+
+ void SendNotification(const CFStringRef inName, CFDictionaryRef inData = NULL, bool inPostToAllSessions = true) const;
+ void ForceRefresh();
+
+// Implementation
+private:
+ void RefreshSettings();
+ void SaveSettings();
+
+ char* mSettingsFilePath;
+ mode_t mSettingsFileAccessMode;
+ CFMutableDictionaryRef mSettingsCache;
+ struct timespec mSettingsCacheTime;
+ bool mSettingsCacheForceRefresh;
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CASharedLibrary.cpp b/distrho/src/CoreAudio106/PublicUtility/CASharedLibrary.cpp
new file mode 100755
index 00000000..6217a0dd
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CASharedLibrary.cpp
@@ -0,0 +1,112 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CASharedLibrary.h"
+
+//#define CASharedLibrary_Use_DYLD 1
+#if CASharedLibrary_Use_DYLD
+ #include <mach-o/dyld.h>
+#else
+ #include <dlfcn.h>
+ #include <stddef.h>
+#endif
+
+//=============================================================================
+// CASharedLibrary
+//=============================================================================
+
+void* CASharedLibrary::LoadLibraryAndGetRoutineAddress(const char* inRoutineName, const char* /*inLibraryName*/, const char* inLibraryPath)
+{
+ void* theRoutine = 0;
+
+#if CASharedLibrary_Use_DYLD
+ const struct mach_header* theImage = NSAddImage(inLibraryPath, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+ if(theImage != 0)
+ {
+ NSSymbol theSymbol = NSLookupSymbolInImage(theImage, inRoutineName, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND);
+ if(theSymbol != 0)
+ {
+ theRoutine = NSAddressOfSymbol(theSymbol);
+ }
+ }
+#else
+ void* theImage = dlopen(inLibraryPath, RTLD_LAZY);
+ if(theImage != NULL)
+ {
+ // we assume that all routine names passed here have a leading underscore which gets shaved
+ // off when passed to dlsym
+ theRoutine = dlsym(theImage, &(inRoutineName[1]));
+ }
+
+#endif
+
+ return theRoutine;
+}
+
+void* CASharedLibrary::GetRoutineAddressIfLibraryLoaded(const char* inRoutineName, const char* /*inLibraryName*/, const char* inLibraryPath)
+{
+ void* theRoutine = 0;
+
+#if CASharedLibrary_Use_DYLD
+ const struct mach_header* theImage = NSAddImage(inLibraryPath, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED);
+ if(theImage != 0)
+ {
+ NSSymbol theSymbol = NSLookupSymbolInImage(theImage, inRoutineName, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND);
+ if(theSymbol != 0)
+ {
+ theRoutine = NSAddressOfSymbol(theSymbol);
+ }
+ }
+#else
+ void* theImage = dlopen(inLibraryPath, RTLD_LAZY | RTLD_NOLOAD);
+ if(theImage != NULL)
+ {
+ // we assume that all routine names passed here have a leading underscore which gets shaved
+ // off when passed to dlsym
+ theRoutine = dlsym(theImage, &(inRoutineName[1]));
+ }
+#endif
+
+ return theRoutine;
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CASharedLibrary.h b/distrho/src/CoreAudio106/PublicUtility/CASharedLibrary.h
new file mode 100755
index 00000000..29481e9a
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CASharedLibrary.h
@@ -0,0 +1,58 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CASharedLibrary_h__)
+#define __CASharedLibrary_h__
+
+//=============================================================================
+// CASharedLibrary
+//=============================================================================
+
+class CASharedLibrary
+{
+
+// Symbol Operations
+public:
+ static void* LoadLibraryAndGetRoutineAddress(const char* inRoutineName, const char* inLibraryName, const char* inLibraryPath);
+ static void* GetRoutineAddressIfLibraryLoaded(const char* inRoutineName, const char* inLibraryName, const char* inLibraryPath);
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CASpectralProcessor.cpp b/distrho/src/CoreAudio106/PublicUtility/CASpectralProcessor.cpp
new file mode 100755
index 00000000..1c49e7aa
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CASpectralProcessor.cpp
@@ -0,0 +1,370 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+//#include "AudioFormulas.h"
+#include "CASpectralProcessor.h"
+#include "CABitOperations.h"
+
+
+#include <vecLib/vectorOps.h>
+
+
+#define OFFSETOF(class, field)((size_t)&((class*)0)->field)
+
+CASpectralProcessor::CASpectralProcessor(UInt32 inFFTSize, UInt32 inHopSize, UInt32 inNumChannels, UInt32 inMaxFrames)
+ : mFFTSize(inFFTSize), mHopSize(inHopSize), mNumChannels(inNumChannels), mMaxFrames(inMaxFrames),
+ mLog2FFTSize(Log2Ceil(mFFTSize)),
+ mFFTMask(mFFTSize - 1),
+ mFFTByteSize(mFFTSize * sizeof(Float32)),
+ mIOBufSize(NextPowerOfTwo(mFFTSize + mMaxFrames)),
+ mIOMask(mIOBufSize - 1),
+ mInputSize(0),
+ mInputPos(0), mOutputPos(-mFFTSize & mIOMask),
+ mInFFTPos(0), mOutFFTPos(0),
+ mSpectralFunction(0), mUserData(0)
+{
+ mWindow.alloc(mFFTSize, false);
+ SineWindow(); // set default window.
+
+ mChannels.alloc(mNumChannels);
+ mSpectralBufferList.allocBytes(OFFSETOF(SpectralBufferList, mDSPSplitComplex[mNumChannels]), true);
+ mSpectralBufferList->mNumberSpectra = mNumChannels;
+ for (UInt32 i = 0; i < mNumChannels; ++i)
+ {
+ mChannels[i].mInputBuf.alloc(mIOBufSize, true);
+ mChannels[i].mOutputBuf.alloc(mIOBufSize, true);
+ mChannels[i].mFFTBuf.alloc(mFFTSize, true);
+ mChannels[i].mSplitFFTBuf.alloc(mFFTSize, true);
+ mSpectralBufferList->mDSPSplitComplex[i].realp = mChannels[i].mSplitFFTBuf();
+ mSpectralBufferList->mDSPSplitComplex[i].imagp = mChannels[i].mSplitFFTBuf() + (mFFTSize >> 1);
+ }
+
+ mFFTSetup = vDSP_create_fftsetup (mLog2FFTSize, FFT_RADIX2);
+
+}
+
+CASpectralProcessor::~CASpectralProcessor()
+{
+ mWindow.free();
+ mChannels.free();
+ mSpectralBufferList.free();
+ vDSP_destroy_fftsetup(mFFTSetup);
+}
+
+void CASpectralProcessor::Reset()
+{
+ mInputPos = 0;
+ mOutputPos = -mFFTSize & mIOMask;
+ mInFFTPos = 0;
+ mOutFFTPos = 0;
+
+ for (UInt32 i = 0; i < mNumChannels; ++i)
+ {
+ memset(mChannels[i].mInputBuf(), 0, mIOBufSize * sizeof(Float32));
+ memset(mChannels[i].mOutputBuf(), 0, mIOBufSize * sizeof(Float32));
+ memset(mChannels[i].mFFTBuf(), 0, mFFTSize * sizeof(Float32));
+ }
+}
+
+const double two_pi = 2. * M_PI;
+
+void CASpectralProcessor::HanningWindow()
+{
+ // this is also vector optimized
+
+ double w = two_pi / (double)(mFFTSize - 1);
+ for (UInt32 i = 0; i < mFFTSize; ++i)
+ {
+ mWindow[i] = (0.5 - 0.5 * cos(w * (double)i));
+ }
+}
+
+void CASpectralProcessor::SineWindow()
+{
+ double w = M_PI / (double)(mFFTSize - 1);
+ for (UInt32 i = 0; i < mFFTSize; ++i)
+ {
+ mWindow[i] = sin(w * (double)i);
+ }
+}
+
+void CASpectralProcessor::Process(UInt32 inNumFrames, AudioBufferList* inInput, AudioBufferList* outOutput)
+{
+ // copy from buffer list to input buffer
+ CopyInput(inNumFrames, inInput);
+
+ // if enough input to process, then process.
+ while (mInputSize >= mFFTSize)
+ {
+ CopyInputToFFT(); // copy from input buffer to fft buffer
+ DoWindowing();
+ DoFwdFFT();
+ ProcessSpectrum(mFFTSize, mSpectralBufferList());
+ DoInvFFT();
+ DoWindowing();
+ OverlapAddOutput();
+ }
+
+ // copy from output buffer to buffer list
+ CopyOutput(inNumFrames, outOutput);
+}
+
+void CASpectralProcessor::DoWindowing()
+{
+ Float32 *win = mWindow();
+ if (!win) return;
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ Float32 *x = mChannels[i].mFFTBuf();
+ vDSP_vmul(x, 1, win, 1, x, 1, mFFTSize);
+ }
+ //printf("DoWindowing %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+}
+
+
+
+void CASpectralProcessor::CopyInput(UInt32 inNumFrames, AudioBufferList* inInput)
+{
+ UInt32 numBytes = inNumFrames * sizeof(Float32);
+ UInt32 firstPart = mIOBufSize - mInputPos;
+
+
+ if (firstPart < inNumFrames) {
+ UInt32 firstPartBytes = firstPart * sizeof(Float32);
+ UInt32 secondPartBytes = numBytes - firstPartBytes;
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ memcpy(mChannels[i].mInputBuf + mInputPos, inInput->mBuffers[i].mData, firstPartBytes);
+ memcpy(mChannels[i].mInputBuf, (UInt8*)inInput->mBuffers[i].mData + firstPartBytes, secondPartBytes);
+ }
+ } else {
+ UInt32 numBytes = inNumFrames * sizeof(Float32);
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ memcpy(mChannels[i].mInputBuf + mInputPos, inInput->mBuffers[i].mData, numBytes);
+ }
+ }
+ //printf("CopyInput %g %g\n", mChannels[0].mInputBuf[mInputPos], mChannels[0].mInputBuf[(mInputPos + 200) & mIOMask]);
+ //printf("CopyInput mInputPos %u mIOBufSize %u\n", (unsigned)mInputPos, (unsigned)mIOBufSize);
+ mInputSize += inNumFrames;
+ mInputPos = (mInputPos + inNumFrames) & mIOMask;
+}
+
+void CASpectralProcessor::CopyOutput(UInt32 inNumFrames, AudioBufferList* outOutput)
+{
+ //printf("->CopyOutput %g %g\n", mChannels[0].mOutputBuf[mOutputPos], mChannels[0].mOutputBuf[(mOutputPos + 200) & mIOMask]);
+ //printf("CopyOutput mOutputPos %u\n", (unsigned)mOutputPos);
+ UInt32 numBytes = inNumFrames * sizeof(Float32);
+ UInt32 firstPart = mIOBufSize - mOutputPos;
+ if (firstPart < inNumFrames) {
+ UInt32 firstPartBytes = firstPart * sizeof(Float32);
+ UInt32 secondPartBytes = numBytes - firstPartBytes;
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ memcpy(outOutput->mBuffers[i].mData, mChannels[i].mOutputBuf + mOutputPos, firstPartBytes);
+ memcpy((UInt8*)outOutput->mBuffers[i].mData + firstPartBytes, mChannels[i].mOutputBuf, secondPartBytes);
+ memset(mChannels[i].mOutputBuf + mOutputPos, 0, firstPartBytes);
+ memset(mChannels[i].mOutputBuf, 0, secondPartBytes);
+ }
+ } else {
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ memcpy(outOutput->mBuffers[i].mData, mChannels[i].mOutputBuf + mOutputPos, numBytes);
+ memset(mChannels[i].mOutputBuf + mOutputPos, 0, numBytes);
+ }
+ }
+ //printf("<-CopyOutput %g %g\n", ((Float32*)outOutput->mBuffers[0].mData)[0], ((Float32*)outOutput->mBuffers[0].mData)[200]);
+ mOutputPos = (mOutputPos + inNumFrames) & mIOMask;
+}
+
+void CASpectralProcessor::PrintSpectralBufferList()
+{
+ UInt32 half = mFFTSize >> 1;
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ DSPSplitComplex &freqData = mSpectralBufferList->mDSPSplitComplex[i];
+
+ for (UInt32 j=0; j<half; j++){
+ printf(" bin[%d]: %lf + %lfi\n", (int) j, freqData.realp[j], freqData.imagp[j]);
+ }
+ }
+}
+
+
+void CASpectralProcessor::CopyInputToFFT()
+{
+ //printf("CopyInputToFFT mInFFTPos %u\n", (unsigned)mInFFTPos);
+ UInt32 firstPart = mIOBufSize - mInFFTPos;
+ UInt32 firstPartBytes = firstPart * sizeof(Float32);
+ if (firstPartBytes < mFFTByteSize) {
+ UInt32 secondPartBytes = mFFTByteSize - firstPartBytes;
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ memcpy(mChannels[i].mFFTBuf(), mChannels[i].mInputBuf() + mInFFTPos, firstPartBytes);
+ memcpy((UInt8*)mChannels[i].mFFTBuf() + firstPartBytes, mChannels[i].mInputBuf(), secondPartBytes);
+ }
+ } else {
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ memcpy(mChannels[i].mFFTBuf(), mChannels[i].mInputBuf() + mInFFTPos, mFFTByteSize);
+ }
+ }
+ mInputSize -= mHopSize;
+ mInFFTPos = (mInFFTPos + mHopSize) & mIOMask;
+ //printf("CopyInputToFFT %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+}
+
+void CASpectralProcessor::OverlapAddOutput()
+{
+ //printf("OverlapAddOutput mOutFFTPos %u\n", (unsigned)mOutFFTPos);
+ UInt32 firstPart = mIOBufSize - mOutFFTPos;
+ if (firstPart < mFFTSize) {
+ UInt32 secondPart = mFFTSize - firstPart;
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ float* out1 = mChannels[i].mOutputBuf() + mOutFFTPos;
+ vDSP_vadd(out1, 1, mChannels[i].mFFTBuf(), 1, out1, 1, firstPart);
+ float* out2 = mChannels[i].mOutputBuf();
+ vDSP_vadd(out2, 1, mChannels[i].mFFTBuf() + firstPart, 1, out2, 1, secondPart);
+ }
+ } else {
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ float* out1 = mChannels[i].mOutputBuf() + mOutFFTPos;
+ vDSP_vadd(out1, 1, mChannels[i].mFFTBuf(), 1, out1, 1, mFFTSize);
+ }
+ }
+ //printf("OverlapAddOutput %g %g\n", mChannels[0].mOutputBuf[mOutFFTPos], mChannels[0].mOutputBuf[(mOutFFTPos + 200) & mIOMask]);
+ mOutFFTPos = (mOutFFTPos + mHopSize) & mIOMask;
+}
+
+
+void CASpectralProcessor::DoFwdFFT()
+{
+ //printf("->DoFwdFFT %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+ UInt32 half = mFFTSize >> 1;
+ for (UInt32 i=0; i<mNumChannels; ++i)
+ {
+ vDSP_ctoz((DSPComplex*)mChannels[i].mFFTBuf(), 2, &mSpectralBufferList->mDSPSplitComplex[i], 1, half);
+ vDSP_fft_zrip(mFFTSetup, &mSpectralBufferList->mDSPSplitComplex[i], 1, mLog2FFTSize, FFT_FORWARD);
+ }
+ //printf("<-DoFwdFFT %g %g\n", direction, mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+}
+
+void CASpectralProcessor::DoInvFFT()
+{
+ //printf("->DoInvFFT %g %g\n", mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+ UInt32 half = mFFTSize >> 1;
+ for (UInt32 i=0; i<mNumChannels; ++i)
+ {
+ vDSP_fft_zrip(mFFTSetup, &mSpectralBufferList->mDSPSplitComplex[i], 1, mLog2FFTSize, FFT_INVERSE);
+ vDSP_ztoc(&mSpectralBufferList->mDSPSplitComplex[i], 1, (DSPComplex*)mChannels[i].mFFTBuf(), 2, half);
+ float scale = 0.5 / mFFTSize;
+ vDSP_vsmul(mChannels[i].mFFTBuf(), 1, &scale, mChannels[i].mFFTBuf(), 1, mFFTSize );
+ }
+ //printf("<-DoInvFFT %g %g\n", direction, mChannels[0].mFFTBuf()[0], mChannels[0].mFFTBuf()[200]);
+}
+
+void CASpectralProcessor::SetSpectralFunction(SpectralFunction inFunction, void* inUserData)
+{
+ mSpectralFunction = inFunction;
+ mUserData = inUserData;
+}
+
+void CASpectralProcessor::ProcessSpectrum(UInt32 inFFTSize, SpectralBufferList* inSpectra)
+{
+ if (mSpectralFunction)
+ (mSpectralFunction)(inSpectra, mUserData);
+}
+
+#pragma mark ___Utility___
+
+void CASpectralProcessor::GetMagnitude(AudioBufferList* list, Float32* min, Float32* max)
+{
+ UInt32 half = mFFTSize >> 1;
+ for (UInt32 i=0; i<mNumChannels; ++i) {
+ DSPSplitComplex &freqData = mSpectralBufferList->mDSPSplitComplex[i];
+
+ Float32* b = (Float32*) list->mBuffers[i].mData;
+
+ vDSP_zvabs(&freqData,1,b,1,half);
+
+ vDSP_maxmgv(b, 1, &max[i], half);
+ vDSP_minmgv(b, 1, &min[i], half);
+
+ }
+}
+
+
+void CASpectralProcessor::GetFrequencies(Float32* freqs, Float32 sampleRate)
+{
+ UInt32 half = mFFTSize >> 1;
+
+ for (UInt32 i=0; i< half; i++){
+ freqs[i] = ((Float32)(i))*sampleRate/((Float32)mFFTSize);
+ }
+}
+
+
+bool CASpectralProcessor::ProcessForwards(UInt32 inNumFrames, AudioBufferList* inInput)
+{
+ // copy from buffer list to input buffer
+ CopyInput(inNumFrames, inInput);
+
+ bool processed = false;
+ // if enough input to process, then process.
+ while (mInputSize >= mFFTSize)
+ {
+ CopyInputToFFT(); // copy from input buffer to fft buffer
+ DoWindowing();
+ DoFwdFFT();
+ ProcessSpectrum(mFFTSize, mSpectralBufferList()); // here you would copy the fft results out to a buffer indicated in mUserData, say for sonogram drawing
+ processed = true;
+ }
+
+ return processed;
+}
+
+bool CASpectralProcessor::ProcessBackwards(UInt32 inNumFrames, AudioBufferList* outOutput)
+{
+
+ ProcessSpectrum(mFFTSize, mSpectralBufferList());
+ DoInvFFT();
+ DoWindowing();
+ OverlapAddOutput();
+
+ // copy from output buffer to buffer list
+ CopyOutput(inNumFrames, outOutput);
+
+ return true;
+}
+
+
diff --git a/distrho/src/CoreAudio106/PublicUtility/CASpectralProcessor.h b/distrho/src/CoreAudio106/PublicUtility/CASpectralProcessor.h
new file mode 100755
index 00000000..c749117a
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CASpectralProcessor.h
@@ -0,0 +1,140 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _SpectralProcesor_H_
+#define _SpectralProcesor_H_
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+#include <CoreAudio/CoreAudioTypes.h>
+#include <CoreFoundation/CoreFoundation.h>
+#else
+#include <CoreAudioTypes.h>
+#include <CoreFoundation.h>
+#endif
+
+#include <Accelerate/Accelerate.h>
+
+#include "CAAutoDisposer.h"
+
+struct SpectralBufferList
+{
+ UInt32 mNumberSpectra;
+ DSPSplitComplex mDSPSplitComplex[1];
+};
+
+class CASpectralProcessor
+{
+public:
+ CASpectralProcessor(UInt32 inFFTSize, UInt32 inHopSize, UInt32 inNumChannels, UInt32 inMaxFrames);
+ virtual ~CASpectralProcessor();
+
+ void Reset();
+
+ void Process(UInt32 inNumFrames, AudioBufferList* inInput, AudioBufferList* outOutput);
+
+ typedef void (*SpectralFunction)(SpectralBufferList* inSpectra, void* inUserData);
+
+ void SetSpectralFunction(SpectralFunction inFunction, void* inUserData);
+
+ UInt32 FFTSize() const { return mFFTSize; }
+ UInt32 MaxFrames() const { return mMaxFrames; }
+ UInt32 NumChannels() const { return mNumChannels; }
+ UInt32 HopSize() const { return mHopSize; }
+ Float32* Window() const { return mWindow; }
+
+
+ void HanningWindow(); // set up a hanning window
+ void SineWindow();
+
+ void GetFrequencies(Float32* freqs, Float32 sampleRate); // only for processed forward
+ void GetMagnitude(AudioBufferList* inCopy, Float32* min, Float32* max); // only for processed forward
+
+ virtual bool ProcessForwards(UInt32 inNumFrames, AudioBufferList* inInput);
+ bool ProcessBackwards(UInt32 inNumFrames, AudioBufferList* outOutput);
+
+
+ void PrintSpectralBufferList();
+
+protected:
+ void CopyInput(UInt32 inNumFrames, AudioBufferList* inInput);
+ void CopyInputToFFT();
+ void DoWindowing();
+ void DoFwdFFT();
+ void DoInvFFT();
+ void OverlapAddOutput();
+ void CopyOutput(UInt32 inNumFrames, AudioBufferList* inOutput);
+ void ProcessSpectrum(UInt32 inFFTSize, SpectralBufferList* inSpectra);
+
+ UInt32 mFFTSize;
+ UInt32 mHopSize;
+ UInt32 mNumChannels;
+ UInt32 mMaxFrames;
+
+ UInt32 mLog2FFTSize;
+ UInt32 mFFTMask;
+ UInt32 mFFTByteSize;
+ UInt32 mIOBufSize;
+ UInt32 mIOMask;
+ UInt32 mInputSize;
+ UInt32 mInputPos;
+ UInt32 mOutputPos;
+ UInt32 mInFFTPos;
+ UInt32 mOutFFTPos;
+ FFTSetup mFFTSetup;
+
+ CAAutoFree<Float32> mWindow;
+ struct SpectralChannel
+ {
+ CAAutoFree<Float32> mInputBuf; // log2ceil(FFT size + max frames)
+ CAAutoFree<Float32> mOutputBuf; // log2ceil(FFT size + max frames)
+ CAAutoFree<Float32> mFFTBuf; // FFT size
+ CAAutoFree<Float32> mSplitFFTBuf; // FFT size
+ };
+ CAAutoArrayDelete<SpectralChannel> mChannels;
+
+ CAAutoFree<SpectralBufferList> mSpectralBufferList;
+
+ SpectralFunction mSpectralFunction;
+ void *mUserData;
+
+};
+
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAStreamBasicDescription.cpp b/distrho/src/CoreAudio106/PublicUtility/CAStreamBasicDescription.cpp
new file mode 100755
index 00000000..d45e44b5
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAStreamBasicDescription.cpp
@@ -0,0 +1,573 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CAStreamBasicDescription.h"
+#include "CAMath.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CFByteOrder.h>
+#else
+ #include <CFByteOrder.h>
+#endif
+
+#pragma mark This file needs to compile on earlier versions of the OS, so please keep that in mind when editing it
+
+char *CAStringForOSType (OSType t, char *writeLocation)
+{
+ char *p = writeLocation;
+ unsigned char str[4], *q = str;
+ *(UInt32 *)str = CFSwapInt32HostToBig(t);
+
+ bool hasNonPrint = false;
+ for (int i = 0; i < 4; ++i) {
+ if (!(isprint(*q) && *q != '\\')) {
+ hasNonPrint = true;
+ break;
+ }
+ }
+
+ if (hasNonPrint)
+ p += sprintf (p, "0x");
+ else
+ *p++ = '\'';
+
+ for (int i = 0; i < 4; ++i) {
+ if (hasNonPrint) {
+ p += sprintf(p, "%02X", *q++);
+ } else {
+ *p++ = *q++;
+ }
+ }
+ if (!hasNonPrint)
+ *p++ = '\'';
+ *p = '\0';
+ return writeLocation;
+}
+
+
+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;
+ mReserved = 0;
+}
+
+char *CAStreamBasicDescription::AsString(char *buf, size_t _bufsize) const
+{
+ int bufsize = (int)_bufsize; // must be signed to protect against overflow
+ char *theBuffer = buf;
+ int nc;
+ char formatID[24];
+ CAStringForOSType (mFormatID, formatID);
+ nc = snprintf(buf, bufsize, "%2d ch, %6.0f Hz, %s (0x%08X) ", (int)NumberChannels(), mSampleRate, formatID, (int)mFormatFlags);
+ buf += nc; if ((bufsize -= nc) <= 0) goto exit;
+ if (mFormatID == kAudioFormatLinearPCM) {
+ bool isInt = !(mFormatFlags & kLinearPCMFormatFlagIsFloat);
+ int wordSize = SampleWordSize();
+ const char *endian = (wordSize > 1) ?
+ ((mFormatFlags & kLinearPCMFormatFlagIsBigEndian) ? " big-endian" : " little-endian" ) : "";
+ const char *sign = isInt ?
+ ((mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) ? " signed" : " unsigned") : "";
+ const char *floatInt = isInt ? "integer" : "float";
+ char packed[32];
+ if (wordSize > 0 && PackednessIsSignificant()) {
+ if (mFormatFlags & kLinearPCMFormatFlagIsPacked)
+ snprintf(packed, sizeof(packed), "packed in %d bytes", wordSize);
+ else
+ snprintf(packed, sizeof(packed), "unpacked in %d bytes", wordSize);
+ } else
+ packed[0] = '\0';
+ const char *align = (wordSize > 0 && AlignmentIsSignificant()) ?
+ ((mFormatFlags & kLinearPCMFormatFlagIsAlignedHigh) ? " high-aligned" : " low-aligned") : "";
+ const char *deinter = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) ? ", deinterleaved" : "";
+ const char *commaSpace = (packed[0]!='\0') || (align[0]!='\0') ? ", " : "";
+ char bitdepth[20];
+
+ int fracbits = (mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
+ if (fracbits > 0)
+ snprintf(bitdepth, sizeof(bitdepth), "%d.%d", (int)mBitsPerChannel - fracbits, fracbits);
+ else
+ snprintf(bitdepth, sizeof(bitdepth), "%d", (int)mBitsPerChannel);
+
+ nc = snprintf(buf, bufsize, "%s-bit%s%s %s%s%s%s%s",
+ bitdepth, endian, sign, floatInt,
+ commaSpace, packed, align, deinter);
+ // buf += nc; if ((bufsize -= nc) <= 0) goto exit;
+ } else if (mFormatID == '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)
+ nc = snprintf(buf, bufsize, "from %d-bit source, ", sourceBits);
+ else
+ nc = snprintf(buf, bufsize, "from UNKNOWN source bit depth, ");
+ buf += nc; if ((bufsize -= nc) <= 0) goto exit;
+ nc = snprintf(buf, bufsize, "%d frames/packet", (int)mFramesPerPacket);
+ // buf += nc; if ((bufsize -= nc) <= 0) goto exit;
+ }
+ else
+ nc = snprintf(buf, bufsize, "%d bits/channel, %d bytes/packet, %d frames/packet, %d bytes/frame",
+ (int)mBitsPerChannel, (int)mBytesPerPacket, (int)mFramesPerPacket, (int)mBytesPerFrame);
+exit:
+ return theBuffer;
+}
+
+void CAStreamBasicDescription::NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription)
+{
+ // the only thing that changes is to make mixable linear PCM into the canonical linear PCM format
+ if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0))
+ {
+ // the canonical linear PCM format
+ ioDescription.mFormatFlags = kAudioFormatFlagsCanonical;
+ ioDescription.mBytesPerPacket = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
+ ioDescription.mFramesPerPacket = 1;
+ ioDescription.mBytesPerFrame = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
+ ioDescription.mBitsPerChannel = 8 * SizeOf32(AudioSampleType);
+ }
+}
+
+void CAStreamBasicDescription::ResetFormat(AudioStreamBasicDescription& ioDescription)
+{
+ ioDescription.mSampleRate = 0;
+ ioDescription.mFormatID = 0;
+ ioDescription.mBytesPerPacket = 0;
+ ioDescription.mFramesPerPacket = 0;
+ ioDescription.mBytesPerFrame = 0;
+ ioDescription.mChannelsPerFrame = 0;
+ ioDescription.mBitsPerChannel = 0;
+ ioDescription.mFormatFlags = 0;
+}
+
+void CAStreamBasicDescription::FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription)
+{
+ if(fiszero(ioDescription.mSampleRate))
+ {
+ ioDescription.mSampleRate = inTemplateDescription.mSampleRate;
+ }
+ if(ioDescription.mFormatID == 0)
+ {
+ ioDescription.mFormatID = inTemplateDescription.mFormatID;
+ }
+ if(ioDescription.mFormatFlags == 0)
+ {
+ ioDescription.mFormatFlags = inTemplateDescription.mFormatFlags;
+ }
+ if(ioDescription.mBytesPerPacket == 0)
+ {
+ ioDescription.mBytesPerPacket = inTemplateDescription.mBytesPerPacket;
+ }
+ if(ioDescription.mFramesPerPacket == 0)
+ {
+ ioDescription.mFramesPerPacket = inTemplateDescription.mFramesPerPacket;
+ }
+ if(ioDescription.mBytesPerFrame == 0)
+ {
+ ioDescription.mBytesPerFrame = inTemplateDescription.mBytesPerFrame;
+ }
+ if(ioDescription.mChannelsPerFrame == 0)
+ {
+ ioDescription.mChannelsPerFrame = inTemplateDescription.mChannelsPerFrame;
+ }
+ if(ioDescription.mBitsPerChannel == 0)
+ {
+ ioDescription.mBitsPerChannel = inTemplateDescription.mBitsPerChannel;
+ }
+}
+
+void CAStreamBasicDescription::GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, UInt32 inMaxNameLength, bool inAbbreviate)
+{
+ switch(inDescription.mFormatID)
+ {
+ case kAudioFormatLinearPCM:
+ {
+ const char* theEndianString = NULL;
+ if((inDescription.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0)
+ {
+ #if TARGET_RT_LITTLE_ENDIAN
+ theEndianString = "Big Endian";
+ #endif
+ }
+ else
+ {
+ #if TARGET_RT_BIG_ENDIAN
+ theEndianString = "Little Endian";
+ #endif
+ }
+
+ const char* theKindString = NULL;
+ if((inDescription.mFormatFlags & kAudioFormatFlagIsFloat) != 0)
+ {
+ theKindString = (inAbbreviate ? "Float" : "Floating Point");
+ }
+ else if((inDescription.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
+ {
+ theKindString = (inAbbreviate ? "SInt" : "Signed Integer");
+ }
+ else
+ {
+ theKindString = (inAbbreviate ? "UInt" : "Unsigned Integer");
+ }
+
+ const char* thePackingString = NULL;
+ if((inDescription.mFormatFlags & kAudioFormatFlagIsPacked) == 0)
+ {
+ if((inDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) != 0)
+ {
+ thePackingString = "High";
+ }
+ else
+ {
+ thePackingString = "Low";
+ }
+ }
+
+ const char* theMixabilityString = NULL;
+ if((inDescription.mFormatFlags & kIsNonMixableFlag) == 0)
+ {
+ theMixabilityString = "Mixable";
+ }
+ else
+ {
+ theMixabilityString = "Unmixable";
+ }
+
+ if(inAbbreviate)
+ {
+ if(theEndianString != NULL)
+ {
+ if(thePackingString != NULL)
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Ch %s %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
+ }
+ else
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Ch %s %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, theKindString, (int)inDescription.mBitsPerChannel);
+ }
+ }
+ else
+ {
+ if(thePackingString != NULL)
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Ch %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)((inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8));
+ }
+ else
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Ch %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theKindString, (int)inDescription.mBitsPerChannel);
+ }
+ }
+ }
+ else
+ {
+ if(theEndianString != NULL)
+ {
+ if(thePackingString != NULL)
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
+ }
+ else
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString);
+ }
+ }
+ else
+ {
+ if(thePackingString != NULL)
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
+ }
+ else
+ {
+ snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString);
+ }
+ }
+ }
+ }
+ break;
+
+ case kAudioFormatAC3:
+ strlcpy(outName, "AC-3", sizeof(outName));
+ break;
+
+ case kAudioFormat60958AC3:
+ strlcpy(outName, "AC-3 for SPDIF", sizeof(outName));
+ break;
+
+ default:
+ CACopy4CCToCString(outName, inDescription.mFormatID);
+ break;
+ };
+}
+
+#if CoreAudio_Debug
+#include "CALogMacros.h"
+
+void CAStreamBasicDescription::PrintToLog(const AudioStreamBasicDescription& inDesc)
+{
+ PrintFloat (" Sample Rate: ", inDesc.mSampleRate);
+ Print4CharCode (" Format ID: ", inDesc.mFormatID);
+ PrintHex (" Format Flags: ", inDesc.mFormatFlags);
+ PrintInt (" Bytes per Packet: ", inDesc.mBytesPerPacket);
+ PrintInt (" Frames per Packet: ", inDesc.mFramesPerPacket);
+ PrintInt (" Bytes per Frame: ", inDesc.mBytesPerFrame);
+ PrintInt (" Channels per Frame: ", inDesc.mChannelsPerFrame);
+ PrintInt (" Bits per Channel: ", inDesc.mBitsPerChannel);
+}
+#endif
+
+bool operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
+{
+ bool theAnswer = false;
+ bool isDone = false;
+
+ // note that if either side is 0, that field is skipped
+
+ // format ID is the first order sort
+ if((!isDone) && ((x.mFormatID != 0) && (y.mFormatID != 0)))
+ {
+ if(x.mFormatID != y.mFormatID)
+ {
+ // formats are sorted numerically except that linear
+ // PCM is always first
+ if(x.mFormatID == kAudioFormatLinearPCM)
+ {
+ theAnswer = true;
+ }
+ else if(y.mFormatID == kAudioFormatLinearPCM)
+ {
+ theAnswer = false;
+ }
+ else
+ {
+ theAnswer = x.mFormatID < y.mFormatID;
+ }
+ isDone = true;
+ }
+ }
+
+
+ // mixable is always better than non-mixable for linear PCM and should be the second order sort item
+ if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
+ {
+ if(((x.mFormatFlags & kIsNonMixableFlag) == 0) && ((y.mFormatFlags & kIsNonMixableFlag) != 0))
+ {
+ theAnswer = true;
+ isDone = true;
+ }
+ else if(((x.mFormatFlags & kIsNonMixableFlag) != 0) && ((y.mFormatFlags & kIsNonMixableFlag) == 0))
+ {
+ theAnswer = false;
+ isDone = true;
+ }
+ }
+
+ // floating point vs integer for linear PCM only
+ if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
+ {
+ if((x.mFormatFlags & kAudioFormatFlagIsFloat) != (y.mFormatFlags & kAudioFormatFlagIsFloat))
+ {
+ // floating point is better than integer
+ theAnswer = y.mFormatFlags & kAudioFormatFlagIsFloat;
+ isDone = true;
+ }
+ }
+
+ // bit depth
+ if((!isDone) && ((x.mBitsPerChannel != 0) && (y.mBitsPerChannel != 0)))
+ {
+ if(x.mBitsPerChannel != y.mBitsPerChannel)
+ {
+ // deeper bit depths are higher quality
+ theAnswer = x.mBitsPerChannel < y.mBitsPerChannel;
+ isDone = true;
+ }
+ }
+
+ // sample rate
+ if((!isDone) && fnonzero(x.mSampleRate) && fnonzero(y.mSampleRate))
+ {
+ if(fnotequal(x.mSampleRate, y.mSampleRate))
+ {
+ // higher sample rates are higher quality
+ theAnswer = x.mSampleRate < y.mSampleRate;
+ isDone = true;
+ }
+ }
+
+ // number of channels
+ if((!isDone) && ((x.mChannelsPerFrame != 0) && (y.mChannelsPerFrame != 0)))
+ {
+ if(x.mChannelsPerFrame != y.mChannelsPerFrame)
+ {
+ // more channels is higher quality
+ theAnswer = x.mChannelsPerFrame < y.mChannelsPerFrame;
+ isDone = true;
+ }
+ }
+
+ return theAnswer;
+}
+
+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 CAStreamBasicDescription::IsEqual(const AudioStreamBasicDescription &other, bool interpretingWildcards) const
+{
+ if (interpretingWildcards)
+ return *this == other;
+ return memcmp(this, &other, offsetof(AudioStreamBasicDescription, mReserved)) == 0;
+}
+
+bool SanityCheck(const AudioStreamBasicDescription& x)
+{
+ // This function returns false if there are sufficiently insane values in any field.
+ // It is very conservative so even some very unlikely values will pass.
+ // This is just meant to catch the case where the data from a file is corrupted.
+
+ return
+ (x.mSampleRate >= 0.)
+ && (x.mBytesPerPacket < 1000000)
+ && (x.mFramesPerPacket < 1000000)
+ && (x.mBytesPerFrame < 1000000)
+ && (x.mChannelsPerFrame <= 1024)
+ && (x.mBitsPerChannel <= 1024)
+ && (x.mFormatID != 0)
+ && !(x.mFormatID == kAudioFormatLinearPCM && (x.mFramesPerPacket != 1 || x.mBytesPerPacket != x.mBytesPerFrame));
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAStreamBasicDescription.h b/distrho/src/CoreAudio106/PublicUtility/CAStreamBasicDescription.h
new file mode 100755
index 00000000..2c1bb1f8
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAStreamBasicDescription.h
@@ -0,0 +1,297 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAStreamBasicDescription_h__
+#define __CAStreamBasicDescription_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include "CoreAudioTypes.h"
+ #include "CoreFoundation.h"
+#endif
+
+#include "CADebugMacros.h"
+#include <string.h> // for memset, memcpy
+#include <stdio.h> // for FILE *
+
+#pragma mark This file needs to compile on more earlier versions of the OS, so please keep that in mind when editing it
+
+extern char *CAStringForOSType (OSType t, char *writeLocation);
+
+// define Leopard specific symbols for backward compatibility if applicable
+#if COREAUDIOTYPES_VERSION < 1050
+typedef Float32 AudioSampleType;
+enum { kAudioFormatFlagsCanonical = kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked };
+#endif
+#if COREAUDIOTYPES_VERSION < 1051
+typedef Float32 AudioUnitSampleType;
+enum {
+ kLinearPCMFormatFlagsSampleFractionShift = 7,
+ kLinearPCMFormatFlagsSampleFractionMask = (0x3F << kLinearPCMFormatFlagsSampleFractionShift),
+};
+#endif
+
+// define the IsMixable format flag for all versions of the system
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3)
+ enum { kIsNonMixableFlag = kAudioFormatFlagIsNonMixable };
+#else
+ enum { kIsNonMixableFlag = (1L << 6) };
+#endif
+
+//=============================================================================
+// CAStreamBasicDescription
+//
+// This is a wrapper class for the AudioStreamBasicDescription struct.
+// It adds a number of convenience routines, but otherwise adds nothing
+// to the footprint of the original struct.
+//=============================================================================
+class CAStreamBasicDescription :
+ public AudioStreamBasicDescription
+{
+
+// Constants
+public:
+ static const AudioStreamBasicDescription sEmpty;
+
+// 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);
+ }
+
+ bool IsNativeEndian() const
+ {
+ return (mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian;
+ }
+
+ // for sanity with interleaved/deinterleaved possibilities, never access mChannelsPerFrame, use these:
+ UInt32 NumberInterleavedChannels() const { return IsInterleaved() ? mChannelsPerFrame : 1; }
+ UInt32 NumberChannelStreams() const { return IsInterleaved() ? 1 : mChannelsPerFrame; }
+ UInt32 NumberChannels() const { return mChannelsPerFrame; }
+ UInt32 SampleWordSize() const {
+ return (mBytesPerFrame > 0 && NumberInterleavedChannels()) ? mBytesPerFrame / NumberInterleavedChannels() : 0;
+ }
+
+ UInt32 FramesToBytes(UInt32 nframes) const { return nframes * mBytesPerFrame; }
+ UInt32 BytesToFrames(UInt32 nbytes) const {
+ Assert(mBytesPerFrame > 0, "bytesPerFrame must be > 0 in BytesToFrames");
+ return nbytes / mBytesPerFrame;
+ }
+
+ bool SameChannelsAndInterleaving(const CAStreamBasicDescription &a) const
+ {
+ return this->NumberChannels() == a.NumberChannels() && this->IsInterleaved() == a.IsInterleaved();
+ }
+
+ // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ //
+ // manipulation
+
+ void SetCanonical(UInt32 nChannels, bool interleaved)
+ // note: leaves sample rate untouched
+ {
+ mFormatID = kAudioFormatLinearPCM;
+ int sampleSize = SizeOf32(AudioSampleType);
+ mFormatFlags = kAudioFormatFlagsCanonical;
+ mBitsPerChannel = 8 * sampleSize;
+ mChannelsPerFrame = nChannels;
+ mFramesPerPacket = 1;
+ if (interleaved)
+ mBytesPerPacket = mBytesPerFrame = nChannels * sampleSize;
+ else {
+ mBytesPerPacket = mBytesPerFrame = sampleSize;
+ mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+ }
+ }
+
+ bool IsCanonical() const
+ {
+ if (mFormatID != kAudioFormatLinearPCM) return false;
+ UInt32 reqFormatFlags;
+ UInt32 flagsMask = (kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsAlignedHigh | kLinearPCMFormatFlagsSampleFractionMask);
+ bool interleaved = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
+ unsigned sampleSize = SizeOf32(AudioSampleType);
+ reqFormatFlags = kAudioFormatFlagsCanonical;
+ UInt32 reqFrameSize = interleaved ? (mChannelsPerFrame * sampleSize) : sampleSize;
+
+ return ((mFormatFlags & flagsMask) == reqFormatFlags
+ && mBitsPerChannel == 8 * sampleSize
+ && mFramesPerPacket == 1
+ && mBytesPerFrame == reqFrameSize
+ && mBytesPerPacket == reqFrameSize);
+ }
+
+ void SetAUCanonical(UInt32 nChannels, bool interleaved)
+ {
+ mFormatID = kAudioFormatLinearPCM;
+#if CA_PREFER_FIXED_POINT
+ mFormatFlags = kAudioFormatFlagsCanonical | (kAudioUnitSampleFractionBits << kLinearPCMFormatFlagsSampleFractionShift);
+#else
+ mFormatFlags = kAudioFormatFlagsCanonical;
+#endif
+ mChannelsPerFrame = nChannels;
+ mFramesPerPacket = 1;
+ mBitsPerChannel = 8 * SizeOf32(AudioUnitSampleType);
+ if (interleaved)
+ mBytesPerPacket = mBytesPerFrame = nChannels * SizeOf32(AudioUnitSampleType);
+ else {
+ mBytesPerPacket = mBytesPerFrame = SizeOf32(AudioUnitSampleType);
+ mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+ }
+ }
+
+ void ChangeNumberChannels(UInt32 nChannels, bool interleaved)
+ // alter an existing format
+ {
+ Assert(IsPCM(), "ChangeNumberChannels only works for PCM formats");
+ UInt32 wordSize = SampleWordSize(); // get this before changing ANYTHING
+ if (wordSize == 0)
+ wordSize = (mBitsPerChannel + 7) / 8;
+ mChannelsPerFrame = nChannels;
+ mFramesPerPacket = 1;
+ if (interleaved) {
+ mBytesPerPacket = mBytesPerFrame = nChannels * wordSize;
+ mFormatFlags &= ~kAudioFormatFlagIsNonInterleaved;
+ } else {
+ mBytesPerPacket = mBytesPerFrame = wordSize;
+ mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+ }
+ }
+
+ // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ //
+ // other
+
+ bool IsEqual(const AudioStreamBasicDescription &other, bool interpretingWildcards=true) const;
+
+ void Print() const {
+ Print (stdout);
+ }
+
+ void Print(FILE* file) const {
+ PrintFormat (file, "", "AudioStreamBasicDescription:");
+ }
+
+ void PrintFormat(FILE *f, const char *indent, const char *name) const {
+ char buf[256];
+ fprintf(f, "%s%s %s\n", indent, name, AsString(buf, sizeof(buf)));
+ }
+
+ void PrintFormat2(FILE *f, const char *indent, const char *name) const { // no trailing newline
+ char buf[256];
+ fprintf(f, "%s%s %s", indent, name, AsString(buf, sizeof(buf)));
+ }
+
+ char * AsString(char *buf, size_t bufsize) const;
+
+ static void Print (const AudioStreamBasicDescription &inDesc)
+ {
+ CAStreamBasicDescription desc(inDesc);
+ desc.Print ();
+ }
+
+ OSStatus Save(CFPropertyListRef *outData) const;
+
+ OSStatus Restore(CFPropertyListRef &inData);
+
+// Operations
+ static bool IsMixable(const AudioStreamBasicDescription& inDescription) { return (inDescription.mFormatID == kAudioFormatLinearPCM) && ((inDescription.mFormatFlags & kIsNonMixableFlag) == 0); }
+ static void NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription);
+ static void ResetFormat(AudioStreamBasicDescription& ioDescription);
+ static void FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription);
+ static void GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, UInt32 inMaxNameLength, 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/distrho/src/CoreAudio106/PublicUtility/CAStreamRangedDescription.cpp b/distrho/src/CoreAudio106/PublicUtility/CAStreamRangedDescription.cpp
new file mode 100755
index 00000000..57b800cd
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAStreamRangedDescription.cpp
@@ -0,0 +1,70 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Self Include
+#include "CAStreamRangedDescription.h"
+
+//==================================================================================================
+// CAStreamRangedDescription
+//==================================================================================================
+
+const AudioStreamRangedDescription CAStreamRangedDescription::sEmpty = { { 0.0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0.0, 0.0 } };
+
+#if CoreAudio_Debug
+#include "CALogMacros.h"
+
+void CAStreamRangedDescription::PrintToLog(const AudioStreamRangedDescription& inDesc)
+{
+ PrintFloat (" Sample Rate: ", inDesc.mFormat.mSampleRate);
+ PrintFloat (" Max Sample Rate: ", inDesc.mSampleRateRange.mMaximum);
+ PrintFloat (" Min Sample Rate: ", inDesc.mSampleRateRange.mMinimum);
+ Print4CharCode (" Format ID: ", inDesc.mFormat.mFormatID);
+ PrintHex (" Format Flags: ", inDesc.mFormat.mFormatFlags);
+ PrintInt (" Bytes per Packet: ", inDesc.mFormat.mBytesPerPacket);
+ PrintInt (" Frames per Packet: ", inDesc.mFormat.mFramesPerPacket);
+ PrintInt (" Bytes per Frame: ", inDesc.mFormat.mBytesPerFrame);
+ PrintInt (" Channels per Frame: ", inDesc.mFormat.mChannelsPerFrame);
+ PrintInt (" Bits per Channel: ", inDesc.mFormat.mBitsPerChannel);
+}
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAStreamRangedDescription.h b/distrho/src/CoreAudio106/PublicUtility/CAStreamRangedDescription.h
new file mode 100755
index 00000000..49910d68
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAStreamRangedDescription.h
@@ -0,0 +1,93 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CAStreamRangedDescription_h__)
+#define __CAStreamRangedDescription_h__
+
+//==================================================================================================
+// Includes
+//==================================================================================================
+
+// Super Class Includes
+#include <CoreAudio/AudioHardware.h>
+
+// PublicUtility Includes
+#include "CAAudioValueRange.h"
+#include "CAStreamBasicDescription.h"
+
+//==================================================================================================
+// CAStreamRangedDescription
+//==================================================================================================
+
+class CAStreamRangedDescription
+:
+ public AudioStreamRangedDescription
+{
+
+// Constants
+public:
+ static const AudioStreamRangedDescription sEmpty;
+
+// Construction/Destruction
+public:
+ CAStreamRangedDescription() { memset(this, 0, sizeof(AudioStreamRangedDescription)); }
+ CAStreamRangedDescription(const CAStreamRangedDescription& inFormat) { mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; }
+ CAStreamRangedDescription(const AudioStreamRangedDescription& inFormat) { mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; }
+ CAStreamRangedDescription(const AudioStreamBasicDescription& inFormat) { mFormat = inFormat; mSampleRateRange.mMinimum = inFormat.mSampleRate; mSampleRateRange.mMaximum = inFormat.mSampleRate; }
+ CAStreamRangedDescription(const AudioStreamBasicDescription& inFormat, const AudioValueRange& inSampleRateRange) { mFormat = inFormat; mSampleRateRange = inSampleRateRange; }
+ CAStreamRangedDescription& operator=(const CAStreamRangedDescription& inFormat) { mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; return *this; }
+ CAStreamRangedDescription& operator=(const AudioStreamRangedDescription& inFormat) { mFormat = inFormat.mFormat; mSampleRateRange = inFormat.mSampleRateRange; return *this; }
+
+ static bool IsMixable(const AudioStreamRangedDescription& inDescription) { return (inDescription.mFormat.mFormatID == kAudioFormatLinearPCM) && ((inDescription.mFormat.mFormatFlags & kIsNonMixableFlag) == 0); }
+#if CoreAudio_Debug
+ static void PrintToLog(const AudioStreamRangedDescription& inDesc);
+#endif
+};
+
+inline bool operator<(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return (x.mFormat < y.mFormat) && (x.mSampleRateRange < y.mSampleRateRange); }
+inline bool operator==(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return (x.mFormat == y.mFormat) && (x.mSampleRateRange == y.mSampleRateRange); }
+#if TARGET_OS_MAC || (TARGET_OS_WIN32 && (_MSC_VER > 600))
+inline bool operator!=(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return !(x == y); }
+inline bool operator<=(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return (x < y) || (x == y); }
+inline bool operator>=(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return !(x < y); }
+inline bool operator>(const AudioStreamRangedDescription& x, const AudioStreamRangedDescription& y) { return !((x < y) || (x == y)); }
+#endif
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAThreadSafeList.h b/distrho/src/CoreAudio106/PublicUtility/CAThreadSafeList.h
new file mode 100755
index 00000000..2da8f71e
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAThreadSafeList.h
@@ -0,0 +1,250 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAThreadSafeList_h__
+#define __CAThreadSafeList_h__
+
+#include "CAAtomicStack.h"
+
+// linked list of T's
+// T must define operator ==
+template <class T>
+class TThreadSafeList {
+private:
+ enum EEventType { kAdd, kRemove, kClear };
+ class Node {
+ public:
+ Node * mNext;
+ EEventType mEventType;
+ T mObject;
+
+ void set_next(Node *node) { mNext = node; }
+ Node * get_next() { return mNext; }
+ };
+
+public:
+ class iterator {
+ public:
+ iterator() { }
+ iterator(Node *n) : mNode(n) { }
+
+ bool operator == (const iterator &other) const { return this->mNode == other.mNode; }
+ bool operator != (const iterator &other) const { return this->mNode != other.mNode; }
+
+ T & operator * () const { return mNode->mObject; }
+
+ iterator & operator ++ () { mNode = mNode->get_next(); return *this; } // preincrement
+ iterator operator ++ (int) { iterator tmp = *this; mNode = mNode->get_next(); return tmp; } // postincrement
+
+ private:
+ Node * mNode;
+ };
+
+ TThreadSafeList() { }
+ ~TThreadSafeList()
+ {
+ mActiveList.free_all();
+ mPendingList.free_all();
+ mFreeList.free_all();
+ }
+
+ // These may be called on any thread
+
+ void deferred_add(const T &obj) // can be called on any thread
+ {
+ Node *node = AllocNode();
+ node->mEventType = kAdd;
+ node->mObject = obj;
+ mPendingList.push_atomic(node);
+ //mPendingList.dump("pending after add");
+ }
+
+ void deferred_remove(const T &obj) // can be called on any thread
+ {
+ Node *node = AllocNode();
+ node->mEventType = kRemove;
+ node->mObject = obj;
+ mPendingList.push_atomic(node);
+ //mPendingList.dump("pending after remove");
+ }
+
+ void deferred_clear() // can be called on any thread
+ {
+ Node *node = AllocNode();
+ node->mEventType = kClear;
+ mPendingList.push_atomic(node);
+ }
+
+ // These must be called from only one thread
+
+ void update() // must only be called from one thread
+ {
+ NodeStack reversed;
+ Node *event, *node, *next;
+ bool workDone = false;
+
+ // reverse the events so they are in order
+ event = mPendingList.pop_all();
+ while (event != NULL) {
+ next = event->mNext;
+ reversed.push_NA(event);
+ event = next;
+ workDone = true;
+ }
+ if (workDone) {
+ //reversed.dump("pending popped");
+ //mActiveList.dump("active before update");
+
+ // now process them
+ while ((event = reversed.pop_NA()) != NULL) {
+ switch (event->mEventType) {
+ case kAdd:
+ {
+ Node **pnode;
+ bool needToInsert = true;
+ for (pnode = mActiveList.phead(); *pnode != NULL; pnode = &node->mNext) {
+ node = *pnode;
+ if (node->mObject == event->mObject) {
+ //printf("already active!!!\n");
+ FreeNode(event);
+ needToInsert = false;
+ break;
+ }
+ }
+ if (needToInsert) {
+ // link the new event in at the end of the active list
+ *pnode = event;
+ event->mNext = NULL;
+ }
+ }
+ break;
+ case kRemove:
+ // find matching node in the active list, remove it
+ for (Node **pnode = mActiveList.phead(); *pnode != NULL; ) {
+ node = *pnode;
+ if (node->mObject == event->mObject) {
+ *pnode = node->mNext; // remove from linked list
+ FreeNode(node);
+ break;
+ }
+ pnode = &node->mNext;
+ }
+ // dispose the request node
+ FreeNode(event);
+ break;
+ case kClear:
+ for (node = mActiveList.head(); node != NULL; ) {
+ next = node->mNext;
+ FreeNode(node);
+ node = next;
+ }
+ FreeNode(event);
+ break;
+ default:
+ //printf("invalid node type %d!\n", event->mEventType);
+ break;
+ }
+ }
+ //mActiveList.dump("active after update");
+ }
+ }
+
+ iterator begin() const {
+ //mActiveList.dump("active at begin");
+ return iterator(mActiveList.head());
+ }
+ iterator end() const { return iterator(NULL); }
+
+
+private:
+ Node * AllocNode()
+ {
+ Node *node = mFreeList.pop_atomic();
+ if (node == NULL)
+ node = (Node *)CA_malloc(sizeof(Node));
+ return node;
+ }
+
+ void FreeNode(Node *node)
+ {
+ mFreeList.push_atomic(node);
+ }
+
+private:
+ class NodeStack : public TAtomicStack<Node> {
+ public:
+ void free_all() {
+ Node *node;
+ while ((node = this->pop_NA()) != NULL)
+ free(node);
+ }
+
+ Node ** phead() { return &this->mHead; }
+ Node * head() const { return this->mHead; }
+
+ /*void dump(char *label) const
+ {
+ char buf[1024];
+ int count = 0;
+ Node *node = mHead;
+ sprintf(buf, "%s:", label);
+ while (node != NULL) {
+ sprintf(buf+strlen(buf), " %p/%d", node, node->mEventType);
+ if (++count == 5) { sprintf(buf+strlen(buf), "..."); break; }
+ node = node->mNext;
+ }
+ puts(buf);
+ }*/
+
+ /*int size() const
+ {
+ int count = 0;
+ for (Node *node = mHead; node != NULL; node = node->mNext)
+ ++count;
+ return count;
+ }*/
+ };
+
+ NodeStack mActiveList; // what's actually in the container - only accessed on one thread
+ NodeStack mPendingList; // add or remove requests - threadsafe
+ NodeStack mFreeList; // free nodes for reuse - threadsafe
+};
+
+#endif // __CAThreadSafeList_h__
diff --git a/distrho/src/CoreAudio106/PublicUtility/CATink.h b/distrho/src/CoreAudio106/PublicUtility/CATink.h
new file mode 100755
index 00000000..64b28757
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CATink.h
@@ -0,0 +1,140 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CATink_h__)
+#define __CATink_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreServices/CoreServices.h>
+#else
+ #include <CoreServices.h>
+#endif
+
+
+//=============================================================================
+// CATink
+//
+// A Tink is a small jump island that can make one function appear as if it
+// has many addresses. Note that Tinks are not supported for 64 bit environments
+// as the APIs that made tinks useful have been replaced by APIs that do away
+// with all the reasons for using a tink.
+//=============================================================================
+
+template <class F>
+class CATink
+{
+
+public:
+ CATink(F proc) { Set(proc); }
+
+ ~CATink() { Set((F)0xDEADDEAD); } // jump to an obviously bad (odd) address if accessed after destruction
+
+#if TARGET_CPU_PPC
+ void Set(F proc)
+ {
+ /*
+ lis r11,0x1234
+ 00000000: 3D601234 lis r11,4660
+ ori r11,r11,0x5678
+ 00000004: 616B5678 ori r11,r11,$5678
+ mtctr r11
+ 00000008: 7D6903A6 mtctr r11
+ bctr
+ 0000000C: 4E800420 bctr
+ */
+ UInt32 p = UInt32(proc);
+ mCode[0] = 0x3D600000 | (p >> 16);
+ mCode[1] = 0x616B0000 | (p & 0xFFFF);
+ mCode[2] = 0x7D6903A6;
+ mCode[3] = 0x4E800420;
+ MakeDataExecutable(mCode, sizeof(mCode));
+ }
+
+ operator F () { return F(mCode); }
+
+private:
+ UInt32 mCode[4];
+#elif TARGET_CPU_X86
+ void Set(F proc)
+ {
+ /*
+ <tink>: push $0x12345678
+ <tink+5>: ret
+ <tink>: 0x34567868
+ <tink+4>: 0x00e8c312
+ */
+ UInt32 p = UInt32(proc);
+ mCode[0] = ((p & 0xFFFFFF) << 8) | 0x00000068;
+ mCode[1] = 0xCCCCC300 | (p >> 24);
+ MakeDataExecutable(mCode, sizeof(mCode));
+ }
+
+ operator F () { return F(&mCode[0]); }
+
+private:
+ UInt32 mCode[2];
+#else
+ #warning: CPU not directly supported by CATink
+
+ // For other CPU's, just wrap the function pointer for now.
+ // this bypasses what we're trying to accomplish with the Tink
+ // (multiple unique "instances" of a function), but it will at
+ // least compile and run.
+
+ void Set(F proc) { mProcPtr = proc; }
+
+ operator F () { return mProcPtr; }
+private:
+ F mProcPtr;
+#endif
+
+// Tinks cannot be allocated in STL Containers, so we make a few key methods private
+private:
+ CATink(){}
+ CATink(const CATink&){}
+ CATink& operator=(const CATink&){ return *this;}
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CATokenMap.h b/distrho/src/CoreAudio106/PublicUtility/CATokenMap.h
new file mode 100755
index 00000000..e1e44bf1
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CATokenMap.h
@@ -0,0 +1,206 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CATokenMap_h__)
+#define __CATokenMap_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+// System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+
+// PublicUtility Includes
+#include "CAMutex.h"
+
+// Standard Library Includes
+#include <map>
+#include <iterator>
+
+//=============================================================================
+// CATokenMap
+//=============================================================================
+
+template <class T>
+class CATokenMap
+{
+
+// Types
+private:
+ typedef std::map<UInt32, T*> TokenMap;
+
+// Construction/Destruction
+public:
+ CATokenMap() : mTokenMap(), mNextToken(256), mTokenMapMutex("CATokenMap Mutex") {}
+ ~CATokenMap() {}
+
+// Operations
+public:
+ bool Lock()
+ {
+ return mTokenMapMutex.Lock();
+ }
+
+ void Unlock()
+ {
+ mTokenMapMutex.Unlock();
+ }
+
+ UInt32 GetToken(T* inObject) const
+ {
+ CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex));
+ UInt32 theAnswer = 0;
+ typename TokenMap::const_iterator i = mTokenMap.begin();
+ while((theAnswer == 0) && (i != mTokenMap.end()))
+ {
+ if(i->second == inObject)
+ {
+ theAnswer = i->first;
+ }
+ std::advance(i, 1);
+ }
+ return theAnswer;
+ }
+
+ T* GetObject(UInt32 inToken) const
+ {
+ CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex));
+ typename TokenMap::const_iterator i = mTokenMap.find(inToken);
+ return i != mTokenMap.end() ? i->second : NULL;
+ }
+
+ T* GetObject(const void* inToken) const
+ {
+ #if __LP64__
+ return GetObject((UInt32)((UInt64)inToken));
+ #else
+ return GetObject((UInt32)inToken);
+ #endif
+ }
+
+ UInt32 GetNumberObjects() const
+ {
+ CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex));
+ return mTokenMap.size();
+ }
+
+ T* GetObjectByIndex(UInt32 inIndex) const
+ {
+ T* theAnswer = NULL;
+ CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex));
+ if(inIndex < mTokenMap.size())
+ {
+ typename TokenMap::const_iterator i = mTokenMap.begin();
+ std::advance(i, inIndex);
+ theAnswer = (i != mTokenMap.end()) ? i->second : NULL;
+ }
+ return theAnswer;
+ }
+
+ void AddMapping(UInt32 inToken, T* inObject)
+ {
+ CAMutex::Locker theLocker(mTokenMapMutex);
+ typename TokenMap::iterator i = mTokenMap.find(inToken);
+ if(i != mTokenMap.end())
+ {
+ i->second = inObject;
+ }
+ else
+ {
+ mTokenMap.insert(typename TokenMap::value_type(inToken, inObject));
+ }
+ }
+
+ void RemoveMapping(UInt32 inToken, T* /*inObject*/)
+ {
+ CAMutex::Locker theLocker(mTokenMapMutex);
+ typename TokenMap::iterator i = mTokenMap.find(inToken);
+ if(i != mTokenMap.end())
+ {
+ mTokenMap.erase(i);
+ }
+ }
+
+ UInt32 GetNextToken()
+ {
+ return mNextToken++;
+ }
+
+ UInt32 MapObject(T* inObject)
+ {
+ CAMutex::Locker theLocker(mTokenMapMutex);
+ UInt32 theToken = GetNextToken();
+ mTokenMap.insert(typename TokenMap::value_type(theToken, inObject));
+ return theToken;
+ }
+
+ void UnmapObject(T* inObject)
+ {
+ CAMutex::Locker theLocker(mTokenMapMutex);
+ bool isDone = false;
+ typename TokenMap::iterator i = mTokenMap.begin();
+ while(!isDone && (i != mTokenMap.end()))
+ {
+ if(i->second == inObject)
+ {
+ mTokenMap.erase(i);
+ isDone = true;
+ }
+ else
+ {
+ std::advance(i, 1);
+ }
+ }
+ }
+
+// Implementation
+private:
+ TokenMap mTokenMap;
+ UInt32 mNextToken;
+ CAMutex mTokenMapMutex;
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAVectorUnit.cpp b/distrho/src/CoreAudio106/PublicUtility/CAVectorUnit.cpp
new file mode 100755
index 00000000..6e1c49ea
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAVectorUnit.cpp
@@ -0,0 +1,183 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CAVectorUnit.h"
+
+#if !TARGET_OS_WIN32
+ #include <sys/sysctl.h>
+#elif HAS_IPP
+ #include "ippdefs.h"
+ #include "ippcore.h"
+#endif
+
+int CAVectorUnit::sVectorUnitType = kVecUninitialized;
+
+#if TARGET_OS_WIN32
+// Use cpuid to check if SSE2 is available.
+// Before calling this function make sure cpuid is available
+static SInt32 IsSSE2Available()
+{
+ int return_value;
+
+ {
+ int r_edx;
+ _asm
+ {
+ mov eax, 0x01
+ cpuid
+ mov r_edx, edx
+ }
+ return_value = (r_edx >> 26) & 0x1;
+ }
+ return return_value;
+}
+
+// Use cpuid to check if SSE3 is available.
+// Before calling this function make sure cpuid is available
+static SInt32 IsSSE3Available()
+{
+ SInt32 return_value;
+
+ {
+ SInt32 r_ecx;
+ _asm
+ {
+ mov eax, 0x01
+ cpuid
+ mov r_ecx, ecx
+ }
+ return_value = r_ecx & 0x1;
+ }
+ return return_value;
+}
+
+// Return true if the cpuid instruction is available.
+// The cpuid instruction is available if bit 21 in the EFLAGS register can be changed
+// This function may not work on Intel CPUs prior to Pentium (didn't test)
+static bool IsCpuidAvailable()
+{
+ SInt32 return_value = 0x0;
+ _asm{
+ pushfd ; //push original EFLAGS
+ pop eax ; //get original EFLAGS
+ mov ecx, eax ; //save original EFLAGS
+ xor eax, 200000h ; //flip ID bit in EFLAGS
+ push eax ; //save new EFLAGS value on stack
+ popfd ; //replace current EFLAGS value
+ pushfd ; //get new EFLAGS
+ pop eax ; //store new EFLAGS in EAX
+ xor eax, ecx ;
+ je end_cpuid_identify ; //can't toggle ID bit
+ mov return_value, 0x1;
+end_cpuid_identify:
+ nop;
+ }
+ return return_value;
+}
+
+#endif
+
+SInt32 CAVectorUnit::CheckVectorUnit()
+{
+ int result = kVecNone;
+
+#if TARGET_OS_WIN32
+#if HAS_IPP
+ // Initialize the static IPP library! This needs to be done before
+ // any IPP function calls, otherwise we may have a performance penalty
+ int status = ippStaticInit();
+ if ( status == ippStsNonIntelCpu )
+ {
+ IppCpuType cpuType = ippGetCpuType();
+ if ( cpuType >= ippCpuSSE || cpuType <= ippCpuSSE42 )
+ ippStaticInitCpu( cpuType );
+ }
+#endif
+ {
+ // On Windows we use cpuid to detect the vector unit because it works on Intel and AMD.
+ // The IPP library does not detect SSE on AMD processors.
+ if (IsCpuidAvailable())
+ {
+ if(IsSSE3Available())
+ {
+ result = kVecSSE3;
+ }
+ else if(IsSSE2Available())
+ {
+ result = kVecSSE2;
+ }
+ }
+ }
+#elif TARGET_OS_MAC
+#if DEBUG
+ if (getenv("CA_NoVector")) {
+ fprintf(stderr, "CA_NoVector set; Vector unit optimized routines will be bypassed\n");
+ return result;
+ }
+ else
+#endif
+ {
+ #if (TARGET_CPU_PPC || TARGET_CPU_PPC64)
+ int sels[2] = { CTL_HW, HW_VECTORUNIT };
+ int vType = 0; //0 == scalar only
+ size_t length = sizeof(vType);
+ int error = sysctl(sels, 2, &vType, &length, NULL, 0);
+ if (!error && vType > 0)
+ result = kVecAltivec;
+ #elif (TARGET_CPU_X86 || TARGET_CPU_X86_64)
+ int answer = 0;
+ size_t length = sizeof(answer);
+ int error = sysctlbyname("hw.optional.sse3", &answer, &length, NULL, 0);
+ if (!error && answer)
+ result = kVecSSE3;
+ else {
+ answer = 0;
+ length = sizeof(answer);
+ error = sysctlbyname("hw.optional.sse2", &answer, &length, NULL, 0);
+ if (!error && answer)
+ result = kVecSSE2;
+ }
+ #endif
+ }
+#endif
+ sVectorUnitType = result;
+ return result;
+}
+
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAVectorUnit.h b/distrho/src/CoreAudio106/PublicUtility/CAVectorUnit.h
new file mode 100755
index 00000000..dbd344db
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAVectorUnit.h
@@ -0,0 +1,72 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAVectorUnit_h__
+#define __CAVectorUnit_h__
+
+#include <TargetConditionals.h>
+#include "CAVectorUnitTypes.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CFBase.h>
+#else
+ #include "CFBase.h"
+#endif
+
+// Unify checks for vector units into a single function.
+// Allow setting an environment variable "CA_NoVector" to turn off vectorized code at runtime (very useful for performance testing).
+
+class CAVectorUnit {
+public:
+ static SInt32 GetVectorUnitType() { int x = sVectorUnitType; return (x != kVecUninitialized) ? x : CheckVectorUnit(); }
+ static bool HasVectorUnit() { return GetVectorUnitType() > kVecNone; }
+ static bool HasAltivec() { return GetVectorUnitType() == kVecAltivec; }
+ static bool HasSSE2() { return GetVectorUnitType() >= kVecSSE2; }
+ static bool HasSSE3() { return GetVectorUnitType() == kVecSSE3; }
+
+private:
+ static SInt32 CheckVectorUnit();
+
+ static int sVectorUnitType;
+};
+
+#endif // __CAVectorUnit_h__
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAVectorUnitTypes.h b/distrho/src/CoreAudio106/PublicUtility/CAVectorUnitTypes.h
new file mode 100755
index 00000000..18595748
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAVectorUnitTypes.h
@@ -0,0 +1,52 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAVectorUnitTypes_h__
+#define __CAVectorUnitTypes_h__
+
+enum {
+ kVecUninitialized = -1,
+ kVecNone = 0,
+ kVecAltivec = 1,
+ kVecSSE2 = 100,
+ kVecSSE3 = 101
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAVolumeCurve.cpp b/distrho/src/CoreAudio106/PublicUtility/CAVolumeCurve.cpp
new file mode 100755
index 00000000..2e98a8b2
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAVolumeCurve.cpp
@@ -0,0 +1,476 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+//=============================================================================
+// Includes
+//=============================================================================
+
+#include "CAVolumeCurve.h"
+#include "CADebugMacros.h"
+#include <math.h>
+
+//=============================================================================
+// CAVolumeCurve
+//=============================================================================
+
+CAVolumeCurve::CAVolumeCurve()
+:
+ mTag(0),
+ mCurveMap(),
+ mIsApplyingTransferFunction(true),
+ mTransferFunction(kPow2Over1Curve),
+ mRawToScalarExponentNumerator(2.0),
+ mRawToScalarExponentDenominator(1.0)
+{
+}
+
+CAVolumeCurve::~CAVolumeCurve()
+{
+}
+
+SInt32 CAVolumeCurve::GetMinimumRaw() const
+{
+ SInt32 theAnswer = 0;
+
+ if(!mCurveMap.empty())
+ {
+ CurveMap::const_iterator theIterator = mCurveMap.begin();
+ theAnswer = theIterator->first.mMinimum;
+ }
+
+ return theAnswer;
+}
+
+SInt32 CAVolumeCurve::GetMaximumRaw() const
+{
+ SInt32 theAnswer = 0;
+
+ if(!mCurveMap.empty())
+ {
+ CurveMap::const_iterator theIterator = mCurveMap.begin();
+ std::advance(theIterator, mCurveMap.size() - 1);
+ theAnswer = theIterator->first.mMaximum;
+ }
+
+ return theAnswer;
+}
+
+Float64 CAVolumeCurve::GetMinimumDB() const
+{
+ Float64 theAnswer = 0;
+
+ if(!mCurveMap.empty())
+ {
+ CurveMap::const_iterator theIterator = mCurveMap.begin();
+ theAnswer = theIterator->second.mMinimum;
+ }
+
+ return theAnswer;
+}
+
+Float64 CAVolumeCurve::GetMaximumDB() const
+{
+ Float64 theAnswer = 0;
+
+ if(!mCurveMap.empty())
+ {
+ CurveMap::const_iterator theIterator = mCurveMap.begin();
+ std::advance(theIterator, mCurveMap.size() - 1);
+ theAnswer = theIterator->second.mMaximum;
+ }
+
+ return theAnswer;
+}
+
+void CAVolumeCurve::SetTransferFunction(int inTransferFunction)
+{
+ mTransferFunction = inTransferFunction;
+
+ // figure out the co-efficients
+ switch(inTransferFunction)
+ {
+ case kLinearCurve:
+ mIsApplyingTransferFunction = false;
+ mRawToScalarExponentNumerator = 1.0;
+ mRawToScalarExponentDenominator = 1.0;
+ break;
+
+ case kPow1Over3Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 1.0;
+ mRawToScalarExponentDenominator = 3.0;
+ break;
+
+ case kPow1Over2Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 1.0;
+ mRawToScalarExponentDenominator = 2.0;
+ break;
+
+ case kPow3Over4Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 3.0;
+ mRawToScalarExponentDenominator = 4.0;
+ break;
+
+ case kPow3Over2Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 3.0;
+ mRawToScalarExponentDenominator = 2.0;
+ break;
+
+ case kPow2Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 2.0;
+ mRawToScalarExponentDenominator = 1.0;
+ break;
+
+ case kPow3Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 3.0;
+ mRawToScalarExponentDenominator = 1.0;
+ break;
+
+ case kPow4Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 4.0;
+ mRawToScalarExponentDenominator = 1.0;
+ break;
+
+ case kPow5Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 5.0;
+ mRawToScalarExponentDenominator = 1.0;
+ break;
+
+ case kPow6Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 6.0;
+ mRawToScalarExponentDenominator = 1.0;
+ break;
+
+ case kPow7Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 7.0;
+ mRawToScalarExponentDenominator = 1.0;
+ break;
+
+ case kPow8Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 8.0;
+ mRawToScalarExponentDenominator = 1.0;
+ break;
+
+ case kPow9Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 9.0;
+ mRawToScalarExponentDenominator = 1.0;
+ break;
+
+ case kPow10Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 10.0;
+ mRawToScalarExponentDenominator = 1.0;
+ break;
+
+ case kPow11Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 11.0;
+ mRawToScalarExponentDenominator = 1.0;
+ break;
+
+ case kPow12Over1Curve:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 12.0;
+ mRawToScalarExponentDenominator = 1.0;
+ break;
+
+ default:
+ mIsApplyingTransferFunction = true;
+ mRawToScalarExponentNumerator = 2.0;
+ mRawToScalarExponentDenominator = 1.0;
+ break;
+ };
+}
+
+void CAVolumeCurve::AddRange(SInt32 inMinRaw, SInt32 inMaxRaw, Float64 inMinDB, Float64 inMaxDB)
+{
+ CARawPoint theRaw(inMinRaw, inMaxRaw);
+ CADBPoint theDB(inMinDB, inMaxDB);
+
+ bool isOverlapped = false;
+ bool isDone = false;
+ CurveMap::iterator theIterator = mCurveMap.begin();
+ while((theIterator != mCurveMap.end()) && !isOverlapped && !isDone)
+ {
+ isOverlapped = CARawPoint::Overlap(theRaw, theIterator->first);
+ isDone = theRaw >= theIterator->first;
+
+ if(!isOverlapped && !isDone)
+ {
+ std::advance(theIterator, 1);
+ }
+ }
+
+ if(!isOverlapped)
+ {
+ mCurveMap.insert(CurveMap::value_type(theRaw, theDB));
+ }
+ else
+ {
+ DebugMessage("CAVolumeCurve::AddRange: new point overlaps");
+ }
+}
+
+void CAVolumeCurve::ResetRange()
+{
+ mCurveMap.clear();
+}
+
+bool CAVolumeCurve::CheckForContinuity() const
+{
+ bool theAnswer = true;
+
+ CurveMap::const_iterator theIterator = mCurveMap.begin();
+ if(theIterator != mCurveMap.end())
+ {
+ SInt32 theRaw = theIterator->first.mMinimum;
+ Float64 theDB = theIterator->second.mMinimum;
+ do
+ {
+ SInt32 theRawMin = theIterator->first.mMinimum;
+ SInt32 theRawMax = theIterator->first.mMaximum;
+ SInt32 theRawRange = theRawMax - theRawMin;
+
+ Float64 theDBMin = theIterator->second.mMinimum;
+ Float64 theDBMax = theIterator->second.mMaximum;
+ Float64 theDBRange = theDBMax - theDBMin;
+
+ theAnswer = theRaw == theRawMin;
+ theAnswer = theDB == theDBMin;
+
+ theRaw += theRawRange;
+ theDB += theDBRange;
+
+ std::advance(theIterator, 1);
+ }
+ while((theIterator != mCurveMap.end()) && theAnswer);
+ }
+
+ return theAnswer;
+}
+
+SInt32 CAVolumeCurve::ConvertDBToRaw(Float64 inDB) const
+{
+ // clamp the value to the dB range
+ Float64 theOverallDBMin = GetMinimumDB();
+ Float64 theOverallDBMax = GetMaximumDB();
+
+ if(inDB < theOverallDBMin) inDB = theOverallDBMin;
+ if(inDB > theOverallDBMax) inDB = theOverallDBMax;
+
+ // get the first entry in the curve map;
+ CurveMap::const_iterator theIterator = mCurveMap.begin();
+
+ // initialize the answer to the minimum raw of the first item in the curve map
+ SInt32 theAnswer = theIterator->first.mMinimum;
+
+ // iterate through the curve map until we run out of dB
+ bool isDone = false;
+ while(!isDone && (theIterator != mCurveMap.end()))
+ {
+ SInt32 theRawMin = theIterator->first.mMinimum;
+ SInt32 theRawMax = theIterator->first.mMaximum;
+ SInt32 theRawRange = theRawMax - theRawMin;
+
+ Float64 theDBMin = theIterator->second.mMinimum;
+ Float64 theDBMax = theIterator->second.mMaximum;
+ Float64 theDBRange = theDBMax - theDBMin;
+
+ Float64 theDBPerRaw = theDBRange / static_cast<Float64>(theRawRange);
+
+ // figure out how many steps we are into this entry in the curve map
+ if(inDB > theDBMax)
+ {
+ // we're past the end of this one, so add in the whole range for this entry
+ theAnswer += theRawRange;
+ }
+ else
+ {
+ // it's somewhere within the current entry
+ // figure out how many steps it is
+ Float64 theNumberRawSteps = inDB - theDBMin;
+ theNumberRawSteps /= theDBPerRaw;
+
+ // only move in whole steps
+ theNumberRawSteps = round(theNumberRawSteps);
+
+ // add this many steps to the answer
+ theAnswer += static_cast<SInt32>(theNumberRawSteps);
+
+ // mark that we are done
+ isDone = true;
+ }
+
+ // go to the next entry in the curve map
+ std::advance(theIterator, 1);
+ }
+
+ return theAnswer;
+}
+
+Float64 CAVolumeCurve::ConvertRawToDB(SInt32 inRaw) const
+{
+ Float64 theAnswer = 0;
+
+ // clamp the raw value
+ SInt32 theOverallRawMin = GetMinimumRaw();
+ SInt32 theOverallRawMax = GetMaximumRaw();
+
+ if(inRaw < theOverallRawMin) inRaw = theOverallRawMin;
+ if(inRaw > theOverallRawMax) inRaw = theOverallRawMax;
+
+ // figure out how many raw steps need to be taken from the first one
+ SInt32 theNumberRawSteps = inRaw - theOverallRawMin;
+
+ // get the first item in the curve map
+ CurveMap::const_iterator theIterator = mCurveMap.begin();
+
+ // initialize the answer to the minimum dB of the first item in the curve map
+ theAnswer = theIterator->second.mMinimum;
+
+ // iterate through the curve map until we run out of steps
+ while((theNumberRawSteps > 0) && (theIterator != mCurveMap.end()))
+ {
+ // compute some values
+ SInt32 theRawMin = theIterator->first.mMinimum;
+ SInt32 theRawMax = theIterator->first.mMaximum;
+ SInt32 theRawRange = theRawMax - theRawMin;
+
+ Float64 theDBMin = theIterator->second.mMinimum;
+ Float64 theDBMax = theIterator->second.mMaximum;
+ Float64 theDBRange = theDBMax - theDBMin;
+
+ Float64 theDBPerRaw = theDBRange / static_cast<Float64>(theRawRange);
+
+ // there might be more steps than the current map entry accounts for
+ SInt32 theRawStepsToAdd = std::min(theRawRange, theNumberRawSteps);
+
+ // add this many steps worth of db to the answer;
+ theAnswer += theRawStepsToAdd * theDBPerRaw;
+
+ // figure out how many steps are left
+ theNumberRawSteps -= theRawStepsToAdd;
+
+ // go to the next map entry
+ std::advance(theIterator, 1);
+ }
+
+ return theAnswer;
+}
+
+Float64 CAVolumeCurve::ConvertRawToScalar(SInt32 inRaw) const
+{
+ // get some important values
+ Float64 theDBMin = GetMinimumDB();
+ Float64 theDBMax = GetMaximumDB();
+ Float64 theDBRange = theDBMax - theDBMin;
+ SInt32 theRawMin = GetMinimumRaw();
+ SInt32 theRawMax = GetMaximumRaw();
+ SInt32 theRawRange = theRawMax - theRawMin;
+
+ // range the raw value
+ if(inRaw < theRawMin) inRaw = theRawMin;
+ if(inRaw > theRawMax) inRaw = theRawMax;
+
+ // calculate the distance in the range inRaw is
+ Float64 theAnswer = static_cast<Float64>(inRaw - theRawMin) / static_cast<Float64>(theRawRange);
+
+ // only apply a curve to the scalar values if the dB range is greater than 30
+ if(mIsApplyingTransferFunction && (theDBRange > 30.0))
+ {
+ theAnswer = pow(theAnswer, mRawToScalarExponentNumerator / mRawToScalarExponentDenominator);
+ }
+
+ return theAnswer;
+}
+
+Float64 CAVolumeCurve::ConvertDBToScalar(Float64 inDB) const
+{
+ SInt32 theRawValue = ConvertDBToRaw(inDB);
+ Float64 theAnswer = ConvertRawToScalar(theRawValue);
+ return theAnswer;
+}
+
+SInt32 CAVolumeCurve::ConvertScalarToRaw(Float64 inScalar) const
+{
+ // range the scalar value
+ inScalar = std::min(1.0, std::max(0.0, inScalar));
+
+ // get some important values
+ Float64 theDBMin = GetMinimumDB();
+ Float64 theDBMax = GetMaximumDB();
+ Float64 theDBRange = theDBMax - theDBMin;
+ SInt32 theRawMin = GetMinimumRaw();
+ SInt32 theRawMax = GetMaximumRaw();
+ SInt32 theRawRange = theRawMax - theRawMin;
+
+ // have to undo the curve if the dB range is greater than 30
+ if(mIsApplyingTransferFunction && (theDBRange > 30.0))
+ {
+ inScalar = pow(inScalar, mRawToScalarExponentDenominator / mRawToScalarExponentNumerator);
+ }
+
+ // now we can figure out how many raw steps this is
+ Float64 theNumberRawSteps = inScalar * static_cast<Float64>(theRawRange);
+ theNumberRawSteps = round(theNumberRawSteps);
+
+ // the answer is the minimum raw value plus the number of raw steps
+ SInt32 theAnswer = theRawMin + static_cast<SInt32>(theNumberRawSteps);
+
+ return theAnswer;
+}
+
+Float64 CAVolumeCurve::ConvertScalarToDB(Float64 inScalar) const
+{
+ SInt32 theRawValue = ConvertScalarToRaw(inScalar);
+ Float64 theAnswer = ConvertRawToDB(theRawValue);
+ return theAnswer;
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAVolumeCurve.h b/distrho/src/CoreAudio106/PublicUtility/CAVolumeCurve.h
new file mode 100755
index 00000000..53b903ec
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAVolumeCurve.h
@@ -0,0 +1,172 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#if !defined(__CAVolumeCurve_h__)
+#define __CAVolumeCurve_h__
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include <CoreAudioTypes.h>
+#endif
+#include <map>
+
+//=============================================================================
+// Types
+//=============================================================================
+
+struct CARawPoint
+{
+ SInt32 mMinimum;
+ SInt32 mMaximum;
+
+ CARawPoint() : mMinimum(0), mMaximum(0) {}
+ CARawPoint(const CARawPoint& inPoint) : mMinimum(inPoint.mMinimum), mMaximum(inPoint.mMaximum) {}
+ CARawPoint(SInt32 inMinimum, SInt32 inMaximum) : mMinimum(inMinimum), mMaximum(inMaximum) {}
+ CARawPoint& operator=(const CARawPoint& inPoint) { mMinimum = inPoint.mMinimum; mMaximum = inPoint.mMaximum; return *this; }
+
+ static bool Overlap(const CARawPoint& x, const CARawPoint& y) { return (x.mMinimum < y.mMaximum) && (x.mMaximum > y.mMinimum); }
+};
+
+inline bool operator<(const CARawPoint& x, const CARawPoint& y) { return x.mMinimum < y.mMinimum; }
+inline bool operator==(const CARawPoint& x, const CARawPoint& y) { return (x.mMinimum == y.mMinimum) && (x.mMaximum == y.mMaximum); }
+inline bool operator!=(const CARawPoint& x, const CARawPoint& y) { return !(x == y); }
+inline bool operator<=(const CARawPoint& x, const CARawPoint& y) { return (x < y) || (x == y); }
+inline bool operator>=(const CARawPoint& x, const CARawPoint& y) { return !(x < y); }
+inline bool operator>(const CARawPoint& x, const CARawPoint& y) { return !((x < y) || (x == y)); }
+
+struct CADBPoint
+{
+ Float64 mMinimum;
+ Float64 mMaximum;
+
+ CADBPoint() : mMinimum(0), mMaximum(0) {}
+ CADBPoint(const CADBPoint& inPoint) : mMinimum(inPoint.mMinimum), mMaximum(inPoint.mMaximum) {}
+ CADBPoint(Float64 inMinimum, Float64 inMaximum) : mMinimum(inMinimum), mMaximum(inMaximum) {}
+ CADBPoint& operator=(const CADBPoint& inPoint) { mMinimum = inPoint.mMinimum; mMaximum = inPoint.mMaximum; return *this; }
+
+ static bool Overlap(const CADBPoint& x, const CADBPoint& y) { return (x.mMinimum < y.mMaximum) && (x.mMaximum >= y.mMinimum); }
+};
+
+inline bool operator<(const CADBPoint& x, const CADBPoint& y) { return x.mMinimum < y.mMinimum; }
+inline bool operator==(const CADBPoint& x, const CADBPoint& y) { return (x.mMinimum == y.mMinimum) && (x.mMaximum == y.mMaximum); }
+inline bool operator!=(const CADBPoint& x, const CADBPoint& y) { return !(x == y); }
+inline bool operator<=(const CADBPoint& x, const CADBPoint& y) { return (x < y) || (x == y); }
+inline bool operator>=(const CADBPoint& x, const CADBPoint& y) { return !(x < y); }
+inline bool operator>(const CADBPoint& x, const CADBPoint& y) { return !((x < y) || (x == y)); }
+
+//=============================================================================
+// CAVolumeCurve
+//=============================================================================
+
+class CAVolumeCurve
+{
+
+// Constants
+public:
+ enum
+ {
+ kLinearCurve = 0,
+ kPow1Over3Curve = 1,
+ kPow1Over2Curve = 2,
+ kPow3Over4Curve = 3,
+ kPow3Over2Curve = 4,
+ kPow2Over1Curve = 5,
+ kPow3Over1Curve = 6,
+ kPow4Over1Curve = 7,
+ kPow5Over1Curve = 8,
+ kPow6Over1Curve = 9,
+ kPow7Over1Curve = 10,
+ kPow8Over1Curve = 11,
+ kPow9Over1Curve = 12,
+ kPow10Over1Curve = 13,
+ kPow11Over1Curve = 14,
+ kPow12Over1Curve = 15
+ };
+
+// Construction/Destruction
+public:
+ CAVolumeCurve();
+ virtual ~CAVolumeCurve();
+
+// Attributes
+public:
+ UInt32 GetTag() const { return mTag; }
+ void SetTag(UInt32 inTag) { mTag = inTag; }
+ SInt32 GetMinimumRaw() const;
+ SInt32 GetMaximumRaw() const;
+ Float64 GetMinimumDB() const;
+ Float64 GetMaximumDB() const;
+
+ void SetIsApplyingTransferFunction(bool inIsApplyingTransferFunction) { mIsApplyingTransferFunction = inIsApplyingTransferFunction; }
+ int GetTransferFunction() const { return mTransferFunction; }
+ void SetTransferFunction(int inTransferFunction);
+
+// Operations
+public:
+ void AddRange(SInt32 mMinRaw, SInt32 mMaxRaw, Float64 inMinDB, Float64 inMaxDB);
+ void ResetRange();
+ bool CheckForContinuity() const;
+
+ SInt32 ConvertDBToRaw(Float64 inDB) const;
+ Float64 ConvertRawToDB(SInt32 inRaw) const;
+ Float64 ConvertRawToScalar(SInt32 inRaw) const;
+ Float64 ConvertDBToScalar(Float64 inDB) const;
+ SInt32 ConvertScalarToRaw(Float64 inScalar) const;
+ Float64 ConvertScalarToDB(Float64 inScalar) const;
+
+// Implementation
+private:
+ typedef std::map<CARawPoint, CADBPoint> CurveMap;
+
+ UInt32 mTag;
+ CurveMap mCurveMap;
+ bool mIsApplyingTransferFunction;
+ UInt32 mTransferFunction;
+ Float64 mRawToScalarExponentNumerator;
+ Float64 mRawToScalarExponentDenominator;
+
+};
+
+#endif
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAXException.cpp b/distrho/src/CoreAudio106/PublicUtility/CAXException.cpp
new file mode 100755
index 00000000..da39296d
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAXException.cpp
@@ -0,0 +1,43 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "CAXException.h"
+
+CAXException::WarningHandler CAXException::sWarningHandler = NULL;
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAXException.h b/distrho/src/CoreAudio106/PublicUtility/CAXException.h
new file mode 100755
index 00000000..333f4f5f
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAXException.h
@@ -0,0 +1,330 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __CAXException_h__
+#define __CAXException_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #include <ConditionalMacros.h>
+ #include <CoreFoundation.h>
+#endif
+#include "CADebugMacros.h"
+#include <ctype.h>
+//#include <stdio.h>
+#include <string.h>
+
+
+class CAX4CCString {
+public:
+ CAX4CCString(OSStatus error) {
+ // see if it appears to be a 4-char-code
+ char *str = mStr;
+ *(UInt32 *)(str + 1) = CFSwapInt32HostToBig(error);
+ if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) {
+ str[0] = str[5] = '\'';
+ str[6] = '\0';
+ } else if (error > -200000 && error < 200000)
+ // no, format it as an integer
+ sprintf(str, "%d", (int)error);
+ else
+ sprintf(str, "0x%x", (int)error);
+ }
+ const char *get() const { return mStr; }
+ operator const char *() const { return mStr; }
+private:
+ char mStr[16];
+};
+
+// An extended exception class that includes the name of the failed operation
+class CAXException {
+public:
+ CAXException(const char *operation, OSStatus err) :
+ mError(err)
+ {
+ if (operation == NULL)
+ mOperation[0] = '\0';
+ else if (strlen(operation) >= sizeof(mOperation)) {
+ memcpy(mOperation, operation, sizeof(mOperation) - 1);
+ mOperation[sizeof(mOperation) - 1] = '\0';
+ } else
+
+ strlcpy(mOperation, operation, sizeof(mOperation));
+ }
+
+ char *FormatError(char *str) const
+ {
+ return FormatError(str, mError);
+ }
+
+ char mOperation[256];
+ const OSStatus mError;
+
+ // -------------------------------------------------
+
+ typedef void (*WarningHandler)(const char *msg, OSStatus err);
+
+ static char *FormatError(char *str, OSStatus error)
+ {
+ strcpy(str, CAX4CCString(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) { \
+ DebugMessageN2("about to throw %s: %s", CAX4CCString(__err).get(), operation);\
+ STOP; \
+ throw CAXException(operation, __err); \
+ } \
+ } while (0)
+
+ #define XThrowIf(condition, error, operation) \
+ do { \
+ if (condition) { \
+ OSStatus __err = error; \
+ DebugMessageN2("about to throw %s: %s", CAX4CCString(__err).get(), operation);\
+ STOP; \
+ throw CAXException(operation, __err); \
+ } \
+ } while (0)
+
+ #define XRequireNoError(error, label) \
+ do { \
+ OSStatus __err = error; \
+ if (__err) { \
+ DebugMessageN2("about to throw %s: %s", CAX4CCString(__err).get(), #error);\
+ STOP; \
+ goto label; \
+ } \
+ } while (0)
+
+ #define XAssert(assertion) \
+ do { \
+ if (!(assertion)) { \
+ DebugMessageN1("error: failed assertion: %s", #assertion); \
+ STOP; \
+ } \
+ } while (0)
+
+ #define XAssertNoError(error) \
+ do { \
+ OSStatus __err = error; \
+ if (__err) { \
+ DebugMessageN2("error %s: %s", CAX4CCString(__err).get(), #error);\
+ STOP; \
+ } \
+ } while (0)
+
+ #define ca_require_noerr(errorCode, exceptionLabel) \
+ do \
+ { \
+ int evalOnceErrorCode = (errorCode); \
+ if ( __builtin_expect(0 != evalOnceErrorCode, 0) ) \
+ { \
+ DebugMessageN5("ca_require_noerr: [%s, %d] (goto %s;) %s:%d", \
+ #errorCode, evalOnceErrorCode, \
+ #exceptionLabel, \
+ __FILE__, \
+ __LINE__); \
+ goto exceptionLabel; \
+ } \
+ } while ( 0 )
+
+ #define ca_verify_noerr(errorCode) \
+ do \
+ { \
+ int evalOnceErrorCode = (errorCode); \
+ if ( __builtin_expect(0 != evalOnceErrorCode, 0) ) \
+ { \
+ DebugMessageN4("ca_verify_noerr: [%s, %d] %s:%d", \
+ #errorCode, evalOnceErrorCode, \
+ __FILE__, \
+ __LINE__); \
+ } \
+ } while ( 0 )
+
+ #define ca_debug_string(message) \
+ do \
+ { \
+ DebugMessageN3("ca_debug_string: %s %s:%d", \
+ message, \
+ __FILE__, \
+ __LINE__); \
+ } while ( 0 )
+
+
+ #define ca_verify(assertion) \
+ do \
+ { \
+ if ( __builtin_expect(!(assertion), 0) ) \
+ { \
+ DebugMessageN3("ca_verify: %s %s:%d", \
+ #assertion, \
+ __FILE__, \
+ __LINE__); \
+ } \
+ } while ( 0 )
+
+ #define ca_require(assertion, exceptionLabel) \
+ do \
+ { \
+ if ( __builtin_expect(!(assertion), 0) ) \
+ { \
+ DebugMessageN4("ca_require: %s %s %s:%d", \
+ #assertion, \
+ #exceptionLabel, \
+ __FILE__, \
+ __LINE__); \
+ goto exceptionLabel; \
+ } \
+ } while ( 0 )
+
+ #define ca_check(assertion) \
+ do \
+ { \
+ if ( __builtin_expect(!(assertion), 0) ) \
+ { \
+ DebugMessageN3("ca_check: %s %s:%d", \
+ #assertion, \
+ __FILE__, \
+ __LINE__); \
+ } \
+ } while ( 0 )
+
+#else
+ #define XThrowIfError(error, operation) \
+ do { \
+ OSStatus __err = error; \
+ if (__err) { \
+ throw CAXException(operation, __err); \
+ } \
+ } while (0)
+
+ #define XThrowIf(condition, error, operation) \
+ do { \
+ if (condition) { \
+ OSStatus __err = error; \
+ throw CAXException(operation, __err); \
+ } \
+ } while (0)
+
+ #define XRequireNoError(error, label) \
+ do { \
+ OSStatus __err = error; \
+ if (__err) { \
+ goto label; \
+ } \
+ } while (0)
+
+ #define XAssert(assertion) \
+ do { \
+ } while (0)
+
+ #define XAssertNoError(error) \
+ do { \
+ /*OSStatus __err =*/ error; \
+ } while (0)
+
+ #define ca_require_noerr(errorCode, exceptionLabel) \
+ do \
+ { \
+ if ( __builtin_expect(0 != (errorCode), 0) ) \
+ { \
+ goto exceptionLabel; \
+ } \
+ } while ( 0 )
+
+ #define ca_verify_noerr(errorCode) \
+ do \
+ { \
+ if ( 0 != (errorCode) ) \
+ { \
+ } \
+ } while ( 0 )
+
+ #define ca_debug_string(message)
+
+ #define ca_verify(assertion) \
+ do \
+ { \
+ if ( !(assertion) ) \
+ { \
+ } \
+ } while ( 0 )
+
+ #define ca_require(assertion, exceptionLabel) \
+ do \
+ { \
+ if ( __builtin_expect(!(assertion), 0) ) \
+ { \
+ goto exceptionLabel; \
+ } \
+ } while ( 0 )
+
+ #define ca_check(assertion) \
+ do \
+ { \
+ if ( !(assertion) ) \
+ { \
+ } \
+ } while ( 0 )
+
+
+#endif
+
+#define XThrow(error, operation) XThrowIf(true, error, operation)
+#define XThrowIfErr(error) XThrowIfError(error, #error)
+
+#endif // __CAXException_h__
diff --git a/distrho/src/CoreAudio106/PublicUtility/MatrixMixerVolumes.cpp b/distrho/src/CoreAudio106/PublicUtility/MatrixMixerVolumes.cpp
new file mode 100755
index 00000000..ff5c339f
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/MatrixMixerVolumes.cpp
@@ -0,0 +1,143 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "MatrixMixerVolumes.h"
+#include "CAXException.h"
+
+OSStatus NumberChannels (AudioUnit au,
+ AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ UInt32 &outChans);
+
+
+OSStatus PrintBuses (FILE* file, char* str, AudioUnit au, AudioUnitScope inScope)
+{
+ OSStatus result;
+ UInt32 busCount;
+ UInt32 theSize = sizeof(busCount);
+
+ ca_require_noerr (result = AudioUnitGetProperty (au, kAudioUnitProperty_ElementCount,
+ inScope, 0, &busCount, &theSize), home);
+
+ fprintf (file, "\t%s Elements:\n\t\t", str);
+ for (UInt32 i = 0; i < busCount; ++i) {
+ Float32 val;
+ ca_require_noerr (result = AudioUnitGetParameter (au, kMatrixMixerParam_Enable, inScope, i, &val), home);
+ UInt32 numChans;
+ ca_require_noerr (result = NumberChannels (au, inScope, i, numChans), home);
+ char frameCharStart = (val != 0 ? '[' : '{');
+ char frameCharEnd = (val != 0 ? ']' : '}');
+ fprintf (file, "%d:%c%d, %c%c ", (int)i, frameCharStart, (int)numChans, (val != 0 ? 'T' : 'F'), frameCharEnd);
+ }
+ fprintf (file, "\n");
+home:
+ return result;
+}
+
+void PrintMatrixMixerVolumes (FILE* file, AudioUnit au)
+{
+ UInt32 dims[2];
+ UInt32 theSize = sizeof(UInt32) * 2;
+ Float32 *theVols = NULL;
+ OSStatus result;
+
+// this call will fail if the unit is NOT initialized as it would present an incomplete state
+ ca_require_noerr (result = AudioUnitGetProperty (au, kAudioUnitProperty_MatrixDimensions,
+ kAudioUnitScope_Global, 0, dims, &theSize), home);
+
+ theSize = ((dims[0] + 1) * (dims[1] + 1)) * sizeof(Float32);
+
+ theVols = static_cast<Float32*> (malloc (theSize));
+
+ ca_require_noerr (result = AudioUnitGetProperty (au, kAudioUnitProperty_MatrixLevels,
+ kAudioUnitScope_Global, 0, theVols, &theSize), home);
+
+home:
+ if (result) {
+ if (theVols)
+ free(theVols);
+ return;
+ }
+
+ theSize /= sizeof(Float32);
+
+ unsigned int inputs = dims[0];
+ unsigned int outputs = dims[1];
+
+ fprintf (file, "\tInput Channels = %d, Output Channels = %d\n", (int)dims[0], (int)dims[1]);
+ PrintBuses (file, "Input", au, kAudioUnitScope_Input);
+ PrintBuses (file, "Output", au, kAudioUnitScope_Output);
+ fprintf (file, "\tGlobal Volume: %.3f\n", theVols [theSize - 1]);
+ for (unsigned int i = 0; i < (inputs + 1); ++i) {
+ if (i < inputs) {
+ fprintf (file, "\t%.3f ", theVols[(i + 1) * (outputs + 1) - 1]);
+
+ for (unsigned int j = 0; j < outputs; ++j)
+ fprintf (file, "(%.3f) ", theVols[(i * (outputs + 1)) + j]);
+ } else {
+ fprintf (file, "\t ");
+ for (unsigned int j = 0; j < outputs; ++j)
+ fprintf (file, " %.3f ", theVols[(i * (outputs + 1)) + j]);
+ }
+ fprintf (file, "\n");
+ }
+
+#if 0
+ for (unsigned int i = 0; i < theSize; ++i)
+ printf ("%f, ", theVols[i]);
+#endif
+ free(theVols);
+}
+
+// Utility routine that gets the number of channels from an audio unit
+OSStatus NumberChannels (AudioUnit au,
+ AudioUnitScope inScope,
+ AudioUnitElement inEl,
+ UInt32 &outChans)
+{
+ AudioStreamBasicDescription desc;
+ UInt32 dataSize = sizeof (AudioStreamBasicDescription);
+ OSStatus result = AudioUnitGetProperty (au, kAudioUnitProperty_StreamFormat,
+ inScope, inEl,
+ &desc, &dataSize);
+ if (!result)
+ outChans = desc.mChannelsPerFrame;
+ return result;
+}
diff --git a/distrho/src/CoreAudio106/PublicUtility/MatrixMixerVolumes.h b/distrho/src/CoreAudio106/PublicUtility/MatrixMixerVolumes.h
new file mode 100755
index 00000000..fe32bcc7
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/MatrixMixerVolumes.h
@@ -0,0 +1,65 @@
+/* Copyright © 2007 Apple Inc. All Rights Reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by
+ Apple Inc. ("Apple") in consideration of your agreement to the
+ following terms, and your use, installation, modification or
+ redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use,
+ install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc.
+ may be used to endorse or promote products derived from the Apple
+ Software without specific prior written permission from Apple. Except
+ as expressly stated in this notice, no other rights or licenses, express
+ or implied, are granted by Apple herein, including but not limited to
+ any patent rights that may be infringed by your derivative works or by
+ other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __MatrixMixerVolumes_h__
+#define __MatrixMixerVolumes_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnit.h>
+#else
+ #include <AudioUnit.h>
+#endif
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+// prints the matrix mixer volumes of a specific audio unit to the given file
+void PrintMatrixMixerVolumes (FILE* file, AudioUnit au);
+
+// prints the mixer volumes for the specific scope of the audio unit
+// results will be printed to the speficied file "file" with identifiying string tag "str"
+OSStatus PrintBuses (FILE* file, char* str, AudioUnit au, AudioUnitScope inScope);
+#if defined(__cplusplus)
+}
+#endif
+
+#endif