summaryrefslogtreecommitdiff
path: root/libs/appleutility/CoreAudio/AudioUnits
diff options
context:
space:
mode:
Diffstat (limited to 'libs/appleutility/CoreAudio/AudioUnits')
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.cpp2393
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.h1048
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.cpp438
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.h82
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.cpp151
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.h119
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp62
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.h66
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.cpp669
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.h144
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUResources.r140
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp565
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.h553
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.cpp370
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.h353
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp403
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h188
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp710
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h230
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp125
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp359
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h90
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp90
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h71
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp843
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h269
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h168
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/MIDIControlHandler.h92
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp419
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h227
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h145
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp140
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h187
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp93
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h232
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h88
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp466
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.h377
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp495
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h213
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp164
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h104
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp76
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.h82
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp706
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.h272
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp354
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h126
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp125
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.h75
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.cpp219
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.h267
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h155
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUMIDIDefs.h138
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUSilentTimeout.h93
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp203
-rw-r--r--libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h163
57 files changed, 17195 insertions, 0 deletions
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.cpp
new file mode 100644
index 0000000000..612bc4d308
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.cpp
@@ -0,0 +1,2393 @@
+/*
+ File: AUBase.cpp
+ Abstract: AUBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUBase.h"
+#include "AUDispatch.h"
+#include "AUInputElement.h"
+#include "AUOutputElement.h"
+#include <algorithm>
+#include <syslog.h>
+#include "CAAudioChannelLayout.h"
+#include "CAHostTimeBase.h"
+#include "CAVectorUnit.h"
+#include "CAXException.h"
+
+
+
+#if TARGET_OS_MAC && (TARGET_CPU_X86 || TARGET_CPU_X86_64)
+ // our compiler does ALL floating point with SSE
+ inline int GETCSR () { int _result; asm volatile ("stmxcsr %0" : "=m" (*&_result) ); return _result; }
+ inline void SETCSR (int a) { int _temp = a; asm volatile( "ldmxcsr %0" : : "m" (*&_temp ) ); }
+
+ #define DISABLE_DENORMALS int _savemxcsr = GETCSR(); SETCSR(_savemxcsr | 0x8040);
+ #define RESTORE_DENORMALS SETCSR(_savemxcsr);
+#else
+ #define DISABLE_DENORMALS
+ #define RESTORE_DENORMALS
+#endif
+
+static bool sAUBaseCFStringsInitialized = false;
+// this is used for the presets
+static CFStringRef kUntitledString = NULL;
+//these are the current keys for the class info document
+static CFStringRef kVersionString = NULL;
+static CFStringRef kTypeString = NULL;
+static CFStringRef kSubtypeString = NULL;
+static CFStringRef kManufacturerString = NULL;
+static CFStringRef kDataString = NULL;
+static CFStringRef kNameString = NULL;
+static CFStringRef kRenderQualityString = NULL;
+static CFStringRef kCPULoadString = NULL;
+static CFStringRef kElementNameString = NULL;
+static CFStringRef kPartString = NULL;
+
+SInt32 AUBase::sVectorUnitType = kVecUninitialized;
+
+//_____________________________________________________________________________
+//
+AUBase::AUBase( AudioComponentInstance inInstance,
+ UInt32 numInputElements,
+ UInt32 numOutputElements,
+ UInt32 numGroupElements) :
+ ComponentBase(inInstance),
+ mElementsCreated(false),
+ mInitialized(false),
+ mHasBegunInitializing(false),
+ mInitNumInputEls(numInputElements), mInitNumOutputEls(numOutputElements),
+#if !CA_BASIC_AU_FEATURES
+ mInitNumGroupEls(numGroupElements),
+#endif
+ mRenderCallbacksTouched(false),
+ mRenderThreadID (NULL),
+ mWantsRenderThreadID (false),
+ mLastRenderError(0),
+ mUsesFixedBlockSize(false),
+ mBuffersAllocated(false),
+ mLogString (NULL),
+ mNickName (NULL),
+ mAUMutex(NULL)
+ #if !CA_NO_AU_UI_FEATURES
+ ,
+ mContextName(NULL)
+ #endif
+{
+ ResetRenderTime ();
+
+ if(!sAUBaseCFStringsInitialized)
+ {
+ kUntitledString = CFSTR("Untitled");
+ kVersionString = CFSTR(kAUPresetVersionKey);
+ kTypeString = CFSTR(kAUPresetTypeKey);
+ kSubtypeString = CFSTR(kAUPresetSubtypeKey);
+ kManufacturerString = CFSTR(kAUPresetManufacturerKey);
+ kDataString = CFSTR(kAUPresetDataKey);
+ kNameString = CFSTR(kAUPresetNameKey);
+ kRenderQualityString = CFSTR(kAUPresetRenderQualityKey);
+ kCPULoadString = CFSTR(kAUPresetCPULoadKey);
+ kElementNameString = CFSTR(kAUPresetElementNameKey);
+ kPartString = CFSTR(kAUPresetPartKey);
+ sAUBaseCFStringsInitialized = true;
+ }
+
+ if (sVectorUnitType == kVecUninitialized) {
+ sVectorUnitType = CAVectorUnit::GetVectorUnitType() ;
+ }
+
+ mAudioUnitAPIVersion = 2;
+
+ SetMaxFramesPerSlice(kAUDefaultMaxFramesPerSlice);
+
+ GlobalScope().Initialize(this, kAudioUnitScope_Global, 1);
+
+#if !CA_NO_AU_UI_FEATURES
+ memset (&mHostCallbackInfo, 0, sizeof (mHostCallbackInfo));
+#endif
+
+
+ mCurrentPreset.presetNumber = -1;
+ mCurrentPreset.presetName = kUntitledString;
+ CFRetain (mCurrentPreset.presetName);
+}
+
+//_____________________________________________________________________________
+//
+AUBase::~AUBase()
+{
+ if (mCurrentPreset.presetName) CFRelease (mCurrentPreset.presetName);
+#if !CA_NO_AU_UI_FEATURES
+ if (mContextName) CFRelease (mContextName);
+#endif
+ if (mLogString) delete [] mLogString;
+ if (mNickName) CFRelease(mNickName);
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::CreateElements()
+{
+ if (!mElementsCreated) {
+ Inputs().Initialize(this, kAudioUnitScope_Input, mInitNumInputEls);
+ Outputs().Initialize(this, kAudioUnitScope_Output, mInitNumOutputEls);
+#if !CA_BASIC_AU_FEATURES
+ Groups().Initialize(this, kAudioUnitScope_Group, mInitNumGroupEls);
+#endif
+ CreateExtendedElements();
+
+ mElementsCreated = true;
+ }
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::SetMaxFramesPerSlice(UInt32 nFrames)
+{
+ mMaxFramesPerSlice = nFrames;
+ if (mBuffersAllocated)
+ ReallocateBuffers();
+ PropertyChanged(kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0);
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::CanSetMaxFrames() const
+{
+ return IsInitialized() ? kAudioUnitErr_Initialized : OSStatus(noErr);
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::ReallocateBuffers()
+{
+ CreateElements();
+
+ UInt32 nOutputs = Outputs().GetNumberOfElements();
+ for (UInt32 i = 0; i < nOutputs; ++i) {
+ AUOutputElement *output = GetOutput(i);
+ output->AllocateBuffer(); // does no work if already allocated
+ }
+ UInt32 nInputs = Inputs().GetNumberOfElements();
+ for (UInt32 i = 0; i < nInputs; ++i) {
+ AUInputElement *input = GetInput(i);
+ input->AllocateBuffer(); // does no work if already allocated
+ }
+ mBuffersAllocated = true;
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::DeallocateIOBuffers()
+{
+ if (!mBuffersAllocated)
+ return;
+
+ UInt32 nOutputs = Outputs().GetNumberOfElements();
+ for (UInt32 i = 0; i < nOutputs; ++i) {
+ AUOutputElement *output = GetOutput(i);
+ output->DeallocateBuffer();
+ }
+ UInt32 nInputs = Inputs().GetNumberOfElements();
+ for (UInt32 i = 0; i < nInputs; ++i) {
+ AUInputElement *input = GetInput(i);
+ input->DeallocateBuffer();
+ }
+ mBuffersAllocated = false;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DoInitialize()
+{
+ OSStatus result = noErr;
+
+ if (!mInitialized) {
+ result = Initialize();
+ if (result == noErr) {
+ if (CanScheduleParameters())
+ mParamList.reserve(24);
+ mHasBegunInitializing = true;
+ ReallocateBuffers(); // calls CreateElements()
+ mInitialized = true; // signal that it's okay to render
+ CAMemoryBarrier();
+ }
+ }
+
+ return result;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::Initialize()
+{
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::PreDestructor()
+{
+ // this is called from the ComponentBase dispatcher, which doesn't know anything about our (optional) lock
+ CAMutex::Locker lock(mAUMutex);
+ DoCleanup();
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::DoCleanup()
+{
+ if (mInitialized)
+ Cleanup();
+
+ DeallocateIOBuffers();
+ ResetRenderTime ();
+
+ mInitialized = false;
+ mHasBegunInitializing = false;
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::Cleanup()
+{
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ ResetRenderTime ();
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DispatchGetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus result = noErr;
+ bool validateElement = true;
+
+ switch (inID) {
+ case kAudioUnitProperty_MakeConnection:
+ ca_require(inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(AudioUnitConnection);
+ outWritable = true;
+ break;
+
+
+ case kAudioUnitProperty_SetRenderCallback:
+ ca_require(AudioUnitAPIVersion() > 1, InvalidProperty);
+ ca_require(inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(AURenderCallbackStruct);
+ outWritable = true;
+ break;
+
+ case kAudioUnitProperty_StreamFormat:
+ outDataSize = sizeof(CAStreamBasicDescription);
+ outWritable = IsStreamFormatWritable(inScope, inElement);
+ break;
+
+ case kAudioUnitProperty_SampleRate:
+ outDataSize = sizeof(Float64);
+ outWritable = IsStreamFormatWritable(inScope, inElement);
+ break;
+
+ case kAudioUnitProperty_ClassInfo:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(CFPropertyListRef);
+ outWritable = true;
+ break;
+
+ case kAudioUnitProperty_FactoryPresets:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ result = GetPresets(NULL);
+ if (!result) {
+ outDataSize = sizeof(CFArrayRef);
+ outWritable = false;
+ }
+ break;
+
+ case kAudioUnitProperty_PresentPreset:
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+#ifndef __LP64__
+ case kAudioUnitProperty_CurrentPreset:
+#endif
+#endif
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(AUPreset);
+ outWritable = true;
+ break;
+
+ case kAudioUnitProperty_ElementName:
+ outDataSize = sizeof (CFStringRef);
+ outWritable = true;
+ break;
+
+ case kAudioUnitProperty_ParameterList:
+ {
+ UInt32 nparams = 0;
+ result = GetParameterList(inScope, NULL, nparams);
+
+ outDataSize = sizeof(AudioUnitParameterID) * nparams;
+ outWritable = false;
+ validateElement = false;
+ }
+ break;
+
+ case kAudioUnitProperty_ParameterInfo:
+ outDataSize = sizeof(AudioUnitParameterInfo);
+ outWritable = false;
+ validateElement = false;
+ break;
+
+ case kAudioUnitProperty_ParameterHistoryInfo:
+ outDataSize = sizeof(AudioUnitParameterHistoryInfo);
+ outWritable = false;
+ validateElement = false;
+ break;
+
+ case kAudioUnitProperty_ElementCount:
+ outDataSize = sizeof(UInt32);
+ outWritable = BusCountWritable(inScope);
+ validateElement = false;
+ break;
+
+ case kAudioUnitProperty_Latency:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(Float64);
+ outWritable = false;
+ break;
+
+ case kAudioUnitProperty_TailTime:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ if (SupportsTail()) {
+ outDataSize = sizeof(Float64);
+ outWritable = false;
+ } else
+ goto InvalidProperty;
+ break;
+
+ case kAudioUnitProperty_MaximumFramesPerSlice:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(UInt32);
+ outWritable = true;
+ break;
+
+ case kAudioUnitProperty_LastRenderError:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(OSStatus);
+ outWritable = false;
+ break;
+
+ case kAudioUnitProperty_SupportedNumChannels:
+ {
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ UInt32 num = SupportedNumChannels (NULL);
+ if (num) {
+ outDataSize = sizeof (AUChannelInfo) * num;
+ result = noErr;
+ } else
+ goto InvalidProperty;
+ outWritable = false;
+ break;
+ }
+
+ case kAudioUnitProperty_SupportedChannelLayoutTags:
+ {
+ UInt32 numLayouts = GetChannelLayoutTags(inScope, inElement, NULL);
+ if (numLayouts) {
+ outDataSize = numLayouts * sizeof(AudioChannelLayoutTag);
+ result = noErr;
+ } else
+ goto InvalidProperty;
+ outWritable = false;
+ validateElement = false; //already done it
+ break;
+ }
+
+ case kAudioUnitProperty_AudioChannelLayout:
+ {
+ outWritable = false;
+ outDataSize = GetAudioChannelLayout(inScope, inElement, NULL, outWritable);
+ if (outDataSize) {
+ result = noErr;
+ } else {
+ if (GetChannelLayoutTags(inScope, inElement, NULL) == 0)
+ goto InvalidProperty;
+ else
+ result = kAudioUnitErr_InvalidPropertyValue;
+ }
+ validateElement = false; //already done it
+ break;
+ }
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE
+ case kAudioUnitProperty_ShouldAllocateBuffer:
+ ca_require((inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Output), InvalidScope);
+ outWritable = true;
+ outDataSize = sizeof(UInt32);
+ break;
+#endif
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ case kAudioUnitProperty_FastDispatch:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ if (!IsCMgrObject()) goto InvalidProperty;
+ outDataSize = sizeof(void *);
+ outWritable = false;
+ validateElement = false;
+ break;
+
+ case kAudioUnitProperty_GetUIComponentList:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = GetNumCustomUIComponents();
+ if (outDataSize == 0)
+ goto InvalidProperty;
+ outDataSize *= sizeof (AudioComponentDescription);
+
+ outWritable = false;
+ break;
+#endif
+
+ case kAudioUnitProperty_ParameterValueStrings:
+ result = GetParameterValueStrings(inScope, inElement, NULL);
+ if (result == noErr) {
+ outDataSize = sizeof(CFArrayRef);
+ outWritable = false;
+ validateElement = false;
+ }
+ break;
+
+#if !CA_NO_AU_HOST_CALLBACKS
+ case kAudioUnitProperty_HostCallbacks:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(mHostCallbackInfo);
+ outWritable = true;
+ break;
+#endif
+#if !CA_NO_AU_UI_FEATURES
+ case kAudioUnitProperty_ContextName:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(CFStringRef);
+ outWritable = true;
+ break;
+
+ case kAudioUnitProperty_IconLocation:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outWritable = false;
+ if (!HasIcon())
+ goto InvalidProperty;
+ outDataSize = sizeof(CFURLRef);
+ break;
+
+ case kAudioUnitProperty_ParameterClumpName:
+ outDataSize = sizeof(AudioUnitParameterNameInfo );
+ outWritable = false;
+ break;
+
+#endif // !CA_NO_AU_UI_FEATURES
+
+ case 'lrst' : // kAudioUnitProperty_LastRenderedSampleTime
+ outDataSize = sizeof(Float64);
+ outWritable = false;
+ break;
+
+ case kAudioUnitProperty_NickName:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ outDataSize = sizeof(CFStringRef);
+ outWritable = true;
+ break;
+
+ default:
+ result = GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);
+ validateElement = false;
+ break;
+ }
+
+ if (result == noErr && validateElement) {
+ ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+ }
+
+ return result;
+InvalidProperty:
+ return kAudioUnitErr_InvalidProperty;
+InvalidScope:
+ return kAudioUnitErr_InvalidScope;
+InvalidElement:
+ return kAudioUnitErr_InvalidElement;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DispatchGetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ // NOTE: We're currently only called from AUBase::ComponentEntryDispatch, which
+ // calls DispatchGetPropertyInfo first, which performs validation of the scope/element,
+ // and ensures that the outData buffer is non-null and large enough.
+ OSStatus result = noErr;
+
+ switch (inID) {
+ case kAudioUnitProperty_StreamFormat:
+ *(CAStreamBasicDescription *)outData = GetStreamFormat(inScope, inElement);
+ break;
+
+ case kAudioUnitProperty_SampleRate:
+ *(Float64 *)outData = GetStreamFormat(inScope, inElement).mSampleRate;
+ break;
+
+ case kAudioUnitProperty_ParameterList:
+ {
+ UInt32 nparams = 0;
+ result = GetParameterList(inScope, (AudioUnitParameterID *)outData, nparams);
+ }
+ break;
+
+ case kAudioUnitProperty_ParameterInfo:
+ result = GetParameterInfo(inScope, inElement, *(AudioUnitParameterInfo *)outData);
+ break;
+
+ case kAudioUnitProperty_ParameterHistoryInfo:
+ {
+ AudioUnitParameterHistoryInfo* info = (AudioUnitParameterHistoryInfo*)outData;
+ result = GetParameterHistoryInfo(inScope, inElement, info->updatesPerSecond, info->historyDurationInSeconds);
+ }
+ break;
+
+ case kAudioUnitProperty_ClassInfo:
+ {
+ *(CFPropertyListRef *)outData = NULL;
+ result = SaveState((CFPropertyListRef *)outData);
+ }
+ break;
+
+ case kAudioUnitProperty_FactoryPresets:
+ {
+ *(CFArrayRef *)outData = NULL;
+ result = GetPresets ((CFArrayRef *)outData);
+ }
+ break;
+
+ case kAudioUnitProperty_PresentPreset:
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+#ifndef __LP64__
+ case kAudioUnitProperty_CurrentPreset:
+#endif
+#endif
+ {
+ *(AUPreset *)outData = mCurrentPreset;
+
+ // retain current string (as client owns a reference to it and will release it)
+ if (inID == kAudioUnitProperty_PresentPreset && mCurrentPreset.presetName)
+ CFRetain (mCurrentPreset.presetName);
+
+ result = noErr;
+ }
+ break;
+
+ case kAudioUnitProperty_ElementName:
+ {
+ AUElement * element = GetElement(inScope, inElement);
+ if (element->HasName()) {
+ *(CFStringRef *)outData = element->GetName();
+ CFRetain (element->GetName());
+ result = noErr;
+ } else
+ result = kAudioUnitErr_InvalidPropertyValue;
+ }
+ break;
+
+ case kAudioUnitProperty_ElementCount:
+ *(UInt32 *)outData = GetScope(inScope).GetNumberOfElements();
+ break;
+
+ case kAudioUnitProperty_Latency:
+ *(Float64 *)outData = GetLatency();
+ break;
+
+ case kAudioUnitProperty_TailTime:
+ if (SupportsTail())
+ *(Float64 *)outData = GetTailTime();
+ else
+ result = kAudioUnitErr_InvalidProperty;
+ break;
+
+ case kAudioUnitProperty_MaximumFramesPerSlice:
+ *(UInt32 *)outData = mMaxFramesPerSlice;
+ break;
+
+ case kAudioUnitProperty_LastRenderError:
+ *(OSStatus *)outData = mLastRenderError;
+ mLastRenderError = 0;
+ break;
+
+ case kAudioUnitProperty_SupportedNumChannels:
+ {
+ const AUChannelInfo* infoPtr = NULL;
+ UInt32 num = SupportedNumChannels (&infoPtr);
+ if(num != 0 && infoPtr != NULL)
+ memcpy (outData, infoPtr, num * sizeof (AUChannelInfo));
+ }
+ break;
+
+ case kAudioUnitProperty_SupportedChannelLayoutTags:
+ {
+ AudioChannelLayoutTag* ptr = outData ? static_cast<AudioChannelLayoutTag*>(outData) : NULL;
+ UInt32 numLayouts = GetChannelLayoutTags (inScope, inElement, ptr);
+ if (numLayouts == 0)
+ result = kAudioUnitErr_InvalidProperty;
+ }
+ break;
+
+ case kAudioUnitProperty_AudioChannelLayout:
+ {
+ AudioChannelLayout* ptr = outData ? static_cast<AudioChannelLayout*>(outData) : NULL;
+ Boolean writable;
+ UInt32 dataSize = GetAudioChannelLayout(inScope, inElement, ptr, writable);
+ if (!dataSize) {
+ result = kAudioUnitErr_InvalidProperty;
+ }
+ break;
+ }
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE
+ case kAudioUnitProperty_ShouldAllocateBuffer:
+ {
+ AUIOElement * element = GetIOElement(inScope, inElement);
+ *(UInt32*)outData = element->WillAllocateBuffer();
+ break;
+ }
+#endif
+
+ case kAudioUnitProperty_ParameterValueStrings:
+ result = GetParameterValueStrings(inScope, inElement, (CFArrayRef *)outData);
+ break;
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ case kAudioUnitProperty_FastDispatch:
+ if (!IsCMgrObject()) result = kAudioUnitErr_InvalidProperty;
+ else {
+ switch (inElement) {
+ case kAudioUnitGetParameterSelect:
+ *(AudioUnitGetParameterProc *)outData = (AudioUnitGetParameterProc)CMgr_AudioUnitBaseGetParameter;
+ break;
+ case kAudioUnitSetParameterSelect:
+ *(AudioUnitSetParameterProc *)outData = (AudioUnitSetParameterProc)CMgr_AudioUnitBaseSetParameter;
+ break;
+ case kAudioUnitRenderSelect:
+ if (AudioUnitAPIVersion() > 1)
+ *(AudioUnitRenderProc *)outData = (AudioUnitRenderProc)CMgr_AudioUnitBaseRender;
+ else result = kAudioUnitErr_InvalidElement;
+ break;
+ default:
+ result = GetProperty(inID, inScope, inElement, outData);
+ break;
+ }
+ }
+ break;
+
+ case kAudioUnitProperty_GetUIComponentList:
+ GetUIComponentDescs ((ComponentDescription*)outData);
+ break;
+#endif
+
+#if !CA_NO_AU_HOST_CALLBACKS
+ case kAudioUnitProperty_HostCallbacks:
+ memcpy(outData, &mHostCallbackInfo, sizeof(mHostCallbackInfo));
+ break;
+#endif
+#if !CA_NO_AU_UI_FEATURES
+ case kAudioUnitProperty_IconLocation:
+ {
+ CFURLRef iconLocation = CopyIconLocation();
+ if (iconLocation) {
+ *(CFURLRef*)outData = iconLocation;
+ } else
+ result = kAudioUnitErr_InvalidProperty;
+ }
+ break;
+
+ case kAudioUnitProperty_ContextName:
+ *(CFStringRef *)outData = mContextName;
+ if (mContextName) {
+ CFRetain(mContextName);
+ // retain CFString (if exists) since client will be responsible for its release
+ result = noErr;
+ } else {
+ result = kAudioUnitErr_InvalidPropertyValue;
+ }
+ break;
+
+ case kAudioUnitProperty_ParameterClumpName:
+ {
+ AudioUnitParameterNameInfo * ioClumpInfo = (AudioUnitParameterNameInfo*) outData;
+ if (ioClumpInfo->inID == kAudioUnitClumpID_System) // this ID value is reserved
+ result = kAudioUnitErr_InvalidPropertyValue;
+ else
+ {
+ result = CopyClumpName(inScope, ioClumpInfo->inID, ioClumpInfo->inDesiredLength, &ioClumpInfo->outName);
+
+ // this is provided for compatbility with existing implementations that don't know
+ // about this new mechanism
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = GetProperty (inID, inScope, inElement, outData);
+ }
+ }
+ break;
+
+#endif // !CA_NO_AU_UI_FEATURES
+
+ case 'lrst' : // kAudioUnitProperty_LastRenderedSampleTime
+ *(Float64*)outData = mCurrentRenderTime.mSampleTime;
+ break;
+
+ case kAudioUnitProperty_NickName:
+ // Ownership follows Core Foundation's 'Copy Rule'
+ if (mNickName) CFRetain(mNickName);
+ *(CFStringRef*)outData = mNickName;
+ break;
+
+ default:
+ result = GetProperty(inID, inScope, inElement, outData);
+ break;
+ }
+ return result;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DispatchSetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ OSStatus result = noErr;
+
+ switch (inID) {
+ case kAudioUnitProperty_MakeConnection:
+ ca_require(inDataSize >= sizeof(AudioUnitConnection), InvalidPropertyValue);
+ {
+ AudioUnitConnection &connection = *(AudioUnitConnection *)inData;
+ result = SetConnection(connection);
+ }
+ break;
+
+
+ case kAudioUnitProperty_SetRenderCallback:
+ {
+ ca_require(inDataSize >= sizeof(AURenderCallbackStruct), InvalidPropertyValue);
+ ca_require(AudioUnitAPIVersion() > 1, InvalidProperty);
+ AURenderCallbackStruct &callback = *(AURenderCallbackStruct*)inData;
+ result = SetInputCallback(kAudioUnitProperty_SetRenderCallback, inElement, callback.inputProc, callback.inputProcRefCon);
+ }
+ break;
+
+ case kAudioUnitProperty_ElementCount:
+ ca_require(inDataSize == sizeof(UInt32), InvalidPropertyValue);
+ ca_require(BusCountWritable(inScope), NotWritable);
+ result = SetBusCount(inScope, *(UInt32*)inData);
+ if (result == noErr) {
+ PropertyChanged(inID, inScope, inElement);
+ }
+ break;
+
+ case kAudioUnitProperty_MaximumFramesPerSlice:
+ ca_require(inDataSize == sizeof(UInt32), InvalidPropertyValue);
+ result = CanSetMaxFrames();
+ if (result) return result;
+ SetMaxFramesPerSlice(*(UInt32 *)inData);
+ break;
+
+ case kAudioUnitProperty_StreamFormat:
+ {
+ if (inDataSize < 36) goto InvalidPropertyValue;
+ ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+
+ CAStreamBasicDescription newDesc;
+ // now we're going to be ultra conservative! because of discrepancies between
+ // sizes of this struct based on aligment padding inconsistencies
+ memset (&newDesc, 0, sizeof(newDesc));
+ memcpy (&newDesc, inData, 36);
+
+ ca_require(ValidFormat(inScope, inElement, newDesc), InvalidFormat);
+
+ const CAStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement);
+
+ if ( !curDesc.IsEqual(newDesc, false) ) {
+ ca_require(IsStreamFormatWritable(inScope, inElement), NotWritable);
+ result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc);
+ }
+ }
+ break;
+
+ case kAudioUnitProperty_SampleRate:
+ {
+ ca_require(inDataSize == sizeof(Float64), InvalidPropertyValue);
+ ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+
+ const CAStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement);
+ CAStreamBasicDescription newDesc = curDesc;
+ newDesc.mSampleRate = *(Float64 *)inData;
+
+ ca_require(ValidFormat(inScope, inElement, newDesc), InvalidFormat);
+
+ if ( !curDesc.IsEqual(newDesc, false) ) {
+ ca_require(IsStreamFormatWritable(inScope, inElement), NotWritable);
+ result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc);
+ }
+ }
+ break;
+
+ case kAudioUnitProperty_AudioChannelLayout:
+ {
+ const AudioChannelLayout *layout = static_cast<const AudioChannelLayout *>(inData);
+ size_t headerSize = sizeof(AudioChannelLayout) - sizeof(AudioChannelDescription);
+
+ ca_require(inDataSize >= headerSize + layout->mNumberChannelDescriptions * sizeof(AudioChannelDescription), InvalidPropertyValue);
+ result = SetAudioChannelLayout(inScope, inElement, layout);
+ if (result == noErr)
+ PropertyChanged(inID, inScope, inElement);
+ break;
+ }
+
+ case kAudioUnitProperty_ClassInfo:
+ ca_require(inDataSize == sizeof(CFPropertyListRef *), InvalidPropertyValue);
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ result = RestoreState(*(CFPropertyListRef *)inData);
+ break;
+
+ case kAudioUnitProperty_PresentPreset:
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+#ifndef __LP64__
+ case kAudioUnitProperty_CurrentPreset:
+#endif
+#endif
+ {
+ ca_require(inDataSize == sizeof(AUPreset), InvalidPropertyValue);
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ AUPreset & newPreset = *(AUPreset *)inData;
+
+ if (newPreset.presetNumber >= 0)
+ {
+ result = NewFactoryPresetSet(newPreset);
+ // NewFactoryPresetSet SHOULD call SetAFactoryPreset if the preset is valid
+ // from its own list of preset number->name
+ if (!result)
+ PropertyChanged(inID, inScope, inElement);
+ }
+ else if (newPreset.presetName)
+ {
+ result = NewCustomPresetSet(newPreset);
+ if (!result)
+ PropertyChanged(inID, inScope, inElement);
+ }
+ else
+ result = kAudioUnitErr_InvalidPropertyValue;
+ }
+ break;
+
+ case kAudioUnitProperty_ElementName:
+ {
+ ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+ ca_require(inDataSize == sizeof(CFStringRef), InvalidPropertyValue);
+ AUElement * element = GetScope(inScope).GetElement (inElement);
+ element->SetName (*(CFStringRef *)inData);
+ PropertyChanged(inID, inScope, inElement);
+ }
+ break;
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE
+ case kAudioUnitProperty_ShouldAllocateBuffer:
+ {
+ ca_require((inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Output), InvalidScope);
+ ca_require(GetElement(inScope, inElement) != NULL, InvalidElement);
+ ca_require(inDataSize == sizeof(UInt32), InvalidPropertyValue);
+ ca_require(!IsInitialized(), Initialized);
+
+ AUIOElement * element = GetIOElement(inScope, inElement);
+ element->SetWillAllocateBuffer(*(UInt32 *)inData != 0);
+ }
+ break;
+#endif
+
+#if !CA_NO_AU_HOST_CALLBACKS
+ case kAudioUnitProperty_HostCallbacks:
+ {
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ UInt32 availSize = std::min(inDataSize, (UInt32)sizeof(HostCallbackInfo));
+ bool hasChanged = !memcmp (&mHostCallbackInfo, inData, availSize);
+ memset (&mHostCallbackInfo, 0, sizeof (mHostCallbackInfo));
+ memcpy (&mHostCallbackInfo, inData, availSize);
+ if (hasChanged)
+ PropertyChanged(inID, inScope, inElement);
+ break;
+ }
+#endif
+#if !CA_NO_AU_UI_FEATURES
+ case kAudioUnitProperty_SetExternalBuffer:
+ ca_require(inDataSize >= sizeof(AudioUnitExternalBuffer), InvalidPropertyValue);
+ ca_require(IsInitialized(), Uninitialized);
+ {
+ AudioUnitExternalBuffer &buf = *(AudioUnitExternalBuffer*)inData;
+ if (intptr_t(buf.buffer) & 0x0F) result = kAudio_ParamError;
+ else if (inScope == kAudioUnitScope_Input) {
+ AUInputElement *input = GetInput(inElement);
+ input->UseExternalBuffer(buf);
+ } else {
+ AUOutputElement *output = GetOutput(inElement);
+ output->UseExternalBuffer(buf);
+ }
+ }
+ break;
+
+ case kAudioUnitProperty_ContextName:
+ {
+ ca_require(inDataSize == sizeof(CFStringRef), InvalidPropertyValue);
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ CFStringRef inStr = *(CFStringRef *)inData;
+ if (mContextName) CFRelease(mContextName);
+ if (inStr) CFRetain(inStr);
+ mContextName = inStr;
+ PropertyChanged(inID, inScope, inElement);
+ }
+ break;
+
+#endif // !CA_NO_AU_UI_FEATURES
+
+ case kAudioUnitProperty_NickName:
+ {
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inDataSize == sizeof(CFStringRef), InvalidPropertyValue);
+ CFStringRef inStr = *(CFStringRef *)inData;
+ if (mNickName) CFRelease(mNickName);
+ if (inStr) CFRetain(inStr);
+ mNickName = inStr;
+ PropertyChanged(inID, inScope, inElement);
+ break;
+ }
+
+ default:
+ result = SetProperty(inID, inScope, inElement, inData, inDataSize);
+ if (result == noErr)
+ PropertyChanged(inID, inScope, inElement);
+
+ break;
+ }
+ return result;
+NotWritable:
+ return kAudioUnitErr_PropertyNotWritable;
+InvalidFormat:
+ return kAudioUnitErr_FormatNotSupported;
+#if !CA_NO_AU_UI_FEATURES
+Uninitialized:
+ return kAudioUnitErr_Uninitialized;
+#endif
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || CA_USE_AUDIO_PLUGIN_ONLY
+Initialized:
+ return kAudioUnitErr_Initialized;
+#endif
+InvalidScope:
+ return kAudioUnitErr_InvalidScope;
+InvalidProperty:
+ return kAudioUnitErr_InvalidProperty;
+InvalidPropertyValue:
+ return kAudioUnitErr_InvalidPropertyValue;
+InvalidElement:
+ return kAudioUnitErr_InvalidElement;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DispatchRemovePropertyValue (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ OSStatus result = noErr;
+ switch (inID)
+ {
+ case kAudioUnitProperty_AudioChannelLayout:
+ {
+ result = RemoveAudioChannelLayout(inScope, inElement);
+ if (result == noErr)
+ PropertyChanged(inID, inScope, inElement);
+ break;
+ }
+
+#if !CA_NO_AU_HOST_CALLBACKS
+ case kAudioUnitProperty_HostCallbacks:
+ {
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ bool hasValue = false;
+ void* ptr = &mHostCallbackInfo;
+ for (unsigned int i = 0; i < sizeof (HostCallbackInfo); ++i) {
+ if (static_cast<char*>(ptr)[i]) {
+ hasValue = true;
+ break;
+ }
+ }
+ if (hasValue) {
+ memset (&mHostCallbackInfo, 0, sizeof (HostCallbackInfo));
+ PropertyChanged(inID, inScope, inElement);
+ }
+ break;
+ }
+#endif
+#if !CA_NO_AU_UI_FEATURES
+ case kAudioUnitProperty_ContextName:
+ if (mContextName) CFRelease(mContextName);
+ mContextName = NULL;
+ result = noErr;
+ break;
+
+#endif // !CA_NO_AU_UI_FEATURES
+
+ case kAudioUnitProperty_NickName:
+ {
+ if(inScope == kAudioUnitScope_Global) {
+ if (mNickName) CFRelease(mNickName);
+ mNickName = NULL;
+ PropertyChanged(inID, inScope, inElement);
+ } else {
+ result = kAudioUnitErr_InvalidScope;
+ }
+ break;
+ }
+
+ default:
+ result = RemovePropertyValue (inID, inScope, inElement);
+ break;
+ }
+
+ return result;
+#if !CA_NO_AU_UI_FEATURES || !CA_NO_AU_HOST_CALLBACKS
+InvalidScope:
+ return kAudioUnitErr_InvalidScope;
+#endif
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::GetPropertyInfo( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::RemovePropertyValue ( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ return kAudioUnitErr_InvalidPropertyValue;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::AddPropertyListener( AudioUnitPropertyID inID,
+ AudioUnitPropertyListenerProc inProc,
+ void * inProcRefCon)
+{
+ PropertyListener pl;
+
+ pl.propertyID = inID;
+ pl.listenerProc = inProc;
+ pl.listenerRefCon = inProcRefCon;
+
+ if (mPropertyListeners.empty())
+ mPropertyListeners.reserve(32);
+ mPropertyListeners.push_back(pl);
+
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::RemovePropertyListener( AudioUnitPropertyID inID,
+ AudioUnitPropertyListenerProc inProc,
+ void * inProcRefCon,
+ bool refConSpecified)
+{
+ // iterate in reverse so that it's safe to erase in the middle of the vector
+ for (int i = (int)mPropertyListeners.size(); --i >=0; ) {
+ PropertyListeners::iterator it = mPropertyListeners.begin() + i;
+ if ((*it).propertyID == inID && (*it).listenerProc == inProc && (!refConSpecified || (*it).listenerRefCon == inProcRefCon))
+ mPropertyListeners.erase(it);
+ }
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::PropertyChanged( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ for (PropertyListeners::iterator it = mPropertyListeners.begin(); it != mPropertyListeners.end(); ++it)
+ if ((*it).propertyID == inID)
+ ((*it).listenerProc)((*it).listenerRefCon, mComponentInstance, inID, inScope, inElement);
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::SetRenderNotification( AURenderCallback inProc,
+ void * inRefCon)
+{
+ if (inProc == NULL)
+ return kAudio_ParamError;
+
+ mRenderCallbacksTouched = true;
+ mRenderCallbacks.deferred_add(RenderCallback(inProc, inRefCon));
+ // this will do nothing if it's already in the list
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::RemoveRenderNotification( AURenderCallback inProc,
+ void * inRefCon)
+{
+ mRenderCallbacks.deferred_remove(RenderCallback(inProc, inRefCon));
+ return noErr; // error?
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::GetParameter( AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioUnitParameterValue & outValue)
+{
+ AUElement *elem = SafeGetElement(inScope, inElement);
+ outValue = elem->GetParameter(inID);
+ return noErr;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::SetParameter( AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioUnitParameterValue inValue,
+ UInt32 inBufferOffsetInFrames)
+{
+ AUElement *elem = SafeGetElement(inScope, inElement);
+ elem->SetParameter(inID, inValue);
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::ScheduleParameter ( const AudioUnitParameterEvent *inParameterEvent,
+ UInt32 inNumEvents)
+{
+ bool canScheduleParameters = CanScheduleParameters();
+
+ for (UInt32 i = 0; i < inNumEvents; ++i)
+ {
+ if (inParameterEvent[i].eventType == kParameterEvent_Immediate)
+ {
+ SetParameter (inParameterEvent[i].parameter,
+ inParameterEvent[i].scope,
+ inParameterEvent[i].element,
+ inParameterEvent[i].eventValues.immediate.value,
+ inParameterEvent[i].eventValues.immediate.bufferOffset);
+ }
+ if (canScheduleParameters) {
+ mParamList.push_back (inParameterEvent[i]);
+ }
+ }
+
+ return noErr;
+}
+
+// ____________________________________________________________________________
+//
+static bool SortParameterEventList(const AudioUnitParameterEvent &ev1, const AudioUnitParameterEvent &ev2 )
+{
+ int offset1 = ev1.eventType == kParameterEvent_Immediate ? ev1.eventValues.immediate.bufferOffset : ev1.eventValues.ramp.startBufferOffset;
+ int offset2 = ev2.eventType == kParameterEvent_Immediate ? ev2.eventValues.immediate.bufferOffset : ev2.eventValues.ramp.startBufferOffset;
+
+ if(offset1 < offset2) return true;
+ return false;
+}
+
+
+// ____________________________________________________________________________
+//
+OSStatus AUBase::ProcessForScheduledParams( ParameterEventList &inParamList,
+ UInt32 inFramesToProcess,
+ void *inUserData )
+{
+ OSStatus result = noErr;
+
+ int totalFramesToProcess = inFramesToProcess;
+
+ int framesRemaining = totalFramesToProcess;
+
+ unsigned int currentStartFrame = 0; // start of the whole buffer
+
+
+
+ // sort the ParameterEventList by startBufferOffset
+ std::sort(inParamList.begin(), inParamList.end(), SortParameterEventList);
+
+ ParameterEventList::iterator iter = inParamList.begin();
+
+
+ while(framesRemaining > 0 )
+ {
+ // first of all, go through the ramped automation events and find out where the next
+ // division of our whole buffer will be
+
+ int currentEndFrame = totalFramesToProcess; // start out assuming we'll process all the way to
+ // the end of the buffer
+
+ iter = inParamList.begin();
+
+ // find the next break point
+ while(iter != inParamList.end() )
+ {
+ AudioUnitParameterEvent &event = *iter;
+
+ int offset = event.eventType == kParameterEvent_Immediate ? event.eventValues.immediate.bufferOffset : event.eventValues.ramp.startBufferOffset;
+
+ if(offset > (int)currentStartFrame && offset < currentEndFrame )
+ {
+ currentEndFrame = offset;
+ break;
+ }
+
+ // consider ramp end to be a possible choice (there may be gaps in the supplied ramp events)
+ if(event.eventType == kParameterEvent_Ramped )
+ {
+ offset = event.eventValues.ramp.startBufferOffset + event.eventValues.ramp.durationInFrames;
+
+ if(offset > (int)currentStartFrame && offset < currentEndFrame )
+ {
+ currentEndFrame = offset;
+ }
+ }
+
+ iter++;
+ }
+
+ int framesThisTime = currentEndFrame - currentStartFrame;
+
+ // next, setup the parameter maps to be current for the ramp parameters active during
+ // this time segment...
+
+ for(ParameterEventList::iterator iter2 = inParamList.begin(); iter2 != inParamList.end(); iter2++ )
+ {
+ AudioUnitParameterEvent &event = *iter2;
+
+ bool eventFallsInSlice;
+
+
+ if(event.eventType == kParameterEvent_Ramped)
+ eventFallsInSlice = event.eventValues.ramp.startBufferOffset < currentEndFrame
+ && event.eventValues.ramp.startBufferOffset + event.eventValues.ramp.durationInFrames > currentStartFrame;
+ else /* kParameterEvent_Immediate */
+ // actually, for the same parameter, there may be future immediate events which override this one,
+ // but it's OK since the event list is sorted in time order, we're guaranteed to end up with the current one
+ eventFallsInSlice = event.eventValues.immediate.bufferOffset <= currentStartFrame;
+
+ if(eventFallsInSlice)
+ {
+ AUElement *element = GetElement(event.scope, event.element );
+
+ if(element) element->SetScheduledEvent( event.parameter,
+ event,
+ currentStartFrame,
+ currentEndFrame - currentStartFrame );
+ }
+ }
+
+
+
+ // Finally, actually do the processing for this slice.....
+
+ result = ProcessScheduledSlice( inUserData,
+ currentStartFrame,
+ framesThisTime,
+ inFramesToProcess );
+
+ if(result != noErr) break;
+
+ framesRemaining -= framesThisTime;
+ currentStartFrame = currentEndFrame; // now start from where we left off last time
+ }
+
+ return result;
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::SetWantsRenderThreadID (bool inFlag)
+{
+ if (inFlag == mWantsRenderThreadID)
+ return;
+
+ mWantsRenderThreadID = inFlag;
+ if (!mWantsRenderThreadID)
+ mRenderThreadID = NULL;
+}
+
+//_____________________________________________________________________________
+//
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DoRender( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inFramesToProcess,
+ AudioBufferList & ioData)
+{
+ OSStatus theError;
+ RenderCallbackList::iterator rcit;
+
+ AUTRACE(kCATrace_AUBaseRenderStart, mComponentInstance, (uintptr_t)this, inBusNumber, inFramesToProcess, (uintptr_t)ioData.mBuffers[0].mData);
+ DISABLE_DENORMALS
+
+ try {
+ ca_require(IsInitialized(), Uninitialized);
+ ca_require(mAudioUnitAPIVersion >= 2, ParamErr);
+ if (inFramesToProcess > mMaxFramesPerSlice) {
+ static time_t lastTimeMessagePrinted = 0;
+ time_t now = time(NULL);
+ if (now != lastTimeMessagePrinted) {
+ lastTimeMessagePrinted = now;
+ syslog(LOG_ERR, "kAudioUnitErr_TooManyFramesToProcess : inFramesToProcess=%u, mMaxFramesPerSlice=%u", (unsigned)inFramesToProcess, (unsigned)mMaxFramesPerSlice);
+ DebugMessageN4("%s:%d inFramesToProcess=%u, mMaxFramesPerSlice=%u; TooManyFrames", __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)mMaxFramesPerSlice);
+ }
+ goto TooManyFrames;
+ }
+ ca_require (!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), ParamErr);
+
+ AUOutputElement *output = GetOutput(inBusNumber); // will throw if non-existant
+ if (output->GetStreamFormat().NumberChannelStreams() != ioData.mNumberBuffers) {
+ DebugMessageN4("%s:%d ioData.mNumberBuffers=%u, output->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError",
+ __FILE__, __LINE__, (unsigned)ioData.mNumberBuffers, (unsigned)output->GetStreamFormat().NumberChannelStreams());
+ goto ParamErr;
+ }
+
+ unsigned expectedBufferByteSize = inFramesToProcess * output->GetStreamFormat().mBytesPerFrame;
+ for (unsigned ibuf = 0; ibuf < ioData.mNumberBuffers; ++ibuf) {
+ AudioBuffer &buf = ioData.mBuffers[ibuf];
+ if (buf.mData != NULL) {
+ // only care about the size if the buffer is non-null
+ if (buf.mDataByteSize < expectedBufferByteSize) {
+ // if the buffer is too small, we cannot render safely. kAudio_ParamError.
+ DebugMessageN7("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; ioData.mBuffers[%u].mDataByteSize=%u; kAudio_ParamError",
+ __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)output->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, ibuf, (unsigned)buf.mDataByteSize);
+ goto ParamErr;
+ }
+ // Some clients incorrectly pass bigger buffers than expectedBufferByteSize.
+ // We will generally set the buffer size at the end of rendering, before we return.
+ // However we should ensure that no one, DURING rendering, READS a
+ // potentially incorrect size. This can lead to doing too much work, or
+ // reading past the end of an input buffer into unmapped memory.
+ buf.mDataByteSize = expectedBufferByteSize;
+ }
+ }
+
+ if (WantsRenderThreadID())
+ {
+ #if TARGET_OS_MAC
+ mRenderThreadID = pthread_self();
+ #elif TARGET_OS_WIN32
+ mRenderThreadID = GetCurrentThreadId();
+ #endif
+ }
+
+ AudioUnitRenderActionFlags flags;
+ if (mRenderCallbacksTouched) {
+ mRenderCallbacks.update();
+ flags = ioActionFlags | kAudioUnitRenderAction_PreRender;
+ for (rcit = mRenderCallbacks.begin(); rcit != mRenderCallbacks.end(); ++rcit) {
+ RenderCallback &rc = *rcit;
+ AUTRACE(kCATrace_AUBaseRenderCallbackStart, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 1, 0);
+ (*(AURenderCallback)rc.mRenderNotify)(rc.mRenderNotifyRefCon,
+ &flags,
+ &inTimeStamp, inBusNumber, inFramesToProcess, &ioData);
+ AUTRACE(kCATrace_AUBaseRenderCallbackEnd, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 1, 0);
+ }
+ }
+
+ theError = DoRenderBus(ioActionFlags, inTimeStamp, inBusNumber, output, inFramesToProcess, ioData);
+
+ if (mRenderCallbacksTouched) {
+ flags = ioActionFlags | kAudioUnitRenderAction_PostRender;
+
+ if (SetRenderError (theError)) {
+ flags |= kAudioUnitRenderAction_PostRenderError;
+ }
+
+ for (rcit = mRenderCallbacks.begin(); rcit != mRenderCallbacks.end(); ++rcit) {
+ RenderCallback &rc = *rcit;
+ AUTRACE(kCATrace_AUBaseRenderCallbackStart, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 2, 0);
+ (*(AURenderCallback)rc.mRenderNotify)(rc.mRenderNotifyRefCon,
+ &flags,
+ &inTimeStamp, inBusNumber, inFramesToProcess, &ioData);
+ AUTRACE(kCATrace_AUBaseRenderCallbackEnd, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 2, 0);
+ }
+ }
+
+ // The vector's being emptied
+ // because these events should only apply to this Render cycle, so anything
+ // left over is from a preceding cycle and should be dumped. New scheduled
+ // parameters must be scheduled from the next pre-render callback.
+ if (!mParamList.empty())
+ mParamList.clear();
+
+ }
+ catch (OSStatus err) {
+ theError = err;
+ goto errexit;
+ }
+ catch (...) {
+ theError = -1;
+ goto errexit;
+ }
+done:
+ RESTORE_DENORMALS
+ AUTRACE(kCATrace_AUBaseRenderEnd, mComponentInstance, (intptr_t)this, theError, ioActionFlags, CATrace::ablData(ioData));
+
+ return theError;
+
+Uninitialized: theError = kAudioUnitErr_Uninitialized; goto errexit;
+ParamErr: theError = kAudio_ParamError; goto errexit;
+TooManyFrames: theError = kAudioUnitErr_TooManyFramesToProcess; goto errexit;
+errexit:
+ DebugMessageN2 (" from %s, render err: %d", GetLoggingString(), (int)theError);
+ SetRenderError(theError);
+ goto done;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::DoProcess ( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inFramesToProcess,
+ AudioBufferList & ioData)
+{
+ OSStatus theError;
+ AUTRACE(kCATrace_AUBaseRenderStart, mComponentInstance, (intptr_t)this, -1, inFramesToProcess, 0);
+ DISABLE_DENORMALS
+
+ try {
+
+ if (!(ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)) {
+ ca_require(IsInitialized(), Uninitialized);
+ ca_require(inFramesToProcess <= mMaxFramesPerSlice, TooManyFrames);
+ ca_require(!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), ParamErr);
+
+ AUInputElement *input = GetInput(0); // will throw if non-existant
+ if (input->GetStreamFormat().NumberChannelStreams() != ioData.mNumberBuffers) {
+ DebugMessageN4("%s:%d ioData.mNumberBuffers=%u, input->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError",
+ __FILE__, __LINE__, (unsigned)ioData.mNumberBuffers, (unsigned)input->GetStreamFormat().NumberChannelStreams());
+ goto ParamErr;
+ }
+
+ unsigned expectedBufferByteSize = inFramesToProcess * input->GetStreamFormat().mBytesPerFrame;
+ for (unsigned ibuf = 0; ibuf < ioData.mNumberBuffers; ++ibuf) {
+ AudioBuffer &buf = ioData.mBuffers[ibuf];
+ if (buf.mData != NULL) {
+ // only care about the size if the buffer is non-null
+ if (buf.mDataByteSize < expectedBufferByteSize) {
+ // if the buffer is too small, we cannot render safely. kAudio_ParamError.
+ DebugMessageN7("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; ioData.mBuffers[%u].mDataByteSize=%u; kAudio_ParamError",
+ __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)input->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, ibuf, (unsigned)buf.mDataByteSize);
+ goto ParamErr;
+ }
+ // Some clients incorrectly pass bigger buffers than expectedBufferByteSize.
+ // We will generally set the buffer size at the end of rendering, before we return.
+ // However we should ensure that no one, DURING rendering, READS a
+ // potentially incorrect size. This can lead to doing too much work, or
+ // reading past the end of an input buffer into unmapped memory.
+ buf.mDataByteSize = expectedBufferByteSize;
+ }
+ }
+ }
+
+ if (WantsRenderThreadID())
+ {
+ #if TARGET_OS_MAC
+ mRenderThreadID = pthread_self();
+ #elif TARGET_OS_WIN32
+ mRenderThreadID = GetCurrentThreadId();
+ #endif
+ }
+
+ if (NeedsToRender (inTimeStamp)) {
+ theError = ProcessBufferLists (ioActionFlags, ioData, ioData, inFramesToProcess);
+ } else
+ theError = noErr;
+
+ }
+ catch (OSStatus err) {
+ theError = err;
+ goto errexit;
+ }
+ catch (...) {
+ theError = -1;
+ goto errexit;
+ }
+done:
+ RESTORE_DENORMALS
+ AUTRACE(kCATrace_AUBaseRenderEnd, mComponentInstance, (intptr_t)this, theError, ioActionFlags, CATrace::ablData(ioData));
+
+ return theError;
+
+Uninitialized: theError = kAudioUnitErr_Uninitialized; goto errexit;
+ParamErr: theError = kAudio_ParamError; goto errexit;
+TooManyFrames: theError = kAudioUnitErr_TooManyFramesToProcess; goto errexit;
+errexit:
+ DebugMessageN2 (" from %s, process err: %d", GetLoggingString(), (int)theError);
+ SetRenderError(theError);
+ goto done;
+}
+
+OSStatus AUBase::DoProcessMultiple ( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inFramesToProcess,
+ UInt32 inNumberInputBufferLists,
+ const AudioBufferList ** inInputBufferLists,
+ UInt32 inNumberOutputBufferLists,
+ AudioBufferList ** ioOutputBufferLists)
+{
+ OSStatus theError;
+ DISABLE_DENORMALS
+
+ try {
+
+ if (!(ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)) {
+ ca_require(IsInitialized(), Uninitialized);
+ ca_require(inFramesToProcess <= mMaxFramesPerSlice, TooManyFrames);
+ ca_require (!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), ParamErr);
+
+ for (unsigned ibl = 0; ibl < inNumberInputBufferLists; ++ibl) {
+ if (inInputBufferLists[ibl] != NULL) {
+ AUInputElement *input = GetInput(ibl); // will throw if non-existant
+ unsigned expectedBufferByteSize = inFramesToProcess * input->GetStreamFormat().mBytesPerFrame;
+
+ if (input->GetStreamFormat().NumberChannelStreams() != inInputBufferLists[ibl]->mNumberBuffers) {
+ DebugMessageN5("%s:%d inInputBufferLists[%u]->mNumberBuffers=%u, input->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError",
+ __FILE__, __LINE__, ibl, (unsigned)inInputBufferLists[ibl]->mNumberBuffers, (unsigned)input->GetStreamFormat().NumberChannelStreams());
+ goto ParamErr;
+ }
+
+ for (unsigned ibuf = 0; ibuf < inInputBufferLists[ibl]->mNumberBuffers; ++ibuf) {
+ const AudioBuffer &buf = inInputBufferLists[ibl]->mBuffers[ibuf];
+ if (buf.mData != NULL) {
+ if (buf.mDataByteSize < expectedBufferByteSize) {
+ // the buffer is too small
+ DebugMessageN8("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; inInputBufferLists[%u].mBuffers[%u].mDataByteSize=%u; kAudio_ParamError",
+ __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)input->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, ibl, ibuf, (unsigned)buf.mDataByteSize);
+ goto ParamErr;
+ }
+ } else {
+ // the buffer must exist
+ goto ParamErr;
+ }
+ }
+ } else {
+ // skip NULL input audio buffer list
+ }
+ }
+
+ for (unsigned obl = 0; obl < inNumberOutputBufferLists; ++obl) {
+ if (ioOutputBufferLists[obl] != NULL) {
+ AUOutputElement *output = GetOutput(obl); // will throw if non-existant
+ unsigned expectedBufferByteSize = inFramesToProcess * output->GetStreamFormat().mBytesPerFrame;
+
+ if (output->GetStreamFormat().NumberChannelStreams() != ioOutputBufferLists[obl]->mNumberBuffers) {
+ DebugMessageN5("%s:%d ioOutputBufferLists[%u]->mNumberBuffers=%u, output->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError",
+ __FILE__, __LINE__, obl, (unsigned)ioOutputBufferLists[obl]->mNumberBuffers, (unsigned)output->GetStreamFormat().NumberChannelStreams());
+ goto ParamErr;
+ }
+
+ for (unsigned obuf = 0; obuf < ioOutputBufferLists[obl]->mNumberBuffers; ++obuf) {
+ AudioBuffer &buf = ioOutputBufferLists[obl]->mBuffers[obuf];
+ if (buf.mData != NULL) {
+ // only care about the size if the buffer is non-null
+ if (buf.mDataByteSize < expectedBufferByteSize) {
+ // if the buffer is too small, we cannot render safely. kAudio_ParamError.
+ DebugMessageN8("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; ioOutputBufferLists[%u]->mBuffers[%u].mDataByteSize=%u; kAudio_ParamError",
+ __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)output->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, obl, obuf, (unsigned)buf.mDataByteSize);
+ goto ParamErr;
+ }
+ // Some clients incorrectly pass bigger buffers than expectedBufferByteSize.
+ // We will generally set the buffer size at the end of rendering, before we return.
+ // However we should ensure that no one, DURING rendering, READS a
+ // potentially incorrect size. This can lead to doing too much work, or
+ // reading past the end of an input buffer into unmapped memory.
+ buf.mDataByteSize = expectedBufferByteSize;
+ }
+ }
+ } else {
+ // skip NULL output audio buffer list
+ }
+ }
+ }
+
+ if (WantsRenderThreadID())
+ {
+#if TARGET_OS_MAC
+ mRenderThreadID = pthread_self();
+#elif TARGET_OS_WIN32
+ mRenderThreadID = GetCurrentThreadId();
+#endif
+ }
+
+ if (NeedsToRender (inTimeStamp)) {
+ theError = ProcessMultipleBufferLists (ioActionFlags, inFramesToProcess, inNumberInputBufferLists, inInputBufferLists, inNumberOutputBufferLists, ioOutputBufferLists);
+ } else
+ theError = noErr;
+ }
+ catch (OSStatus err) {
+ theError = err;
+ goto errexit;
+ }
+ catch (...) {
+ theError = -1;
+ goto errexit;
+ }
+done:
+ RESTORE_DENORMALS
+
+ return theError;
+
+Uninitialized: theError = kAudioUnitErr_Uninitialized; goto errexit;
+ParamErr: theError = kAudio_ParamError; goto errexit;
+TooManyFrames: theError = kAudioUnitErr_TooManyFramesToProcess; goto errexit;
+errexit:
+ DebugMessageN2 (" from %s, processmultiple err: %d", GetLoggingString(), (int)theError);
+ SetRenderError(theError);
+ goto done;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::SetInputCallback( UInt32 inPropertyID,
+ AudioUnitElement inElement,
+ AURenderCallback inProc,
+ void * inRefCon)
+{
+ AUInputElement *input = GetInput(inElement); // may throw
+
+ input->SetInputCallback(inProc, inRefCon);
+ PropertyChanged(inPropertyID, kAudioUnitScope_Input, inElement);
+
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::SetConnection( const AudioUnitConnection & inConnection)
+{
+
+ OSStatus err;
+ AUInputElement *input = GetInput(inConnection.destInputNumber); // may throw
+
+ if (inConnection.sourceAudioUnit) {
+ // connecting, not disconnecting
+ CAStreamBasicDescription sourceDesc;
+ UInt32 size = sizeof(CAStreamBasicDescription);
+ ca_require_noerr(err = AudioUnitGetProperty(
+ inConnection.sourceAudioUnit,
+ kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Output,
+ inConnection.sourceOutputNumber,
+ &sourceDesc,
+ &size), errexit);
+ ca_require_noerr(err = DispatchSetProperty (kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Input, inConnection.destInputNumber,
+ &sourceDesc, sizeof(CAStreamBasicDescription)), errexit);
+ }
+ input->SetConnection(inConnection);
+
+ PropertyChanged(kAudioUnitProperty_MakeConnection, kAudioUnitScope_Input, inConnection.destInputNumber);
+ return noErr;
+
+errexit:
+ return err;
+}
+
+//_____________________________________________________________________________
+//
+UInt32 AUBase::SupportedNumChannels ( const AUChannelInfo** outInfo)
+{
+ return 0;
+}
+
+//_____________________________________________________________________________
+//
+bool AUBase::ValidFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inNewFormat)
+{
+ return FormatIsCanonical(inNewFormat);
+}
+
+//_____________________________________________________________________________
+//
+bool AUBase::IsStreamFormatWritable( AudioUnitScope scope,
+ AudioUnitElement element)
+{
+ switch (scope) {
+ case kAudioUnitScope_Input:
+ {
+ AUInputElement *input = GetInput(element);
+ if (input->HasConnection()) return false; // can't write format when input comes from connection
+ }
+ // ... fall ...
+ case kAudioUnitScope_Output:
+ return StreamFormatWritable(scope, element);
+
+//#warning "aliasing of global scope format should be pushed to subclasses"
+ case kAudioUnitScope_Global:
+ return StreamFormatWritable(kAudioUnitScope_Output, 0);
+ }
+ return false;
+}
+
+//_____________________________________________________________________________
+//
+const CAStreamBasicDescription &
+ AUBase::GetStreamFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+//#warning "aliasing of global scope format should be pushed to subclasses"
+ AUIOElement *element;
+
+ switch (inScope) {
+ case kAudioUnitScope_Input:
+ element = Inputs().GetIOElement(inElement);
+ break;
+ case kAudioUnitScope_Output:
+ element = Outputs().GetIOElement(inElement);
+ break;
+ case kAudioUnitScope_Global: // global stream description is an alias for that of output 0
+ element = Outputs().GetIOElement(0);
+ break;
+ default:
+ COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+ }
+ return element->GetStreamFormat();
+}
+
+OSStatus AUBase::SetBusCount( AudioUnitScope inScope,
+ UInt32 inCount)
+{
+ if (IsInitialized())
+ return kAudioUnitErr_Initialized;
+
+ GetScope(inScope).SetNumberOfElements(inCount);
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::ChangeStreamFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inPrevFormat,
+ const CAStreamBasicDescription & inNewFormat)
+{
+//#warning "aliasing of global scope format should be pushed to subclasses"
+ AUIOElement *element;
+
+ switch (inScope) {
+ case kAudioUnitScope_Input:
+ element = Inputs().GetIOElement(inElement);
+ break;
+ case kAudioUnitScope_Output:
+ element = Outputs().GetIOElement(inElement);
+ break;
+ case kAudioUnitScope_Global:
+ element = Outputs().GetIOElement(0);
+ break;
+ default:
+ COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+ }
+ element->SetStreamFormat(inNewFormat);
+ PropertyChanged(kAudioUnitProperty_StreamFormat, inScope, inElement);
+ return noErr;
+}
+
+UInt32 AUBase::GetChannelLayoutTags( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag * outLayoutTags)
+{
+ return GetIOElement(inScope, inElement)->GetChannelLayoutTags(outLayoutTags);
+}
+
+UInt32 AUBase::GetAudioChannelLayout( AudioUnitScope scope,
+ AudioUnitElement element,
+ AudioChannelLayout * outLayoutPtr,
+ Boolean & outWritable)
+{
+ AUIOElement * el = GetIOElement(scope, element);
+ return el->GetAudioChannelLayout(outLayoutPtr, outWritable);
+}
+
+OSStatus AUBase::RemoveAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ OSStatus result = noErr;
+ AUIOElement * el = GetIOElement(inScope, inElement);
+ Boolean writable;
+ if (el->GetAudioChannelLayout(NULL, writable)) {
+ result = el->RemoveAudioChannelLayout();
+ }
+ return result;
+}
+
+OSStatus AUBase::SetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const AudioChannelLayout * inLayout)
+{
+ AUIOElement* ioEl = GetIOElement (inScope, inElement);
+
+ // the num channels of the layout HAS TO MATCH the current channels of the Element's stream format
+ UInt32 currentChannels = ioEl->GetStreamFormat().NumberChannels();
+ UInt32 numChannelsInLayout = CAAudioChannelLayout::NumberChannels(*inLayout);
+ if (currentChannels != numChannelsInLayout)
+ return kAudioUnitErr_InvalidPropertyValue;
+
+ UInt32 numLayouts = GetChannelLayoutTags (inScope, inElement, NULL);
+ if (numLayouts == 0)
+ return kAudioUnitErr_InvalidProperty;
+ AudioChannelLayoutTag *tags = (AudioChannelLayoutTag *)CA_malloc (numLayouts * sizeof (AudioChannelLayoutTag));
+ GetChannelLayoutTags (inScope, inElement, tags);
+ bool foundTag = false;
+ for (unsigned int i = 0; i < numLayouts; ++i) {
+ if (tags[i] == inLayout->mChannelLayoutTag || tags[i] == kAudioChannelLayoutTag_UseChannelDescriptions) {
+ foundTag = true;
+ break;
+ }
+ }
+ free(tags);
+
+ if (foundTag == false)
+ return kAudioUnitErr_InvalidPropertyValue;
+
+ return ioEl->SetAudioChannelLayout(*inLayout);
+}
+
+static void AddNumToDictionary (CFMutableDictionaryRef dict, CFStringRef key, SInt32 value)
+{
+ CFNumberRef num = CFNumberCreate (NULL, kCFNumberSInt32Type, &value);
+ CFDictionarySetValue (dict, key, num);
+ CFRelease (num);
+}
+
+#define kCurrentSavedStateVersion 0
+
+OSStatus AUBase::SaveState( CFPropertyListRef * outData)
+{
+ AudioComponentDescription desc = GetComponentDescription();
+
+ CFMutableDictionaryRef dict = CFDictionaryCreateMutable (NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+// first step -> save the version to the data ref
+ SInt32 value = kCurrentSavedStateVersion;
+ AddNumToDictionary (dict, kVersionString, value);
+
+// second step -> save the component type, subtype, manu to the data ref
+ value = desc.componentType;
+ AddNumToDictionary (dict, kTypeString, value);
+
+ value = desc.componentSubType;
+ AddNumToDictionary (dict, kSubtypeString, value);
+
+ value = desc.componentManufacturer;
+ AddNumToDictionary (dict, kManufacturerString, value);
+
+// fourth step -> save the state of all parameters on all scopes and elements
+ CFMutableDataRef data = CFDataCreateMutable(NULL, 0);
+ for (AudioUnitScope iscope = 0; iscope < 3; ++iscope) {
+ AUScope &scope = GetScope(iscope);
+ scope.SaveState (data);
+ }
+
+ SaveExtendedScopes(data);
+
+// save all this in the data section of the dictionary
+ CFDictionarySetValue(dict, kDataString, data);
+ CFRelease (data);
+
+//OK - now we're going to do some properties
+//save the preset name...
+ CFDictionarySetValue (dict, kNameString, mCurrentPreset.presetName);
+
+// Does the unit support the RenderQuality property - if so, save it...
+ value = 0;
+ OSStatus result = DispatchGetProperty (kAudioUnitProperty_RenderQuality,
+ kAudioUnitScope_Global,
+ 0,
+ &value);
+
+ if (result == noErr) {
+ AddNumToDictionary (dict, kRenderQualityString, value);
+ }
+
+// Does the unit support the CPULoad Quality property - if so, save it...
+ Float32 cpuLoad;
+ result = DispatchGetProperty (6/*kAudioUnitProperty_CPULoad*/,
+ kAudioUnitScope_Global,
+ 0,
+ &cpuLoad);
+
+ if (result == noErr) {
+ CFNumberRef num = CFNumberCreate (NULL, kCFNumberFloatType, &cpuLoad);
+ CFDictionarySetValue (dict, kCPULoadString, num);
+ CFRelease (num);
+ }
+
+// Do we have any element names for any of our scopes?
+ // first check to see if we have any names...
+ bool foundName = false;
+ for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
+ foundName = GetScope (i).HasElementWithName();
+ if (foundName)
+ break;
+ }
+ // OK - we found a name away we go...
+ if (foundName) {
+ CFMutableDictionaryRef nameDict = CFDictionaryCreateMutable (NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
+ GetScope (i).AddElementNamesToDict (nameDict);
+ }
+
+ CFDictionarySetValue (dict, kElementNameString, nameDict);
+ CFRelease (nameDict);
+ }
+
+// we're done!!!
+ *outData = dict;
+
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::RestoreState( CFPropertyListRef plist)
+{
+ if (CFGetTypeID(plist) != CFDictionaryGetTypeID()) return kAudioUnitErr_InvalidPropertyValue;
+
+ AudioComponentDescription desc = GetComponentDescription();
+
+ CFDictionaryRef dict = static_cast<CFDictionaryRef>(plist);
+
+// zeroeth step - make sure the Part key is NOT present, as this method is used
+// to restore the GLOBAL state of the dictionary
+ if (CFDictionaryContainsKey (dict, kPartString))
+ return kAudioUnitErr_InvalidPropertyValue;
+
+// first step -> check the saved version in the data ref
+// at this point we're only dealing with version==0
+ CFNumberRef cfnum = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue (dict, kVersionString));
+ if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue;
+ SInt32 value;
+ CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+ if (value != kCurrentSavedStateVersion) return kAudioUnitErr_InvalidPropertyValue;
+
+// second step -> check that this data belongs to this kind of audio unit
+// by checking the component subtype and manuID
+// We're not checking the type, since there may be different versions (effect, format-converter, offline)
+// of essentially the same AU
+ cfnum = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue (dict, kSubtypeString));
+ if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue;
+ CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+ if (UInt32(value) != desc.componentSubType) return kAudioUnitErr_InvalidPropertyValue;
+
+ cfnum = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue (dict, kManufacturerString));
+ if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue;
+ CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+ if (UInt32(value) != desc.componentManufacturer) return kAudioUnitErr_InvalidPropertyValue;
+
+// fourth step -> restore the state of all of the parameters for each scope and element
+ CFDataRef data = reinterpret_cast<CFDataRef>(CFDictionaryGetValue (dict, kDataString));
+ if (data != NULL)
+ {
+ const UInt8 *p, *pend;
+
+ p = CFDataGetBytePtr(data);
+ pend = p + CFDataGetLength(data);
+
+ // we have a zero length data, which may just mean there were no parameters to save!
+ // if (p >= pend) return noErr;
+
+ while (p < pend) {
+ UInt32 scopeIdx = CFSwapInt32BigToHost(*(UInt32 *)p);
+ p += sizeof(UInt32);
+
+ AUScope &scope = GetScope(scopeIdx);
+ p = scope.RestoreState(p);
+ }
+ }
+
+//OK - now we're going to do some properties
+//restore the preset name...
+ CFStringRef name = reinterpret_cast<CFStringRef>(CFDictionaryGetValue (dict, kNameString));
+ if (mCurrentPreset.presetName) CFRelease (mCurrentPreset.presetName);
+ if (name)
+ {
+ mCurrentPreset.presetName = name;
+ mCurrentPreset.presetNumber = -1;
+ }
+ else { // no name entry make the default one
+ mCurrentPreset.presetName = kUntitledString;
+ mCurrentPreset.presetNumber = -1;
+ }
+
+ CFRetain (mCurrentPreset.presetName);
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+#ifndef __LP64__
+ PropertyChanged(kAudioUnitProperty_CurrentPreset, kAudioUnitScope_Global, 0);
+#endif
+#endif
+ PropertyChanged(kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global, 0);
+
+// Does the dict contain render quality information?
+ if (CFDictionaryGetValueIfPresent (dict, kRenderQualityString, reinterpret_cast<const void**>(&cfnum)))
+ {
+ CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value);
+ DispatchSetProperty (kAudioUnitProperty_RenderQuality,
+ kAudioUnitScope_Global,
+ 0,
+ &value,
+ sizeof(value));
+ }
+
+// Does the unit support the CPULoad Quality property - if so, save it...
+ if (CFDictionaryGetValueIfPresent (dict, kCPULoadString, reinterpret_cast<const void**>(&cfnum)))
+ {
+ Float32 floatValue;
+ CFNumberGetValue (cfnum, kCFNumberFloatType, &floatValue);
+ DispatchSetProperty (6/*kAudioUnitProperty_CPULoad*/,
+ kAudioUnitScope_Global,
+ 0,
+ &floatValue,
+ sizeof(floatValue));
+ }
+
+// Do we have any element names for any of our scopes?
+ CFDictionaryRef nameDict;
+ if (CFDictionaryGetValueIfPresent (dict, kElementNameString, reinterpret_cast<const void**>(&nameDict)))
+ {
+ char string[64];
+ for (int i = 0; i < kNumScopes; ++i)
+ {
+ snprintf (string, sizeof(string), "%d", i);
+ CFStringRef key = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
+ CFDictionaryRef elementDict;
+ if (CFDictionaryGetValueIfPresent (nameDict, key, reinterpret_cast<const void**>(&elementDict)))
+ {
+ bool didAddElements = GetScope (i).RestoreElementNames (elementDict);
+ if (didAddElements)
+ PropertyChanged (kAudioUnitProperty_ElementCount, i, 0);
+ }
+ CFRelease (key);
+ }
+ }
+
+ return noErr;
+}
+
+OSStatus AUBase::GetPresets ( CFArrayRef * outData) const
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+OSStatus AUBase::NewFactoryPresetSet (const AUPreset & inNewFactoryPreset)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+OSStatus AUBase::NewCustomPresetSet (const AUPreset & inNewCustomPreset)
+{
+ CFRelease (mCurrentPreset.presetName);
+ mCurrentPreset = inNewCustomPreset;
+ CFRetain (mCurrentPreset.presetName);
+ return noErr;
+}
+
+ // set the default preset for the unit -> the number of the preset MUST be >= 0
+ // and the name should be valid, or the preset WON'T take
+bool AUBase::SetAFactoryPresetAsCurrent (const AUPreset & inPreset)
+{
+ if (inPreset.presetNumber < 0 || inPreset.presetName == NULL) return false;
+ CFRelease (mCurrentPreset.presetName);
+ mCurrentPreset = inPreset;
+ CFRetain (mCurrentPreset.presetName);
+ return true;
+}
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+int AUBase::GetNumCustomUIComponents ()
+{
+ return 0;
+}
+
+void AUBase::GetUIComponentDescs (ComponentDescription* inDescArray) {}
+#endif
+
+bool AUBase::HasIcon ()
+{
+#if !CA_NO_AU_UI_FEATURES
+ CFURLRef url = CopyIconLocation();
+ if (url) {
+ CFRelease (url);
+ return true;
+ }
+#endif
+ return false;
+}
+
+CFURLRef AUBase::CopyIconLocation ()
+{
+ return NULL;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::GetParameterList( AudioUnitScope inScope,
+ AudioUnitParameterID * outParameterList,
+ UInt32 & outNumParameters)
+{
+ AUScope &scope = GetScope(inScope);
+ AUElement *elementWithMostParameters = NULL;
+ UInt32 maxNumParams = 0;
+
+ int nElems = scope.GetNumberOfElements();
+ for (int ielem = 0; ielem < nElems; ++ielem) {
+ AUElement *element = scope.GetElement(ielem);
+ UInt32 nParams = element->GetNumberOfParameters();
+ if (nParams > maxNumParams) {
+ maxNumParams = nParams;
+ elementWithMostParameters = element;
+ }
+ }
+
+ if (outParameterList != NULL && elementWithMostParameters != NULL)
+ elementWithMostParameters->GetParameterList(outParameterList);
+
+ outNumParameters = maxNumParams;
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::GetParameterInfo( AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ AudioUnitParameterInfo &outParameterInfo )
+{
+ return kAudioUnitErr_InvalidParameter;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::GetParameterValueStrings(AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ CFArrayRef * outStrings)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::GetParameterHistoryInfo( AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ Float32 & outUpdatesPerSecond,
+ Float32 & outHistoryDurationInSeconds)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUBase::CopyClumpName( AudioUnitScope inScope,
+ UInt32 inClumpID,
+ UInt32 inDesiredNameLength,
+ CFStringRef * outClumpName)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::SetNumberOfElements( AudioUnitScope inScope,
+ UInt32 numElements)
+{
+ if (inScope == kAudioUnitScope_Global && numElements != 1)
+ COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+
+ GetScope(inScope).SetNumberOfElements(numElements);
+}
+
+//_____________________________________________________________________________
+//
+AUElement * AUBase::CreateElement( AudioUnitScope scope,
+ AudioUnitElement element)
+{
+ switch (scope) {
+ case kAudioUnitScope_Global:
+ return new AUElement(this);
+ case kAudioUnitScope_Input:
+ return new AUInputElement(this);
+ case kAudioUnitScope_Output:
+ return new AUOutputElement(this);
+#if !CA_BASIC_AU_FEATURES
+ case kAudioUnitScope_Group:
+ return new AUElement(this);
+ case kAudioUnitScope_Part:
+ return new AUElement(this);
+#endif
+ }
+ COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+
+ return NULL; // get rid of compiler warning
+}
+
+//_____________________________________________________________________________
+//
+bool AUBase::FormatIsCanonical( const CAStreamBasicDescription &f)
+{
+ return (f.mFormatID == kAudioFormatLinearPCM
+ && f.mFramesPerPacket == 1
+ && f.mBytesPerPacket == f.mBytesPerFrame
+// && f.mChannelsPerFrame >= 0 -- this is always true since it's unsigned
+ // so far, it's a valid PCM format
+#if CA_PREFER_FIXED_POINT
+ && (f.mFormatFlags & kLinearPCMFormatFlagIsFloat) == 0
+ && (((f.mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift) == kAudioUnitSampleFractionBits)
+#else
+ && (f.mFormatFlags & kLinearPCMFormatFlagIsFloat) != 0
+#endif
+ && ((f.mChannelsPerFrame == 1) || ((f.mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0) == (mAudioUnitAPIVersion == 1))
+#if TARGET_RT_BIG_ENDIAN
+ && (f.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) != 0
+#else
+ && (f.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) == 0
+#endif
+ && f.mBitsPerChannel == 8 * sizeof(AudioUnitSampleType)
+ && f.mBytesPerFrame == f.NumberInterleavedChannels() * sizeof(AudioUnitSampleType)
+ );
+}
+
+//_____________________________________________________________________________
+//
+void AUBase::MakeCanonicalFormat( CAStreamBasicDescription & f,
+ int nChannels)
+{
+ f.SetAUCanonical(nChannels, mAudioUnitAPIVersion < 2); // interleaved for v1, non for v2
+ f.mSampleRate = 0.0;
+}
+
+const Float64 AUBase::kNoLastRenderedSampleTime = -1.;
+
+#include "AUBaseHelper.h"
+
+char* AUBase::GetLoggingString () const
+{
+ if (mLogString) return mLogString;
+
+ AudioComponentDescription desc = GetComponentDescription();
+
+ const size_t logStringSize = 256;
+ const_cast<AUBase*>(this)->mLogString = new char[logStringSize];
+ char str[24];
+ char str1[24];
+ char str2[24];
+ snprintf (const_cast<AUBase*>(this)->mLogString, logStringSize, "AU (%p): %s %s %s",
+ GetComponentInstance(),
+ CAStringForOSType(desc.componentType, str, sizeof(str)),
+ CAStringForOSType(desc.componentSubType, str1, sizeof(str1)),
+ CAStringForOSType(desc.componentManufacturer, str2, sizeof(str2)));
+
+ return mLogString;
+}
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.h
new file mode 100644
index 0000000000..0c78221cc8
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUBase.h
@@ -0,0 +1,1048 @@
+/*
+ File: AUBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUBase_h__
+#define __AUBase_h__
+
+#include <TargetConditionals.h>
+
+#if TARGET_OS_MAC
+ #include <pthread.h>
+#elif TARGET_OS_WIN32
+ #include <windows.h>
+#else
+ #error Unsupported Operating System
+#endif
+
+#include <vector>
+
+#include "AUScopeElement.h"
+#include "AUInputElement.h"
+#include "AUOutputElement.h"
+#include "AUBuffer.h"
+#include "CAMath.h"
+#include "CAThreadSafeList.h"
+#include "CAVectorUnit.h"
+#include "CAMutex.h"
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnit.h>
+ #if !CA_BASIC_AU_FEATURES
+ #include <AudioUnit/MusicDevice.h>
+ #endif
+#else
+ #include "AudioUnit.h"
+ #if !CA_BASIC_AU_FEATURES
+ #include "MusicDevice.h"
+ #endif
+#endif
+
+#ifndef AUTRACE
+ #define AUTRACE(code, obj, a, b, c, d)
+#endif
+
+#include "AUPlugInDispatch.h"
+
+
+
+// ________________________________________________________________________
+// These are to be moved to the public AudioUnit headers
+
+#define kAUDefaultSampleRate 44100.0
+#if !TARGET_OS_WIN32
+#define kAUDefaultMaxFramesPerSlice 1156
+//this allows enough default frames for a 512 dest 44K and SRC from 96K
+// add a padding of 4 frames for any altivec rounding
+#else
+#define kAUDefaultMaxFramesPerSlice 2048
+#endif
+
+// ________________________________________________________________________
+
+/*! @class AUBase */
+class AUBase : public ComponentBase {
+public:
+
+ /*! @ctor AUBase */
+ AUBase( AudioComponentInstance inInstance,
+ UInt32 numInputElements,
+ UInt32 numOutputElements,
+ UInt32 numGroupElements = 0);
+ /*! @dtor AUBase */
+ virtual ~AUBase();
+
+ /*! @method PostConstructor */
+ virtual void PostConstructor() { CreateElements(); }
+
+ /*! @method PreDestructor */
+ virtual void PreDestructor();
+
+ /*! @method CreateElements */
+ void CreateElements();
+ // Called immediately after construction, when virtual methods work.
+ // Or, a subclass may call this in order to have access to elements
+ // in its constructor.
+
+ /*! @method CreateExtendedElements */
+ virtual void CreateExtendedElements() {}
+
+#pragma mark -
+#pragma mark AU dispatch
+ // ________________________________________________________________________
+ // Virtual methods (mostly) directly corresponding to the entry points. Many of these
+ // have useful implementations here and will not need overriding.
+
+ /*! @method DoInitialize */
+ OSStatus DoInitialize();
+ // this implements the entry point and makes sure that initialization
+ // is only attempted exactly once...
+
+ /*! @method Initialize */
+ virtual OSStatus Initialize();
+ // ... so that overrides to this method can assume that they will only
+ // be called exactly once.
+
+ /*! @method IsInitialized */
+ bool IsInitialized() const { return mInitialized; }
+ /*! @method HasBegunInitializing */
+ bool HasBegunInitializing() const { return mHasBegunInitializing; }
+
+ /*! @method DoCleanup */
+ void DoCleanup();
+ // same pattern as with Initialize
+
+ /*! @method Cleanup */
+ virtual void Cleanup();
+
+ /*! @method Reset */
+ virtual OSStatus Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ // Note about GetPropertyInfo, GetProperty, SetProperty:
+ // Certain properties are trapped out in these dispatch functions and handled with different virtual
+ // methods. (To discourage hacks and keep vtable size down, these are non-virtual)
+
+ /*! @method DispatchGetPropertyInfo */
+ OSStatus DispatchGetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ /*! @method DispatchGetProperty */
+ OSStatus DispatchGetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+
+ /*! @method DispatchSetProperty */
+ OSStatus DispatchSetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+
+ OSStatus DispatchRemovePropertyValue( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ /*! @method GetPropertyInfo */
+ virtual OSStatus GetPropertyInfo( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ /*! @method GetProperty */
+ virtual OSStatus GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+
+ /*! @method SetProperty */
+ virtual OSStatus SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+
+ /*! @method ClearPropertyUsage */
+ virtual OSStatus RemovePropertyValue ( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ /*! @method AddPropertyListener */
+ virtual OSStatus AddPropertyListener( AudioUnitPropertyID inID,
+ AudioUnitPropertyListenerProc inProc,
+ void * inProcRefCon);
+
+ /*! @method RemovePropertyListener */
+ virtual OSStatus RemovePropertyListener( AudioUnitPropertyID inID,
+ AudioUnitPropertyListenerProc inProc,
+ void * inProcRefCon,
+ bool refConSpecified);
+
+ /*! @method SetRenderNotification */
+ virtual OSStatus SetRenderNotification( AURenderCallback inProc,
+ void * inRefCon);
+
+ /*! @method RemoveRenderNotification */
+ virtual OSStatus RemoveRenderNotification(
+ AURenderCallback inProc,
+ void * inRefCon);
+
+ /*! @method GetParameter */
+ virtual OSStatus GetParameter( AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioUnitParameterValue & outValue);
+
+ /*! @method SetParameter */
+ virtual OSStatus SetParameter( AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioUnitParameterValue inValue,
+ UInt32 inBufferOffsetInFrames);
+
+ /*! @method CanScheduleParams */
+ virtual bool CanScheduleParameters() const = 0;
+
+ /*! @method ScheduleParameter */
+ virtual OSStatus ScheduleParameter ( const AudioUnitParameterEvent *inParameterEvent,
+ UInt32 inNumEvents);
+
+
+ /*! @method DoRender */
+ OSStatus DoRender( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList & ioData);
+
+
+ /*! @method Process */
+ OSStatus DoProcess ( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inFramesToProcess,
+ AudioBufferList & ioData);
+
+ /*! @method ProcessMultiple */
+ OSStatus DoProcessMultiple ( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inFramesToProcess,
+ UInt32 inNumberInputBufferLists,
+ const AudioBufferList ** inInputBufferLists,
+ UInt32 inNumberOutputBufferLists,
+ AudioBufferList ** ioOutputBufferLists);
+
+ /*! @method ProcessBufferLists */
+ virtual OSStatus ProcessBufferLists( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioBufferList & inBuffer,
+ AudioBufferList & outBuffer,
+ UInt32 inFramesToProcess )
+ {
+ return kAudio_UnimplementedError;
+ }
+
+ /*! @method ProcessMultipleBufferLists */
+ virtual OSStatus ProcessMultipleBufferLists( AudioUnitRenderActionFlags & ioActionFlags,
+ UInt32 inFramesToProcess,
+ UInt32 inNumberInputBufferLists,
+ const AudioBufferList ** inInputBufferLists,
+ UInt32 inNumberOutputBufferLists,
+ AudioBufferList ** ioOutputBufferLists)
+ {
+ return kAudio_UnimplementedError;
+ }
+
+ /*! @method ComplexRender */
+ virtual OSStatus ComplexRender( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inOutputBusNumber,
+ UInt32 inNumberOfPackets,
+ UInt32 * outNumberOfPackets,
+ AudioStreamPacketDescription * outPacketDescriptions,
+ AudioBufferList & ioData,
+ void * outMetadata,
+ UInt32 * outMetadataByteSize)
+ {
+ return kAudio_UnimplementedError;
+ }
+
+ // Override this method if your AU processes multiple output busses completely independently --
+ // you'll want to just call Render without the NeedsToRender check.
+ // Otherwise, override Render().
+ //
+ // N.B. Implementations of this method can assume that the output's buffer list has already been
+ // prepared and access it with GetOutput(inBusNumber)->GetBufferList() instead of
+ // GetOutput(inBusNumber)->PrepareBuffer(nFrames) -- if PrepareBuffer is called, a
+ // copy may occur after rendering.
+ /*! @method RenderBus */
+ virtual OSStatus RenderBus( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames)
+ {
+ if (NeedsToRender(inTimeStamp))
+ return Render(ioActionFlags, inTimeStamp, inNumberFrames);
+ return noErr; // was presumably already rendered via another bus
+ }
+
+ // N.B. For a unit with only one output bus, it can assume in its implementation of this
+ // method that the output's buffer list has already been prepared and access it with
+ // GetOutput(0)->GetBufferList() instead of GetOutput(0)->PrepareBuffer(nFrames)
+ // -- if PrepareBuffer is called, a copy may occur after rendering.
+ /*! @method Render */
+ virtual OSStatus Render( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames)
+ {
+ return noErr;
+ }
+
+
+#pragma mark -
+#pragma mark Property Dispatch
+
+ static const Float64 kNoLastRenderedSampleTime;
+
+ // ________________________________________________________________________
+ // These are generated from DispatchGetProperty/DispatchGetPropertyInfo/DispatchSetProperty
+
+ /*! @method BusCountWritable */
+ virtual bool BusCountWritable( AudioUnitScope inScope)
+ {
+ return false;
+ }
+ virtual OSStatus SetBusCount( AudioUnitScope inScope,
+ UInt32 inCount);
+
+ /*! @method SetConnection */
+ virtual OSStatus SetConnection( const AudioUnitConnection & inConnection);
+
+ /*! @method SetInputCallback */
+ virtual OSStatus SetInputCallback( UInt32 inPropertyID,
+ AudioUnitElement inElement,
+ AURenderCallback inProc,
+ void * inRefCon);
+
+ /*! @method GetParameterList */
+ virtual OSStatus GetParameterList( AudioUnitScope inScope,
+ AudioUnitParameterID * outParameterList,
+ UInt32 & outNumParameters);
+ // outParameterList may be a null pointer
+
+ /*! @method GetParameterInfo */
+ virtual OSStatus GetParameterInfo( AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ AudioUnitParameterInfo & outParameterInfo);
+
+ virtual OSStatus GetParameterHistoryInfo(AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ Float32 & outUpdatesPerSecond,
+ Float32 & outHistoryDurationInSeconds);
+
+ /*! @method SaveState */
+ virtual OSStatus SaveState( CFPropertyListRef * outData);
+
+ /*! @method SaveExtendedScopes */
+ virtual void SaveExtendedScopes( CFMutableDataRef outData) {};
+
+ /*! @method RestoreState */
+ virtual OSStatus RestoreState( CFPropertyListRef inData);
+
+ /*! @method GetParameterValueStrings */
+ virtual OSStatus GetParameterValueStrings(AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ CFArrayRef * outStrings);
+
+ /*! @method CopyClumpName */
+ virtual OSStatus CopyClumpName( AudioUnitScope inScope,
+ UInt32 inClumpID,
+ UInt32 inDesiredNameLength,
+ CFStringRef * outClumpName);
+
+ /*! @method GetPresets */
+ virtual OSStatus GetPresets ( CFArrayRef * outData) const;
+
+ // set the default preset for the unit -> the number of the preset MUST be >= 0
+ // and the name should be valid, or the preset WON'T take
+ /*! @method SetAFactoryPresetAsCurrent */
+ bool SetAFactoryPresetAsCurrent (const AUPreset & inPreset);
+
+ // Called when someone sets a new, valid preset
+ // If this is a valid preset, then the subclass sets its state to that preset
+ // and returns noErr.
+ // If not a valid preset, return an error, and the pre-existing preset is restored
+ /*! @method NewFactoryPresetSet */
+ virtual OSStatus NewFactoryPresetSet (const AUPreset & inNewFactoryPreset);
+
+ /*! @method NewCustomPresetSet */
+ virtual OSStatus NewCustomPresetSet (const AUPreset & inNewCustomPreset);
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ /*! @method GetNumCustomUIComponents */
+ virtual int GetNumCustomUIComponents ();
+
+ /*! @method GetUIComponentDescs */
+ virtual void GetUIComponentDescs (ComponentDescription* inDescArray);
+#endif
+
+ /*! @method CopyIconLocation */
+ virtual CFURLRef CopyIconLocation ();
+
+ // default is no latency, and unimplemented tail time
+ /*! @method GetLatency */
+ virtual Float64 GetLatency() {return 0.0;}
+ /*! @method GetTailTime */
+ virtual Float64 GetTailTime() {return 0;}
+ /*! @method SupportsRampAndTail */
+ virtual bool SupportsTail () { return false; }
+
+ /*! @method IsStreamFormatWritable */
+ bool IsStreamFormatWritable( AudioUnitScope scope,
+ AudioUnitElement element);
+
+ /*! @method StreamFormatWritable */
+ virtual bool StreamFormatWritable( AudioUnitScope scope,
+ AudioUnitElement element) = 0;
+ // scope will always be input or output
+
+ // pass in a pointer to get the struct, and num channel infos
+ // you can pass in NULL to just get the number
+ // a return value of 0 (the default in AUBase) means the property is not supported...
+ /*! @method SupportedNumChannels */
+ virtual UInt32 SupportedNumChannels ( const AUChannelInfo** outInfo);
+
+ /*! @method ValidFormat */
+ virtual bool ValidFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inNewFormat);
+ // Will only be called after StreamFormatWritable
+ // has succeeded.
+ // Default implementation requires canonical format:
+ // native-endian 32-bit float, any sample rate,
+ // any number of channels; override when other
+ // formats are supported. A subclass's override can
+ // choose to always return true and trap invalid
+ // formats in ChangeStreamFormat.
+
+
+ /*! @method FormatIsCanonical */
+ bool FormatIsCanonical( const CAStreamBasicDescription &format);
+
+ /*! @method MakeCanonicalFormat */
+ void MakeCanonicalFormat( CAStreamBasicDescription & outDesc,
+ int numChannels = 2);
+
+ /*! @method GetStreamFormat */
+ virtual const CAStreamBasicDescription &
+ GetStreamFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ /*! @method ChangeStreamFormat */
+ virtual OSStatus ChangeStreamFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inPrevFormat,
+ const CAStreamBasicDescription & inNewFormat);
+ // Will only be called after StreamFormatWritable
+ // and ValidFormat have succeeded.
+
+ // ________________________________________________________________________
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch( ComponentParameters * params,
+ AUBase * This);
+#endif
+
+ // ________________________________________________________________________
+ // Methods useful for subclasses
+
+ /*! @method GetScope */
+ AUScope & GetScope( AudioUnitScope inScope)
+ {
+ if (inScope >= kNumScopes) {
+ AUScope * scope = GetScopeExtended(inScope);
+ if (!scope) COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+ return *scope;
+ }
+ return mScopes[inScope];
+ }
+
+ /*! @method GetScopeExtended */
+ virtual AUScope * GetScopeExtended (AudioUnitScope inScope) { return NULL; }
+
+ /*! @method GlobalScope */
+ AUScope & GlobalScope() { return mScopes[kAudioUnitScope_Global]; }
+ /*! @method Inputs */
+ AUScope & Inputs() { return mScopes[kAudioUnitScope_Input]; }
+ /*! @method Outputs */
+ AUScope & Outputs() { return mScopes[kAudioUnitScope_Output]; }
+#if !CA_BASIC_AU_FEATURES
+ /*! @method Groups */
+ AUScope & Groups() { return mScopes[kAudioUnitScope_Group]; }
+#endif
+ /*! @method Globals */
+ AUElement * Globals() { return mScopes[kAudioUnitScope_Global].GetElement(0); }
+
+ /*! @method SetNumberOfElements */
+ void SetNumberOfElements( AudioUnitScope inScope,
+ UInt32 numElements);
+
+ /*! @method GetElement */
+ AUElement * GetElement( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+ {
+ return GetScope(inScope).GetElement(inElement);
+ }
+
+ /*! @method GetIOElement */
+ AUIOElement * GetIOElement( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+ {
+ return GetScope(inScope).GetIOElement(inElement);
+ }
+
+ /*! @method SafeGetElement */
+ AUElement * SafeGetElement( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+ {
+ return GetScope(inScope).SafeGetElement(inElement);
+ }
+
+ /*! @method GetInput */
+ AUInputElement * GetInput( AudioUnitElement inElement)
+ {
+ return static_cast<AUInputElement *>(Inputs().SafeGetElement(inElement));
+ }
+
+ /*! @method GetOutput */
+ AUOutputElement * GetOutput( AudioUnitElement inElement)
+ {
+ return static_cast<AUOutputElement *>(Outputs().SafeGetElement(inElement));
+ }
+
+#if !CA_BASIC_AU_FEATURES
+ /*! @method GetGroup */
+ AUElement * GetGroup( AudioUnitElement inElement)
+ {
+ return Groups().SafeGetElement(inElement);
+ }
+#endif
+
+ /*! @method PullInput */
+ OSStatus PullInput( UInt32 inBusNumber,
+ AudioUnitRenderActionFlags &ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames)
+ {
+ AUInputElement *input = GetInput(inBusNumber); // throws if error
+ return input->PullInput(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
+ }
+
+ /*! @method GetMaxFramesPerSlice */
+ UInt32 GetMaxFramesPerSlice() const { return mMaxFramesPerSlice; }
+ /*! @method UsesFixedBlockSize */
+ bool UsesFixedBlockSize() const { return mUsesFixedBlockSize; }
+ /*! @method SetUsesFixedBlockSize */
+ void SetUsesFixedBlockSize(bool inUsesFixedBlockSize) { mUsesFixedBlockSize = inUsesFixedBlockSize; }
+
+ /*! @method GetVectorUnitType */
+ static SInt32 GetVectorUnitType() { return sVectorUnitType; }
+ /*! @method HasVectorUnit */
+ static bool HasVectorUnit() { return sVectorUnitType > 0; }
+ /*! @method HasAltivec */
+ static bool HasAltivec() { return sVectorUnitType == kVecAltivec; }
+ /*! @method HasSSE2 */
+ static bool HasSSE2() { return sVectorUnitType >= kVecSSE2; }
+ /*! @method HasSSE3 */
+ static bool HasSSE3() { return sVectorUnitType >= kVecSSE3; }
+
+ /*! @method AudioUnitAPIVersion */
+ UInt8 AudioUnitAPIVersion() const { return mAudioUnitAPIVersion; }
+
+ /*! @method IsRenderThread */
+ bool InRenderThread () const
+ {
+#if TARGET_OS_MAC
+ return (mRenderThreadID ? pthread_equal (mRenderThreadID, pthread_self()) : false);
+#elif TARGET_OS_WIN32
+ return (mRenderThreadID ? mRenderThreadID == GetCurrentThreadId() : false);
+#endif
+ }
+
+ /*! @method HasInput */
+ bool HasInput( AudioUnitElement inElement) {
+ AUInputElement *in = static_cast<AUInputElement *>(Inputs().GetElement(inElement));
+ return in != NULL && in->IsActive();
+ }
+ // says whether an input is connected or has a callback
+
+ /*! @method PropertyChanged */
+ virtual void PropertyChanged( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+#if !CA_NO_AU_UI_FEATURES
+ // These calls can be used to call a Host's Callbacks. The method returns -1 if the host
+ // hasn't supplied the callback. Any other result is returned by the host.
+ // As in the API contract, for a parameter's value, you specify a pointer
+ // to that data type. Specify NULL for a parameter that you are not interested
+ // as this can save work in the host.
+
+ /*! @method CallHostBeatAndTempo */
+ OSStatus CallHostBeatAndTempo (Float64 *outCurrentBeat,
+ Float64 *outCurrentTempo)
+ {
+ return (mHostCallbackInfo.beatAndTempoProc
+ ? (*mHostCallbackInfo.beatAndTempoProc) (mHostCallbackInfo.hostUserData,
+ outCurrentBeat,
+ outCurrentTempo)
+ : -1);
+ }
+
+ /*! @method CallHostMusicalTimeLocation */
+ OSStatus CallHostMusicalTimeLocation (UInt32 *outDeltaSampleOffsetToNextBeat,
+ Float32 *outTimeSig_Numerator,
+ UInt32 *outTimeSig_Denominator,
+ Float64 *outCurrentMeasureDownBeat)
+ {
+ return (mHostCallbackInfo.musicalTimeLocationProc
+ ? (*mHostCallbackInfo.musicalTimeLocationProc) (mHostCallbackInfo.hostUserData,
+ outDeltaSampleOffsetToNextBeat,
+ outTimeSig_Numerator,
+ outTimeSig_Denominator,
+ outCurrentMeasureDownBeat)
+ : -1);
+ }
+
+ /*! @method CallHostTransportState */
+ OSStatus CallHostTransportState (Boolean *outIsPlaying,
+ Boolean *outTransportStateChanged,
+ Float64 *outCurrentSampleInTimeLine,
+ Boolean *outIsCycling,
+ Float64 *outCycleStartBeat,
+ Float64 *outCycleEndBeat)
+ {
+ return (mHostCallbackInfo.transportStateProc
+ ? (*mHostCallbackInfo.transportStateProc) (mHostCallbackInfo.hostUserData,
+ outIsPlaying,
+ outTransportStateChanged,
+ outCurrentSampleInTimeLine,
+ outIsCycling,
+ outCycleStartBeat,
+ outCycleEndBeat)
+ : -1);
+ }
+#endif
+
+ char* GetLoggingString () const;
+
+ CAMutex* GetMutex() { return mAUMutex; }
+
+ // ________________________________________________________________________
+ /*! @method CreateElement */
+ virtual AUElement * CreateElement( AudioUnitScope scope,
+ AudioUnitElement element);
+
+#pragma mark -
+#pragma mark AU Output Base Dispatch
+ // ________________________________________________________________________
+ // ________________________________________________________________________
+ // ________________________________________________________________________
+ // output unit methods
+ /*! @method Start */
+ virtual OSStatus Start() { return kAudio_UnimplementedError; }
+ /*! @method Stop */
+ virtual OSStatus Stop() { return kAudio_UnimplementedError; }
+
+#if !CA_BASIC_AU_FEATURES
+#pragma mark -
+#pragma mark AU Music Base Dispatch
+
+#if !TARGET_OS_IPHONE
+// these methods are deprecated, so we don't include them except for compatability
+ /*! @method PrepareInstrument */
+ virtual OSStatus PrepareInstrument(MusicDeviceInstrumentID inInstrument) { return kAudio_UnimplementedError; }
+
+ /*! @method PrepareInstrument */
+ virtual OSStatus ReleaseInstrument(MusicDeviceInstrumentID inInstrument) { return kAudio_UnimplementedError; }
+#endif
+
+ // ________________________________________________________________________
+ // ________________________________________________________________________
+ // ________________________________________________________________________
+ // music device/music effect methods -- incomplete
+ /*! @method MIDIEvent */
+ virtual OSStatus MIDIEvent( UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame) { return kAudio_UnimplementedError; }
+
+ /*! @method SysEx */
+ virtual OSStatus SysEx( const UInt8 * inData,
+ UInt32 inLength) { return kAudio_UnimplementedError;}
+
+ /*! @method StartNote */
+ virtual OSStatus StartNote( MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams) { return kAudio_UnimplementedError; }
+
+ /*! @method StopNote */
+ virtual OSStatus StopNote( MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame) { return kAudio_UnimplementedError; }
+#endif
+
+ // ________________________________________________________________________
+ // ________________________________________________________________________
+ // ________________________________________________________________________
+
+protected:
+#pragma mark -
+#pragma mark Implementation methods
+
+ /*! @method ReallocateBuffers */
+ virtual void ReallocateBuffers();
+ // needs to be called when mMaxFramesPerSlice changes
+ virtual void DeallocateIOBuffers();
+
+ /*! @method FillInParameterName */
+ static void FillInParameterName (AudioUnitParameterInfo& ioInfo, CFStringRef inName, bool inShouldRelease)
+ {
+ ioInfo.cfNameString = inName;
+ ioInfo.flags |= kAudioUnitParameterFlag_HasCFNameString;
+ if (inShouldRelease)
+ ioInfo.flags |= kAudioUnitParameterFlag_CFNameRelease;
+ CFStringGetCString (inName, ioInfo.name, offsetof (AudioUnitParameterInfo, clumpID), kCFStringEncodingUTF8);
+ }
+
+ static void HasClump (AudioUnitParameterInfo& ioInfo, UInt32 inClumpID)
+ {
+ ioInfo.clumpID = inClumpID;
+ ioInfo.flags |= kAudioUnitParameterFlag_HasClump;
+ }
+
+ /*! @method SetMaxFramesPerSlice */
+ virtual void SetMaxFramesPerSlice(UInt32 nFrames);
+
+ /*! @method CanSetMaxFrames */
+ virtual OSStatus CanSetMaxFrames() const;
+
+ /*! @method WantsRenderThreadID */
+ bool WantsRenderThreadID () const { return mWantsRenderThreadID; }
+
+ /*! @method SetWantsRenderThreadID */
+ void SetWantsRenderThreadID (bool inFlag);
+
+ /*! @method SetRenderError */
+ OSStatus SetRenderError (OSStatus inErr)
+ {
+ if (inErr && mLastRenderError == 0) {
+ mLastRenderError = inErr;
+ PropertyChanged(kAudioUnitProperty_LastRenderError, kAudioUnitScope_Global, 0);
+ }
+ return inErr;
+ }
+
+private:
+ /*! @method DoRenderBus */
+ // shared between Render and RenderSlice, inlined to minimize function call overhead
+ OSStatus DoRenderBus( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inBusNumber,
+ AUOutputElement * theOutput,
+ UInt32 inNumberFrames,
+ AudioBufferList & ioData)
+ {
+ if (ioData.mBuffers[0].mData == NULL || (theOutput->WillAllocateBuffer() && Outputs().GetNumberOfElements() > 1))
+ // will render into cache buffer
+ theOutput->PrepareBuffer(inNumberFrames);
+ else
+ // will render into caller's buffer
+ theOutput->SetBufferList(ioData);
+ OSStatus result = RenderBus(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
+ if (result == noErr) {
+ if (ioData.mBuffers[0].mData == NULL) {
+ theOutput->CopyBufferListTo(ioData);
+ AUTRACE(kCATrace_AUBaseDoRenderBus, mComponentInstance, inNumberFrames, (intptr_t)theOutput->GetBufferList().mBuffers[0].mData, 0, *(UInt32 *)ioData.mBuffers[0].mData);
+ } else {
+ theOutput->CopyBufferContentsTo(ioData);
+ AUTRACE(kCATrace_AUBaseDoRenderBus, mComponentInstance, inNumberFrames, (intptr_t)theOutput->GetBufferList().mBuffers[0].mData, (intptr_t)ioData.mBuffers[0].mData, *(UInt32 *)ioData.mBuffers[0].mData);
+ theOutput->InvalidateBufferList();
+ }
+ }
+ return result;
+ }
+
+ /*! @method HasIcon */
+ bool HasIcon ();
+
+ /*! @method ResetRenderTime */
+ void ResetRenderTime ()
+ {
+ memset (&mCurrentRenderTime, 0, sizeof(mCurrentRenderTime));
+ mCurrentRenderTime.mSampleTime = kNoLastRenderedSampleTime;
+ }
+
+protected:
+ /*! @method GetAudioChannelLayout */
+ virtual UInt32 GetChannelLayoutTags( AudioUnitScope scope,
+ AudioUnitElement element,
+ AudioChannelLayoutTag * outLayoutTags);
+
+ /*! @method GetAudioChannelLayout */
+ virtual UInt32 GetAudioChannelLayout( AudioUnitScope scope,
+ AudioUnitElement element,
+ AudioChannelLayout * outLayoutPtr,
+ Boolean & outWritable);
+
+ /*! @method SetAudioChannelLayout */
+ virtual OSStatus SetAudioChannelLayout( AudioUnitScope scope,
+ AudioUnitElement element,
+ const AudioChannelLayout * inLayout);
+
+ /*! @method RemoveAudioChannelLayout */
+ virtual OSStatus RemoveAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element);
+
+ /*! @method NeedsToRender */
+ bool NeedsToRender( const AudioTimeStamp & inTimeStamp)
+ {
+ bool needsToRender = fnotequal(inTimeStamp.mSampleTime, mCurrentRenderTime.mSampleTime);
+ if (needsToRender) // only copy this if we need to render
+ mCurrentRenderTime = inTimeStamp;
+ return needsToRender;
+ }
+
+ // Scheduled parameter implementation:
+
+ typedef std::vector<AudioUnitParameterEvent> ParameterEventList;
+
+ // Usually, you won't override this method. You only need to call this if your DSP code
+ // is prepared to handle scheduled immediate and ramped parameter changes.
+ // Before calling this method, it is assumed you have already called PullInput() on the input busses
+ // for which the DSP code depends. ProcessForScheduledParams() will call (potentially repeatedly)
+ // virtual method ProcessScheduledSlice() to perform the actual DSP for a given sub-division of
+ // the buffer. The job of ProcessForScheduledParams() is to sub-divide the buffer into smaller
+ // pieces according to the scheduled times found in the ParameterEventList (usually coming
+ // directly from a previous call to ScheduleParameter() ), setting the appropriate immediate or
+ // ramped parameter values for the corresponding scopes and elements, then calling ProcessScheduledSlice()
+ // to do the actual DSP for each of these divisions.
+ virtual OSStatus ProcessForScheduledParams( ParameterEventList &inParamList,
+ UInt32 inFramesToProcess,
+ void *inUserData );
+
+ // This method is called (potentially repeatedly) by ProcessForScheduledParams()
+ // in order to perform the actual DSP required for this portion of the entire buffer
+ // being processed. The entire buffer can be divided up into smaller "slices"
+ // according to the timestamps on the scheduled parameters...
+ //
+ // sub-classes wishing to handle scheduled parameter changes should override this method
+ // in order to do the appropriate DSP. AUEffectBase already overrides this for standard
+ // effect AudioUnits.
+ virtual OSStatus ProcessScheduledSlice( void *inUserData,
+ UInt32 inStartFrameInBuffer,
+ UInt32 inSliceFramesToProcess,
+ UInt32 inTotalBufferFrames ) {return noErr;}; // default impl does nothing...
+
+
+ /*! @method CurrentRenderTime */
+ const AudioTimeStamp & CurrentRenderTime () const { return mCurrentRenderTime; }
+
+ // ________________________________________________________________________
+ // Private data members to discourage hacking in subclasses
+private:
+ struct RenderCallback {
+ RenderCallback(AURenderCallback proc, void *ref) :
+ mRenderNotify(proc),
+ mRenderNotifyRefCon(ref)
+ { }
+
+ AURenderCallback mRenderNotify;
+ void * mRenderNotifyRefCon;
+
+ bool operator == (const RenderCallback &other) {
+ return this->mRenderNotify == other.mRenderNotify &&
+ this->mRenderNotifyRefCon == other.mRenderNotifyRefCon;
+ }
+ };
+ typedef TThreadSafeList<RenderCallback> RenderCallbackList;
+
+#if !CA_BASIC_AU_FEATURES
+ enum { kNumScopes = 4 };
+#else
+ enum { kNumScopes = 3 };
+#endif
+
+ /*! @var mElementsCreated */
+ bool mElementsCreated;
+protected:
+ /*! @var mInitialized */
+ bool mInitialized;
+ /*! @var mHasBegunInitializing */
+ bool mHasBegunInitializing;
+private:
+ /*! @var mAudioUnitAPIVersion */
+ UInt8 mAudioUnitAPIVersion;
+
+ /*! @var mInitNumInputEls */
+ const UInt32 mInitNumInputEls;
+ /*! @var mInitNumOutputEls */
+ const UInt32 mInitNumOutputEls;
+#if !CA_BASIC_AU_FEATURES
+ /*! @var mInitNumGroupEls */
+ const UInt32 mInitNumGroupEls;
+#endif
+ /*! @var mScopes */
+ AUScope mScopes[kNumScopes];
+
+ /*! @var mRenderCallbacks */
+ RenderCallbackList mRenderCallbacks;
+ bool mRenderCallbacksTouched;
+
+ /*! @var mRenderThreadID */
+#if TARGET_OS_MAC
+ pthread_t mRenderThreadID;
+#elif TARGET_OS_WIN32
+ UInt32 mRenderThreadID;
+#endif
+
+ /*! @var mWantsRenderThreadID */
+ bool mWantsRenderThreadID;
+
+ /*! @var mCurrentRenderTime */
+ AudioTimeStamp mCurrentRenderTime;
+
+ /*! @var mMaxFramesPerSlice */
+ UInt32 mMaxFramesPerSlice;
+
+ /*! @var mLastRenderError */
+ OSStatus mLastRenderError;
+ /*! @var mCurrentPreset */
+ AUPreset mCurrentPreset;
+
+protected:
+ /*! @var mUsesFixedBlockSize */
+ bool mUsesFixedBlockSize;
+
+ struct PropertyListener {
+ AudioUnitPropertyID propertyID;
+ AudioUnitPropertyListenerProc listenerProc;
+ void * listenerRefCon;
+ };
+ typedef std::vector<PropertyListener> PropertyListeners;
+
+ /*! @var mParamList */
+ ParameterEventList mParamList;
+ /*! @var mPropertyListeners */
+ PropertyListeners mPropertyListeners;
+
+ /*! @var mBuffersAllocated */
+ bool mBuffersAllocated;
+
+ /*! @var mLogString */
+ // if this is NOT null, it will contain identifying info about this AU.
+ char* mLogString;
+
+ /*! @var mNickName */
+ CFStringRef mNickName;
+
+ /*! @var mAUMutex */
+ CAMutex * mAUMutex;
+
+private:
+ /*! @var sVectorUnitType */
+ static SInt32 sVectorUnitType;
+
+#if !CA_NO_AU_HOST_CALLBACKS
+protected:
+ /*! @var mHostCallbackInfo */
+ HostCallbackInfo mHostCallbackInfo;
+
+#endif
+#if !CA_NO_AU_UI_FEATURES
+protected:
+ /*! @var mContextInfo */
+ CFStringRef mContextName;
+#endif
+};
+
+inline OSStatus AUInputElement::PullInputWithBufferList(
+ AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ AudioUnitElement inElement,
+ UInt32 nFrames,
+ AudioBufferList * inBufferList)
+{
+ OSStatus theResult;
+
+ if (HasConnection()) {
+ // only support connections for V2 audio units
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ if (mConnRenderProc != NULL)
+ theResult = reinterpret_cast<AudioUnitRenderProc>(mConnRenderProc)(
+ mConnInstanceStorage, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
+ else
+#endif
+ theResult = AudioUnitRender(
+ mConnection.sourceAudioUnit, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
+ } else {
+ // kFromCallback:
+ theResult = (mInputProc)(
+ mInputProcRefCon, &ioActionFlags, &inTimeStamp, inElement, nFrames, inBufferList);
+ }
+
+ if (mInputType == kNoInput) // defense: the guy upstream could have disconnected
+ // it's a horrible thing to do, but may happen!
+ return kAudioUnitErr_NoConnection;
+
+
+ return theResult;
+}
+
+#endif // __AUBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.cpp
new file mode 100644
index 0000000000..1f0f01c7d5
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.cpp
@@ -0,0 +1,438 @@
+/*
+ File: AUDispatch.cpp
+ Abstract: AUDispatch.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUBase.h"
+#include "CAXException.h"
+#include "AUDispatch.h"
+
+
+
+#if TARGET_OS_MAC
+ #if __LP64__
+ // comp instance, parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index + 1];
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
+ #endif
+#elif TARGET_OS_WIN32
+ // (no comp instance), parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index];
+#endif
+
+
+OSStatus AUBase::ComponentEntryDispatch(ComponentParameters *params, AUBase *This)
+{
+ if (This == NULL) return kAudio_ParamError;
+
+ OSStatus result = noErr;
+
+ switch (params->what) {
+ case kComponentCanDoSelect:
+ switch (GetSelectorForCanDo(params)) {
+ // any selectors
+ case kAudioUnitInitializeSelect:
+ case kAudioUnitUninitializeSelect:
+ case kAudioUnitGetPropertyInfoSelect:
+ case kAudioUnitGetPropertySelect:
+ case kAudioUnitSetPropertySelect:
+ case kAudioUnitAddPropertyListenerSelect:
+#if (!__LP64__)
+ case kAudioUnitRemovePropertyListenerSelect:
+#endif
+ case kAudioUnitGetParameterSelect:
+ case kAudioUnitSetParameterSelect:
+ case kAudioUnitResetSelect:
+ result = 1;
+ break;
+ // v1 selectors
+
+ // v2 selectors
+ case kAudioUnitRemovePropertyListenerWithUserDataSelect:
+ case kAudioUnitAddRenderNotifySelect:
+ case kAudioUnitRemoveRenderNotifySelect:
+ case kAudioUnitScheduleParametersSelect:
+ case kAudioUnitRenderSelect:
+ result = (This->AudioUnitAPIVersion() > 1);
+ break;
+
+ default:
+ return ComponentBase::ComponentEntryDispatch(params, This);
+ }
+ break;
+
+ case kAudioUnitInitializeSelect:
+ {
+ CAMutex::Locker lock2(This->GetMutex());
+ result = This->DoInitialize();
+ }
+ break;
+
+ case kAudioUnitUninitializeSelect:
+ {
+ CAMutex::Locker lock2(This->GetMutex());
+ This->DoCleanup();
+ result = noErr;
+ }
+ break;
+
+ case kAudioUnitGetPropertyInfoSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitPropertyID, pinID, 0, 5);
+ PARAM(AudioUnitScope, pinScope, 1, 5);
+ PARAM(AudioUnitElement, pinElement, 2, 5);
+ PARAM(UInt32 *, poutDataSize, 3, 5);
+ PARAM(Boolean *, poutWritable, 4, 5);
+
+ // pass our own copies so that we assume responsibility for testing
+ // the caller's pointers against null and our C++ classes can
+ // always assume they're non-null
+ UInt32 dataSize;
+ Boolean writable;
+
+ result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement, dataSize, writable);
+ if (poutDataSize != NULL)
+ *poutDataSize = dataSize;
+ if (poutWritable != NULL)
+ *poutWritable = writable;
+ }
+ break;
+
+ case kAudioUnitGetPropertySelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitPropertyID, pinID, 0, 5);
+ PARAM(AudioUnitScope, pinScope, 1, 5);
+ PARAM(AudioUnitElement, pinElement, 2, 5);
+ PARAM(void *, poutData, 3, 5);
+ PARAM(UInt32 *, pioDataSize, 4, 5);
+
+ UInt32 actualPropertySize, clientBufferSize;
+ Boolean writable;
+ char *tempBuffer;
+ void *destBuffer;
+
+ if (pioDataSize == NULL) {
+ ca_debug_string("AudioUnitGetProperty: null size pointer");
+ result = kAudio_ParamError;
+ goto finishGetProperty;
+ }
+ if (poutData == NULL) {
+ UInt32 dataSize;
+
+ result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement, dataSize, writable);
+ *pioDataSize = dataSize;
+ goto finishGetProperty;
+ }
+
+ clientBufferSize = *pioDataSize;
+ if (clientBufferSize == 0)
+ {
+ ca_debug_string("AudioUnitGetProperty: *ioDataSize == 0 on entry");
+ // $$$ or should we allow this as a shortcut for finding the size?
+ result = kAudio_ParamError;
+ goto finishGetProperty;
+ }
+
+ result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement,
+ actualPropertySize, writable);
+ if (result)
+ goto finishGetProperty;
+
+ if (clientBufferSize < actualPropertySize)
+ {
+ tempBuffer = new char[actualPropertySize];
+ destBuffer = tempBuffer;
+ } else {
+ tempBuffer = NULL;
+ destBuffer = poutData;
+ }
+
+ result = This->DispatchGetProperty(pinID, pinScope, pinElement, destBuffer);
+
+ if (result == noErr) {
+ if (clientBufferSize < actualPropertySize && tempBuffer != NULL)
+ {
+ memcpy(poutData, tempBuffer, clientBufferSize);
+ delete[] tempBuffer;
+ // pioDataSize remains correct, the number of bytes we wrote
+ } else
+ *pioDataSize = actualPropertySize;
+ } else
+ *pioDataSize = 0;
+
+ finishGetProperty:
+ ;
+
+ }
+ break;
+
+ case kAudioUnitSetPropertySelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitPropertyID, pinID, 0, 5);
+ PARAM(AudioUnitScope, pinScope, 1, 5);
+ PARAM(AudioUnitElement, pinElement, 2, 5);
+ PARAM(const void *, pinData, 3, 5);
+ PARAM(UInt32, pinDataSize, 4, 5);
+
+ if (pinData && pinDataSize)
+ result = This->DispatchSetProperty(pinID, pinScope, pinElement, pinData, pinDataSize);
+ else {
+ if (pinData == NULL && pinDataSize == 0) {
+ result = This->DispatchRemovePropertyValue (pinID, pinScope, pinElement);
+ } else {
+ if (pinData == NULL) {
+ ca_debug_string("AudioUnitSetProperty: inData == NULL");
+ result = kAudio_ParamError;
+ goto finishSetProperty;
+ }
+
+ if (pinDataSize == 0) {
+ ca_debug_string("AudioUnitSetProperty: inDataSize == 0");
+ result = kAudio_ParamError;
+ goto finishSetProperty;
+ }
+ }
+ }
+ finishSetProperty:
+ ;
+
+ }
+ break;
+
+ case kAudioUnitAddPropertyListenerSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitPropertyID, pinID, 0, 3);
+ PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 3);
+ PARAM(void *, pinProcRefCon, 2, 3);
+ result = This->AddPropertyListener(pinID, pinProc, pinProcRefCon);
+ }
+ break;
+
+#if (!__LP64__)
+ case kAudioUnitRemovePropertyListenerSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitPropertyID, pinID, 0, 2);
+ PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 2);
+ result = This->RemovePropertyListener(pinID, pinProc, NULL, false);
+ }
+ break;
+#endif
+
+ case kAudioUnitRemovePropertyListenerWithUserDataSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitPropertyID, pinID, 0, 3);
+ PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 3);
+ PARAM(void *, pinProcRefCon, 2, 3);
+ result = This->RemovePropertyListener(pinID, pinProc, pinProcRefCon, true);
+ }
+ break;
+
+ case kAudioUnitAddRenderNotifySelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AURenderCallback, pinProc, 0, 2);
+ PARAM(void *, pinProcRefCon, 1, 2);
+ result = This->SetRenderNotification (pinProc, pinProcRefCon);
+ }
+ break;
+
+ case kAudioUnitRemoveRenderNotifySelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AURenderCallback, pinProc, 0, 2);
+ PARAM(void *, pinProcRefCon, 1, 2);
+ result = This->RemoveRenderNotification (pinProc, pinProcRefCon);
+ }
+ break;
+
+ case kAudioUnitGetParameterSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitParameterID, pinID, 0, 4);
+ PARAM(AudioUnitScope, pinScope, 1, 4);
+ PARAM(AudioUnitElement, pinElement, 2, 4);
+ PARAM(AudioUnitParameterValue *, poutValue, 3, 4);
+ result = (poutValue == NULL ? kAudio_ParamError : This->GetParameter(pinID, pinScope, pinElement, *poutValue));
+ }
+ break;
+
+ case kAudioUnitSetParameterSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex()); // is this realtime or no???
+ PARAM(AudioUnitParameterID, pinID, 0, 5);
+ PARAM(AudioUnitScope, pinScope, 1, 5);
+ PARAM(AudioUnitElement, pinElement, 2, 5);
+ PARAM(AudioUnitParameterValue, pinValue, 3, 5);
+ PARAM(UInt32, pinBufferOffsetInFrames, 4, 5);
+ result = This->SetParameter(pinID, pinScope, pinElement, pinValue, pinBufferOffsetInFrames);
+ }
+ break;
+
+ case kAudioUnitScheduleParametersSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex()); // is this realtime or no???
+ if (This->AudioUnitAPIVersion() > 1)
+ {
+ PARAM(AudioUnitParameterEvent *, pinParameterEvent, 0, 2);
+ PARAM(UInt32, pinNumParamEvents, 1, 2);
+ result = This->ScheduleParameter (pinParameterEvent, pinNumParamEvents);
+ } else
+ result = badComponentSelector;
+ }
+ break;
+
+
+ case kAudioUnitRenderSelect:
+ {
+ // realtime; no lock
+ {
+ PARAM(AudioUnitRenderActionFlags *, pinActionFlags, 0, 5);
+ PARAM(const AudioTimeStamp *, pinTimeStamp, 1, 5);
+ PARAM(UInt32, pinOutputBusNumber, 2, 5);
+ PARAM(UInt32, pinNumberFrames, 3, 5);
+ PARAM(AudioBufferList *, pioData, 4, 5);
+ AudioUnitRenderActionFlags tempFlags;
+
+ if (pinTimeStamp == NULL || pioData == NULL)
+ result = kAudio_ParamError;
+ else {
+ if (pinActionFlags == NULL) {
+ tempFlags = 0;
+ pinActionFlags = &tempFlags;
+ }
+ result = This->DoRender(*pinActionFlags, *pinTimeStamp, pinOutputBusNumber, pinNumberFrames, *pioData);
+ }
+ }
+ }
+ break;
+
+ case kAudioUnitResetSelect:
+ {
+ CAMutex::Locker lock(This->GetMutex());
+ PARAM(AudioUnitScope, pinScope, 0, 2);
+ PARAM(AudioUnitElement, pinElement, 1, 2);
+ This->ResetRenderTime();
+ result = This->Reset(pinScope, pinElement);
+ }
+ break;
+
+ default:
+ result = ComponentBase::ComponentEntryDispatch(params, This);
+ break;
+ }
+
+ return result;
+}
+
+// Fast dispatch entry points -- these need to replicate all error-checking logic from above
+
+OSStatus CMgr_AudioUnitBaseGetParameter( AUBase * This,
+ AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ float *outValue)
+{
+ OSStatus result = AUBase::noErr;
+
+ try {
+ if (This == NULL || outValue == NULL) return kAudio_ParamError;
+ result = This->GetParameter(inID, inScope, inElement, *outValue);
+ }
+ COMPONENT_CATCH
+
+ return result;
+}
+
+OSStatus CMgr_AudioUnitBaseSetParameter( AUBase * This,
+ AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ float inValue,
+ UInt32 inBufferOffset)
+{
+ OSStatus result = AUBase::noErr;
+
+ try {
+ if (This == NULL) return kAudio_ParamError;
+ result = This->SetParameter(inID, inScope, inElement, inValue, inBufferOffset);
+ }
+ COMPONENT_CATCH
+
+ return result;
+}
+
+OSStatus CMgr_AudioUnitBaseRender( AUBase * This,
+ AudioUnitRenderActionFlags *ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList * ioData)
+{
+ if (inTimeStamp == NULL || ioData == NULL) return kAudio_ParamError;
+
+ OSStatus result = AUBase::noErr;
+ AudioUnitRenderActionFlags tempFlags;
+
+ try {
+ if (ioActionFlags == NULL) {
+ tempFlags = 0;
+ ioActionFlags = &tempFlags;
+ }
+ result = This->DoRender(*ioActionFlags, *inTimeStamp, inBusNumber, inNumberFrames, *ioData);
+ }
+ COMPONENT_CATCH
+
+ return result;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.h
new file mode 100644
index 0000000000..5acd96250a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUDispatch.h
@@ -0,0 +1,82 @@
+/*
+ File: AUDispatch.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUDispatch_h__
+#define __AUDispatch_h__
+
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnit.h>
+#else
+ #include "AudioUnit.h"
+#endif
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+/*! @function AudioUnitBaseGetParameter */
+OSStatus CMgr_AudioUnitBaseGetParameter( AUBase * This,
+ AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ float * outValue);
+
+/*! @function AudioUnitBaseSetParameter */
+OSStatus CMgr_AudioUnitBaseSetParameter( AUBase * This,
+ AudioUnitParameterID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ float inValue,
+ UInt32 inBufferOffset);
+
+/*! @function AudioUnitBaseRender */
+OSStatus CMgr_AudioUnitBaseRender( AUBase * This,
+ AudioUnitRenderActionFlags *ioActionFlags,
+ const AudioTimeStamp * inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList * ioData);
+#endif
+
+#endif // __AUDispatch_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.cpp
new file mode 100644
index 0000000000..2e148e8ba7
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.cpp
@@ -0,0 +1,151 @@
+/*
+ File: AUInputElement.cpp
+ Abstract: AUInputElement.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUBase.h"
+
+inline bool HasGoodBufferPointers(const AudioBufferList &abl, UInt32 nBytes)
+{
+ const AudioBuffer *buf = abl.mBuffers;
+ for (UInt32 i = abl.mNumberBuffers; i--;++buf) {
+ if (buf->mData == NULL || buf->mDataByteSize < nBytes)
+ return false;
+ }
+ return true;
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUInputElement::AUInputElement
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+AUInputElement::AUInputElement(AUBase *audioUnit) :
+ AUIOElement(audioUnit),
+ mInputType(kNoInput)
+{
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUInputElement::SetConnection
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void AUInputElement::SetConnection(const AudioUnitConnection &conn)
+{
+ if (conn.sourceAudioUnit == 0) {
+ Disconnect();
+ return;
+ }
+
+ mInputType = kFromConnection;
+ mConnection = conn;
+ AllocateBuffer();
+
+ mConnInstanceStorage = NULL;
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ mConnRenderProc = NULL;
+ UInt32 size = sizeof(AudioUnitRenderProc);
+ OSStatus result = AudioUnitGetProperty( conn.sourceAudioUnit,
+ kAudioUnitProperty_FastDispatch,
+ kAudioUnitScope_Global,
+ kAudioUnitRenderSelect,
+ &mConnRenderProc,
+ &size);
+ if (result == noErr)
+ mConnInstanceStorage = CMgr_GetComponentInstanceStorage (conn.sourceAudioUnit);
+ else
+ mConnRenderProc = NULL;
+#endif
+}
+
+void AUInputElement::Disconnect()
+{
+ mInputType = kNoInput;
+ mIOBuffer.Deallocate();
+}
+
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUInputElement::SetInputCallback
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void AUInputElement::SetInputCallback(AURenderCallback proc, void *refCon)
+{
+ if (proc == NULL)
+ Disconnect();
+ else {
+ mInputType = kFromCallback;
+ mInputProc = proc;
+ mInputProcRefCon = refCon;
+ AllocateBuffer();
+ }
+}
+
+OSStatus AUInputElement::SetStreamFormat(const CAStreamBasicDescription &fmt)
+{
+ OSStatus err = AUIOElement::SetStreamFormat(fmt);
+ if (err == AUBase::noErr)
+ AllocateBuffer();
+ return err;
+}
+
+OSStatus AUInputElement::PullInput( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ AudioUnitElement inElement,
+ UInt32 nFrames)
+{
+ if (!IsActive())
+ return kAudioUnitErr_NoConnection;
+
+ AudioBufferList *pullBuffer;
+
+ if (HasConnection() || !WillAllocateBuffer())
+ pullBuffer = &mIOBuffer.PrepareNullBuffer(mStreamFormat, nFrames);
+ else
+ pullBuffer = &mIOBuffer.PrepareBuffer(mStreamFormat, nFrames);
+
+ return PullInputWithBufferList (ioActionFlags, inTimeStamp, inElement, nFrames, pullBuffer);
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.h
new file mode 100644
index 0000000000..891e4c60b7
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUInputElement.h
@@ -0,0 +1,119 @@
+/*
+ File: AUInputElement.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUInput_h__
+#define __AUInput_h__
+
+#include "AUScopeElement.h"
+#include "AUBuffer.h"
+
+/*! @class AUInputElement */
+class AUInputElement : public AUIOElement {
+public:
+
+ /*! @ctor AUInputElement */
+ AUInputElement(AUBase *audioUnit);
+ /*! @dtor ~AUInputElement */
+ virtual ~AUInputElement() { }
+
+ // AUElement override
+ /*! @method SetStreamFormat */
+ virtual OSStatus SetStreamFormat(const CAStreamBasicDescription &desc);
+ /*! @method NeedsBufferSpace */
+ virtual bool NeedsBufferSpace() const { return IsCallback(); }
+
+ /*! @method SetConnection */
+ void SetConnection(const AudioUnitConnection &conn);
+ /*! @method SetInputCallback */
+ void SetInputCallback(AURenderCallback proc, void *refCon);
+
+ /*! @method IsActive */
+ bool IsActive() const { return mInputType != kNoInput; }
+ /*! @method IsCallback */
+ bool IsCallback() const { return mInputType == kFromCallback; }
+ /*! @method HasConnection */
+ bool HasConnection() const { return mInputType == kFromConnection; }
+
+ /*! @method PullInput */
+ OSStatus PullInput( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ AudioUnitElement inElement,
+ UInt32 inNumberFrames);
+
+ /*! @method PullInputWithBufferList */
+ OSStatus PullInputWithBufferList( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ AudioUnitElement inElement,
+ UInt32 nFrames,
+ AudioBufferList * inBufferList);
+protected:
+ /*! @method Disconnect */
+ void Disconnect();
+
+ enum EInputType { kNoInput, kFromConnection, kFromCallback };
+
+ /*! @var mInputType */
+ EInputType mInputType;
+
+ // if from callback:
+ /*! @var mInputProc */
+ AURenderCallback mInputProc;
+ /*! @var mInputProcRefCon */
+ void * mInputProcRefCon;
+
+ // if from connection:
+ /*! @var mConnection */
+ AudioUnitConnection mConnection;
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ /*! @var mConnRenderProc */
+ AudioUnitRenderProc mConnRenderProc;
+#endif
+ /*! @var mConnInstanceStorage */
+ void * mConnInstanceStorage; // for the input component
+};
+
+
+#endif // __AUInput_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp
new file mode 100644
index 0000000000..5eb34a1c20
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp
@@ -0,0 +1,62 @@
+/*
+ File: AUOutputElement.cpp
+ Abstract: AUOutputElement.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUOutputElement.h"
+#include "AUBase.h"
+
+AUOutputElement::AUOutputElement(AUBase *audioUnit) :
+ AUIOElement(audioUnit)
+{
+ AllocateBuffer();
+}
+
+OSStatus AUOutputElement::SetStreamFormat(const CAStreamBasicDescription &desc)
+{
+ OSStatus result = AUIOElement::SetStreamFormat(desc); // inherited
+ if (result == AUBase::noErr)
+ AllocateBuffer();
+ return result;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.h
new file mode 100644
index 0000000000..3e6a938fff
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUOutputElement.h
@@ -0,0 +1,66 @@
+/*
+ File: AUOutputElement.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUOutput_h__
+#define __AUOutput_h__
+
+#include "AUScopeElement.h"
+#include "AUBuffer.h"
+
+ /*! @class AUOutputElement */
+class AUOutputElement : public AUIOElement {
+public:
+ /*! @ctor AUOutputElement */
+ AUOutputElement(AUBase *audioUnit);
+
+ // AUElement override
+ /*! @method SetStreamFormat */
+ virtual OSStatus SetStreamFormat(const CAStreamBasicDescription &desc);
+ /*! @method NeedsBufferSpace */
+ virtual bool NeedsBufferSpace() const { return true; }
+};
+
+#endif // __AUOutput_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.cpp
new file mode 100644
index 0000000000..3bab198369
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.cpp
@@ -0,0 +1,669 @@
+/*
+ File: AUPlugInDispatch.cpp
+ Abstract: AUPlugInDispatch.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUPlugInDispatch.h"
+#include "CAXException.h"
+#include "ComponentBase.h"
+#include "AUBase.h"
+
+#define ACPI ((AudioComponentPlugInInstance *)self)
+#define AUI ((AUBase *)&ACPI->mInstanceStorage)
+
+#define AUI_LOCK CAMutex::Locker auLock(AUI->GetMutex());
+
+// ------------------------------------------------------------------------------------------------
+static OSStatus AUMethodInitialize(void *self)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->DoInitialize();
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodUninitialize(void *self)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ AUI->DoCleanup();
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodGetPropertyInfo(void *self, AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32 *outDataSize, Boolean *outWritable)
+{
+ OSStatus result = noErr;
+ try {
+ UInt32 dataSize = 0; // 13517289 GetPropetyInfo was returning an uninitialized value when there is an error. This is a problem for auval.
+ Boolean writable = false;
+
+ AUI_LOCK
+ result = AUI->DispatchGetPropertyInfo(prop, scope, elem, dataSize, writable);
+ if (outDataSize != NULL)
+ *outDataSize = dataSize;
+ if (outWritable != NULL)
+ *outWritable = writable;
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodGetProperty(void *self, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void *outData, UInt32 *ioDataSize)
+{
+ OSStatus result = noErr;
+ try {
+ UInt32 actualPropertySize, clientBufferSize;
+ Boolean writable;
+ char *tempBuffer;
+ void *destBuffer;
+
+ AUI_LOCK
+ if (ioDataSize == NULL) {
+ ca_debug_string("AudioUnitGetProperty: null size pointer");
+ result = kAudio_ParamError;
+ goto finishGetProperty;
+ }
+ if (outData == NULL) {
+ UInt32 dataSize;
+
+ result = AUI->DispatchGetPropertyInfo(inID, inScope, inElement, dataSize, writable);
+ *ioDataSize = dataSize;
+ goto finishGetProperty;
+ }
+
+ clientBufferSize = *ioDataSize;
+ if (clientBufferSize == 0)
+ {
+ ca_debug_string("AudioUnitGetProperty: *ioDataSize == 0 on entry");
+ // $$$ or should we allow this as a shortcut for finding the size?
+ result = kAudio_ParamError;
+ goto finishGetProperty;
+ }
+
+ result = AUI->DispatchGetPropertyInfo(inID, inScope, inElement, actualPropertySize, writable);
+ if (result != noErr)
+ goto finishGetProperty;
+
+ if (clientBufferSize < actualPropertySize)
+ {
+ tempBuffer = new char[actualPropertySize];
+ destBuffer = tempBuffer;
+ } else {
+ tempBuffer = NULL;
+ destBuffer = outData;
+ }
+
+ result = AUI->DispatchGetProperty(inID, inScope, inElement, destBuffer);
+
+ if (result == noErr) {
+ if (clientBufferSize < actualPropertySize && tempBuffer != NULL)
+ {
+ memcpy(outData, tempBuffer, clientBufferSize);
+ delete[] tempBuffer;
+ // ioDataSize remains correct, the number of bytes we wrote
+ } else
+ *ioDataSize = actualPropertySize;
+ } else
+ *ioDataSize = 0;
+ }
+ COMPONENT_CATCH
+finishGetProperty:
+ return result;
+}
+
+static OSStatus AUMethodSetProperty(void *self, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, const void *inData, UInt32 inDataSize)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ if (inData && inDataSize)
+ result = AUI->DispatchSetProperty(inID, inScope, inElement, inData, inDataSize);
+ else {
+ if (inData == NULL && inDataSize == 0) {
+ result = AUI->DispatchRemovePropertyValue(inID, inScope, inElement);
+ } else {
+ if (inData == NULL) {
+ ca_debug_string("AudioUnitSetProperty: inData == NULL");
+ result = kAudio_ParamError;
+ goto finishSetProperty;
+ }
+
+ if (inDataSize == 0) {
+ ca_debug_string("AudioUnitSetProperty: inDataSize == 0");
+ result = kAudio_ParamError;
+ goto finishSetProperty;
+ }
+ }
+ }
+ }
+ COMPONENT_CATCH
+finishSetProperty:
+ return result;
+}
+
+static OSStatus AUMethodAddPropertyListener(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void *userData)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->AddPropertyListener(prop, proc, userData);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodRemovePropertyListener(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->RemovePropertyListener(prop, proc, NULL, false);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodRemovePropertyListenerWithUserData(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void *userData)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->RemovePropertyListener(prop, proc, userData, true);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodAddRenderNotify(void *self, AURenderCallback proc, void *userData)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->SetRenderNotification(proc, userData);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodRemoveRenderNotify(void *self, AURenderCallback proc, void *userData)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->RemoveRenderNotification(proc, userData);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodGetParameter(void *self, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue *value)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = (value == NULL ? kAudio_ParamError : AUI->GetParameter(param, scope, elem, *value));
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodSetParameter(void *self, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a (potentially) realtime method; no lock
+ result = AUI->SetParameter(param, scope, elem, value, bufferOffset);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodScheduleParameters(void *self, const AudioUnitParameterEvent *events, UInt32 numEvents)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a (potentially) realtime method; no lock
+ result = AUI->ScheduleParameter(events, numEvents);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodRender(void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
+{
+ OSStatus result = noErr;
+
+#if !TARGET_OS_IPHONE
+ try {
+#endif
+ // this is a processing method; no lock
+ AudioUnitRenderActionFlags tempFlags;
+
+ if (inTimeStamp == NULL || ioData == NULL)
+ result = kAudio_ParamError;
+ else {
+ if (ioActionFlags == NULL) {
+ tempFlags = 0;
+ ioActionFlags = &tempFlags;
+ }
+ result = AUI->DoRender(*ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberFrames, *ioData);
+ }
+
+#if !TARGET_OS_IPHONE
+ }
+ COMPONENT_CATCH
+#endif
+
+ return result;
+}
+
+static OSStatus AUMethodComplexRender(void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberOfPackets, UInt32 *outNumberOfPackets, AudioStreamPacketDescription *outPacketDescriptions, AudioBufferList *ioData, void *outMetadata, UInt32 *outMetadataByteSize)
+{
+ OSStatus result = noErr;
+
+#if !TARGET_OS_IPHONE
+ try {
+#endif
+ // this is a processing method; no lock
+ AudioUnitRenderActionFlags tempFlags;
+
+ if (inTimeStamp == NULL || ioData == NULL)
+ result = kAudio_ParamError;
+ else {
+ if (ioActionFlags == NULL) {
+ tempFlags = 0;
+ ioActionFlags = &tempFlags;
+ }
+ result = AUI->ComplexRender(*ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberOfPackets, outNumberOfPackets, outPacketDescriptions, *ioData, outMetadata, outMetadataByteSize);
+ }
+
+#if !TARGET_OS_IPHONE
+ }
+ COMPONENT_CATCH
+#endif
+
+ return result;
+}
+
+static OSStatus AUMethodReset(void *self, AudioUnitScope scope, AudioUnitElement elem)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->Reset(scope, elem);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodProcess (void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, AudioBufferList *ioData)
+{
+ OSStatus result = noErr;
+
+#if !TARGET_OS_IPHONE
+ try {
+#endif
+ // this is a processing method; no lock
+ bool doParamCheck = true;
+
+ AudioUnitRenderActionFlags tempFlags;
+
+ if (ioActionFlags == NULL) {
+ tempFlags = 0;
+ ioActionFlags = &tempFlags;
+ } else {
+ if (*ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)
+ doParamCheck = false;
+ }
+
+ if (doParamCheck && (inTimeStamp == NULL || ioData == NULL))
+ result = kAudio_ParamError;
+ else {
+ result = AUI->DoProcess(*ioActionFlags, *inTimeStamp, inNumberFrames, *ioData);
+ }
+
+#if !TARGET_OS_IPHONE
+ }
+ COMPONENT_CATCH
+#endif
+
+ return result;
+}
+
+static OSStatus AUMethodProcessMultiple (void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, UInt32 inNumberInputBufferLists, const AudioBufferList **inInputBufferLists, UInt32 inNumberOutputBufferLists, AudioBufferList **ioOutputBufferLists)
+{
+ OSStatus result = noErr;
+
+#if !TARGET_OS_IPHONE
+ try {
+#endif
+ // this is a processing method; no lock
+ bool doParamCheck = true;
+
+ AudioUnitRenderActionFlags tempFlags;
+
+ if (ioActionFlags == NULL) {
+ tempFlags = 0;
+ ioActionFlags = &tempFlags;
+ } else {
+ if (*ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)
+ doParamCheck = false;
+ }
+
+ if (doParamCheck && (inTimeStamp == NULL || inInputBufferLists == NULL || ioOutputBufferLists == NULL))
+ result = kAudio_ParamError;
+ else {
+ result = AUI->DoProcessMultiple(*ioActionFlags, *inTimeStamp, inNumberFrames, inNumberInputBufferLists, inInputBufferLists, inNumberOutputBufferLists, ioOutputBufferLists);
+ }
+
+#if !TARGET_OS_IPHONE
+ }
+ COMPONENT_CATCH
+#endif
+
+ return result;
+}
+// ------------------------------------------------------------------------------------------------
+
+static OSStatus AUMethodStart(void *self)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->Start();
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodStop(void *self)
+{
+ OSStatus result = noErr;
+ try {
+ AUI_LOCK
+ result = AUI->Stop();
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+#if !CA_BASIC_AU_FEATURES
+// I don't know what I'm doing here; conflicts with the multiple inheritence in MusicDeviceBase.
+static OSStatus AUMethodMIDIEvent(void *self, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a potential render-time method; no lock
+ result = AUI->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodSysEx(void *self, const UInt8 *inData, UInt32 inLength)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a potential render-time method; no lock
+ result = AUI->SysEx(inData, inLength);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodStartNote(void *self, MusicDeviceInstrumentID inInstrument, MusicDeviceGroupID inGroupID, NoteInstanceID *outNoteInstanceID, UInt32 inOffsetSampleFrame, const MusicDeviceNoteParams *inParams)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a potential render-time method; no lock
+ if (inParams == NULL || outNoteInstanceID == NULL)
+ result = kAudio_ParamError;
+ else
+ result = AUI->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodStopNote(void *self, MusicDeviceGroupID inGroupID, NoteInstanceID inNoteInstanceID, UInt32 inOffsetSampleFrame)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a potential render-time method; no lock
+ result = AUI->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+#if !TARGET_OS_IPHONE
+static OSStatus AUMethodPrepareInstrument (void *self, MusicDeviceInstrumentID inInstrument)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a potential render-time method; no lock
+ result = AUI->PrepareInstrument(inInstrument);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+static OSStatus AUMethodReleaseInstrument (void *self, MusicDeviceInstrumentID inInstrument)
+{
+ OSStatus result = noErr;
+ try {
+ // this is a potential render-time method; no lock
+ result = AUI->ReleaseInstrument(inInstrument);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+#endif // TARGET_OS_IPHONE
+#endif // CA_BASIC_AU_FEATURES
+
+
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#pragma mark -
+#pragma mark Lookup Methods
+
+AudioComponentMethod AUBaseLookup::Lookup (SInt16 selector)
+{
+ switch (selector) {
+ case kAudioUnitInitializeSelect: return (AudioComponentMethod)AUMethodInitialize;
+ case kAudioUnitUninitializeSelect: return (AudioComponentMethod)AUMethodUninitialize;
+ case kAudioUnitGetPropertyInfoSelect: return (AudioComponentMethod)AUMethodGetPropertyInfo;
+ case kAudioUnitGetPropertySelect: return (AudioComponentMethod)AUMethodGetProperty;
+ case kAudioUnitSetPropertySelect: return (AudioComponentMethod)AUMethodSetProperty;
+ case kAudioUnitAddPropertyListenerSelect:return (AudioComponentMethod)AUMethodAddPropertyListener;
+ case kAudioUnitRemovePropertyListenerSelect:
+ return (AudioComponentMethod)AUMethodRemovePropertyListener;
+ case kAudioUnitRemovePropertyListenerWithUserDataSelect:
+ return (AudioComponentMethod)AUMethodRemovePropertyListenerWithUserData;
+ case kAudioUnitAddRenderNotifySelect: return (AudioComponentMethod)AUMethodAddRenderNotify;
+ case kAudioUnitRemoveRenderNotifySelect:return (AudioComponentMethod)AUMethodRemoveRenderNotify;
+ case kAudioUnitGetParameterSelect: return (AudioComponentMethod)AUMethodGetParameter;
+ case kAudioUnitSetParameterSelect: return (AudioComponentMethod)AUMethodSetParameter;
+ case kAudioUnitScheduleParametersSelect:return (AudioComponentMethod)AUMethodScheduleParameters;
+ case kAudioUnitRenderSelect: return (AudioComponentMethod)AUMethodRender;
+ case kAudioUnitResetSelect: return (AudioComponentMethod)AUMethodReset;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+AudioComponentMethod AUOutputLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+ if (method) return method;
+
+ switch (selector) {
+ case kAudioOutputUnitStartSelect: return (AudioComponentMethod)AUMethodStart;
+ case kAudioOutputUnitStopSelect: return (AudioComponentMethod)AUMethodStop;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+AudioComponentMethod AUComplexOutputLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+ if (method) return method;
+
+ method = AUOutputLookup::Lookup(selector);
+ if (method) return method;
+
+ if (selector == kAudioUnitComplexRenderSelect)
+ return (AudioComponentMethod)AUMethodComplexRender;
+ return NULL;
+}
+
+AudioComponentMethod AUBaseProcessLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+ if (method) return method;
+
+ if (selector == kAudioUnitProcessSelect)
+ return (AudioComponentMethod)AUMethodProcess;
+
+ return NULL;
+}
+
+AudioComponentMethod AUBaseProcessMultipleLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+ if (method) return method;
+
+ if (selector == kAudioUnitProcessMultipleSelect)
+ return (AudioComponentMethod)AUMethodProcessMultiple;
+
+ return NULL;
+}
+
+AudioComponentMethod AUBaseProcessAndMultipleLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+ if (method) return method;
+
+ method = AUBaseProcessMultipleLookup::Lookup(selector);
+ if (method) return method;
+
+ method = AUBaseProcessLookup::Lookup(selector);
+ if (method) return method;
+
+ return NULL;
+}
+
+#if !CA_BASIC_AU_FEATURES
+inline AudioComponentMethod MIDI_Lookup (SInt16 selector)
+{
+ switch (selector) {
+ case kMusicDeviceMIDIEventSelect: return (AudioComponentMethod)AUMethodMIDIEvent;
+ case kMusicDeviceSysExSelect: return (AudioComponentMethod)AUMethodSysEx;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+AudioComponentMethod AUMIDILookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+ if (method) return method;
+
+ return MIDI_Lookup(selector);
+}
+
+AudioComponentMethod AUMIDIProcessLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseProcessLookup::Lookup(selector);
+ if (method) return method;
+
+ return MIDI_Lookup(selector);
+}
+
+AudioComponentMethod AUMusicLookup::Lookup (SInt16 selector)
+{
+ AudioComponentMethod method = AUBaseLookup::Lookup(selector);
+ if (method) return method;
+
+ switch (selector) {
+ case kMusicDeviceStartNoteSelect: return (AudioComponentMethod)AUMethodStartNote;
+ case kMusicDeviceStopNoteSelect: return (AudioComponentMethod)AUMethodStopNote;
+#if !TARGET_OS_IPHONE
+ case kMusicDevicePrepareInstrumentSelect: return (AudioComponentMethod)AUMethodPrepareInstrument;
+ case kMusicDeviceReleaseInstrumentSelect: return (AudioComponentMethod)AUMethodReleaseInstrument;
+#endif
+ default:
+ break;
+ }
+ return MIDI_Lookup (selector);
+}
+
+AudioComponentMethod AUAuxBaseLookup::Lookup (SInt16 selector)
+{
+ switch (selector) {
+ case kAudioUnitGetPropertyInfoSelect: return (AudioComponentMethod)AUMethodGetPropertyInfo;
+ case kAudioUnitGetPropertySelect: return (AudioComponentMethod)AUMethodGetProperty;
+ case kAudioUnitSetPropertySelect: return (AudioComponentMethod)AUMethodSetProperty;
+
+ case kAudioUnitGetParameterSelect: return (AudioComponentMethod)AUMethodGetParameter;
+ case kAudioUnitSetParameterSelect: return (AudioComponentMethod)AUMethodSetParameter;
+
+ default:
+ break;
+ }
+ return NULL;
+}
+#endif
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.h
new file mode 100644
index 0000000000..6ebea75fd6
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUPlugInDispatch.h
@@ -0,0 +1,144 @@
+/*
+ File: AUPlugInDispatch.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUPlugInBase_h__
+#define __AUPlugInBase_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioComponent.h>
+ #if !CA_BASIC_AU_FEATURES
+ #include <AudioUnit/MusicDevice.h>
+ #endif
+#else
+ #include "AudioComponent.h"
+ #include "MusicDevice.h"
+#endif
+
+#include "ComponentBase.h"
+
+struct AUBaseLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUBaseFactory : public APFactory<AUBaseLookup, Implementor>
+{
+};
+
+struct AUOutputLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUOutputBaseFactory : public APFactory<AUOutputLookup, Implementor>
+{
+};
+
+struct AUComplexOutputLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUOutputComplexBaseFactory : public APFactory<AUComplexOutputLookup, Implementor>
+{
+};
+
+struct AUBaseProcessLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUBaseProcessFactory : public APFactory<AUBaseProcessLookup, Implementor>
+{
+};
+
+struct AUBaseProcessMultipleLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUBaseProcessMultipleFactory : public APFactory<AUBaseProcessMultipleLookup, Implementor>
+{
+};
+
+struct AUBaseProcessAndMultipleLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUBaseProcessAndMultipleFactory : public APFactory<AUBaseProcessAndMultipleLookup, Implementor>
+{
+};
+
+#if !CA_BASIC_AU_FEATURES
+struct AUMIDILookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUMIDIEffectFactory : public APFactory<AUMIDILookup, Implementor>
+{
+};
+
+struct AUMIDIProcessLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUMIDIProcessFactory : public APFactory<AUMIDIProcessLookup, Implementor>
+{
+};
+
+struct AUMusicLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUMusicDeviceFactory : public APFactory<AUMusicLookup, Implementor>
+{
+};
+
+struct AUAuxBaseLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AUAuxBaseFactory : public APFactory<AUAuxBaseLookup, Implementor>
+{
+};
+#endif // CA_BASIC_AU_FEATURES
+
+#endif // __AUPlugInBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUResources.r b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUResources.r
new file mode 100644
index 0000000000..55040fc396
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUResources.r
@@ -0,0 +1,140 @@
+/*
+ File: AUResources.r
+ Abstract: AUResources.r
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUResources.r
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* sample macro definitions -- all of these symbols must be defined
+#define RES_ID kHALOutputResID
+#define COMP_TYPE kAudioUnitComponentType
+#define COMP_SUBTYPE kAudioUnitOutputSubType
+#define COMP_MANUF kAudioUnitAudioHardwareOutputSubSubType
+#define VERSION 0x00010000
+#define NAME "AudioHALOutput"
+#define DESCRIPTION "Audio hardware output AudioUnit"
+#define ENTRY_POINT "AUHALEntry"
+*/
+#define UseExtendedThingResource 1
+
+#include <CoreServices/CoreServices.r>
+
+// this is a define used to indicate that a component has no static data that would mean
+// that no more than one instance could be open at a time - never been true for AUs
+#ifndef cmpThreadSafeOnMac
+#define cmpThreadSafeOnMac 0x10000000
+#endif
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+resource 'STR ' (RES_ID, purgeable) {
+ NAME
+};
+
+resource 'STR ' (RES_ID + 1, purgeable) {
+ DESCRIPTION
+};
+
+resource 'dlle' (RES_ID) {
+ ENTRY_POINT
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+resource 'thng' (RES_ID, NAME) {
+ COMP_TYPE,
+ COMP_SUBTYPE,
+ COMP_MANUF,
+ 0, 0, 0, 0, // no 68K
+ 'STR ', RES_ID,
+ 'STR ', RES_ID + 1,
+ 0, 0, /* icon */
+ VERSION,
+ componentHasMultiplePlatforms | componentDoAutoVersion,
+ 0,
+ {
+ #if defined(ppc_YES)
+ cmpThreadSafeOnMac,
+ 'dlle', RES_ID, platformPowerPCNativeEntryPoint
+ #define NeedLeadingComma 1
+ #endif
+ #if defined(ppc64_YES)
+ #if defined(NeedLeadingComma)
+ ,
+ #endif
+ cmpThreadSafeOnMac,
+ 'dlle', RES_ID, platformPowerPC64NativeEntryPoint
+ #define NeedLeadingComma 1
+ #endif
+ #if defined(i386_YES)
+ #if defined(NeedLeadingComma)
+ ,
+ #endif
+ cmpThreadSafeOnMac,
+ 'dlle', RES_ID, platformIA32NativeEntryPoint
+ #define NeedLeadingComma 1
+ #endif
+ #if defined(x86_64_YES)
+ #if defined(NeedLeadingComma)
+ ,
+ #endif
+ cmpThreadSafeOnMac,
+ 'dlle', RES_ID, 8
+ #define NeedLeadingComma 1
+ #endif
+ }
+};
+
+#undef RES_ID
+#undef COMP_TYPE
+#undef COMP_SUBTYPE
+#undef COMP_MANUF
+#undef VERSION
+#undef NAME
+#undef DESCRIPTION
+#undef ENTRY_POINT
+#undef NeedLeadingComma
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp
new file mode 100644
index 0000000000..24bd18e434
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp
@@ -0,0 +1,565 @@
+/*
+ File: AUScopeElement.cpp
+ Abstract: AUScopeElement.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUScopeElement.h"
+#include "AUBase.h"
+
+//_____________________________________________________________________________
+//
+// By default, parameterIDs may be arbitrarily spaced, and an STL map
+// will be used for access. Calling UseIndexedParameters() will
+// instead use an STL vector for faster indexed access.
+// This assumes the paramIDs are numbered 0.....inNumberOfParameters-1
+// Call this before defining/adding any parameters with SetParameter()
+//
+void AUElement::UseIndexedParameters(int inNumberOfParameters)
+{
+ mIndexedParameters.resize (inNumberOfParameters);
+ mUseIndexedParameters = true;
+}
+
+//_____________________________________________________________________________
+//
+// Helper method.
+// returns the ParameterMapEvent object associated with the paramID
+//
+inline ParameterMapEvent& AUElement::GetParamEvent(AudioUnitParameterID paramID)
+{
+ ParameterMapEvent *event;
+
+ if(mUseIndexedParameters)
+ {
+ if(paramID >= mIndexedParameters.size() )
+ COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
+
+ event = &mIndexedParameters[paramID];
+ }
+ else
+ {
+ ParameterMap::iterator i = mParameters.find(paramID);
+ if (i == mParameters.end())
+ COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
+
+ event = &(*i).second;
+ }
+
+ return *event;
+}
+
+//_____________________________________________________________________________
+//
+// Helper method.
+// returns whether the specified paramID is known to the element
+//
+bool AUElement::HasParameterID (AudioUnitParameterID paramID) const
+{
+ if(mUseIndexedParameters)
+ {
+ if(paramID >= mIndexedParameters.size() )
+ return false;
+
+ return true;
+ }
+
+ ParameterMap::const_iterator i = mParameters.find(paramID);
+ if (i == mParameters.end())
+ return false;
+
+ return true;
+}
+
+//_____________________________________________________________________________
+//
+// caller assumes that this is actually an immediate parameter
+//
+AudioUnitParameterValue AUElement::GetParameter(AudioUnitParameterID paramID)
+{
+ ParameterMapEvent &event = GetParamEvent(paramID);
+
+ return event.GetValue();
+}
+
+
+//_____________________________________________________________________________
+//
+void AUElement::GetRampSliceStartEnd( AudioUnitParameterID paramID,
+ AudioUnitParameterValue & outStartValue,
+ AudioUnitParameterValue & outEndValue,
+ AudioUnitParameterValue & outValuePerFrameDelta )
+
+{
+ ParameterMapEvent &event = GetParamEvent(paramID);
+
+ // works even if the value is constant (immediate parameter value)
+ event.GetRampSliceStartEnd(outStartValue, outEndValue, outValuePerFrameDelta );
+}
+
+//_____________________________________________________________________________
+//
+AudioUnitParameterValue AUElement::GetEndValue( AudioUnitParameterID paramID)
+
+{
+ ParameterMapEvent &event = GetParamEvent(paramID);
+
+ // works even if the value is constant (immediate parameter value)
+ return event.GetEndValue();
+}
+
+//_____________________________________________________________________________
+//
+void AUElement::SetParameter(AudioUnitParameterID paramID, AudioUnitParameterValue inValue, bool okWhenInitialized)
+{
+ if(mUseIndexedParameters)
+ {
+ ParameterMapEvent &event = GetParamEvent(paramID);
+ event.SetValue(inValue);
+ }
+ else
+ {
+ ParameterMap::iterator i = mParameters.find(paramID);
+
+ if (i == mParameters.end())
+ {
+ if (mAudioUnit->IsInitialized() && !okWhenInitialized) {
+ // The AU should not be creating new parameters once initialized.
+ // If a client tries to set an undefined parameter, we could throw as follows,
+ // but this might cause a regression. So it is better to just fail silently.
+ // COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
+#if DEBUG
+ fprintf(stderr, "WARNING: %s SetParameter for undefined param ID %d while initialized. Ignoring..\n",
+ mAudioUnit->GetLoggingString(), (int)paramID);
+#endif
+ } else {
+ // create new entry in map for the paramID (only happens first time)
+ ParameterMapEvent event(inValue);
+ mParameters[paramID] = event;
+ }
+ }
+ else
+ {
+ // paramID already exists in map so simply change its value
+ ParameterMapEvent &event = (*i).second;
+ event.SetValue(inValue);
+ }
+ }
+}
+
+//_____________________________________________________________________________
+//
+void AUElement::SetScheduledEvent( AudioUnitParameterID paramID,
+ const AudioUnitParameterEvent &inEvent,
+ UInt32 inSliceOffsetInBuffer,
+ UInt32 inSliceDurationFrames,
+ bool okWhenInitialized )
+{
+ if(mUseIndexedParameters)
+ {
+ ParameterMapEvent &event = GetParamEvent(paramID);
+ event.SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
+ }
+ else
+ {
+ ParameterMap::iterator i = mParameters.find(paramID);
+
+ if (i == mParameters.end())
+ {
+ if (mAudioUnit->IsInitialized() && !okWhenInitialized) {
+ // The AU should not be creating new parameters once initialized.
+ // If a client tries to set an undefined parameter, we could throw as follows,
+ // but this might cause a regression. So it is better to just fail silently.
+ // COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
+#if DEBUG
+ fprintf(stderr, "WARNING: %s SetScheduledEvent for undefined param ID %d while initialized. Ignoring..\n",
+ mAudioUnit->GetLoggingString(), (int)paramID);
+#endif
+ } else {
+ // create new entry in map for the paramID (only happens first time)
+ ParameterMapEvent event(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames);
+ mParameters[paramID] = event;
+ }
+ }
+ else
+ {
+ // paramID already exists in map so simply change its value
+ ParameterMapEvent &event = (*i).second;
+
+ event.SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
+ }
+ }
+}
+
+
+
+//_____________________________________________________________________________
+//
+void AUElement::GetParameterList(AudioUnitParameterID *outList)
+{
+ if(mUseIndexedParameters)
+ {
+ UInt32 nparams = static_cast<UInt32>(mIndexedParameters.size());
+ for (UInt32 i = 0; i < nparams; i++ )
+ *outList++ = (AudioUnitParameterID)i;
+ }
+ else
+ {
+ for (ParameterMap::iterator i = mParameters.begin(); i != mParameters.end(); ++i)
+ *outList++ = (*i).first;
+ }
+}
+
+//_____________________________________________________________________________
+//
+void AUElement::SaveState(CFMutableDataRef data)
+{
+ if(mUseIndexedParameters)
+ {
+ UInt32 nparams = static_cast<UInt32>(mIndexedParameters.size());
+ UInt32 theData = CFSwapInt32HostToBig(nparams);
+ CFDataAppendBytes(data, (UInt8 *)&theData, sizeof(nparams));
+
+ for (UInt32 i = 0; i < nparams; i++)
+ {
+ struct {
+ UInt32 paramID;
+ //CFSwappedFloat32 value; crashes gcc3 PFE
+ UInt32 value; // really a big-endian float
+ } entry;
+
+ entry.paramID = CFSwapInt32HostToBig(i);
+
+ AudioUnitParameterValue v = mIndexedParameters[i].GetValue();
+ entry.value = CFSwapInt32HostToBig(*(UInt32 *)&v );
+
+ CFDataAppendBytes(data, (UInt8 *)&entry, sizeof(entry));
+ }
+ }
+ else
+ {
+ UInt32 nparams = CFSwapInt32HostToBig(static_cast<uint32_t>(mParameters.size()));
+ CFDataAppendBytes(data, (UInt8 *)&nparams, sizeof(nparams));
+
+ for (ParameterMap::iterator i = mParameters.begin(); i != mParameters.end(); ++i) {
+ struct {
+ UInt32 paramID;
+ //CFSwappedFloat32 value; crashes gcc3 PFE
+ UInt32 value; // really a big-endian float
+ } entry;
+
+ entry.paramID = CFSwapInt32HostToBig((*i).first);
+
+ AudioUnitParameterValue v = (*i).second.GetValue();
+ entry.value = CFSwapInt32HostToBig(*(UInt32 *)&v );
+
+ CFDataAppendBytes(data, (UInt8 *)&entry, sizeof(entry));
+ }
+ }
+}
+
+//_____________________________________________________________________________
+//
+const UInt8 * AUElement::RestoreState(const UInt8 *state)
+{
+ union FloatInt32 { UInt32 i; AudioUnitParameterValue f; };
+ const UInt8 *p = state;
+ UInt32 nparams = CFSwapInt32BigToHost(*(UInt32 *)p);
+ p += sizeof(UInt32);
+
+ for (UInt32 i = 0; i < nparams; ++i) {
+ struct {
+ AudioUnitParameterID paramID;
+ AudioUnitParameterValue value;
+ } entry;
+
+ entry.paramID = CFSwapInt32BigToHost(*(UInt32 *)p);
+ p += sizeof(UInt32);
+ FloatInt32 temp;
+ temp.i = CFSwapInt32BigToHost(*(UInt32 *)p);
+ entry.value = temp.f;
+ p += sizeof(AudioUnitParameterValue);
+
+ SetParameter(entry.paramID, entry.value);
+ }
+ return p;
+}
+
+//_____________________________________________________________________________
+//
+void AUElement::SetName (CFStringRef inName)
+{
+ if (mElementName) CFRelease (mElementName);
+ mElementName = inName;
+ if (mElementName) CFRetain (mElementName);
+}
+
+
+//_____________________________________________________________________________
+//
+AUIOElement::AUIOElement(AUBase *audioUnit) :
+ AUElement(audioUnit),
+ mWillAllocate (true)
+{
+ mStreamFormat.SetAUCanonical(2, // stereo
+ audioUnit->AudioUnitAPIVersion() == 1);
+ // interleaved if API version 1, deinterleaved if version 2
+ mStreamFormat.mSampleRate = kAUDefaultSampleRate;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUIOElement::SetStreamFormat(const CAStreamBasicDescription &desc)
+{
+ mStreamFormat = desc;
+ return AUBase::noErr;
+}
+
+//_____________________________________________________________________________
+// inFramesToAllocate == 0 implies the AudioUnit's max-frames-per-slice will be used
+void AUIOElement::AllocateBuffer(UInt32 inFramesToAllocate)
+{
+ if (GetAudioUnit()->HasBegunInitializing())
+ {
+ UInt32 framesToAllocate = inFramesToAllocate > 0 ? inFramesToAllocate : GetAudioUnit()->GetMaxFramesPerSlice();
+
+// printf ("will allocate: %d\n", (int)((mWillAllocate && NeedsBufferSpace()) ? framesToAllocate : 0));
+
+ mIOBuffer.Allocate(mStreamFormat, (mWillAllocate && NeedsBufferSpace()) ? framesToAllocate : 0);
+ }
+}
+
+//_____________________________________________________________________________
+//
+void AUIOElement::DeallocateBuffer()
+{
+ mIOBuffer.Deallocate();
+}
+
+//_____________________________________________________________________________
+//
+// AudioChannelLayout support
+
+// outLayoutTagsPtr WILL be NULL if called to find out how many
+// layouts that Audio Unit will report
+// return 0 (ie. NO channel layouts) if the AU doesn't require channel layout knowledge
+UInt32 AUIOElement::GetChannelLayoutTags (AudioChannelLayoutTag *outLayoutTagsPtr)
+{
+ return 0;
+}
+
+// As the AudioChannelLayout can be a variable length structure
+// (though in most cases it won't be!!!)
+// The size of the ACL is always returned by the method
+// if outMapPtr is NOT-NULL, then AU should copy into this pointer (outMapPtr) the current ACL that it has in use.
+// the AU should also return whether the property is writable (that is the client can provide any arbitrary ACL that the audio unit will then honour)
+// or if the property is read only - which is the generally preferred mode.
+// If the AU doesn't require an AudioChannelLayout, then just return 0.
+UInt32 AUIOElement::GetAudioChannelLayout (AudioChannelLayout *outMapPtr,
+ Boolean &outWritable)
+{
+ return 0;
+}
+
+// the incoming channel map will be at least as big as a basic AudioChannelLayout
+// but its contents will determine its actual size
+// Subclass should overide if channel map is writable
+OSStatus AUIOElement::SetAudioChannelLayout (const AudioChannelLayout &inData)
+{
+ return kAudioUnitErr_InvalidProperty;
+}
+
+// Some units support optional usage of channel maps - typically converter units
+// that can do channel remapping between different maps. In that optional case
+// the user should be able to remove a channel map if that is possible.
+// Typically this is NOT the case (e.g., the 3DMixer even in the stereo case
+// needs to know if it is rendering to speakers or headphones)
+OSStatus AUIOElement::RemoveAudioChannelLayout ()
+{
+ return kAudioUnitErr_InvalidPropertyValue;
+}
+
+
+//_____________________________________________________________________________
+//
+AUScope::~AUScope()
+{
+ for (ElementVector::iterator it = mElements.begin(); it != mElements.end(); ++it)
+ delete *it;
+}
+
+//_____________________________________________________________________________
+//
+void AUScope::SetNumberOfElements(UInt32 numElements)
+{
+ if (mDelegate)
+ return mDelegate->SetNumberOfElements(numElements);
+
+ if (numElements > mElements.size()) {
+ mElements.reserve(numElements);
+ while (numElements > mElements.size()) {
+ AUElement *elem = mCreator->CreateElement(GetScope(), static_cast<UInt32>(mElements.size()));
+ mElements.push_back(elem);
+ }
+ } else
+ while (numElements < mElements.size()) {
+ AUElement *elem = mElements.back();
+ mElements.pop_back();
+ delete elem;
+ }
+}
+
+//_____________________________________________________________________________
+//
+bool AUScope::HasElementWithName () const
+{
+ for (UInt32 i = 0; i < GetNumberOfElements(); ++i) {
+ AUElement * el = const_cast<AUScope*>(this)->GetElement (i);
+ if (el && el->HasName()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+//_____________________________________________________________________________
+//
+
+void AUScope::AddElementNamesToDict (CFMutableDictionaryRef & inNameDict)
+{
+ if (HasElementWithName())
+ {
+ static char string[32];
+ CFMutableDictionaryRef elementDict = CFDictionaryCreateMutable (NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CFStringRef str;
+ for (UInt32 i = 0; i < GetNumberOfElements(); ++i) {
+ AUElement * el = GetElement (i);
+ if (el && el->HasName()) {
+ snprintf (string, sizeof(string), "%d", int(i));
+ str = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
+ CFDictionarySetValue (elementDict, str, el->GetName());
+ CFRelease (str);
+ }
+ }
+
+ snprintf (string, sizeof(string), "%d", int(mScope));
+ str = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
+ CFDictionarySetValue (inNameDict, str, elementDict);
+ CFRelease (str);
+ CFRelease (elementDict);
+ }
+}
+
+//_____________________________________________________________________________
+//
+bool AUScope::RestoreElementNames (CFDictionaryRef& inNameDict)
+{
+ static char string[32];
+
+ //first we have to see if we have enough elements
+ bool didAddElements = false;
+ unsigned int maxElNum = GetNumberOfElements();
+
+ int dictSize = static_cast<int>(CFDictionaryGetCount(inNameDict));
+ CFStringRef * keys = (CFStringRef*)CA_malloc (dictSize * sizeof (CFStringRef));
+ CFDictionaryGetKeysAndValues (inNameDict, reinterpret_cast<const void**>(keys), NULL);
+ for (int i = 0; i < dictSize; i++)
+ {
+ unsigned int intKey = 0;
+ CFStringGetCString (keys[i], string, 32, kCFStringEncodingASCII);
+ int result = sscanf (string, "%u", &intKey);
+ // check if sscanf succeeded and element index is less than max elements.
+ if (result && UInt32(intKey) < maxElNum)
+ {
+ CFStringRef elName = reinterpret_cast<CFStringRef>(CFDictionaryGetValue (inNameDict, keys[i]));
+ AUElement* element = GetElement (intKey);
+ if (element)
+ element->SetName (elName);
+ }
+ }
+ free (keys);
+
+ return didAddElements;
+}
+
+void AUScope::SaveState(CFMutableDataRef data)
+{
+ AudioUnitElement nElems = GetNumberOfElements();
+ for (AudioUnitElement ielem = 0; ielem < nElems; ++ielem) {
+ AUElement *element = GetElement(ielem);
+ UInt32 nparams = element->GetNumberOfParameters();
+ if (nparams > 0) {
+ struct {
+ UInt32 scope;
+ UInt32 element;
+ } hdr;
+
+ hdr.scope = CFSwapInt32HostToBig(GetScope());
+ hdr.element = CFSwapInt32HostToBig(ielem);
+ CFDataAppendBytes(data, (UInt8 *)&hdr, sizeof(hdr));
+
+ element->SaveState(data);
+ }
+ }
+}
+
+const UInt8 * AUScope::RestoreState(const UInt8 *state)
+{
+ const UInt8 *p = state;
+ UInt32 elementIdx = CFSwapInt32BigToHost(*(UInt32 *)p); p += sizeof(UInt32);
+ AUElement *element = GetElement(elementIdx);
+ if (!element) {
+ struct {
+ AudioUnitParameterID paramID;
+ AudioUnitParameterValue value;
+ } entry;
+ UInt32 nparams = CFSwapInt32BigToHost(*(UInt32 *)p);
+ p += sizeof(UInt32);
+
+ p += nparams * sizeof(entry);
+ } else
+ p = element->RestoreState(p);
+
+ return p;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.h
new file mode 100644
index 0000000000..47ebe2f338
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/AUScopeElement.h
@@ -0,0 +1,553 @@
+/*
+ File: AUScopeElement.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUScopeElement_h__
+#define __AUScopeElement_h__
+
+#include <map>
+#include <vector>
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnit.h>
+#else
+ #include <AudioUnit.h>
+#endif
+#include "ComponentBase.h"
+#include "AUBuffer.h"
+
+
+class AUBase;
+
+// ____________________________________________________________________________
+//
+// represents a parameter's value (either constant or ramped)
+/*! @class ParameterMapEvent */
+class ParameterMapEvent
+{
+public:
+/*! @ctor ParameterMapEvent */
+ ParameterMapEvent()
+ : mEventType(kParameterEvent_Immediate), mBufferOffset(0), mDurationInFrames(0), mValue1(0.0f), mValue2(0.0f), mSliceDurationFrames(0)
+ {}
+
+/*! @ctor ParameterMapEvent */
+ ParameterMapEvent(AudioUnitParameterValue inValue)
+ : mEventType(kParameterEvent_Immediate), mBufferOffset(0), mDurationInFrames(0), mValue1(inValue), mValue2(inValue), mSliceDurationFrames(0)
+ {}
+
+ // constructor for scheduled event
+/*! @ctor ParameterMapEvent */
+ ParameterMapEvent( const AudioUnitParameterEvent &inEvent,
+ UInt32 inSliceOffsetInBuffer,
+ UInt32 inSliceDurationFrames )
+ {
+ SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
+ };
+
+/*! @method SetScheduledEvent */
+ void SetScheduledEvent( const AudioUnitParameterEvent &inEvent,
+ UInt32 inSliceOffsetInBuffer,
+ UInt32 inSliceDurationFrames )
+ {
+ mEventType = inEvent.eventType;
+ mSliceDurationFrames = inSliceDurationFrames;
+
+ if(mEventType == kParameterEvent_Immediate )
+ {
+ // constant immediate value for the whole slice
+ mValue1 = inEvent.eventValues.immediate.value;
+ mValue2 = mValue1;
+ mDurationInFrames = inSliceDurationFrames;
+ mBufferOffset = 0;
+ }
+ else
+ {
+ mDurationInFrames = inEvent.eventValues.ramp.durationInFrames;
+ mBufferOffset = inEvent.eventValues.ramp.startBufferOffset - inSliceOffsetInBuffer; // shift over for this slice
+ mValue1 = inEvent.eventValues.ramp.startValue;
+ mValue2 = inEvent.eventValues.ramp.endValue;
+ }
+ };
+
+
+
+/*! @method GetEventType */
+ AUParameterEventType GetEventType() const {return mEventType;};
+
+/*! @method GetValue */
+ AudioUnitParameterValue GetValue() const {return mValue1;}; // only valid if immediate event type
+/*! @method GetEndValue */
+ AudioUnitParameterValue GetEndValue() const {return mValue2;}; // only valid if immediate event type
+/*! @method SetValue */
+ void SetValue(AudioUnitParameterValue inValue)
+ {
+ mEventType = kParameterEvent_Immediate;
+ mValue1 = inValue;
+ mValue2 = inValue;
+ }
+
+ // interpolates the start and end values corresponding to the current processing slice
+ // most ramp parameter implementations will want to use this method
+ // the start value will correspond to the start of the slice
+ // the end value will correspond to the end of the slice
+/*! @method GetRampSliceStartEnd */
+ void GetRampSliceStartEnd( AudioUnitParameterValue & outStartValue,
+ AudioUnitParameterValue & outEndValue,
+ AudioUnitParameterValue & outValuePerFrameDelta )
+ {
+ if (mEventType == kParameterEvent_Ramped) {
+ outValuePerFrameDelta = (mValue2 - mValue1) / mDurationInFrames;
+
+ outStartValue = mValue1 + outValuePerFrameDelta * (-mBufferOffset); // corresponds to frame 0 of this slice
+ outEndValue = outStartValue + outValuePerFrameDelta * mSliceDurationFrames;
+ } else {
+ outValuePerFrameDelta = 0;
+ outStartValue = outEndValue = mValue1;
+ }
+ };
+
+ // Some ramp parameter implementations will want to interpret the ramp using their
+ // own interpolation method (perhaps non-linear)
+ // This method gives the raw ramp information, relative to this processing slice
+ // for the client to interpret as desired
+/*! @method GetRampInfo */
+ void GetRampInfo( SInt32 & outBufferOffset,
+ UInt32 & outDurationInFrames,
+ AudioUnitParameterValue & outStartValue,
+ AudioUnitParameterValue & outEndValue )
+ {
+ outBufferOffset = mBufferOffset;
+ outDurationInFrames = mDurationInFrames;
+ outStartValue = mValue1;
+ outEndValue = mValue2;
+ };
+
+#if DEBUG
+ void Print()
+ {
+ printf("ParameterEvent @ %p\n", this);
+ printf(" mEventType = %d\n", (int)mEventType);
+ printf(" mBufferOffset = %d\n", (int)mBufferOffset);
+ printf(" mDurationInFrames = %d\n", (int)mDurationInFrames);
+ printf(" mSliceDurationFrames = %d\n", (int)mSliceDurationFrames);
+ printf(" mValue1 = %.5f\n", mValue1);
+ printf(" mValue2 = %.5f\n", mValue2);
+ }
+#endif
+
+private:
+ AUParameterEventType mEventType;
+
+ SInt32 mBufferOffset; // ramp start offset relative to start of this slice (may be negative)
+ UInt32 mDurationInFrames; // total duration of ramp parameter
+ AudioUnitParameterValue mValue1; // value if immediate : startValue if ramp
+ AudioUnitParameterValue mValue2; // endValue (only used for ramp)
+
+ UInt32 mSliceDurationFrames; // duration of this processing slice
+};
+
+
+
+// ____________________________________________________________________________
+//
+class AUIOElement;
+
+/*! @class AUElement */
+class AUElement {
+public:
+/*! @ctor AUElement */
+ AUElement(AUBase *audioUnit) : mAudioUnit(audioUnit),
+ mUseIndexedParameters(false), mElementName(0) { }
+
+/*! @dtor ~AUElement */
+ virtual ~AUElement() { if (mElementName) CFRelease (mElementName); }
+
+/*! @method GetNumberOfParameters */
+ virtual UInt32 GetNumberOfParameters()
+ {
+ if(mUseIndexedParameters) return static_cast<UInt32>(mIndexedParameters.size()); else return static_cast<UInt32>(mParameters.size());
+ }
+/*! @method GetParameterList */
+ virtual void GetParameterList(AudioUnitParameterID *outList);
+/*! @method HasParameterID */
+ bool HasParameterID (AudioUnitParameterID paramID) const;
+
+/*! @method GetParameter */
+ AudioUnitParameterValue GetParameter(AudioUnitParameterID paramID);
+/*! @method SetParameter */
+ void SetParameter(AudioUnitParameterID paramID, AudioUnitParameterValue value, bool okWhenInitialized = false);
+ // Only set okWhenInitialized to true when you know the outside world cannot access this element. Otherwise the parameter map could get corrupted.
+
+ // interpolates the start and end values corresponding to the current processing slice
+ // most ramp parameter implementations will want to use this method
+/*! @method GetRampSliceStartEnd */
+ void GetRampSliceStartEnd( AudioUnitParameterID paramID,
+ AudioUnitParameterValue & outStartValue,
+ AudioUnitParameterValue & outEndValue,
+ AudioUnitParameterValue & outValuePerFrameDelta );
+
+/*! @method GetEndValue */
+ AudioUnitParameterValue GetEndValue( AudioUnitParameterID paramID);
+
+/*! @method SetRampParameter */
+ void SetScheduledEvent( AudioUnitParameterID paramID,
+ const AudioUnitParameterEvent &inEvent,
+ UInt32 inSliceOffsetInBuffer,
+ UInt32 inSliceDurationFrames,
+ bool okWhenInitialized = false );
+ // Only set okWhenInitialized to true when you know the outside world cannot access this element. Otherwise the parameter map could get corrupted.
+
+
+/*! @method GetAudioUnit */
+ AUBase * GetAudioUnit() const { return mAudioUnit; };
+
+/*! @method SaveState */
+ void SaveState(CFMutableDataRef data);
+/*! @method RestoreState */
+ const UInt8 * RestoreState(const UInt8 *state);
+/*! @method GetName */
+ CFStringRef GetName () const { return mElementName; }
+/*! @method SetName */
+ void SetName (CFStringRef inName);
+/*! @method HasName */
+ bool HasName () const { return mElementName != 0; }
+/*! @method UseIndexedParameters */
+ virtual void UseIndexedParameters(int inNumberOfParameters);
+
+/*! @method AsIOElement*/
+ virtual AUIOElement* AsIOElement () { return NULL; }
+
+protected:
+ inline ParameterMapEvent& GetParamEvent(AudioUnitParameterID paramID);
+
+private:
+ typedef std::map<AudioUnitParameterID, ParameterMapEvent, std::less<AudioUnitParameterID> > ParameterMap;
+
+/*! @var mAudioUnit */
+ AUBase * mAudioUnit;
+/*! @var mParameters */
+ ParameterMap mParameters;
+
+/*! @var mUseIndexedParameters */
+ bool mUseIndexedParameters;
+/*! @var mIndexedParameters */
+ std::vector<ParameterMapEvent> mIndexedParameters;
+
+/*! @var mElementName */
+ CFStringRef mElementName;
+};
+
+
+
+// ____________________________________________________________________________
+//
+/*! @class AUIOElement */
+class AUIOElement : public AUElement {
+public:
+/*! @ctor AUIOElement */
+ AUIOElement(AUBase *audioUnit);
+
+/*! @method GetStreamFormat */
+ const CAStreamBasicDescription &GetStreamFormat() const { return mStreamFormat; }
+
+/*! @method SetStreamFormat */
+ virtual OSStatus SetStreamFormat(const CAStreamBasicDescription &desc);
+
+/*! @method AllocateBuffer */
+ virtual void AllocateBuffer(UInt32 inFramesToAllocate = 0);
+/*! @method DeallocateBuffer */
+ void DeallocateBuffer();
+/*! @method NeedsBufferSpace */
+ virtual bool NeedsBufferSpace() const = 0;
+
+/*! @method SetWillAllocateBuffer */
+ void SetWillAllocateBuffer(bool inFlag) {
+ mWillAllocate = inFlag;
+ }
+/*! @method WillAllocateBuffer */
+ bool WillAllocateBuffer() const {
+ return mWillAllocate;
+ }
+
+/*! @method UseExternalBuffer */
+ void UseExternalBuffer(const AudioUnitExternalBuffer &buf) {
+ mIOBuffer.UseExternalBuffer(mStreamFormat, buf);
+ }
+/*! @method PrepareBuffer */
+ AudioBufferList & PrepareBuffer(UInt32 nFrames) {
+ if (mWillAllocate)
+ return mIOBuffer.PrepareBuffer(mStreamFormat, nFrames);
+ throw OSStatus(kAudioUnitErr_InvalidPropertyValue);
+ }
+/*! @method PrepareNullBuffer */
+ AudioBufferList & PrepareNullBuffer(UInt32 nFrames) {
+ return mIOBuffer.PrepareNullBuffer(mStreamFormat, nFrames);
+ }
+/*! @method SetBufferList */
+ AudioBufferList & SetBufferList(AudioBufferList &abl) { return mIOBuffer.SetBufferList(abl); }
+/*! @method SetBuffer */
+ void SetBuffer(UInt32 index, AudioBuffer &ab) { mIOBuffer.SetBuffer(index, ab); }
+/*! @method InvalidateBufferList */
+ void InvalidateBufferList() { mIOBuffer.InvalidateBufferList(); }
+
+/*! @method GetBufferList */
+ AudioBufferList & GetBufferList() const { return mIOBuffer.GetBufferList(); }
+
+/*! @method GetChannelData */
+ AudioUnitSampleType * GetChannelData(int ch) const {
+ if (mStreamFormat.IsInterleaved())
+ return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
+ else
+ return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
+ }
+ Float32 * GetFloat32ChannelData(int ch) const {
+ if (mStreamFormat.IsInterleaved())
+ return static_cast<Float32 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
+ else
+ return static_cast<Float32 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
+ }
+ SInt32 * GetSInt32ChannelData(int ch) const {
+ if (mStreamFormat.IsInterleaved())
+ return static_cast<SInt32 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
+ else
+ return static_cast<SInt32 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
+ }
+ SInt16 * GetInt16ChannelData(int ch) const {
+ if (mStreamFormat.IsInterleaved())
+ return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
+ else
+ return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
+ }
+
+/*! @method CopyBufferListTo */
+ void CopyBufferListTo(AudioBufferList &abl) const {
+ mIOBuffer.CopyBufferListTo(abl);
+ }
+/*! @method CopyBufferContentsTo */
+ void CopyBufferContentsTo(AudioBufferList &abl) const {
+ mIOBuffer.CopyBufferContentsTo(abl);
+ }
+
+/* UInt32 BytesToFrames(UInt32 nBytes) { return nBytes / mStreamFormat.mBytesPerFrame; }
+ UInt32 BytesToFrames(AudioBufferList &abl) {
+ return BytesToFrames(abl.mBuffers[0].mDataByteSize);
+ }
+ UInt32 FramesToBytes(UInt32 nFrames) { return nFrames * mStreamFormat.mBytesPerFrame; }*/
+
+/*! @method IsInterleaved */
+ bool IsInterleaved() const { return mStreamFormat.IsInterleaved(); }
+/*! @method NumberChannels */
+ UInt32 NumberChannels() const { return mStreamFormat.NumberChannels(); }
+/*! @method NumberInterleavedChannels */
+ UInt32 NumberInterleavedChannels() const { return mStreamFormat.NumberInterleavedChannels(); }
+
+/*! @method GetChannelMapTags */
+ virtual UInt32 GetChannelLayoutTags (AudioChannelLayoutTag *outLayoutTagsPtr);
+
+/*! @method GetAudioChannelLayout */
+ virtual UInt32 GetAudioChannelLayout (AudioChannelLayout *outMapPtr, Boolean &outWritable);
+
+/*! @method SetAudioChannelLayout */
+ virtual OSStatus SetAudioChannelLayout (const AudioChannelLayout &inData);
+
+/*! @method RemoveAudioChannelLayout */
+ virtual OSStatus RemoveAudioChannelLayout ();
+
+/*! @method AsIOElement*/
+ virtual AUIOElement* AsIOElement () { return this; }
+
+protected:
+/*! @var mStreamFormat */
+ CAStreamBasicDescription mStreamFormat;
+/*! @var mIOBuffer */
+ AUBufferList mIOBuffer; // for input: input proc buffer, only allocated when needed
+ // for output: output cache, usually allocated early on
+/*! @var mWillAllocate */
+ bool mWillAllocate;
+};
+
+// ____________________________________________________________________________
+//
+// AUScopeDelegates are a way to get virtual scopes.
+/*! @class AUScopeDelegate */
+class AUScopeDelegate {
+public:
+/*! @ctor AUScopeDelegate */
+ AUScopeDelegate() : mCreator(NULL), mScope(0) { }
+/*! @dtor ~AUScopeDelegate */
+ virtual ~AUScopeDelegate() {}
+
+/*! @method Initialize */
+ void Initialize( AUBase *creator,
+ AudioUnitScope scope,
+ UInt32 numElements)
+ {
+ mCreator = creator;
+ mScope = scope;
+ SetNumberOfElements(numElements);
+ }
+
+/*! @method SetNumberOfElements */
+ virtual void SetNumberOfElements(UInt32 numElements) = 0;
+
+/*! @method GetNumberOfElements */
+ virtual UInt32 GetNumberOfElements() = 0;
+
+/*! @method GetElement */
+ virtual AUElement * GetElement(UInt32 elementIndex) = 0;
+
+ AUBase * GetCreator() const { return mCreator; }
+ AudioUnitScope GetScope() const { return mScope; }
+
+
+private:
+/*! @var mCreator */
+ AUBase * mCreator;
+/*! @var mScope */
+ AudioUnitScope mScope;
+};
+
+
+
+// ____________________________________________________________________________
+//
+/*! @class AUScope */
+class AUScope {
+public:
+/*! @ctor AUScope */
+ AUScope() : mCreator(NULL), mScope(0), mDelegate(0) { }
+/*! @dtor ~AUScope */
+ ~AUScope();
+
+/*! @method Initialize */
+ void Initialize(AUBase *creator,
+ AudioUnitScope scope,
+ UInt32 numElements)
+ {
+ mCreator = creator;
+ mScope = scope;
+
+ if (mDelegate)
+ return mDelegate->Initialize(creator, scope, numElements);
+
+ SetNumberOfElements(numElements);
+ }
+
+/*! @method SetNumberOfElements */
+ void SetNumberOfElements(UInt32 numElements);
+
+/*! @method GetNumberOfElements */
+ UInt32 GetNumberOfElements() const
+ {
+ if (mDelegate)
+ return mDelegate->GetNumberOfElements();
+
+ return static_cast<UInt32>(mElements.size());
+ }
+
+/*! @method GetElement */
+ AUElement * GetElement(UInt32 elementIndex) const
+ {
+ if (mDelegate)
+ return mDelegate->GetElement(elementIndex);
+
+ ElementVector::const_iterator i = mElements.begin() + elementIndex;
+ // catch passing -1 in as the elementIndex - causes a wrap around
+ return (i >= mElements.end() || i < mElements.begin()) ? NULL : *i;
+ }
+
+/*! @method SafeGetElement */
+ AUElement * SafeGetElement(UInt32 elementIndex)
+ {
+ AUElement *element = GetElement(elementIndex);
+ if (element == NULL)
+ COMPONENT_THROW(kAudioUnitErr_InvalidElement);
+ return element;
+ }
+
+/*! @method GetIOElement */
+ AUIOElement * GetIOElement(UInt32 elementIndex) const
+ {
+ AUElement *element = GetElement(elementIndex);
+ AUIOElement *ioel = element ? element->AsIOElement () : NULL;
+ if (!ioel)
+ COMPONENT_THROW (kAudioUnitErr_InvalidElement);
+ return ioel;
+ }
+
+/*! @method HasElementWithName */
+ bool HasElementWithName () const;
+
+/*! @method AddElementNamesToDict */
+ void AddElementNamesToDict (CFMutableDictionaryRef & inNameDict);
+
+ bool RestoreElementNames (CFDictionaryRef& inNameDict);
+
+ AudioUnitScope GetScope() const { return mScope; }
+
+ void SetDelegate(AUScopeDelegate* inDelegate) { mDelegate = inDelegate; }
+
+/*! @method SaveState */
+ void SaveState(CFMutableDataRef data);
+
+/*! @method RestoreState */
+ const UInt8 * RestoreState(const UInt8 *state);
+
+private:
+ typedef std::vector<AUElement *> ElementVector;
+/*! @var mCreator */
+ AUBase * mCreator;
+/*! @var mScope */
+ AudioUnitScope mScope;
+/*! @var mElements */
+ ElementVector mElements;
+/*! @var mDelegate */
+ AUScopeDelegate * mDelegate;
+};
+
+
+
+#endif // __AUScopeElement_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.cpp
new file mode 100644
index 0000000000..fc987335dc
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.cpp
@@ -0,0 +1,370 @@
+/*
+ File: ComponentBase.cpp
+ Abstract: ComponentBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "ComponentBase.h"
+#include "CAXException.h"
+
+#if TARGET_OS_MAC
+pthread_mutex_t ComponentInitLocker::sComponentOpenMutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_once_t ComponentInitLocker::sOnce = PTHREAD_ONCE_INIT;
+
+void ComponentInitLocker::InitComponentInitLocker()
+{
+ // have to do this because OS X lacks PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&sComponentOpenMutex, &attr);
+ pthread_mutexattr_destroy(&attr);
+}
+
+#elif TARGET_OS_WIN32
+CAGuard ComponentInitLocker::sComponentOpenGuard("sComponentOpenGuard");
+#endif
+
+ComponentBase::EInstanceType ComponentBase::sNewInstanceType;
+
+static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc);
+#if !CA_USE_AUDIO_PLUGIN_ONLY && !TARGET_OS_WIN32
+ static OSStatus CMgr_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc);
+#endif
+
+ComponentBase::ComponentBase(AudioComponentInstance inInstance)
+ : mComponentInstance(inInstance),
+ mInstanceType(sNewInstanceType)
+{
+ GetComponentDescription();
+}
+
+ComponentBase::~ComponentBase()
+{
+}
+
+void ComponentBase::PostConstructor()
+{
+}
+
+void ComponentBase::PreDestructor()
+{
+}
+
+#define ACPI ((AudioComponentPlugInInstance *)self)
+#define ACImp ((ComponentBase *)&ACPI->mInstanceStorage)
+
+OSStatus ComponentBase::AP_Open(void *self, AudioUnit compInstance)
+{
+ OSStatus result = noErr;
+ try {
+ ComponentInitLocker lock;
+
+ ComponentBase::sNewInstanceType = ComponentBase::kAudioComponentInstance;
+ ComponentBase *cb = (ComponentBase *)(*ACPI->mConstruct)(&ACPI->mInstanceStorage, compInstance);
+ cb->PostConstructor(); // allows base class to do additional initialization
+ // once the derived class is fully constructed
+ result = noErr;
+ }
+ COMPONENT_CATCH
+ if (result)
+ delete ACPI;
+ return result;
+}
+
+OSStatus ComponentBase::AP_Close(void *self)
+{
+ OSStatus result = noErr;
+ try {
+ if (ACImp) {
+ ACImp->PreDestructor();
+ (*ACPI->mDestruct)(&ACPI->mInstanceStorage);
+ free(self);
+ }
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+OSStatus ComponentBase::Version()
+{
+ return 0x00000001;
+}
+
+OSStatus ComponentBase::ComponentEntryDispatch(ComponentParameters *p, ComponentBase *This)
+{
+ if (This == NULL) return kAudio_ParamError;
+
+ OSStatus result = noErr;
+
+ switch (p->what) {
+ case kComponentCloseSelect:
+ This->PreDestructor();
+ delete This;
+ break;
+
+ case kComponentVersionSelect:
+ result = This->Version();
+ break;
+
+ case kComponentCanDoSelect:
+ switch (GetSelectorForCanDo(p)) {
+ case kComponentOpenSelect:
+ case kComponentCloseSelect:
+ case kComponentVersionSelect:
+ case kComponentCanDoSelect:
+ return 1;
+ default:
+ return 0;
+ }
+
+ default:
+ result = badComponentSelector;
+ break;
+ }
+ return result;
+}
+
+SInt16 ComponentBase::GetSelectorForCanDo(ComponentParameters *params)
+{
+ if (params->what != kComponentCanDoSelect) return 0;
+
+ #if TARGET_CPU_X86
+ SInt16 sel = params->params[0];
+ #elif TARGET_CPU_X86_64
+ SInt16 sel = params->params[1];
+ #elif TARGET_CPU_PPC
+ SInt16 sel = (params->params[0] >> 16);
+ #else
+ SInt16 sel = params->params[0];
+ #endif
+
+ return sel;
+/*
+ printf ("flags:%d, paramSize: %d, what: %d\n\t", params->flags, params->paramSize, params->what);
+ for (int i = 0; i < params->paramSize; ++i) {
+ printf ("[%d]:%d(0x%x), ", i, params->params[i], params->params[i]);
+ }
+ printf("\n\tsel:%d\n", sel);
+*/
+}
+
+#endif
+
+#if CA_DO_NOT_USE_AUDIO_COMPONENT
+static OSStatus ComponentBase_GetComponentDescription (const AudioComponentInstance & inInstance, AudioComponentDescription &outDesc);
+#endif
+
+AudioComponentDescription ComponentBase::GetComponentDescription() const
+{
+ AudioComponentDescription desc;
+ OSStatus result = 1;
+
+ if (IsPluginObject()) {
+ ca_require_noerr(result = CB_GetComponentDescription (mComponentInstance, &desc), home);
+ }
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ else {
+ ca_require_noerr(result = CMgr_GetComponentDescription (mComponentInstance, &desc), home);
+ }
+#endif
+
+home:
+ if (result)
+ memset (&desc, 0, sizeof(AudioComponentDescription));
+
+ return desc;
+}
+
+#if CA_USE_AUDIO_PLUGIN_ONLY
+// everything we need is there and we should be linking against it
+static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
+{
+ AudioComponent comp = AudioComponentInstanceGetComponent(inInstance);
+ if (comp)
+ return AudioComponentGetDescription(comp, outDesc);
+
+ return kAudio_ParamError;
+}
+
+#elif !TARGET_OS_WIN32
+// these are the direct dependencies on ComponentMgr calls that an AU
+// that is a component mgr is dependent on
+
+// these are dynamically loaded so that these calls will work on Leopard
+#include <dlfcn.h>
+
+static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
+{
+ typedef AudioComponent (*AudioComponentInstanceGetComponentProc) (AudioComponentInstance);
+ static AudioComponentInstanceGetComponentProc aciGCProc = NULL;
+
+ typedef OSStatus (*AudioComponentGetDescriptionProc)(AudioComponent, AudioComponentDescription *);
+ static AudioComponentGetDescriptionProc acGDProc = NULL;
+
+ static int doneInit = 0;
+ if (doneInit == 0) {
+ doneInit = 1;
+ void* theImage = dlopen("/System/Library/Frameworks/AudioUnit.framework/AudioUnit", RTLD_LAZY);
+ if (theImage != NULL)
+ {
+ aciGCProc = (AudioComponentInstanceGetComponentProc)dlsym (theImage, "AudioComponentInstanceGetComponent");
+ if (aciGCProc) {
+ acGDProc = (AudioComponentGetDescriptionProc)dlsym (theImage, "AudioComponentGetDescription");
+ }
+ }
+ }
+
+ OSStatus result = kAudio_UnimplementedError;
+ if (acGDProc && aciGCProc) {
+ AudioComponent comp = (*aciGCProc)(inInstance);
+ if (comp)
+ result = (*acGDProc)(comp, outDesc);
+ }
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ else {
+ result = CMgr_GetComponentDescription (inInstance, outDesc);
+ }
+#endif
+
+ return result;
+}
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+// these are the direct dependencies on ComponentMgr calls that an AU
+// that is a component mgr is dependent on
+
+// these are dynamically loaded
+
+#include <CoreServices/CoreServices.h>
+#include <AudioUnit/AudioUnit.h>
+#include "CAXException.h"
+#include "ComponentBase.h"
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Component Manager
+// Used for fast dispatch with audio units
+typedef Handle (*GetComponentInstanceStorageProc)(ComponentInstance aComponentInstance);
+static GetComponentInstanceStorageProc sGetComponentInstanceStorageProc = NULL;
+
+typedef OSErr (*GetComponentInfoProc)(Component, ComponentDescription *, void*, void*, void*);
+static GetComponentInfoProc sGetComponentInfoProc = NULL;
+
+typedef void (*SetComponentInstanceStorageProc)(ComponentInstance, Handle);
+static SetComponentInstanceStorageProc sSetComponentInstanceStorageProc = NULL;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+static void CSInitOnce(void* /*unused*/)
+{
+ void *theImage = dlopen("/System/Library/Frameworks/CoreServices.framework/CoreServices", RTLD_LAZY);
+ if (!theImage) return;
+
+ sGetComponentInstanceStorageProc = (GetComponentInstanceStorageProc) dlsym(theImage, "GetComponentInstanceStorage");
+ sGetComponentInfoProc = (GetComponentInfoProc)dlsym (theImage, "GetComponentInfo");
+ sSetComponentInstanceStorageProc = (SetComponentInstanceStorageProc) dlsym(theImage, "SetComponentInstanceStorage");
+}
+
+#if TARGET_OS_MAC
+
+#include <dispatch/dispatch.h>
+
+static dispatch_once_t sCSInitOnce = 0;
+
+static void CSInit ()
+{
+ dispatch_once_f(&sCSInitOnce, NULL, CSInitOnce);
+}
+
+#else
+
+static void CSInit ()
+{
+ static int sDoCSLoad = 1;
+ if (sDoCSLoad) {
+ sDoCSLoad = 0;
+ CSInitOnce(NULL);
+ }
+}
+
+#endif
+
+OSStatus CMgr_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
+{
+ CSInit();
+ if (sGetComponentInfoProc)
+ return (*sGetComponentInfoProc)((Component)inInstance, (ComponentDescription*)outDesc, NULL, NULL, NULL);
+ return kAudio_UnimplementedError;
+}
+
+Handle CMgr_GetComponentInstanceStorage(ComponentInstance aComponentInstance)
+{
+ CSInit();
+ if (sGetComponentInstanceStorageProc)
+ return (*sGetComponentInstanceStorageProc)(aComponentInstance);
+ return NULL;
+}
+
+void CMgr_SetComponentInstanceStorage(ComponentInstance aComponentInstance, Handle theStorage)
+{
+ CSInit();
+ if (sSetComponentInstanceStorageProc)
+ (*sSetComponentInstanceStorageProc)(aComponentInstance, theStorage);
+}
+#endif // !CA_USE_AUDIO_PLUGIN_ONLY
+
+#else
+//#include "ComponentManagerDependenciesWin.h"
+// everything we need is there and we should be linking against it
+static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
+{
+ AudioComponent comp = AudioComponentInstanceGetComponent(inInstance);
+ if (comp)
+ return AudioComponentGetDescription(comp, outDesc);
+
+ return kAudio_ParamError;
+}
+
+#endif
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.h
new file mode 100644
index 0000000000..67417aa9d1
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUBase/ComponentBase.h
@@ -0,0 +1,353 @@
+/*
+ File: ComponentBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __ComponentBase_h__
+#define __ComponentBase_h__
+
+#include <new>
+#include "CADebugMacros.h"
+#include "CAXException.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <AudioUnit/AudioUnit.h>
+
+ #if !CA_USE_AUDIO_PLUGIN_ONLY
+ #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/Components.h>
+
+ #if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)
+ #define AudioComponentInstance ComponentInstance
+ #define AudioComponentDescription ComponentDescription
+ #define AudioComponent Component
+ #endif
+ Handle CMgr_GetComponentInstanceStorage(ComponentInstance aComponentInstance);
+ void CMgr_SetComponentInstanceStorage(ComponentInstance aComponentInstance, Handle theStorage);
+ #endif
+
+ #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+ typedef Float32 AudioUnitParameterValue;
+ #endif
+ #if COREAUDIOTYPES_VERSION < 1051
+ typedef Float32 AudioUnitSampleType;
+ #endif
+
+ #if !TARGET_OS_WIN32
+ #include <pthread.h>
+ #endif
+
+ #if TARGET_OS_WIN32
+ #include "CAGuard.h"
+ #endif
+#else
+ #include "CoreAudioTypes.h"
+ #if !CA_USE_AUDIO_PLUGIN_ONLY
+ #include "ComponentManagerDependenciesWin.h"
+ #endif
+ #include "AudioUnit.h"
+ #include "CAGuard.h"
+#endif
+
+#ifndef COMPONENT_THROW
+ #if VERBOSE_COMPONENT_THROW
+ #define COMPONENT_THROW(throw_err) \
+ do { DebugMessage(#throw_err); throw static_cast<OSStatus>(throw_err); } while (0)
+ #else
+ #define COMPONENT_THROW(throw_err) \
+ throw static_cast<OSStatus>(throw_err)
+ #endif
+#endif
+
+#define COMPONENT_CATCH \
+ catch (const CAXException &ex) { result = ex.mError; } \
+ catch (std::bad_alloc &) { result = kAudio_MemFullError; } \
+ catch (OSStatus catch_err) { result = catch_err; } \
+ catch (OSErr catch_err) { result = catch_err; } \
+ catch (...) { result = -1; }
+
+/*! @class ComponentBase */
+class ComponentBase {
+public:
+ // classic MacErrors
+ enum { noErr = 0};
+
+ /*! @ctor ComponentBase */
+ ComponentBase(AudioComponentInstance inInstance);
+
+ /*! @dtor ~ComponentBase */
+ virtual ~ComponentBase();
+
+ /*! @method PostConstructor */
+ virtual void PostConstructor();
+
+ /*! @method PreDestructor */
+ virtual void PreDestructor();
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ /*! @method Version */
+ virtual OSStatus Version();
+
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch(ComponentParameters *p, ComponentBase *This);
+
+ /*! GetSelectorForCanDo */
+ static SInt16 GetSelectorForCanDo(ComponentParameters *params);
+#endif
+
+ /*! @method GetComponentInstance */
+ AudioComponentInstance GetComponentInstance() const { return mComponentInstance; }
+
+ /*! @method GetComponentDescription */
+ AudioComponentDescription GetComponentDescription() const;
+
+ // This global variable is so that new instances know how they were instantiated: via the Component Manager,
+ // or as AudioComponents. It's ugly, but preferable to altering the constructor of every class in the hierarchy.
+ // It's safe because construction is protected by ComponentInitLocker.
+ enum EInstanceType { kComponentMgrInstance, kAudioComponentInstance };
+ static EInstanceType sNewInstanceType;
+
+ /*! @method IsPluginObject */
+ bool IsPluginObject () const { return mInstanceType == kAudioComponentInstance; }
+ /*! @method IsCMgrObject */
+ bool IsCMgrObject () const { return mInstanceType == kComponentMgrInstance; }
+
+ /*! @method AP_Open */
+ static OSStatus AP_Open(void *self, AudioUnit compInstance);
+
+ /*! @method AP_Close */
+ static OSStatus AP_Close(void *self);
+
+protected:
+ /*! @var mComponentInstance */
+ AudioComponentInstance mComponentInstance;
+ EInstanceType mInstanceType;
+};
+
+class ComponentInitLocker
+{
+#if TARGET_OS_MAC
+public:
+ ComponentInitLocker()
+ {
+ pthread_once(&sOnce, InitComponentInitLocker);
+ pthread_mutex_lock(&sComponentOpenMutex);
+ mPreviousNewInstanceType = ComponentBase::sNewInstanceType;
+ }
+ ~ComponentInitLocker()
+ {
+ ComponentBase::sNewInstanceType = mPreviousNewInstanceType;
+ pthread_mutex_unlock(&sComponentOpenMutex);
+ }
+
+ // There are situations (11844772) where we need to be able to release the lock early.
+ class Unlocker {
+ public:
+ Unlocker()
+ {
+ pthread_mutex_unlock(&sComponentOpenMutex);
+ }
+ ~Unlocker()
+ {
+ pthread_mutex_lock(&sComponentOpenMutex);
+ }
+ };
+
+private:
+ static pthread_mutex_t sComponentOpenMutex;
+ static pthread_once_t sOnce;
+ static void InitComponentInitLocker();
+
+#elif TARGET_OS_WIN32
+public:
+ bool sNeedsUnlocking;
+ ComponentInitLocker() { sNeedsUnlocking = sComponentOpenGuard.Lock(); }
+ ~ComponentInitLocker() { if(sNeedsUnlocking) { sComponentOpenGuard.Unlock(); } }
+private:
+ static CAGuard sComponentOpenGuard;
+#endif
+
+private:
+ ComponentBase::EInstanceType mPreviousNewInstanceType;
+};
+
+/*! @class AudioComponentPlugInInstance */
+struct AudioComponentPlugInInstance {
+ AudioComponentPlugInInterface mPlugInInterface;
+ void * (*mConstruct)(void *memory, AudioComponentInstance ci);
+ void (*mDestruct)(void *memory);
+ void * mPad[2]; // pad to a 16-byte boundary (in either 32 or 64 bit mode)
+ UInt32 mInstanceStorage; // the ACI implementation object is constructed into this memory
+ // this member is just a placeholder. it is aligned to a 16byte boundary
+};
+
+/*! @class APFactory */
+template <class APMethodLookup, class Implementor>
+class APFactory {
+public:
+ static void *Construct(void *memory, AudioComponentInstance compInstance)
+ {
+ return new(memory) Implementor(compInstance);
+ }
+
+ static void Destruct(void *memory)
+ {
+ ((Implementor *)memory)->~Implementor();
+ }
+
+ // This is the AudioComponentFactoryFunction. It returns an AudioComponentPlugInInstance.
+ // The actual implementation object is not created until Open().
+ static AudioComponentPlugInInterface *Factory(const AudioComponentDescription * /* inDesc */)
+ {
+ AudioComponentPlugInInstance *acpi =
+ (AudioComponentPlugInInstance *)malloc( offsetof(AudioComponentPlugInInstance, mInstanceStorage) + sizeof(Implementor) );
+ acpi->mPlugInInterface.Open = ComponentBase::AP_Open;
+ acpi->mPlugInInterface.Close = ComponentBase::AP_Close;
+ acpi->mPlugInInterface.Lookup = APMethodLookup::Lookup;
+ acpi->mPlugInInterface.reserved = NULL;
+ acpi->mConstruct = Construct;
+ acpi->mDestruct = Destruct;
+ acpi->mPad[0] = NULL;
+ acpi->mPad[1] = NULL;
+ return (AudioComponentPlugInInterface*)acpi;
+ }
+
+ // This is for runtime registration (not for plug-ins loaded from bundles).
+ static AudioComponent Register(UInt32 type, UInt32 subtype, UInt32 manuf, CFStringRef name, UInt32 vers, UInt32 flags=0)
+ {
+ AudioComponentDescription desc = { type, subtype, manuf, flags, 0 };
+ return AudioComponentRegister(&desc, name, vers, Factory);
+ }
+};
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+/*! @class ComponentEntryPoint
+ * @discussion This is only used for a component manager version
+*/
+template <class Class>
+class ComponentEntryPoint {
+public:
+ /*! @method Dispatch */
+ static OSStatus Dispatch(ComponentParameters *params, Class *obj)
+ {
+ OSStatus result = noErr;
+
+ try {
+ if (params->what == kComponentOpenSelect) {
+ // solve a host of initialization thread safety issues.
+ ComponentInitLocker lock;
+
+ ComponentBase::sNewInstanceType = ComponentBase::kComponentMgrInstance;
+ ComponentInstance ci = (ComponentInstance)(params->params[0]);
+ Class *This = new Class((AudioComponentInstance)ci);
+ This->PostConstructor(); // allows base class to do additional initialization
+ // once the derived class is fully constructed
+
+ CMgr_SetComponentInstanceStorage(ci, (Handle)This);
+ } else
+ result = Class::ComponentEntryDispatch(params, obj);
+ }
+ COMPONENT_CATCH
+
+ return result;
+ }
+
+ /*! @method Register */
+ static Component Register(OSType compType, OSType subType, OSType manufacturer)
+ {
+ ComponentDescription description = {compType, subType, manufacturer, 0, 0};
+ Component component = RegisterComponent(&description, (ComponentRoutineUPP) Dispatch, registerComponentGlobal, NULL, NULL, NULL);
+ if (component != NULL) {
+ SetDefaultComponent(component, defaultComponentAnyFlagsAnyManufacturerAnySubType);
+ }
+ return component;
+ }
+};
+
+// NOTE: Component Mgr is deprecated in ML.
+// this macro should not be used with new audio components
+// it is only for backwards compatibility with Lion and SL.
+// this macro registers both a plugin and a component mgr version.
+#define AUDIOCOMPONENT_ENTRY(FactoryType, Class) \
+ extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj); \
+ extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj) { \
+ return ComponentEntryPoint<Class>::Dispatch(params, obj); \
+ } \
+ extern "C" void * Class##Factory(const AudioComponentDescription *inDesc); \
+ extern "C" void * Class##Factory(const AudioComponentDescription *inDesc) { \
+ return FactoryType<Class>::Factory(inDesc); \
+ }
+ // the only component we still support are the carbon based view components
+ // you should be using this macro now to exclusively register those types
+#define VIEW_COMPONENT_ENTRY(Class) \
+ extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj); \
+ extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj) { \
+ return ComponentEntryPoint<Class>::Dispatch(params, obj); \
+ }
+
+ /*! @class ComponentRegistrar */
+template <class Class, OSType Type, OSType Subtype, OSType Manufacturer>
+class ComponentRegistrar {
+public:
+ /*! @ctor ComponentRegistrar */
+ ComponentRegistrar() { ComponentEntryPoint<Class>::Register(Type, Subtype, Manufacturer); }
+};
+
+#define COMPONENT_REGISTER(Class,Type,Subtype,Manufacturer) \
+ static ComponentRegistrar<Class, Type, Subtype, Manufacturer> gRegistrar##Class
+#else
+#define COMPONENT_ENTRY(Class)
+#define COMPONENT_REGISTER(Class)
+// this macro is used to generate the Entry Point for a given Audio Plugin
+// you should be using this macro now with audio components
+#define AUDIOCOMPONENT_ENTRY(FactoryType, Class) \
+ extern "C" void * Class##Factory(const AudioComponentDescription *inDesc); \
+ extern "C" void * Class##Factory(const AudioComponentDescription *inDesc) { \
+ return FactoryType<Class>::Factory(inDesc); \
+ }
+
+#endif // !CA_USE_AUDIO_PLUGIN_ONLY
+
+
+#endif // __ComponentBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp
new file mode 100644
index 0000000000..332475335d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp
@@ -0,0 +1,403 @@
+/*
+ File: AUCarbonViewBase.cpp
+ Abstract: AUCarbonViewBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUCarbonViewBase.h"
+#include "AUCarbonViewControl.h"
+#include <algorithm>
+
+AUCarbonViewBase::AUCarbonViewBase(AudioUnitCarbonView inInstance, Float32 inNotificationInterval /* in seconds */) :
+ ComponentBase(inInstance),
+ mEditAudioUnit(0),
+ mParameterListener(NULL),
+#if !__LP64__
+ mEventListener(NULL),
+#endif
+ mTimerRef (NULL),
+ mTimerUPP (NULL),
+ mCarbonWindow(NULL),
+ mCarbonPane(NULL),
+ mXOffset(0),
+ mYOffset(0)
+{
+ AUEventListenerCreate (ParameterListener, this,
+ CFRunLoopGetCurrent(), kCFRunLoopCommonModes,
+ inNotificationInterval, inNotificationInterval,
+ &mParameterListener);
+}
+
+AUCarbonViewBase::~AUCarbonViewBase()
+{
+#if !__LP64__
+ if (mCarbonPane)
+ DisposeControl(mCarbonPane);
+
+ for (ControlList::iterator it = mControlList.begin(); it != mControlList.end(); ++it) {
+ AUCarbonViewControl *ctl = *it;
+ delete ctl;
+ }
+ AUListenerDispose(mParameterListener);
+
+ if (mTimerRef)
+ ::RemoveEventLoopTimer (mTimerRef);
+
+ if (mTimerUPP)
+ DisposeEventLoopTimerUPP (mTimerUPP);
+#endif
+}
+
+void AUCarbonViewBase::AddControl(AUCarbonViewControl *control)
+{
+ ControlList::iterator it = find(mControlList.begin(), mControlList.end(), control);
+ if (it == mControlList.end())
+ mControlList.push_back(control);
+}
+
+void AUCarbonViewBase::RemoveControl(AUCarbonViewControl *control)
+{
+ ControlList::iterator it = find(mControlList.begin(), mControlList.end(), control);
+ if (it != mControlList.end()) {
+ AUCarbonViewControl *ctl = *it;
+ mControlList.erase(it);
+ delete ctl;
+ }
+}
+
+void AUCarbonViewBase::ClearControls ()
+{
+ for (ControlList::iterator it = mControlList.begin(); it != mControlList.end(); ++it) {
+ AUCarbonViewControl *ctl = *it;
+ delete ctl;
+ }
+ mControlList.clear();
+}
+
+void AUCarbonViewBase::ParameterListener(void * inCallbackRefCon,
+ void * inObject,
+ const AudioUnitEvent * inEvent,
+ UInt64 inEventHostTime,
+ Float32 inParameterValue)
+{
+ if (inEvent->mEventType == kAudioUnitEvent_ParameterValueChange) {
+ AUCarbonViewControl *ctl = (AUCarbonViewControl *)inObject;
+ ctl->ParameterToControl(inParameterValue);
+ }
+}
+
+
+OSStatus AUCarbonViewBase::CreateCarbonView(AudioUnit inAudioUnit, WindowRef inWindow, ControlRef inParentControl, const Float32Point &inLocation, const Float32Point &inSize, ControlRef &outParentControl)
+{
+#if !__LP64__
+ mEditAudioUnit = inAudioUnit;
+ mCarbonWindow = inWindow;
+
+ WindowAttributes attributes;
+ verify_noerr(GetWindowAttributes(mCarbonWindow, &attributes));
+ mCompositWindow = (attributes & kWindowCompositingAttribute) != 0;
+
+ Rect area;
+ area.left = short(inLocation.x); area.top = short(inLocation.y);
+ area.right = short(area.left + inSize.x); area.bottom = short(area.top + inSize.y);
+ OSStatus err = ::CreateUserPaneControl(inWindow, &area,
+ kControlSupportsEmbedding,
+ &mCarbonPane); // subclass can resize mCarbonPane to taste
+ verify_noerr(err);
+ if (err) return err;
+ outParentControl = mCarbonPane;
+
+ // register for mouse-down in our pane -- we want to clear focus
+ EventTypeSpec paneEvents[] = {
+ { kEventClassControl, kEventControlClick }
+ };
+ WantEventTypes(GetControlEventTarget(mCarbonPane), GetEventTypeCount(paneEvents), paneEvents);
+
+ if (IsCompositWindow()) {
+ verify_noerr(::HIViewAddSubview(inParentControl, mCarbonPane));
+ mXOffset = 0;
+ mYOffset = 0;
+ }
+ else {
+ verify_noerr(::EmbedControl(mCarbonPane, inParentControl));
+ mXOffset = inLocation.x;
+ mYOffset = inLocation.y;
+ }
+ mBottomRight.h = mBottomRight.v = 0;
+
+ SizeControl(mCarbonPane, 0, 0);
+ if (err = CreateUI(mXOffset, mYOffset))
+ return err;
+
+ // we should only resize the control if a subclass has embedded
+ // controls in this AND this is done with the EmbedControl call below
+ // if mBottomRight is STILL equal to zero, then that wasn't done
+ // so don't size the control
+ Rect paneBounds;
+ GetControlBounds(mCarbonPane, &paneBounds);
+ // only resize mCarbonPane if it has not already been resized during CreateUI
+ if ((paneBounds.top == paneBounds.bottom) && (paneBounds.left == paneBounds.right)) {
+ if (mBottomRight.h != 0 && mBottomRight.v != 0)
+ SizeControl(mCarbonPane, (short) (mBottomRight.h - mXOffset), (short) (mBottomRight.v - mYOffset));
+ }
+
+ if (IsCompositWindow()) {
+ // prepare for handling scroll-events
+ EventTypeSpec scrollEvents[] = {
+ { kEventClassScrollable, kEventScrollableGetInfo },
+ { kEventClassScrollable, kEventScrollableScrollTo }
+ };
+
+ WantEventTypes(GetControlEventTarget(mCarbonPane), GetEventTypeCount(scrollEvents), scrollEvents);
+
+ mCurrentScrollPoint.x = mCurrentScrollPoint.y = 0.0f;
+ }
+
+ return err;
+#else
+ return noErr;
+#endif
+}
+
+OSStatus AUCarbonViewBase::CreateUI(Float32 inXOffset, Float32 inYOffset)
+{
+ return noErr;
+}
+
+OSStatus AUCarbonViewBase::EmbedControl(ControlRef ctl)
+{
+#if !__LP64__
+ Rect r;
+ ::GetControlBounds(ctl, &r);
+ if (r.right > mBottomRight.h) mBottomRight.h = r.right;
+ if (r.bottom > mBottomRight.v) mBottomRight.v = r.bottom;
+
+ if (IsCompositWindow())
+ return ::HIViewAddSubview(mCarbonPane, ctl);
+ else
+ return ::EmbedControl(ctl, mCarbonPane);
+#else
+ return noErr;
+#endif
+}
+
+void AUCarbonViewBase::AddCarbonControl(AUCarbonViewControl::ControlType type, const CAAUParameter &param, ControlRef control)
+{
+ verify_noerr(EmbedControl(control));
+
+ AUCarbonViewControl *auvc = new AUCarbonViewControl(this, mParameterListener, type, param, control);
+ auvc->Bind();
+ AddControl(auvc);
+}
+
+bool AUCarbonViewBase::HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event)
+{
+#if !__LP64__
+ UInt32 eclass = GetEventClass(event);
+ UInt32 ekind = GetEventKind(event);
+ ControlRef control;
+
+ switch (eclass) {
+ case kEventClassControl:
+ {
+ switch (ekind) {
+ case kEventControlClick:
+ GetEventParameter(event, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
+ if (control == mCarbonPane) {
+ ClearKeyboardFocus(mCarbonWindow);
+ return true;
+ }
+ }
+ }
+ break;
+
+ case kEventClassScrollable:
+ {
+ switch (ekind) {
+ case kEventScrollableGetInfo:
+ {
+ // [1/4]
+ /* <-- kEventParamImageSize (out, typeHISize)
+ * On exit, contains the size of the entire scrollable view.
+ */
+ HISize originalSize = { mBottomRight.h, mBottomRight.v };
+ verify_noerr(SetEventParameter(event, kEventParamImageSize, typeHISize, sizeof(HISize), &originalSize));
+
+ // [2/4]
+ /* <-- kEventParamViewSize (out, typeHISize)
+ * On exit, contains the amount of the scrollable view that is
+ * visible.
+ */
+ HIViewRef parentView = HIViewGetSuperview(mCarbonPane);
+ HIRect parentBounds;
+ verify_noerr(HIViewGetBounds(parentView, &parentBounds));
+ //HISize windowSize = { float(windowBounds.right - windowBounds.left),
+ // float(windowBounds.bottom - windowBounds.top) };
+ verify_noerr(SetEventParameter(event, kEventParamViewSize, typeHISize, sizeof(HISize), &(parentBounds.size)));
+
+ // [3/4]
+ /* <-- kEventParamLineSize (out, typeHISize)
+ * On exit, contains the amount that should be scrolled in
+ * response to a single click on a scrollbar arrow.
+ */
+ HISize scrollIncrementSize = { 16.0f, float(20) };
+ verify_noerr(SetEventParameter(event, kEventParamLineSize, typeHISize, sizeof(HISize), &scrollIncrementSize));
+
+ // [4/4]
+ /* <-- kEventParamOrigin (out, typeHIPoint)
+ * On exit, contains the scrollable viewÕs current origin (the
+ * view-relative coordinate that is drawn at the top left
+ * corner of its frame). These coordinates should always be
+ * greater than or equal to zero. They should be less than or
+ * equal to the viewÕs image size minus its view size.
+ */
+ verify_noerr(SetEventParameter(event, kEventParamOrigin, typeHIPoint, sizeof(HIPoint), &mCurrentScrollPoint));
+ }
+ return true;
+
+ case kEventScrollableScrollTo:
+ {
+ /*
+ * kEventClassScrollable / kEventScrollableScrollTo
+ *
+ * Summary:
+ * Requests that an HIScrollViewÕs scrollable view should scroll to
+ * a particular origin.
+ */
+
+ /* --> kEventParamOrigin (in, typeHIPoint)
+ * The new origin for the scrollable view. The origin
+ * coordinates will vary from (0,0) to scrollable viewÕs image
+ * size minus its view size.
+ */
+ HIPoint pointToScrollTo;
+ verify_noerr(GetEventParameter(event, kEventParamOrigin, typeHIPoint, NULL, sizeof(HIPoint), NULL, &pointToScrollTo));
+
+ float xDelta = mCurrentScrollPoint.x - pointToScrollTo.x;
+ float yDelta = mCurrentScrollPoint.y - pointToScrollTo.y;
+ // move visible portion the appropriate amount
+ verify_noerr(HIViewScrollRect(mCarbonPane, NULL, xDelta, yDelta));
+ // set new content to be drawn
+ verify_noerr(HIViewSetBoundsOrigin(mCarbonPane, pointToScrollTo.x, pointToScrollTo.y));
+
+ mCurrentScrollPoint = pointToScrollTo;
+ }
+ return true;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+#endif
+ return false;
+}
+
+/*! @method TellListener */
+void AUCarbonViewBase::TellListener (const CAAUParameter &auvp, AudioUnitCarbonViewEventID event, void *evpar)
+{
+#if !__LP64__
+ if (mEventListener)
+ (*mEventListener)(mEventListenerUserData, mComponentInstance, &auvp, event, evpar);
+#endif
+
+ AudioUnitEvent auEvent;
+ auEvent.mArgument.mParameter = auvp;
+ if (event == kAudioUnitCarbonViewEvent_MouseDownInControl) {
+ auEvent.mEventType = kAudioUnitEvent_BeginParameterChangeGesture;
+ } else {
+ auEvent.mEventType = kAudioUnitEvent_EndParameterChangeGesture;
+ }
+ AUEventListenerNotify(mParameterListener, this, &auEvent);
+}
+
+
+void AUCarbonViewBase::Update (bool inUIThread)
+{
+ for (ControlList::iterator iter = mControlList.begin(); iter != mControlList.end(); ++iter)
+ {
+ (*iter)->Update(inUIThread);
+ }
+}
+
+pascal void AUCarbonViewBase::TheTimerProc (EventLoopTimerRef inTimer, void *inUserData)
+{
+ AUCarbonViewBase* This = reinterpret_cast<AUCarbonViewBase*>(inUserData);
+ This->RespondToEventTimer (inTimer);
+}
+
+void AUCarbonViewBase::RespondToEventTimer (EventLoopTimerRef inTimer)
+{}
+
+/*
+ THESE are reasonable values for these two times
+ 0.005 // delay
+ 0.050 // interval
+*/
+
+OSStatus AUCarbonViewBase::CreateEventLoopTimer (Float32 inDelay, Float32 inInterval)
+{
+ if (mTimerUPP)
+ return noErr;
+
+ mTimerUPP = NewEventLoopTimerUPP(TheTimerProc);
+
+ EventLoopRef mainEventLoop = GetMainEventLoop();
+
+ //doesn't seem to like too small a value
+ if (inDelay < 0.005)
+ inDelay = 0.005;
+
+ OSStatus timerResult = ::InstallEventLoopTimer(
+ mainEventLoop,
+ inDelay,
+ inInterval,
+ mTimerUPP,
+ this,
+ &mTimerRef);
+ return timerResult;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h
new file mode 100644
index 0000000000..910e53ffa6
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h
@@ -0,0 +1,188 @@
+/*
+ File: AUCarbonViewBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUCarbonViewBase_h__
+#define __AUCarbonViewBase_h__
+
+#include <vector>
+#include "AUCarbonViewControl.h"
+#include "ComponentBase.h"
+
+static const Float32 kDefaultNotificationInterval = 0.100;
+
+ /*! @class AUCarbonViewBase */
+class AUCarbonViewBase : public ComponentBase, public CarbonEventHandler
+{
+public:
+ /*! @ctor AUCarbonViewBase */
+ AUCarbonViewBase ( AudioUnitCarbonView inInstance,
+ Float32 inNotificationInterval = kDefaultNotificationInterval /* in seconds */);
+ /*! @dtor ~AUCarbonViewBase */
+ virtual ~AUCarbonViewBase();
+
+ // AUViewBase overrides
+ /*! @method CreateCarbonView */
+ virtual OSStatus CreateCarbonView (AudioUnit inAudioUnit, WindowRef inWindow, ControlRef inParentControl, const Float32Point &inLocation, const Float32Point &inSize, ControlRef &outParentControl);
+
+ // our own virtual methods
+ /*! @method CreateUI */
+ virtual OSStatus CreateUI (Float32 inXOffset, Float32 inYOffset);
+
+ /*! @method HandleEvent */
+ virtual bool HandleEvent (EventHandlerCallRef inHandlerRef, EventRef event);
+
+ /*! @method GetEditAudioUnit */
+ const AudioUnit GetEditAudioUnit () const { return mEditAudioUnit; }
+ //
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch (
+ ComponentParameters * params,
+ AUCarbonViewBase * This);
+
+ /*! @method AddCarbonControl */
+ void AddCarbonControl (
+ AUCarbonViewControl::ControlType type,
+ const CAAUParameter & param,
+ ControlRef control);
+
+ /*! @method GetCarbonWindow */
+ WindowRef GetCarbonWindow () { return mCarbonWindow; }
+ /*! @method GetCarbonPane */
+ ControlRef GetCarbonPane () { return mCarbonPane; }
+ /*! @method EmbedControl */
+ OSStatus EmbedControl (ControlRef ctl);
+
+ /*! @method TellListener */
+ void TellListener (const CAAUParameter &auvp, AudioUnitCarbonViewEventID event, void *evpar);
+
+ // pass in true if wanting an update to the view and you're calling this from a thread
+ // that is safe to do UI in.
+ // If you don't know, pass in false!
+ /*! @method Update */
+ void Update (bool inUIThread);
+
+ /*! @method GetXOffset */
+ Float32 GetXOffset () { return mXOffset; }
+ /*! @method GetYOffset */
+ Float32 GetYOffset () { return mYOffset; }
+
+ /*! @method ClearControls */
+ void ClearControls ();
+
+ /*! @method IsCompositWindow */
+ bool IsCompositWindow () const { return mCompositWindow; }
+
+protected:
+#if !__LP64__
+ /*! @method SetEventListener */
+ void SetEventListener (AudioUnitCarbonViewEventListener listener, void *userData)
+ {
+ mEventListener = listener;
+ mEventListenerUserData = userData;
+ }
+#endif
+
+ /*! @method AddControl */
+ void AddControl (AUCarbonViewControl *control);
+ /*! @method RemoveControl */
+ void RemoveControl (AUCarbonViewControl *control);
+
+ OSStatus CreateEventLoopTimer (Float32 inDelay, Float32 inInterval);
+
+ /*! @method ParameterListener */
+ static void ParameterListener (void * inCallbackRefCon,
+ void * inObject,
+ const AudioUnitEvent * inEvent,
+ UInt64 inEventHostTime,
+ Float32 inParameterValue);
+
+ static pascal void TheTimerProc ( EventLoopTimerRef inTimer,
+ void * inUserData);
+
+ virtual void RespondToEventTimer (EventLoopTimerRef inTimer);
+
+ /*! @var mEditAudioUnit */
+ AudioUnit mEditAudioUnit; // the AU we're controlling
+ /*! @var mParameterListener */
+ AUEventListenerRef mParameterListener;
+
+#if !__LP64__
+ /*! @var mEventListener */
+ AudioUnitCarbonViewEventListener
+ mEventListener;
+#endif
+
+ /*! @var mEventListenerUserData */
+ void * mEventListenerUserData;
+
+private:
+ typedef std::vector<AUCarbonViewControl *> ControlList;
+ /*! @var mControlList */
+ ControlList mControlList;
+
+ EventLoopTimerRef mTimerRef;
+
+ EventLoopTimerUPP mTimerUPP;
+
+protected:
+ /*! @var mCarbonWindow */
+ WindowRef mCarbonWindow;
+ /*! @var mCarbonPane */
+ ControlRef mCarbonPane; // user pane, contains all other controls
+ /*! @var mBottomRight */
+ Point mBottomRight; // largest width and height of child controls
+ /*! @var mXOffset */
+ Float32 mXOffset;
+ /*! @var mYOffset */
+ Float32 mYOffset;
+ /*! @var mCompositWindow */
+ bool mCompositWindow;
+ /*! @var mCurrentScrollPoint */
+ HIPoint mCurrentScrollPoint; // needed for scrolling
+};
+
+
+#endif // __AUCarbonViewBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp
new file mode 100644
index 0000000000..981347b0f1
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp
@@ -0,0 +1,710 @@
+/*
+ File: AUCarbonViewControl.cpp
+ Abstract: AUCarbonViewControl.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUCarbonViewControl.h"
+#include "AUCarbonViewBase.h"
+#include "AUViewLocalizedStringKeys.h"
+
+AUCarbonViewControl::AUCarbonViewControl(AUCarbonViewBase *ownerView, AUParameterListenerRef listener, ControlType type, const CAAUParameter &param, ControlRef control) :
+ mOwnerView(ownerView),
+ mListener(listener),
+ mType(type),
+ mParam(param),
+ mControl(control),
+ mInControlInitialization(0)
+{
+#if !__LP64__
+ SetControlReference(control, SRefCon(this));
+#endif
+}
+
+AUCarbonViewControl::~AUCarbonViewControl()
+{
+ AUListenerRemoveParameter(mListener, this, &mParam);
+}
+
+AUCarbonViewControl* AUCarbonViewControl::mLastControl = NULL;
+
+void AUCarbonViewControl::Bind()
+{
+#if !__LP64__
+ mInControlInitialization = 1; // true
+ AUListenerAddParameter(mListener, this, &mParam);
+ // will cause an almost-immediate callback
+
+ EventTypeSpec events[] = {
+ { kEventClassControl, kEventControlValueFieldChanged } // N.B. OS X only
+ };
+
+ WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
+
+ if (mType == kTypeContinuous || mType == kTypeText || mType == kTypeDiscrete) {
+ EventTypeSpec events[] = {
+ { kEventClassControl, kEventControlHit },
+ { kEventClassControl, kEventControlClick },
+ { kEventClassControl, kEventControlTrack }
+ };
+ WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
+ }
+
+ if (mType == kTypeText) {
+ EventTypeSpec events[] = {
+ { kEventClassControl, kEventControlSetFocusPart }
+ };
+ WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
+ ControlKeyFilterUPP proc = mParam.ValuesHaveStrings() ? StdKeyFilterCallback : NumericKeyFilterCallback;
+ // this will fail for a static text field
+ SetControlData(mControl, 0, kControlEditTextKeyFilterTag, sizeof(proc), &proc);
+ }
+
+ Update(true);
+ mInControlInitialization = 0; // false
+#endif
+}
+
+void AUCarbonViewControl::ParameterToControl(Float32 paramValue)
+{
+#if !__LP64__
+ ++mInControlInitialization;
+ switch (mType) {
+ case kTypeContinuous:
+ SetValueFract(AUParameterValueToLinear(paramValue, &mParam));
+ break;
+ case kTypeDiscrete:
+ {
+ long value = long(paramValue);
+
+ // special case [1] -- menu parameters
+ if (mParam.HasNamedParams()) {
+ // if we're dealing with menus they behave differently!
+ // becaue setting min and max doesn't work correctly for the control value
+ // first menu item always reports a control value of 1
+ ControlKind ctrlKind;
+ if (GetControlKind(mControl, &ctrlKind) == noErr) {
+ if ((ctrlKind.kind == kControlKindPopupArrow)
+ || (ctrlKind.kind == kControlKindPopupButton))
+ {
+ value = value - long(mParam.ParamInfo().minValue) + 1;
+ }
+ }
+ }
+
+ // special case [2] -- Write-only boolean parameters
+ AudioUnitParameterInfo AUPI = mParam.ParamInfo();
+
+ bool isWriteOnlyBoolParameter = ( (AUPI.unit == kAudioUnitParameterUnit_Boolean) &&
+ (AUPI.flags & kAudioUnitParameterFlag_IsWritable) &&
+ !(AUPI.flags & kAudioUnitParameterFlag_IsReadable) );
+ if (!isWriteOnlyBoolParameter) {
+ SetValue (value);
+ }
+ }
+ break;
+ case kTypeText:
+ {
+ CFStringRef cfstr = mParam.GetStringFromValueCopy(&paramValue);
+
+ if ( !(mParam.ParamInfo().flags & kAudioUnitParameterFlag_IsWritable) //READ ONLY PARAMS
+ && (mParam.ParamInfo().flags & kAudioUnitParameterFlag_IsReadable))
+ {
+ if (mParam.GetParamTag()) {
+ CFMutableStringRef str = CFStringCreateMutableCopy(NULL, 256, cfstr);
+ CFRelease (cfstr);
+ CFStringAppend (str, CFSTR(" "));
+ CFStringAppend (str, mParam.GetParamTag());
+ cfstr = str;
+ }
+ }
+ SetTextValue(cfstr);
+ CFRelease (cfstr);
+ }
+ break;
+ }
+ --mInControlInitialization;
+#endif
+}
+
+void AUCarbonViewControl::ControlToParameter()
+{
+#if !__LP64__
+ if (mInControlInitialization)
+ return;
+
+ switch (mType) {
+ case kTypeContinuous:
+ {
+ double controlValue = GetValueFract();
+ Float32 paramValue = AUParameterValueFromLinear(controlValue, &mParam);
+ mParam.SetValue(mListener, this, paramValue);
+ }
+ break;
+ case kTypeDiscrete:
+ {
+ long value = GetValue();
+
+ // special case [1] -- Menus
+ if (mParam.HasNamedParams()) {
+ // if we're dealing with menus they behave differently!
+ // becaue setting min and max doesn't work correctly for the control value
+ // first menu item always reports a control value of 1
+ ControlKind ctrlKind;
+ if (GetControlKind(mControl, &ctrlKind) == noErr) {
+ if ((ctrlKind.kind == kControlKindPopupArrow)
+ || (ctrlKind.kind == kControlKindPopupButton))
+ {
+ value = value + long(mParam.ParamInfo().minValue) - 1;
+ }
+ }
+ }
+
+ // special case [2] -- Write-only boolean parameters
+ AudioUnitParameterInfo AUPI = mParam.ParamInfo();
+
+ bool isWriteOnlyBoolParameter = ( (AUPI.unit == kAudioUnitParameterUnit_Boolean) &&
+ (AUPI.flags & kAudioUnitParameterFlag_IsWritable) &&
+ !(AUPI.flags & kAudioUnitParameterFlag_IsReadable) );
+ if (isWriteOnlyBoolParameter) {
+ value = 1;
+ }
+
+ mParam.SetValue (mListener, this, value);
+ }
+ break;
+ case kTypeText:
+ {
+ Float32 val = mParam.GetValueFromString (GetTextValue());
+ mParam.SetValue(mListener, this, (mParam.IsIndexedParam() ? (int)val : val));
+ if (mParam.ValuesHaveStrings())
+ ParameterToControl(val); //make sure we display the correct text (from the AU)
+ }
+ break;
+ }
+#endif
+}
+
+void AUCarbonViewControl::SetValueFract(double value)
+{
+#if !__LP64__
+ SInt32 minimum = GetControl32BitMinimum(mControl);
+ SInt32 maximum = GetControl32BitMaximum(mControl);
+ SInt32 cval = SInt32(value * (maximum - minimum) + minimum + 0.5);
+ SetControl32BitValue(mControl, cval);
+// printf("set: value=%lf, min=%ld, max=%ld, ctl value=%ld\n", value, minimum, maximum, cval);
+#endif
+}
+
+double AUCarbonViewControl::GetValueFract()
+{
+#if !__LP64__
+ SInt32 minimum = GetControl32BitMinimum(mControl);
+ SInt32 maximum = GetControl32BitMaximum(mControl);
+ SInt32 cval = GetControl32BitValue(mControl);
+ double result = double(cval - minimum) / double(maximum - minimum);
+// printf("get: min=%ld, max=%ld, value=%ld, result=%f\n", minimum, maximum, cval, result);
+ return result;
+#else
+ return 0;
+#endif
+}
+
+void AUCarbonViewControl::SetTextValue(CFStringRef cfstr)
+{
+#if !__LP64__
+ verify_noerr(SetControlData(mControl, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), &cfstr));
+#endif
+}
+
+CFStringRef AUCarbonViewControl::GetTextValue()
+{
+#if !__LP64__
+ CFStringRef cfstr;
+ verify_noerr(GetControlData(mControl, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), &cfstr, NULL));
+ return cfstr;
+#else
+ return CFSTR("");
+#endif
+}
+
+void AUCarbonViewControl::SetValue(long value)
+{
+#if !__LP64__
+ SetControl32BitValue(mControl, value);
+#endif
+}
+
+long AUCarbonViewControl::GetValue()
+{
+#if !__LP64__
+ return GetControl32BitValue(mControl);
+#else
+ return 0;
+#endif
+}
+
+/* Notes on event handling
+
+ Button (Click and release on button)
+ kEventControlClick received
+ kEventControlTrack received
+ kEventControlValueFieldChanged received
+ kEventControlHit received
+
+ Button (Click and release outside of button bounds)
+ kEventControlClick received
+ kEventControlTrack received
+
+ Slider (Click, drag, and release)
+ kEventControlClick received
+ kEventControlTrack received
+ kEventControlValueFieldChanged received
+ kEventControlValueFieldChanged received
+ kEventControlHit received
+
+ Slider (Click, release without changing value)
+ kEventControlClick received
+ kEventControlTrack received
+*/
+bool AUCarbonViewControl::HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event)
+{
+ UInt32 eclass = GetEventClass(event);
+ UInt32 ekind = GetEventKind(event);
+ ControlRef control;
+ bool handled = true;
+
+ switch (eclass) {
+ case kEventClassControl:
+ {
+ AudioUnitParameterInfo AUPI = mParam.ParamInfo();
+
+ bool isWriteOnlyBoolParameter = ( (AUPI.unit == kAudioUnitParameterUnit_Boolean) &&
+ (AUPI.flags & kAudioUnitParameterFlag_IsWritable) &&
+ !(AUPI.flags & kAudioUnitParameterFlag_IsReadable) );
+
+ switch (ekind) {
+ case kEventControlSetFocusPart: // tab
+ handled = !handled; // fall through to next case
+ mLastControl = this;
+ case kEventControlValueFieldChanged:
+ GetEventParameter(event, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
+ verify(control == mControl);
+ ControlToParameter();
+ return handled;
+ case kEventControlClick:
+ if (isWriteOnlyBoolParameter) {
+ GetEventParameter(event, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
+ verify(control == mControl);
+ ControlToParameter();
+ } else if (mLastControl != this) {
+ if (mLastControl != NULL) {
+ mLastControl->Update(false);
+ }
+ mLastControl = this;
+ }
+ mOwnerView->TellListener(mParam, kAudioUnitCarbonViewEvent_MouseDownInControl, NULL);
+ break; // don't return true, continue normal processing
+ case kEventControlHit:
+ if (mLastControl != this) {
+ if (mLastControl != NULL)
+ mLastControl->Update(false);
+ mLastControl = this;
+ }
+ mOwnerView->TellListener(mParam, kAudioUnitCarbonViewEvent_MouseUpInControl, NULL);
+ break; // don't return true, continue normal processing
+ case kEventControlTrack:
+ if (mLastControl != this) {
+ if (mLastControl != NULL)
+ mLastControl->Update(false);
+ mLastControl = this;
+ }
+
+ CallNextEventHandler(inHandlerRef, event);
+ ControlToParameter(); // new code
+ mOwnerView->TellListener(mParam, kAudioUnitCarbonViewEvent_MouseUpInControl, NULL);
+ // old code:
+ // break; // don't return true, continue normal processing
+
+ return handled; // don't return true, continue normal processing
+ }
+ }
+ }
+ return !handled;
+}
+
+pascal void AUCarbonViewControl::SliderTrackProc(ControlRef theControl, ControlPartCode partCode)
+{
+ // this doesn't need to actually do anything
+// AUCarbonViewControl *This = (AUCarbonViewControl *)GetControlReference(theControl);
+}
+
+pascal ControlKeyFilterResult AUCarbonViewControl::StdKeyFilterCallback(ControlRef theControl,
+ SInt16 *keyCode, SInt16 *charCode,
+ EventModifiers *modifiers)
+{
+#if !__LP64__
+ SInt16 c = *charCode;
+ if (c >= ' ' || c == '\b' || c == 0x7F || (c >= 0x1c && c <= 0x1f) || c == '\t')
+ return kControlKeyFilterPassKey;
+ if (c == '\r' || c == 3) { // return or Enter
+ AUCarbonViewControl *This = (AUCarbonViewControl *)GetControlReference(theControl);
+ ControlEditTextSelectionRec sel = { 0, 32767 };
+ SetControlData(This->mControl, 0, kControlEditTextSelectionTag, sizeof(sel), &sel);
+ This->ControlToParameter();
+ }
+#endif
+ return kControlKeyFilterBlockKey;
+}
+
+pascal ControlKeyFilterResult AUCarbonViewControl::NumericKeyFilterCallback(ControlRef theControl,
+ SInt16 *keyCode, SInt16 *charCode,
+ EventModifiers *modifiers)
+{
+#if !__LP64__
+ SInt16 c = *charCode;
+ if (isdigit(c) || c == '+' || c == '-' || c == '.' || c == '\b' || c == 0x7F || (c >= 0x1c && c <= 0x1f)
+ || c == '\t')
+ return kControlKeyFilterPassKey;
+ if (c == '\r' || c == 3) { // return or Enter
+ AUCarbonViewControl *This = (AUCarbonViewControl *)GetControlReference(theControl);
+ ControlEditTextSelectionRec sel = { 0, 32767 };
+ SetControlData(This->mControl, 0, kControlEditTextSelectionTag, sizeof(sel), &sel);
+ This->ControlToParameter();
+ }
+#endif
+ return kControlKeyFilterBlockKey;
+}
+
+Boolean AUCarbonViewControl::SizeControlToFit(ControlRef inControl, SInt16 *outWidth, SInt16 *outHeight)
+{
+#if !__LP64__
+ if (inControl == 0) return false;
+
+ Boolean bValue = false;
+ // this only works on text controls -- returns an error for other controls, but doesn't do anything,
+ // so the error is irrelevant
+ SetControlData(inControl, kControlEntireControl, 'stim' /* kControlStaticTextIsMultilineTag */, sizeof(Boolean), &bValue);
+
+ SInt16 baseLineOffset;
+ Rect bestRect;
+ OSErr err = GetBestControlRect(inControl, &bestRect, &baseLineOffset);
+ if (err != noErr) return false;
+
+ int width = (bestRect.right - bestRect.left) + 1;
+ int height = (bestRect.bottom - bestRect.top) + 1;
+
+ Rect boundsRect;
+ GetControlBounds (inControl, &boundsRect);
+
+ Rect newRect;
+ newRect.top = boundsRect.top;
+ newRect.bottom = newRect.top + height;
+ newRect.left = boundsRect.left;
+ newRect.right = newRect.left + width;
+
+ SetControlBounds (inControl, &newRect);
+
+ if (outWidth)
+ *outWidth = width;
+
+ if (outHeight)
+ *outHeight = height;
+#endif
+ return true;
+}
+
+#pragma mark ___AUPropertyControl
+bool AUPropertyControl::HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event)
+{
+ UInt32 eclass = GetEventClass(event);
+ UInt32 ekind = GetEventKind(event);
+ switch (eclass) {
+ case kEventClassControl:
+ switch (ekind) {
+ case kEventControlValueFieldChanged:
+ HandleControlChange();
+ return true; // handled
+ }
+ }
+
+ return false;
+}
+
+void AUPropertyControl::RegisterEvents ()
+{
+#if !__LP64__
+ EventTypeSpec events[] = {
+ { kEventClassControl, kEventControlValueFieldChanged } // N.B. OS X only
+ };
+
+ WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
+#endif
+}
+
+void AUPropertyControl::EmbedControl (ControlRef theControl)
+{
+ mView->EmbedControl (theControl);
+}
+
+WindowRef AUPropertyControl::GetCarbonWindow()
+{
+ return mView->GetCarbonWindow();
+}
+
+#pragma mark ___AUVPreset
+#if !__LP64__
+static CFStringRef kStringFactoryPreset = kAUViewLocalizedStringKey_FactoryPreset;
+static bool sAUVPresetLocalized = false;
+#endif
+
+AUVPresets::AUVPresets (AUCarbonViewBase* inParentView,
+ CFArrayRef& inPresets,
+ Point inLocation,
+ int nameWidth,
+ int controlWidth,
+ ControlFontStyleRec & inFontStyle)
+ : AUPropertyControl (inParentView),
+ mPresets (inPresets),
+ mView (inParentView)
+{
+#if !__LP64__
+ Rect r;
+
+ // ok we now have an array of factory presets
+ // get their strings and display them
+
+ r.top = inLocation.v; r.bottom = r.top;
+ r.left = inLocation.h; r.right = r.left;
+
+ // localize as necessary
+ if (!sAUVPresetLocalized) {
+ CFBundleRef mainBundle = CFBundleGetBundleWithIdentifier(kLocalizedStringBundle_AUView);
+ if (mainBundle) {
+ kStringFactoryPreset = CFCopyLocalizedStringFromTableInBundle(
+ kAUViewLocalizedStringKey_FactoryPreset, kLocalizedStringTable_AUView,
+ mainBundle, CFSTR("FactoryPreset title string"));
+ sAUVPresetLocalized = true;
+ }
+ }
+
+ // create localized title string
+ CFMutableStringRef factoryPresetsTitle = CFStringCreateMutable(NULL, 0);
+ CFStringAppend(factoryPresetsTitle, kStringFactoryPreset);
+ CFStringAppend(factoryPresetsTitle, kAUViewUnlocalizedString_TitleSeparator);
+
+ ControlRef theControl;
+ verify_noerr(CreateStaticTextControl(mView->GetCarbonWindow(), &r, factoryPresetsTitle, &inFontStyle, &theControl));
+ SInt16 width = 0;
+ AUCarbonViewControl::SizeControlToFit(theControl, &width, &mHeight);
+ CFRelease(factoryPresetsTitle);
+ EmbedControl(theControl);
+
+ r.top -= 2;
+ r.left += width + 10;
+ r.right = r.left;
+ r.bottom = r.top;
+
+ verify_noerr(CreatePopupButtonControl ( mView->GetCarbonWindow(), &r, NULL,
+ -12345, // DON'T GET MENU FROM RESOURCE mMenuID,!!!
+ FALSE, // variableWidth,
+ 0, // titleWidth,
+ 0, // titleJustification,
+ 0, // titleStyle,
+ &mControl));
+
+ MenuRef menuRef;
+ verify_noerr(CreateNewMenu(1, 0, &menuRef));
+
+ int numPresets = CFArrayGetCount(mPresets);
+
+ for (int i = 0; i < numPresets; ++i)
+ {
+ AUPreset* preset = (AUPreset*) CFArrayGetValueAtIndex (mPresets, i);
+ verify_noerr(AppendMenuItemTextWithCFString (menuRef, preset->presetName, 0, 0, 0));
+ }
+
+ verify_noerr(SetControlData(mControl, 0, kControlPopupButtonMenuRefTag, sizeof(menuRef), &menuRef));
+ verify_noerr (SetControlFontStyle (mControl, &inFontStyle));
+
+ SetControl32BitMaximum (mControl, numPresets);
+
+ // size popup
+ SInt16 height = 0;
+
+ AUCarbonViewControl::SizeControlToFit(mControl, &width, &height);
+
+ if (height > mHeight) mHeight = height;
+ if (mHeight < 0) mHeight = 0;
+
+ // find which menu item is the Default preset
+ UInt32 propertySize = sizeof(AUPreset);
+ AUPreset defaultPreset;
+ OSStatus result = AudioUnitGetProperty (mView->GetEditAudioUnit(),
+ kAudioUnitProperty_PresentPreset,
+ kAudioUnitScope_Global,
+ 0,
+ &defaultPreset,
+ &propertySize);
+
+ mPropertyID = kAudioUnitProperty_PresentPreset;
+#endif
+#ifndef __LP64__
+ if (result != noErr) { // if the PresentPreset property is not implemented, fall back to the CurrentPreset property
+ OSStatus result = AudioUnitGetProperty (mView->GetEditAudioUnit(),
+ kAudioUnitProperty_CurrentPreset,
+ kAudioUnitScope_Global,
+ 0,
+ &defaultPreset,
+ &propertySize);
+ mPropertyID = kAudioUnitProperty_CurrentPreset;
+ if (result == noErr)
+ CFRetain (defaultPreset.presetName);
+ }
+#endif
+#if !__LP64__
+ EmbedControl (mControl);
+
+ HandlePropertyChange(defaultPreset);
+
+ RegisterEvents();
+#endif
+}
+
+void AUVPresets::AddInterest (AUEventListenerRef inListener,
+ void * inObject)
+{
+ AudioUnitEvent e;
+ e.mEventType = kAudioUnitEvent_PropertyChange;
+ e.mArgument.mProperty.mAudioUnit = mView->GetEditAudioUnit();
+ e.mArgument.mProperty.mPropertyID = mPropertyID;
+ e.mArgument.mProperty.mScope = kAudioUnitScope_Global;
+ e.mArgument.mProperty.mElement = 0;
+
+ AUEventListenerAddEventType(inListener, inObject, &e);
+}
+
+void AUVPresets::RemoveInterest (AUEventListenerRef inListener,
+ void * inObject)
+{
+ AudioUnitEvent e;
+ e.mEventType = kAudioUnitEvent_PropertyChange;
+ e.mArgument.mProperty.mAudioUnit = mView->GetEditAudioUnit();
+ e.mArgument.mProperty.mPropertyID = mPropertyID;
+ e.mArgument.mProperty.mScope = kAudioUnitScope_Global;
+ e.mArgument.mProperty.mElement = 0;
+
+ AUEventListenerRemoveEventType(inListener, inObject, &e);
+}
+
+void AUVPresets::HandleControlChange ()
+{
+#if !__LP64__
+ SInt32 i = GetControl32BitValue(mControl);
+ if (i > 0)
+ {
+ AUPreset* preset = (AUPreset*) CFArrayGetValueAtIndex (mPresets, i-1);
+
+ verify_noerr(AudioUnitSetProperty (mView->GetEditAudioUnit(),
+ mPropertyID, // either currentPreset or PresentPreset depending on which is supported
+ kAudioUnitScope_Global,
+ 0,
+ preset,
+ sizeof(AUPreset)));
+
+ // when we change a preset we can't expect the AU to update its state
+ // as it isn't meant to know that its being viewed!
+ // so we broadcast a notification to all listeners that all parameters on this AU have changed
+ AudioUnitParameter changedUnit;
+ changedUnit.mAudioUnit = mView->GetEditAudioUnit();
+ changedUnit.mParameterID = kAUParameterListener_AnyParameter;
+ verify_noerr (AUParameterListenerNotify (NULL, NULL, &changedUnit) );
+ }
+#endif
+}
+
+void AUVPresets::HandlePropertyChange(AUPreset &preset)
+{
+#if !__LP64__
+ // check to see if the preset is in our menu
+ int numPresets = CFArrayGetCount(mPresets);
+ if (preset.presetNumber < 0) {
+ SetControl32BitValue (mControl, 0); //controls are one-based
+ } else {
+ for (SInt32 i = 0; i < numPresets; ++i) {
+ AUPreset* currPreset = (AUPreset*) CFArrayGetValueAtIndex (mPresets, i);
+ if (preset.presetNumber == currPreset->presetNumber) {
+ SetControl32BitValue (mControl, ++i); //controls are one-based
+ break;
+ }
+ }
+ }
+
+ if (preset.presetName)
+ CFRelease (preset.presetName);
+#endif
+}
+
+bool AUVPresets::HandlePropertyChange (const AudioUnitProperty &inProp)
+{
+ if (inProp.mPropertyID == mPropertyID)
+ {
+ UInt32 theSize = sizeof(AUPreset);
+ AUPreset currentPreset;
+
+ OSStatus result = AudioUnitGetProperty(inProp.mAudioUnit,
+ inProp.mPropertyID,
+ inProp.mScope,
+ inProp.mElement, &currentPreset, &theSize);
+
+ if (result == noErr) {
+#ifndef __LP64__
+ if (inProp.mPropertyID == kAudioUnitProperty_CurrentPreset && currentPreset.presetName)
+ CFRetain (currentPreset.presetName);
+#endif
+ HandlePropertyChange(currentPreset);
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h
new file mode 100644
index 0000000000..3d5f975614
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h
@@ -0,0 +1,230 @@
+/*
+ File: AUCarbonViewControl.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUCarbonViewControl_h__
+#define __AUCarbonViewControl_h__
+
+#include <Carbon/Carbon.h>
+#include <AudioUnit/AudioUnitCarbonView.h>
+#include <AudioToolbox/AudioUnitUtilities.h>
+#include "CarbonEventHandler.h"
+#include "CAAUParameter.h"
+
+class AUCarbonViewBase;
+
+// ____________________________________________________________________________
+// AUCarbonViewControl
+// Wrapper for a control that is wired to an AudioUnit parameter.
+ /*! @class AUCarbonViewControl */
+class AUCarbonViewControl : public CarbonEventHandler {
+ // note that the controls are never disposed; that's managed by the AUCarbonViewBase's
+ // parent pane which contains all of them ... if we later need to be able to delete
+ // individual controls on the fly, extra work needed
+public:
+ enum ControlType {
+ kTypeContinuous, // e.g. slider
+ kTypeDiscrete, // e.g. pop-up menu
+ kTypeText
+ };
+
+ AUCarbonViewControl(AUCarbonViewBase *ownerView, AUParameterListenerRef listener, ControlType type, const CAAUParameter &param, ControlRef control);
+ ~AUCarbonViewControl();
+
+ /*! @method Bind */
+ virtual void Bind(); // second-stage construction
+
+ /*! @method ControlToParameter */
+ virtual void ControlToParameter();
+ /*! @method ParameterToControl */
+ virtual void ParameterToControl(Float32 newValue);
+
+ /*! @method SetValueFract */
+ virtual void SetValueFract(double value);
+ /*! @method GetValueFract */
+ virtual double GetValueFract();
+ /*! @method SetTextValue */
+ virtual void SetTextValue(CFStringRef str);
+ /*! @method GetTextValue */
+ virtual CFStringRef GetTextValue();
+ /*! @method SetValue */
+ virtual void SetValue(long value);
+ /*! @method GetValue */
+ virtual long GetValue();
+
+ /*! @method GetOwnerView */
+ AUCarbonViewBase * GetOwnerView() {return mOwnerView;}
+
+ /*! @method Update */
+ void Update (bool inUIThread)
+ {
+ if (inUIThread)
+ ParameterToControl (mParam.GetValue());
+ else
+ AUParameterListenerNotify (mListener, this, &mParam);
+ }
+
+
+ // CarbonEventHandler overrides
+ /*! @method HandleEvent */
+ virtual bool HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event);
+
+ /*! @method ControlRef */
+ operator ControlRef() { return mControl; }
+
+ /*! @method SizeControlToFit */
+ static Boolean SizeControlToFit(ControlRef inControl, SInt16 *outWidth = NULL, SInt16 *outHeight = NULL);
+
+ /*! @method SliderTrackProc */
+ static pascal void SliderTrackProc(ControlRef theControl, ControlPartCode partCode);
+ /*! @method NumericKeyFilterCallback */
+ static pascal ControlKeyFilterResult NumericKeyFilterCallback(ControlRef theControl, SInt16 *keyCode, SInt16 *charCode,
+ EventModifiers *modifiers);
+protected:
+ /*! @method ParamInfo */
+ const AudioUnitParameterInfo &ParamInfo() { return mParam.ParamInfo(); }
+
+ /*! @var mOwnerView */
+ AUCarbonViewBase * mOwnerView;
+ /*! @var mListener */
+ AUParameterListenerRef mListener;
+ /*! @var mType */
+ ControlType mType;
+ /*! @var mParam */
+ CAAUParameter mParam;
+
+ /*! @var mControl */
+ ControlRef mControl;
+
+ /*! @method StdKeyFilterCallback */
+ static pascal ControlKeyFilterResult StdKeyFilterCallback(ControlRef theControl, SInt16 *keyCode, SInt16 *charCode,
+ EventModifiers *modifiers);
+ SInt16 mInControlInitialization;
+
+ static AUCarbonViewControl* mLastControl;
+};
+
+ /*! @class AUPropertyControl */
+class AUPropertyControl : public CarbonEventHandler {
+public:
+ /*! @ctor AUPropertyControl */
+ AUPropertyControl (AUCarbonViewBase * inBase) : mControl(0), mView (inBase), mHeight(0) {}
+
+ /*! @method HandleEvent */
+ virtual bool HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event);
+
+ /*! @method HandlePropertyChange */
+ virtual bool HandlePropertyChange (const AudioUnitProperty &inProp) = 0;
+
+ /*! @method AddInterest */
+ virtual void AddInterest (AUEventListenerRef inListener,
+ void * inObject) = 0;
+
+ /*! @method RemoveInterest */
+ virtual void RemoveInterest (AUEventListenerRef inListener,
+ void * inObject) = 0;
+
+ /*! @method GetHeight */
+ int GetHeight() { return mHeight;}
+
+protected:
+ /*! @method HandleControlChange */
+ virtual void HandleControlChange () = 0;
+
+ /*! @method RegisterEvents */
+ void RegisterEvents ();
+
+ /*! @method EmbedControl */
+ void EmbedControl (ControlRef theControl);
+
+ /*! @method GetCarbonWindow */
+ WindowRef GetCarbonWindow();
+
+ /*! @var mControl */
+ ControlRef mControl;
+ /*! @var mView */
+ AUCarbonViewBase* mView;
+ /*! @var mHeight */
+ SInt16 mHeight;
+};
+
+ /*! @class AUVPresets */
+class AUVPresets : public AUPropertyControl {
+public:
+ /*! @ctor HandleControlChange */
+ AUVPresets (AUCarbonViewBase * inBase,
+ CFArrayRef& inPresets,
+ Point inLocation,
+ int nameWidth,
+ int controlWidth,
+ ControlFontStyleRec & inFontStyle);
+
+ virtual ~AUVPresets () { CFRelease (mPresets); }
+
+ /*! @method HandlePropertyChange */
+ virtual bool HandlePropertyChange (const AudioUnitProperty &inProp);
+
+ /*! @method AddInterest */
+ virtual void AddInterest (AUEventListenerRef inListener,
+ void * inObject);
+
+ /*! @method RemoveInterest */
+ virtual void RemoveInterest (AUEventListenerRef inListener,
+ void * inObject);
+
+protected:
+ /*! @method HandleControlChange */
+ virtual void HandleControlChange ();
+
+ /*! @var mPresets */
+ CFArrayRef mPresets;
+ /*! @var mView */
+ AUCarbonViewBase* mView;
+ AudioUnitPropertyID mPropertyID;
+
+ void HandlePropertyChange(AUPreset &preset);
+};
+
+#endif // __AUCarbonViewControl_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp
new file mode 100644
index 0000000000..15a04e827e
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp
@@ -0,0 +1,125 @@
+/*
+ File: AUCarbonViewDispatch.cpp
+ Abstract: AUCarbonViewDispatch.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUCarbonViewBase.h"
+
+// ____________________________________________________________________________
+// component dispatch
+
+#if PRAGMA_STRUCT_ALIGN
+ #pragma options align=mac68k
+#elif PRAGMA_STRUCT_PACKPUSH
+ #pragma pack(push, 2)
+#elif PRAGMA_STRUCT_PACK
+ #pragma pack(2)
+#endif
+ struct AudioUnitCarbonViewCreateGluePB {
+ unsigned char componentFlags;
+ unsigned char componentParamSize;
+ short componentWhat;
+ ControlRef* outControl;
+ const Float32Point* inSize;
+ const Float32Point* inLocation;
+ ControlRef inParentControl;
+ WindowRef inWindow;
+ AudioUnit inAudioUnit;
+ AudioUnitCarbonView inView;
+ };
+#if !__LP64__
+ struct AudioUnitCarbonViewSetEventListenerGluePB {
+ unsigned char componentFlags;
+ unsigned char componentParamSize;
+ short componentWhat;
+ void* inUserData;
+ AudioUnitCarbonViewEventListener inCallback;
+ AudioUnitCarbonView inView;
+ };
+#endif
+#if PRAGMA_STRUCT_ALIGN
+ #pragma options align=reset
+#elif PRAGMA_STRUCT_PACKPUSH
+ #pragma pack(pop)
+#elif PRAGMA_STRUCT_PACK
+ #pragma pack()
+#endif
+
+#define CheckNull(x) if ((x) == NULL) return paramErr;
+
+OSStatus AUCarbonViewBase::ComponentEntryDispatch(ComponentParameters *p, AUCarbonViewBase *This)
+{
+ if (This == NULL) return paramErr;
+
+ OSStatus result = noErr;
+
+ switch (p->what) {
+ case kAudioUnitCarbonViewCreateSelect:
+ {
+ AudioUnitCarbonViewCreateGluePB *pb = (AudioUnitCarbonViewCreateGluePB *)p;
+ CheckNull(pb->inAudioUnit);
+ CheckNull(pb->inWindow);
+ CheckNull(pb->inParentControl);
+ CheckNull(pb->inSize);
+ CheckNull(pb->inLocation);
+ CheckNull(pb->outControl);
+ result = This->CreateCarbonView(pb->inAudioUnit, pb->inWindow, pb->inParentControl,
+ *pb->inLocation, *pb->inSize, *pb->outControl);
+ }
+ break;
+#if !__LP64__
+ case kAudioUnitCarbonViewSetEventListenerSelect:
+ {
+ AudioUnitCarbonViewSetEventListenerGluePB *pb = (AudioUnitCarbonViewSetEventListenerGluePB *)p;
+ This->SetEventListener(pb->inCallback, pb->inUserData);
+ }
+ break;
+#endif
+
+ default:
+ result = ComponentBase::ComponentEntryDispatch(p, This);
+ break;
+ }
+ return result;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp
new file mode 100644
index 0000000000..8976b401c0
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp
@@ -0,0 +1,359 @@
+/*
+ File: AUControlGroup.cpp
+ Abstract: AUControlGroup.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include <Carbon/Carbon.h>
+#include "AUCarbonViewBase.h"
+#include "AUCarbonViewControl.h"
+#include "AUControlGroup.h"
+#include "AUViewLocalizedStringKeys.h"
+
+#define kSliderThinDimension 10
+#define kLabelAndSliderSpacing 4
+
+#if !__LP64__
+static CFStringRef kStringManufacturer = kAUViewLocalizedStringKey_Manufacturer;
+static bool sLocalized = false;
+#endif
+
+void AUControlGroup::CreateLabelledSlider(
+ AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ Point labelSize,
+ const ControlFontStyleRec & inFontStyle)
+{
+#if !__LP64__
+ ControlFontStyleRec fontStyle = inFontStyle;
+ Rect minValRect, maxValRect, sliderRect;
+ ControlRef newControl;
+ int width = area.right - area.left, height = area.bottom - area.top;
+ CFStringRef cfstr;
+ int sliderValueMax, sliderValueMin, sliderValueDefault;
+ AUCarbonViewControl::ControlType sliderType;
+
+ bool horizontal = (width > height);
+
+ if (horizontal) {
+ maxValRect.top = minValRect.top = area.top + (height - labelSize.v) / 2;
+ minValRect.left = area.left;
+ maxValRect.left = area.right - labelSize.h;
+
+ minValRect.bottom = minValRect.top + labelSize.v;
+ minValRect.right = minValRect.left + labelSize.h;
+ maxValRect.bottom = maxValRect.top + labelSize.v;
+ maxValRect.right = maxValRect.left + labelSize.h;
+
+ sliderRect.left = minValRect.right + kLabelAndSliderSpacing;
+ sliderRect.right = maxValRect.left - kLabelAndSliderSpacing;
+ sliderRect.top = area.top + (height - kSliderThinDimension) / 2;
+ sliderRect.bottom = sliderRect.top + kSliderThinDimension + 4;
+
+ if (auvp.IsIndexedParam ()) {
+ sliderValueMin = sliderValueDefault = int(auvp.ParamInfo().minValue);
+ sliderValueMax = int(auvp.ParamInfo().maxValue);
+ sliderType = AUCarbonViewControl::kTypeDiscrete;
+ } else {
+ sliderValueMin = sliderValueDefault = 0;
+ sliderValueMax = sliderRect.right - sliderRect.left;
+ sliderType = AUCarbonViewControl::kTypeContinuous;
+ }
+ } else {
+ maxValRect.left = minValRect.left = area.left + (width - labelSize.h) / 2;
+ maxValRect.top = area.top;
+ minValRect.top = area.bottom - labelSize.v;
+
+ minValRect.bottom = minValRect.top + labelSize.v;
+ minValRect.right = minValRect.left + labelSize.h;
+ maxValRect.bottom = maxValRect.top + labelSize.v;
+ maxValRect.right = maxValRect.left + labelSize.h;
+
+ sliderRect.left = area.left + (width - kSliderThinDimension) / 2;
+ sliderRect.right = sliderRect.left + kSliderThinDimension + 4;
+ sliderRect.top = maxValRect.bottom + kLabelAndSliderSpacing;
+ sliderRect.bottom = minValRect.top - kLabelAndSliderSpacing;
+
+ if (auvp.IsIndexedParam ()) {
+ sliderValueMin = sliderValueDefault = int(auvp.ParamInfo().minValue);
+ sliderValueMax = int(auvp.ParamInfo().maxValue);
+ sliderType = AUCarbonViewControl::kTypeDiscrete;
+ } else {
+ sliderValueMin = sliderValueDefault = 0;
+ sliderValueMax = sliderRect.bottom - sliderRect.top;
+ sliderType = AUCarbonViewControl::kTypeContinuous;
+ }
+ }
+
+ // minimum value label
+ if (labelSize.v > 0 && labelSize.h > 0) {
+ // check to see if the minimum value has a label
+ cfstr = auvp.GetStringFromValueCopy(&auvp.ParamInfo().minValue);
+ fontStyle.just = horizontal ? teFlushRight : teCenter;
+ verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &minValRect, cfstr, &fontStyle, &newControl));
+ CFRelease(cfstr);
+ verify_noerr(auView->EmbedControl(newControl));
+
+ // maximum value label
+ cfstr = auvp.GetStringFromValueCopy(&auvp.ParamInfo().maxValue);
+ fontStyle.just = horizontal ? teFlushLeft : teCenter;
+ verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &maxValRect, cfstr, &fontStyle, &newControl));
+ CFRelease(cfstr);
+ verify_noerr(auView->EmbedControl(newControl));
+ }
+
+ // slider
+ verify_noerr(CreateSliderControl(auView->GetCarbonWindow(), &sliderRect, sliderValueDefault, sliderValueMin, sliderValueMax, kControlSliderDoesNotPoint, 0, true, AUCarbonViewControl::SliderTrackProc, &newControl));
+
+
+ ControlSize small = kControlSizeSmall;
+ SetControlData(newControl, kControlEntireControl, kControlSizeTag, sizeof(ControlSize), &small);
+ auView->AddCarbonControl(sliderType, auvp, newControl);
+#endif
+}
+
+void AUControlGroup::CreateLabelledSliderAndEditText(
+ AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ Point labelSize,
+ Point editTextSize,
+ const ControlFontStyleRec & inFontStyle)
+{
+#if !__LP64__
+ ControlFontStyleRec fontStyle = inFontStyle;
+ Rect sliderArea, textArea;
+ ControlRef newControl;
+ int width = area.right - area.left, height = area.bottom - area.top;
+
+ bool horizontal = (width > height);
+
+ sliderArea = area;
+ textArea = area;
+ if (horizontal) {
+ textArea.left = area.right - editTextSize.h;
+ // provide a large text box if param is generic and its values have strings...
+ if (auvp.ValuesHaveStrings() && (auvp.ParamInfo().unit == kAudioUnitParameterUnit_Generic))
+ {
+ textArea.right += 30;
+ }
+ sliderArea.right = textArea.left - kLabelAndSliderSpacing;
+ textArea.top = area.top + (height - editTextSize.v) / 2;
+ textArea.bottom = textArea.top + editTextSize.v;
+ } else {
+ textArea.top = area.bottom - editTextSize.v;
+ sliderArea.bottom = textArea.top - kLabelAndSliderSpacing;
+ textArea.left = area.left + (width - editTextSize.h) / 2;
+ textArea.right = textArea.left + editTextSize.h;
+ }
+ CreateLabelledSlider(auView, auvp, sliderArea, labelSize, fontStyle);
+
+ verify_noerr(CreateEditUnicodeTextControl(auView->GetCarbonWindow(), &textArea, CFSTR(""), false,
+ &fontStyle, &newControl));
+ auView->AddCarbonControl(AUCarbonViewControl::kTypeText, auvp, newControl);
+#endif
+}
+
+void AUControlGroup::CreatePopupMenu (AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ const ControlFontStyleRec & inFontStyle,
+ const bool inSizeToFit)
+{
+#if !__LP64__
+ ControlRef thePopUp;
+
+ verify_noerr(CreatePopupButtonControl (auView->GetCarbonWindow(), &area, NULL,
+ -12345, // DON'T GET MENU FROM RESOURCE mMenuID
+ FALSE, // variableWidth,
+ 0, // titleWidth,
+ 0, // titleJustification,
+ 0, // titleStyle,
+ &thePopUp));
+
+ ControlSize small = kControlSizeSmall;
+ SetControlData(thePopUp, kControlEntireControl, kControlSizeTag, sizeof(ControlSize), &small);
+
+ MenuRef menuRef;
+ verify_noerr(CreateNewMenu( 1, 0, &menuRef));
+
+ for (int i = 0; i < auvp.GetNumIndexedParams(); ++i) {
+ verify_noerr(AppendMenuItemTextWithCFString (menuRef, auvp.GetParamName(i), kMenuItemAttrIgnoreMeta, 0, 0));
+ }
+
+ verify_noerr(SetControlData(thePopUp, 0, kControlPopupButtonMenuRefTag, sizeof(menuRef), &menuRef));
+ SetControl32BitMaximum(thePopUp, auvp.GetNumIndexedParams());
+
+ verify_noerr (SetControlFontStyle (thePopUp, &inFontStyle));
+
+ if (inSizeToFit) {
+ AUCarbonViewControl::SizeControlToFit(thePopUp);
+ }
+
+ auView->AddCarbonControl(AUCarbonViewControl::kTypeDiscrete, auvp, thePopUp);
+#endif
+}
+
+void AUControlGroup::AddAUInfo ( AUCarbonViewBase * auView,
+ const Point & inLocation,
+ const SInt16 inRightOffset,
+ const SInt16 inTotalWidth)
+{
+#if !__LP64__
+ // get component info
+ ComponentDescription desc;
+ Handle h1 = NewHandleClear(4);
+ OSStatus err = GetComponentInfo ((Component)auView->GetEditAudioUnit(), &desc, h1, 0, 0);
+
+ if (err == noErr) {
+ // Get the manufacturer's name... look for the ':' character convention
+ HLock(h1);
+ char* ptr1 = *h1;
+ int len = *ptr1++;
+ char* displayStr = 0;
+
+ for (int i = 0; i < len; ++i) {
+ if (ptr1[i] == ':') { // found the name
+ ptr1[i++] = 0;
+ displayStr = ptr1;
+ break;
+ }
+ }
+
+ // localize as necessary:
+ if (!sLocalized) {
+ CFBundleRef mainBundle = CFBundleGetBundleWithIdentifier(kLocalizedStringBundle_AUView);
+ if (mainBundle) {
+ kStringManufacturer = CFCopyLocalizedStringFromTableInBundle(
+ kAUViewLocalizedStringKey_Manufacturer, kLocalizedStringTable_AUView,
+ mainBundle, CFSTR("Manufacturer title string"));
+ sLocalized = true;
+ }
+ }
+
+ // display strings
+ ControlRef newControl;
+ Rect r;
+ r.top = SInt16(inLocation.v); r.bottom = SInt16(inLocation.v) + 16;
+ ControlFontStyleRec fontStyle;
+ fontStyle.flags = kControlUseFontMask | kControlUseJustMask;
+ fontStyle.font = kControlFontSmallBoldSystemFont;
+
+ // display manufacturer string
+ if (displayStr) {
+ CFMutableStringRef mfrstring = CFStringCreateMutable(NULL, 0);
+ CFStringAppend(mfrstring, kStringManufacturer); // "Manufacturer"
+ CFStringAppend(mfrstring, kAUViewUnlocalizedString_TitleSeparator);
+ // "Manufacturer: "
+ CFStringRef mfrname = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingUTF8);
+ if (mfrname) {
+ CFStringAppend(mfrstring, mfrname); // "Manufacturer: MFRName"
+ CFRelease (mfrname);
+ }
+
+ r.left = inLocation.h + inRightOffset;
+ r.right = inLocation.h + inTotalWidth - 28;
+ fontStyle.just = teFlushRight;
+
+ verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &r, mfrstring, &fontStyle, &newControl));
+ verify_noerr(auView->EmbedControl(newControl));
+ CFRelease (mfrstring);
+
+ //move displayStr ptr past the manu, to the name
+ // we move the characters down an index, because the handle doesn't have any room
+ // at the end for the \0
+ int i = strlen(displayStr), j = 0;
+ while (displayStr[++i] == ' ' && i < len)
+ ;
+ while (i < len)
+ displayStr[j++] = displayStr[i++];
+ displayStr[j] = 0;
+ } else {
+ displayStr = ptr1;
+ int i = 0, j = 0;
+ do {
+ displayStr[j] = displayStr[i];
+ ++j; ++i;
+ } while (i < len);
+
+ displayStr[j] = 0;
+ }
+
+ // display AudioUnit string
+ r.left = inLocation.h; r.right = r.left + inRightOffset;
+ fontStyle.just = 0;
+
+ CFMutableStringRef cfstr = CFStringCreateMutable(NULL, 0);
+ CFStringAppend(cfstr, kAUViewLocalizedStringKey_AudioUnit); // "Audio Unit"
+ CFStringAppend(cfstr, kAUViewUnlocalizedString_TitleSeparator);
+ // "Audio Unit: "
+
+ CFStringRef auname = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingUTF8);
+ CFStringAppend(cfstr, auname); // "Audio Unit: AUName"
+ CFRelease (auname);
+
+ verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &r, cfstr, &fontStyle, &newControl));
+
+ // size text control correctly
+ Boolean bValue = false;
+ SetControlData(newControl, kControlEntireControl, 'stim' /* kControlStaticTextIsMultilineTag */, sizeof(Boolean), &bValue);
+ SInt16 baseLineOffset;
+ Rect bestRect;
+ err = GetBestControlRect(newControl, &bestRect, &baseLineOffset);
+ if (err == noErr)
+ {
+ int width = (bestRect.right - bestRect.left) + 1;
+ int height = (bestRect.bottom - bestRect.top) + 1;
+ SizeControl (newControl, width, height);
+ }
+
+ verify_noerr(auView->EmbedControl(newControl));
+ CFRelease (cfstr);
+ }
+
+ DisposeHandle (h1);
+#endif
+}
+
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h
new file mode 100644
index 0000000000..0e16100d2a
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h
@@ -0,0 +1,90 @@
+/*
+ File: AUControlGroup.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUControlGroup_h__
+#define __AUControlGroup_h__
+
+#include <Carbon/Carbon.h>
+
+class AUCarbonViewBase;
+class CAAUParameter;
+
+// Utility class to create clusters of controls related to a single parameter
+ /*! @class AUControlGroup */
+class AUControlGroup {
+public:
+ /*! @method CreateLabelledSlider */
+ static void CreateLabelledSlider( AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ Point labelSize,
+ const ControlFontStyleRec & fontStyle);
+
+ /*! @method CreateLabelledSliderAndEditText */
+ static void CreateLabelledSliderAndEditText(
+ AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ Point labelSize,
+ Point editTextSize,
+ const ControlFontStyleRec & fontStyle);
+
+ /*! @method CreatePopupMenu */
+ static void CreatePopupMenu ( AUCarbonViewBase * auView,
+ const CAAUParameter & auvp,
+ const Rect & area,
+ const ControlFontStyleRec & inFontStyle,
+ const bool inSizeToFit = false);
+
+ /*! @method AddAUInfo */
+ static void AddAUInfo ( AUCarbonViewBase * auView,
+ const Point & inLocation,
+ const SInt16 inRightOffset,
+ const SInt16 inTotalWidth);
+};
+
+
+#endif // __AUControlGroup_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp
new file mode 100644
index 0000000000..fe9a731d1d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp
@@ -0,0 +1,90 @@
+/*
+ File: CarbonEventHandler.cpp
+ Abstract: CarbonEventHandler.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CarbonEventHandler.h"
+
+static pascal OSStatus TheEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData)
+{
+ CarbonEventHandler *handler = (CarbonEventHandler *)inUserData;
+ if (handler->HandleEvent(inHandlerRef, inEvent))
+ return noErr;
+ else return eventNotHandledErr;
+}
+
+CarbonEventHandler::CarbonEventHandler() :
+ mHandlers(NULL)
+{
+}
+
+CarbonEventHandler::~CarbonEventHandler()
+{
+ if (mHandlers != NULL) {
+ int count = static_cast<int>(CFDictionaryGetCount(mHandlers));
+ EventHandlerRef *theHandlers = (EventHandlerRef*) malloc(count * sizeof(EventHandlerRef));
+ CFDictionaryGetKeysAndValues(mHandlers, NULL, (const void **)theHandlers);
+
+ for (int i = 0; i < count; i++)
+ RemoveEventHandler(theHandlers[i]);
+ CFDictionaryRemoveAllValues(mHandlers);
+ CFRelease (mHandlers);
+ free(theHandlers);
+ }
+}
+
+void CarbonEventHandler::WantEventTypes(EventTargetRef target, UInt32 inNumTypes, const EventTypeSpec *inList)
+{
+ if (mHandlers == NULL)
+ mHandlers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
+
+ EventHandlerRef handler;
+
+ if (CFDictionaryGetValueIfPresent (mHandlers, target, (const void **)&handler)) // if there is already a handler for the target, add the type
+ verify_noerr(AddEventTypesToHandler(handler, inNumTypes, inList));
+ else {
+ verify_noerr(InstallEventHandler(target, TheEventHandler, inNumTypes, inList, this, &handler));
+ CFDictionaryAddValue(mHandlers, target, handler);
+ }
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h
new file mode 100644
index 0000000000..9225e1acd7
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h
@@ -0,0 +1,71 @@
+/*
+ File: CarbonEventHandler.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __CarbonEventHandler_h__
+#define __CarbonEventHandler_h__
+
+#include <Carbon/Carbon.h>
+
+ /*! @class CarbonEventHandler */
+class CarbonEventHandler {
+public:
+ /*! @ctor CarbonEventHandler */
+ CarbonEventHandler();
+ /*! @dtor ~CarbonEventHandler */
+ virtual ~CarbonEventHandler();
+
+ /*! @method WantEventTypes */
+ virtual void WantEventTypes(EventTargetRef target, UInt32 inNumTypes, const EventTypeSpec *inList);
+
+ /*! @method HandleEvent */
+ virtual bool HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event) = 0;
+
+protected:
+ /*! @var mHandlers */
+ CFMutableDictionaryRef mHandlers;
+};
+
+#endif // __CarbonEventHandler_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp
new file mode 100644
index 0000000000..1ce8b308b4
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp
@@ -0,0 +1,843 @@
+/*
+ File: AUInstrumentBase.cpp
+ Abstract: AUInstrumentBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUInstrumentBase.h"
+#include "AUMIDIDefs.h"
+
+#if DEBUG
+ #define DEBUG_PRINT 0
+ #define DEBUG_PRINT_NOTE 0
+ #define DEBUG_PRINT_RENDER 0
+#endif
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const UInt32 kEventQueueSize = 1024;
+
+AUInstrumentBase::AUInstrumentBase(
+ AudioComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups,
+ UInt32 numParts)
+ : MusicDeviceBase(inInstance, numInputs, numOutputs, numGroups),
+ mAbsoluteSampleFrame(0),
+ mEventQueue(kEventQueueSize),
+ mNumNotes(0),
+ mNumActiveNotes(0),
+ mMaxActiveNotes(0),
+ mNotes(0),
+ mNoteSize(0),
+ mInitNumPartEls(numParts)
+{
+#if DEBUG_PRINT
+ printf("new AUInstrumentBase\n");
+#endif
+ mFreeNotes.mState = kNoteState_Free;
+ SetWantsRenderThreadID(true);
+}
+
+
+AUInstrumentBase::~AUInstrumentBase()
+{
+#if DEBUG_PRINT
+ printf("delete AUInstrumentBase\n");
+#endif
+}
+
+AUElement * AUInstrumentBase::CreateElement(AudioUnitScope inScope, AudioUnitElement element)
+{
+ switch (inScope)
+ {
+ case kAudioUnitScope_Group:
+ return new SynthGroupElement(this, element, new MidiControls);
+ case kAudioUnitScope_Part:
+ return new SynthPartElement (this, element);
+ }
+ return MusicDeviceBase::CreateElement(inScope, element);
+}
+
+void AUInstrumentBase::CreateExtendedElements()
+{
+ Parts().Initialize(this, kAudioUnitScope_Part, mInitNumPartEls);
+}
+
+AUScope * AUInstrumentBase::GetScopeExtended (AudioUnitScope inScope)
+{
+ if (inScope == kAudioUnitScope_Part)
+ return &mPartScope;
+ return NULL;
+}
+
+
+void AUInstrumentBase::SetNotes(UInt32 inNumNotes, UInt32 inMaxActiveNotes, SynthNote* inNotes, UInt32 inNoteDataSize)
+{
+#if DEBUG_PRINT_NOTE
+ printf("AUInstrumentBase::SetNotes %d %d %p %d\n", inNumNotes, inMaxActiveNotes, inNotes, inNoteDataSize);
+#endif
+ mNumNotes = inNumNotes;
+ mMaxActiveNotes = inMaxActiveNotes;
+ mNoteSize = inNoteDataSize;
+ mNotes = inNotes;
+
+ for (UInt32 i=0; i<mNumNotes; ++i)
+ {
+ SynthNote *note = GetNote(i);
+ note->Reset();
+ mFreeNotes.AddNote(note);
+ }
+}
+
+UInt32 AUInstrumentBase::CountActiveNotes()
+{
+ // debugging tool.
+ UInt32 sum = 0;
+ for (UInt32 i=0; i<mNumNotes; ++i)
+ {
+ SynthNote *note = GetNote(i);
+ if (note->GetState() <= kNoteState_Released)
+ sum++;
+ }
+ return sum;
+}
+
+void AUInstrumentBase::AddFreeNote(SynthNote* inNote)
+{
+ // Fast-released notes are already considered inactive and have already decr'd the active count
+ if (inNote->GetState() < kNoteState_FastReleased) {
+ DecNumActiveNotes();
+ }
+#if DEBUG_PRINT_NOTE
+ else {
+ printf("AUInstrumentBase::AddFreeNote: adding fast-released note %p\n", inNote);
+ }
+ printf("AUInstrumentBase::AddFreeNote (%p) mNumActiveNotes %lu\n", inNote, mNumActiveNotes);
+#endif
+ mFreeNotes.AddNote(inNote);
+}
+
+OSStatus AUInstrumentBase::Initialize()
+{
+/*
+TO DO:
+ Currently ValidFormat will check and validate that the num channels is not being
+ changed if the AU doesn't support the SupportedNumChannels property - which is correct
+
+ What needs to happen here is that IFF the AU does support this property, (ie, the AU
+ can be configured to have different num channels than its original configuration) then
+ the state of the AU at Initialization needs to be validated.
+
+ This is work still to be done - see AUEffectBase for the kind of logic that needs to be applied here
+*/
+
+ // override to call SetNotes
+
+ mNoteIDCounter = 128; // reset this every time we initialise
+ mAbsoluteSampleFrame = 0;
+ return noErr;
+}
+
+void AUInstrumentBase::Cleanup()
+{
+ mFreeNotes.Empty();
+}
+
+
+OSStatus AUInstrumentBase::Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::Reset\n");
+#endif
+ if (inScope == kAudioUnitScope_Global)
+ {
+ // kill all notes..
+ mFreeNotes.Empty();
+ for (UInt32 i=0; i<mNumNotes; ++i)
+ {
+ SynthNote *note = GetNote(i);
+ if (note->IsSounding())
+ note->Kill(0);
+ note->ListRemove();
+ mFreeNotes.AddNote(note);
+ }
+ mNumActiveNotes = 0;
+ mAbsoluteSampleFrame = 0;
+
+ // empty lists.
+ UInt32 numGroups = Groups().GetNumberOfElements();
+ for (UInt32 j = 0; j < numGroups; ++j)
+ {
+ SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
+ group->Reset();
+ }
+ }
+ return MusicDeviceBase::Reset(inScope, inElement);
+}
+
+void AUInstrumentBase::PerformEvents(const AudioTimeStamp& inTimeStamp)
+{
+#if DEBUG_PRINT_RENDER
+ printf("AUInstrumentBase::PerformEvents\n");
+#endif
+ SynthEvent *event;
+ SynthGroupElement *group;
+
+ while ((event = mEventQueue.ReadItem()) != NULL)
+ {
+#if DEBUG_PRINT_RENDER
+ printf("event %08X %d\n", event, event->GetEventType());
+#endif
+ switch(event->GetEventType())
+ {
+ case SynthEvent::kEventType_NoteOn :
+ RealTimeStartNote(GetElForGroupID (event->GetGroupID()), event->GetNoteID(),
+ event->GetOffsetSampleFrame(), *event->GetParams());
+ break;
+ case SynthEvent::kEventType_NoteOff :
+ RealTimeStopNote(event->GetGroupID(), event->GetNoteID(),
+ event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_SustainOn :
+ group = GetElForGroupID (event->GetGroupID());
+ group->SustainOn(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_SustainOff :
+ group = GetElForGroupID (event->GetGroupID());
+ group->SustainOff(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_SostenutoOn :
+ group = GetElForGroupID (event->GetGroupID());
+ group->SostenutoOn(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_SostenutoOff :
+ group = GetElForGroupID (event->GetGroupID());
+ group->SostenutoOff(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_AllNotesOff :
+ group = GetElForGroupID (event->GetGroupID());
+ group->AllNotesOff(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_AllSoundOff :
+ group = GetElForGroupID (event->GetGroupID());
+ group->AllSoundOff(event->GetOffsetSampleFrame());
+ break;
+ case SynthEvent::kEventType_ResetAllControllers :
+ group = GetElForGroupID (event->GetGroupID());
+ group->ResetAllControllers(event->GetOffsetSampleFrame());
+ break;
+ }
+
+ mEventQueue.AdvanceReadPtr();
+ }
+}
+
+
+OSStatus AUInstrumentBase::Render( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames)
+{
+ PerformEvents(inTimeStamp);
+
+ AUScope &outputs = Outputs();
+ UInt32 numOutputs = outputs.GetNumberOfElements();
+ for (UInt32 j = 0; j < numOutputs; ++j)
+ {
+ GetOutput(j)->PrepareBuffer(inNumberFrames); // AUBase::DoRenderBus() only does this for the first output element
+ AudioBufferList& bufferList = GetOutput(j)->GetBufferList();
+ for (UInt32 k = 0; k < bufferList.mNumberBuffers; ++k)
+ {
+ memset(bufferList.mBuffers[k].mData, 0, bufferList.mBuffers[k].mDataByteSize);
+ }
+ }
+ UInt32 numGroups = Groups().GetNumberOfElements();
+ for (UInt32 j = 0; j < numGroups; ++j)
+ {
+ SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
+ OSStatus err = group->Render((SInt64)inTimeStamp.mSampleTime, inNumberFrames, outputs);
+ if (err) return err;
+ }
+ mAbsoluteSampleFrame += inNumberFrames;
+ return noErr;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUInstrumentBase::ValidFormat
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+bool AUInstrumentBase::ValidFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inNewFormat)
+{
+ // if the AU supports this, then we should just let this go through to the Init call
+ if (SupportedNumChannels (NULL))
+ return MusicDeviceBase::ValidFormat(inScope, inElement, inNewFormat);
+
+ bool isGood = MusicDeviceBase::ValidFormat (inScope, inElement, inNewFormat);
+ if (!isGood) return false;
+
+ // if we get to here, then the basic criteria is that the
+ // num channels cannot change on an existing bus
+ AUIOElement *el = GetIOElement (inScope, inElement);
+ return (el->GetStreamFormat().NumberChannels() == inNewFormat.NumberChannels());
+}
+
+
+bool AUInstrumentBase::StreamFormatWritable( AudioUnitScope scope,
+ AudioUnitElement element)
+{
+ return IsInitialized() ? false : true;
+}
+
+OSStatus AUInstrumentBase::RealTimeStartNote( SynthGroupElement *inGroup,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams)
+{
+ return noErr;
+}
+
+SynthPartElement * AUInstrumentBase::GetPartElement (AudioUnitElement inPartElement)
+{
+ AUScope & parts = Parts();
+ unsigned int numEls = parts.GetNumberOfElements();
+ for (unsigned int i = 0; i < numEls; ++i) {
+ SynthPartElement* el = reinterpret_cast<SynthPartElement*>(parts.GetElement(i));
+ if (el->GetIndex() == inPartElement) {
+ return el;
+ }
+ }
+ return NULL;
+}
+
+SynthGroupElement * AUInstrumentBase::GetElForGroupID (MusicDeviceGroupID inGroupID)
+{
+ AUScope & groups = Groups();
+ unsigned int numEls = groups.GetNumberOfElements();
+ SynthGroupElement* unassignedEl = NULL;
+
+ for (unsigned int i = 0; i < numEls; ++i) {
+ SynthGroupElement* el = reinterpret_cast<SynthGroupElement*>(groups.GetElement(i));
+ if (el->GroupID() == inGroupID)
+ return el;
+ if (el->GroupID() == SynthGroupElement::kUnassignedGroup) {
+ unassignedEl = el;
+ break; // we fill this up from the start of the group scope vector
+ }
+ }
+ if (unassignedEl) {
+ unassignedEl->SetGroupID(inGroupID);
+ return unassignedEl;
+ }
+ throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement);
+}
+
+OSStatus AUInstrumentBase::RealTimeStopNote(
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame)
+{
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::RealTimeStopNote ch %d id %d\n", inGroupID, inNoteInstanceID);
+#endif
+
+ SynthGroupElement *gp = (inGroupID == kMusicNoteEvent_Unused
+ ? GetElForNoteID (inNoteInstanceID)
+ : GetElForGroupID(inGroupID));
+ if (gp)
+ {
+ gp->NoteOff (inNoteInstanceID, inOffsetSampleFrame);
+ }
+
+ return noErr;
+}
+
+SynthGroupElement * AUInstrumentBase::GetElForNoteID (NoteInstanceID inNoteID)
+{
+#if DEBUG_PRINT
+ printf("GetElForNoteID id %u\n", inNoteID);
+#endif
+ AUScope & groups = Groups();
+ unsigned int numEls = groups.GetNumberOfElements();
+
+ for (unsigned int i = 0; i < numEls; ++i) {
+ SynthGroupElement* el = reinterpret_cast<SynthGroupElement*>(groups.GetElement(i));
+ if (el->GetNote(inNoteID) != NULL) // searches for any note state
+ return el;
+ }
+ throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement);
+}
+
+OSStatus AUInstrumentBase::StartNote( MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams)
+{
+ OSStatus err = noErr;
+
+ NoteInstanceID noteID;
+ if (outNoteInstanceID) {
+ noteID = NextNoteID();
+ *outNoteInstanceID = noteID;
+ } else
+ noteID = (UInt32)inParams.mPitch;
+
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::StartNote ch %u, key %u, offset %u\n", inGroupID, (unsigned) inParams.mPitch, inOffsetSampleFrame);
+#endif
+
+ if (InRenderThread ())
+ {
+ err = RealTimeStartNote(
+ GetElForGroupID(inGroupID),
+ noteID,
+ inOffsetSampleFrame,
+ inParams);
+ }
+ else
+ {
+ SynthEvent *event = mEventQueue.WriteItem();
+ if (!event) return -1; // queue full
+
+ event->Set(
+ SynthEvent::kEventType_NoteOn,
+ inGroupID,
+ noteID,
+ inOffsetSampleFrame,
+ &inParams
+ );
+
+ mEventQueue.AdvanceWritePtr();
+ }
+ return err;
+}
+
+OSStatus AUInstrumentBase::StopNote( MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame)
+{
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::StopNote ch %u, id %u, offset %u\n", (unsigned)inGroupID, (unsigned)inNoteInstanceID, inOffsetSampleFrame);
+#endif
+ OSStatus err = noErr;
+
+ if (InRenderThread ())
+ {
+ err = RealTimeStopNote(
+ inGroupID,
+ inNoteInstanceID,
+ inOffsetSampleFrame);
+ }
+ else
+ {
+ SynthEvent *event = mEventQueue.WriteItem();
+ if (!event) return -1; // queue full
+
+ event->Set(
+ SynthEvent::kEventType_NoteOff,
+ inGroupID,
+ inNoteInstanceID,
+ inOffsetSampleFrame,
+ NULL
+ );
+
+ mEventQueue.AdvanceWritePtr();
+ }
+ return err;
+}
+
+OSStatus AUInstrumentBase::SendPedalEvent(MusicDeviceGroupID inGroupID, UInt32 inEventType, UInt32 inOffsetSampleFrame)
+{
+
+ if (InRenderThread ())
+ {
+ SynthGroupElement *group = GetElForGroupID(inGroupID);
+ if (!group)
+ return kAudioUnitErr_InvalidElement;
+
+ switch (inEventType)
+ {
+ case SynthEvent::kEventType_SustainOn :
+ group->SustainOn(inOffsetSampleFrame);
+ break;
+ case SynthEvent::kEventType_SustainOff :
+ group->SustainOff(inOffsetSampleFrame);
+ break;
+ case SynthEvent::kEventType_SostenutoOn :
+ group->SostenutoOn(inOffsetSampleFrame);
+ break;
+ case SynthEvent::kEventType_SostenutoOff :
+ group->SostenutoOff(inOffsetSampleFrame);
+ break;
+ case SynthEvent::kEventType_AllNotesOff :
+ group->AllNotesOff(inOffsetSampleFrame);
+ mNumActiveNotes = CountActiveNotes();
+ break;
+ case SynthEvent::kEventType_AllSoundOff :
+ group->AllSoundOff(inOffsetSampleFrame);
+ mNumActiveNotes = CountActiveNotes();
+ break;
+ case SynthEvent::kEventType_ResetAllControllers :
+ group->ResetAllControllers(inOffsetSampleFrame);
+ break;
+ }
+ }
+ else
+ {
+ SynthEvent *event = mEventQueue.WriteItem();
+ if (!event) return -1; // queue full
+
+ event->Set(inEventType, inGroupID, 0, 0, NULL);
+
+ mEventQueue.AdvanceWritePtr();
+ }
+ return noErr;
+}
+
+OSStatus AUInstrumentBase::HandleControlChange( UInt8 inChannel,
+ UInt8 inController,
+ UInt8 inValue,
+ UInt32 inStartFrame)
+{
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::HandleControlChange ch %u ctlr: %u val: %u frm: %u\n", inChannel, inController, inValue, inStartFrame);
+#endif
+ SynthGroupElement *gp = GetElForGroupID(inChannel);
+ if (gp)
+ {
+ gp->ChannelMessage(inController, inValue);
+ }
+ else
+ return kAudioUnitErr_InvalidElement;
+ switch (inController)
+ {
+ case kMidiController_Sustain :
+ if (inValue >= 64)
+ SendPedalEvent(inChannel, SynthEvent::kEventType_SustainOn, inStartFrame);
+ else
+ SendPedalEvent(inChannel, SynthEvent::kEventType_SustainOff, inStartFrame);
+ break;
+ case kMidiController_Sostenuto :
+ if (inValue >= 64)
+ SendPedalEvent(inChannel, SynthEvent::kEventType_SostenutoOn, inStartFrame);
+ else
+ SendPedalEvent(inChannel, SynthEvent::kEventType_SostenutoOff, inStartFrame);
+ break;
+ case kMidiController_OmniModeOff:
+ case kMidiController_OmniModeOn:
+ case kMidiController_MonoModeOn:
+ case kMidiController_MonoModeOff:
+ HandleAllSoundOff(inChannel);
+ break;
+ }
+ return noErr;
+}
+
+OSStatus AUInstrumentBase::HandlePitchWheel( UInt8 inChannel,
+ UInt8 inPitch1, // LSB
+ UInt8 inPitch2, // MSB
+ UInt32 inStartFrame)
+{
+ SynthGroupElement *gp = GetElForGroupID(inChannel);
+ if (gp)
+ {
+ gp->ChannelMessage(kMidiMessage_PitchWheel, (inPitch2 << 7) | inPitch1);
+ return noErr;
+ }
+ else
+ return kAudioUnitErr_InvalidElement;
+}
+
+
+OSStatus AUInstrumentBase::HandleChannelPressure(UInt8 inChannel,
+ UInt8 inValue,
+ UInt32 inStartFrame)
+{
+ SynthGroupElement *gp = GetElForGroupID(inChannel);
+ if (gp)
+ {
+ gp->ChannelMessage(kMidiMessage_ChannelPressure, inValue);
+ return noErr;
+ }
+ else
+ return kAudioUnitErr_InvalidElement;
+}
+
+
+OSStatus AUInstrumentBase::HandleProgramChange( UInt8 inChannel,
+ UInt8 inValue)
+{
+#if DEBUG_PRINT
+ printf("AUInstrumentBase::HandleProgramChange %u %u\n", inChannel, inValue);
+#endif
+ SynthGroupElement *gp = GetElForGroupID(inChannel);
+ if (gp)
+ {
+ gp->ChannelMessage(kMidiMessage_ProgramChange, inValue);
+ return noErr;
+ }
+ else
+ return kAudioUnitErr_InvalidElement;
+}
+
+
+OSStatus AUInstrumentBase::HandlePolyPressure( UInt8 inChannel,
+ UInt8 inKey,
+ UInt8 inValue,
+ UInt32 inStartFrame)
+{
+ SynthGroupElement *gp = GetElForGroupID(inChannel);
+ if (gp)
+ {
+ // Combine key and value into single argument. UGLY!
+ gp->ChannelMessage(kMidiMessage_PolyPressure, (inKey << 7) | inValue);
+ return noErr;
+ }
+ else
+ return kAudioUnitErr_InvalidElement;
+}
+
+
+OSStatus AUInstrumentBase::HandleResetAllControllers( UInt8 inChannel)
+{
+ return SendPedalEvent (inChannel, SynthEvent::kEventType_ResetAllControllers, 0);
+}
+
+
+OSStatus AUInstrumentBase::HandleAllNotesOff( UInt8 inChannel)
+{
+ return SendPedalEvent (inChannel, SynthEvent::kEventType_AllNotesOff, 0);
+}
+
+
+OSStatus AUInstrumentBase::HandleAllSoundOff( UInt8 inChannel)
+{
+ return SendPedalEvent (inChannel, SynthEvent::kEventType_AllSoundOff, 0);
+}
+
+SynthNote* AUInstrumentBase::GetAFreeNote(UInt32 inFrame)
+{
+#if DEBUG_PRINT_NOTE
+ printf("AUInstrumentBase::GetAFreeNote: %lu available\n", mFreeNotes.Length());
+#endif
+ SynthNote *note = mFreeNotes.mHead;
+ if (note)
+ {
+ mFreeNotes.RemoveNote(note);
+ return note;
+ }
+
+ return VoiceStealing(inFrame, true);
+}
+
+SynthNote* AUInstrumentBase::VoiceStealing(UInt32 inFrame, bool inKillIt)
+{
+
+#if DEBUG_PRINT_NOTE
+ printf("AUInstrumentBase::VoiceStealing\n");
+#endif
+ // free list was empty so we need to kill a note.
+ UInt32 startState = inKillIt ? kNoteState_FastReleased : kNoteState_Released;
+ for (UInt32 i = startState; i <= startState; --i)
+ {
+#if DEBUG_PRINT_NOTE
+ printf(" checking state %d...\n", i);
+#endif
+ UInt32 numGroups = Groups().GetNumberOfElements();
+ for (UInt32 j = 0; j < numGroups; ++j)
+ {
+ SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
+#if DEBUG_PRINT_NOTE
+ printf("\tsteal group %d size %d\n", j, group->mNoteList[i].Length());
+#endif
+ if (group->mNoteList[i].NotEmpty()) {
+#if DEBUG_PRINT_NOTE
+ printf("\t-- not empty\n");
+#endif
+ SynthNote *note = group->mNoteList[i].FindMostQuietNote();
+ if (inKillIt) {
+#if DEBUG_PRINT_NOTE
+ printf("\t--=== KILL ===---\n");
+#endif
+ note->Kill(inFrame);
+ group->mNoteList[i].RemoveNote(note);
+ if (i != kNoteState_FastReleased)
+ DecNumActiveNotes();
+ return note;
+ } else {
+#if DEBUG_PRINT_NOTE
+ printf("\t--=== FAST RELEASE ===---\n");
+#endif
+ group->mNoteList[i].RemoveNote(note);
+ note->FastRelease(inFrame);
+ group->mNoteList[kNoteState_FastReleased].AddNote(note);
+ DecNumActiveNotes(); // kNoteState_FastReleased counts as inactive for voice stealing purposes.
+ return NULL;
+ }
+ }
+ }
+ }
+#if DEBUG_PRINT_NOTE
+ printf("no notes to steal????\n");
+#endif
+ return NULL; // It should be impossible to get here. It means there were no notes to kill in any state.
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+AUMonotimbralInstrumentBase::AUMonotimbralInstrumentBase(
+ AudioComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups,
+ UInt32 numParts)
+ : AUInstrumentBase(inInstance, numInputs, numOutputs, numGroups, numParts)
+{
+}
+
+OSStatus AUMonotimbralInstrumentBase::RealTimeStartNote(
+ SynthGroupElement *inGroup,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams)
+{
+#if DEBUG_PRINT_RENDER
+ printf("AUMonotimbralInstrumentBase::RealTimeStartNote %d\n", inNoteInstanceID);
+#endif
+
+ if (NumActiveNotes() + 1 > MaxActiveNotes())
+ {
+ VoiceStealing(inOffsetSampleFrame, false);
+ }
+ SynthNote *note = GetAFreeNote(inOffsetSampleFrame);
+ if (!note) return -1;
+
+ SynthPartElement *part = GetPartElement (0); // Only one part for monotimbral
+
+ IncNumActiveNotes();
+ inGroup->NoteOn(note, part, inNoteInstanceID, inOffsetSampleFrame, inParams);
+
+ return noErr;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+OSStatus AUMultitimbralInstrumentBase::GetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus result = noErr;
+
+ switch (inID)
+ {
+#if !TARGET_OS_IPHONE
+ case kMusicDeviceProperty_PartGroup:
+ if (inScope != kAudioUnitScope_Part) return kAudioUnitErr_InvalidScope;
+ outDataSize = sizeof(UInt32);
+ outWritable = true;
+ break;
+#endif
+ default:
+ result = AUInstrumentBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+ }
+ return result;
+}
+
+OSStatus AUMultitimbralInstrumentBase::GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ OSStatus result = noErr;
+
+ switch (inID)
+ {
+#if !TARGET_OS_IPHONE
+ case kMusicDeviceProperty_PartGroup:
+ if (inScope != kAudioUnitScope_Group) return kAudioUnitErr_InvalidScope;
+ // ??
+ return -1; //unimpl
+ break;
+#endif
+ default:
+ result = AUInstrumentBase::GetProperty (inID, inScope, inElement, outData);
+ }
+
+ return result;
+}
+
+
+
+OSStatus AUMultitimbralInstrumentBase::SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ OSStatus result = noErr;
+
+ switch (inID)
+ {
+#if !TARGET_OS_IPHONE
+ case kMusicDeviceProperty_PartGroup:
+ if (inScope != kAudioUnitScope_Group) return kAudioUnitErr_InvalidScope;
+ // ??
+ return -1; //unimpl
+ break;
+#endif
+ default:
+ result = MusicDeviceBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
+ }
+
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h
new file mode 100644
index 0000000000..3ad7e03a66
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h
@@ -0,0 +1,269 @@
+/*
+ File: AUInstrumentBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUInstrumentBase__
+#define __AUInstrumentBase__
+
+#include <vector>
+#include <stdexcept>
+#include <AudioUnit/AudioUnit.h>
+#include <CoreAudio/CoreAudio.h>
+#include <libkern/OSAtomic.h>
+#include "MusicDeviceBase.h"
+#include "LockFreeFIFO.h"
+#include "SynthEvent.h"
+#include "SynthNote.h"
+#include "SynthElement.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+typedef LockFreeFIFOWithFree<SynthEvent> SynthEventQueue;
+
+class AUInstrumentBase : public MusicDeviceBase
+{
+public:
+ AUInstrumentBase(
+ AudioComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups = 16,
+ UInt32 numParts = 1);
+ virtual ~AUInstrumentBase();
+
+ virtual OSStatus Initialize();
+
+ /*! @method Parts */
+ AUScope & Parts() { return mPartScope; }
+
+ /*! @method GetPart */
+ AUElement * GetPart( AudioUnitElement inElement)
+ {
+ return mPartScope.SafeGetElement(inElement);
+ }
+
+ virtual AUScope * GetScopeExtended (AudioUnitScope inScope);
+
+ virtual AUElement * CreateElement( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ virtual void CreateExtendedElements();
+
+ virtual void Cleanup();
+
+ virtual OSStatus Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ virtual bool ValidFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inNewFormat);
+
+ virtual bool StreamFormatWritable( AudioUnitScope scope,
+ AudioUnitElement element);
+
+ virtual bool CanScheduleParameters() const { return false; }
+
+ virtual OSStatus Render( AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames);
+
+ virtual OSStatus StartNote( MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams);
+
+ virtual OSStatus StopNote( MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame);
+
+ virtual OSStatus RealTimeStartNote( SynthGroupElement *inGroup,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams);
+
+ virtual OSStatus RealTimeStopNote( MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame);
+
+ virtual OSStatus HandleControlChange( UInt8 inChannel,
+ UInt8 inController,
+ UInt8 inValue,
+ UInt32 inStartFrame);
+
+ virtual OSStatus HandlePitchWheel( UInt8 inChannel,
+ UInt8 inPitch1,
+ UInt8 inPitch2,
+ UInt32 inStartFrame);
+
+ virtual OSStatus HandleChannelPressure( UInt8 inChannel,
+ UInt8 inValue,
+ UInt32 inStartFrame);
+
+ virtual OSStatus HandleProgramChange( UInt8 inChannel,
+ UInt8 inValue);
+
+ virtual OSStatus HandlePolyPressure( UInt8 inChannel,
+ UInt8 inKey,
+ UInt8 inValue,
+ UInt32 inStartFrame);
+
+ virtual OSStatus HandleResetAllControllers( UInt8 inChannel);
+
+ virtual OSStatus HandleAllNotesOff( UInt8 inChannel);
+
+ virtual OSStatus HandleAllSoundOff( UInt8 inChannel);
+
+ SynthNote* GetNote(UInt32 inIndex)
+ {
+ if (!mNotes)
+ throw std::runtime_error("no notes");
+ return (SynthNote*)((char*)mNotes + inIndex * mNoteSize);
+ }
+
+ SynthNote* GetAFreeNote(UInt32 inFrame);
+ void AddFreeNote(SynthNote* inNote);
+
+ friend class SynthGroupElement;
+protected:
+
+ UInt32 NextNoteID() { return OSAtomicIncrement32((int32_t *)&mNoteIDCounter); }
+
+
+ // call SetNotes in your Initialize() method to give the base class your note structures and to set the maximum
+ // number of active notes. inNoteData should be an array of size inMaxActiveNotes.
+ void SetNotes(UInt32 inNumNotes, UInt32 inMaxActiveNotes, SynthNote* inNotes, UInt32 inNoteSize);
+
+ void PerformEvents( const AudioTimeStamp & inTimeStamp);
+ OSStatus SendPedalEvent(MusicDeviceGroupID inGroupID, UInt32 inEventType, UInt32 inOffsetSampleFrame);
+ virtual SynthNote* VoiceStealing(UInt32 inFrame, bool inKillIt);
+ UInt32 MaxActiveNotes() const { return mMaxActiveNotes; }
+ UInt32 NumActiveNotes() const { return mNumActiveNotes; }
+ void IncNumActiveNotes() { ++mNumActiveNotes; }
+ void DecNumActiveNotes() { --mNumActiveNotes; }
+ UInt32 CountActiveNotes();
+
+ SynthPartElement * GetPartElement (AudioUnitElement inPartElement);
+
+ // this call throws if there's no assigned element for the group ID
+ virtual SynthGroupElement * GetElForGroupID (MusicDeviceGroupID inGroupID);
+ virtual SynthGroupElement * GetElForNoteID (NoteInstanceID inNoteID);
+
+ SInt64 mAbsoluteSampleFrame;
+
+
+private:
+
+ SInt32 mNoteIDCounter;
+
+ SynthEventQueue mEventQueue;
+
+ UInt32 mNumNotes;
+ UInt32 mNumActiveNotes;
+ UInt32 mMaxActiveNotes;
+ SynthNote* mNotes;
+ SynthNoteList mFreeNotes;
+ UInt32 mNoteSize;
+
+ AUScope mPartScope;
+ const UInt32 mInitNumPartEls;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class AUMonotimbralInstrumentBase : public AUInstrumentBase
+{
+public:
+ AUMonotimbralInstrumentBase(
+ AudioComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups = 16,
+ UInt32 numParts = 1);
+
+ virtual OSStatus RealTimeStartNote( SynthGroupElement *inGroup,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams);
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// this is a work in progress! The mono-timbral one is finished though!
+class AUMultitimbralInstrumentBase : public AUInstrumentBase
+{
+public:
+ AUMultitimbralInstrumentBase(
+ AudioComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups,
+ UInt32 numParts);
+
+ virtual OSStatus GetPropertyInfo( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ virtual OSStatus GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+
+ virtual OSStatus SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+
+private:
+
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#endif
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h
new file mode 100644
index 0000000000..ea6c4c26e1
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h
@@ -0,0 +1,168 @@
+/*
+ File: LockFreeFIFO.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include <libkern/OSAtomic.h>
+
+template <class ITEM>
+class LockFreeFIFOWithFree
+{
+ LockFreeFIFOWithFree(); // private, unimplemented.
+public:
+ LockFreeFIFOWithFree(UInt32 inMaxSize)
+ : mReadIndex(0), mWriteIndex(0), mFreeIndex(0)
+ {
+ //assert(IsPowerOfTwo(inMaxSize));
+ mItems = new ITEM[inMaxSize];
+ mMask = inMaxSize - 1;
+ }
+
+ ~LockFreeFIFOWithFree()
+ {
+ delete [] mItems;
+ }
+
+
+ void Reset()
+ {
+ FreeItems();
+ mReadIndex = 0;
+ mWriteIndex = 0;
+ mFreeIndex = 0;
+ }
+
+ ITEM* WriteItem()
+ {
+ //printf("WriteItem %d %d\n", mReadIndex, mWriteIndex);
+ FreeItems(); // free items on the write thread.
+ int32_t nextWriteIndex = (mWriteIndex + 1) & mMask;
+ if (nextWriteIndex == mFreeIndex) return NULL;
+ return &mItems[mWriteIndex];
+ }
+
+ ITEM* ReadItem()
+ {
+ //printf("ReadItem %d %d\n", mReadIndex, mWriteIndex);
+ if (mReadIndex == mWriteIndex) return NULL;
+ return &mItems[mReadIndex];
+ }
+ void AdvanceWritePtr() { OSAtomicCompareAndSwap32(mWriteIndex, (mWriteIndex + 1) & mMask, &mWriteIndex); }
+ void AdvanceReadPtr() { OSAtomicCompareAndSwap32(mReadIndex, (mReadIndex + 1) & mMask, &mReadIndex); }
+private:
+ ITEM* FreeItem()
+ {
+ if (mFreeIndex == mReadIndex) return NULL;
+ return &mItems[mFreeIndex];
+ }
+ void AdvanceFreePtr() { OSAtomicCompareAndSwap32(mFreeIndex, (mFreeIndex + 1) & mMask, &mFreeIndex); }
+
+ void FreeItems()
+ {
+ ITEM* item;
+ while ((item = FreeItem()) != NULL)
+ {
+ item->Free();
+ AdvanceFreePtr();
+ }
+ }
+
+ volatile int32_t mReadIndex, mWriteIndex, mFreeIndex;
+ int32_t mMask;
+ ITEM *mItems;
+};
+
+
+
+// Same as above but no free.
+
+template <class ITEM>
+class LockFreeFIFO
+{
+ LockFreeFIFO(); // private, unimplemented.
+public:
+ LockFreeFIFO(UInt32 inMaxSize)
+ : mReadIndex(0), mWriteIndex(0)
+ {
+ //assert(IsPowerOfTwo(inMaxSize));
+ mItems = new ITEM[inMaxSize];
+ mMask = inMaxSize - 1;
+ }
+
+ ~LockFreeFIFO()
+ {
+ delete [] mItems;
+ }
+
+ void Reset()
+ {
+ mReadIndex = 0;
+ mWriteIndex = 0;
+ }
+
+ ITEM* WriteItem()
+ {
+ int32_t nextWriteIndex = (mWriteIndex + 1) & mMask;
+ if (nextWriteIndex == mReadIndex) return NULL;
+ return &mItems[mWriteIndex];
+ }
+
+ ITEM* ReadItem()
+ {
+ if (mReadIndex == mWriteIndex) return NULL;
+ return &mItems[mReadIndex];
+ }
+
+ // the CompareAndSwap will always succeed. We use CompareAndSwap because it calls the PowerPC sync instruction,
+ // plus any processor bug workarounds for various CPUs.
+ void AdvanceWritePtr() { OSAtomicCompareAndSwap32(mWriteIndex, (mWriteIndex + 1) & mMask, &mWriteIndex); }
+ void AdvanceReadPtr() { OSAtomicCompareAndSwap32(mReadIndex, (mReadIndex + 1) & mMask, &mReadIndex); }
+
+private:
+
+ volatile int32_t mReadIndex, mWriteIndex;
+ int32_t mMask;
+ ITEM *mItems;
+};
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/MIDIControlHandler.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/MIDIControlHandler.h
new file mode 100644
index 0000000000..0f8003fcd5
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/MIDIControlHandler.h
@@ -0,0 +1,92 @@
+/*
+ File: MIDIControlHandler.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __MIDICONTROLHANDLER_H__
+#define __MIDICONTROLHANDLER_H__
+
+#include <CoreAudio/CoreAudio.h>
+
+/*! Abstract interface base class for classes which handle all incoming MIDI data */
+
+class MIDIControlHandler
+{
+public:
+ virtual ~MIDIControlHandler() {}
+ virtual void Reset() = 0; //! Restore all state to defaults
+ virtual bool SetProgramChange(UInt16 inProgram) = 0;
+ virtual bool SetPitchWheel(UInt16 inValue) = 0;
+ virtual bool SetChannelPressure(UInt8 inValue) = 0;
+ virtual bool SetPolyPressure(UInt8 inKey, UInt8 inValue) = 0;
+ virtual bool SetController(UInt8 inControllerNumber, UInt8 inValue) = 0;
+ virtual bool SetSysex(void *inSysexMsg) = 0;
+
+ virtual float GetPitchBend() const = 0;
+
+ /*! Default controller values. These represent MSB values unless indicated in the name */
+
+ enum
+ {
+ kDefault_Midpoint = 0x40, //! Used for all center-null-point controllers
+ kDefault_Volume = 100,
+ kDefault_Pan = kDefault_Midpoint,
+ kDefault_ModWheel = 0,
+ kDefault_Pitch = kDefault_Midpoint,
+ kDefault_Expression = 0x7f,
+ kDefault_ChannelPressure = 0,
+ kDefault_ReverbSend = 40,
+ kDefault_ChorusSend = 0,
+
+ kDefault_RPN_LSB = 0x7f,
+ kDefault_RPN_MSB = 0x7f,
+ kDefault_PitchBendRange = 2,
+ kDefault_FineTuning = kDefault_Midpoint,
+ kDefault_CoarseTuning = kDefault_Midpoint,
+ kDefault_ModDepthRange = 0,
+ kDefault_ModDepthRangeLSB = kDefault_Midpoint
+ };
+};
+
+#endif // __MIDICONTROLHANDLER_H__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp
new file mode 100644
index 0000000000..fd329f84e8
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp
@@ -0,0 +1,419 @@
+/*
+ File: SynthElement.cpp
+ Abstract: SynthElement.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "SynthElement.h"
+#include "AUInstrumentBase.h"
+#include "AUMIDIDefs.h"
+
+#undef DEBUG_PRINT
+#define DEBUG_PRINT 0
+#define DEBUG_PRINT_NOTE 0
+#define DEBUG_PRINT_RENDER 0
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+MidiControls::MidiControls()
+{
+ Reset();
+}
+
+void MidiControls::Reset()
+{
+ memset(mControls, 0, sizeof(mControls));
+ memset(mPolyPressure, 0, sizeof(mPolyPressure));
+ mMonoPressure = 0;
+ mProgramChange = 0;
+ mPitchBend = 0;
+ mActiveRPN = 0;
+ mActiveNRPN = 0;
+ mActiveRPValue = 0;
+ mActiveNRPValue = 0;
+ mControls[kMidiController_Pan] = 64;
+ mControls[kMidiController_Expression] = 127;
+ mPitchBendDepth = 24 << 7;
+ mFPitchBendDepth = 24.0f;
+ mFPitchBend = 0.0f;
+}
+
+
+SynthElement::SynthElement(AUInstrumentBase *audioUnit, UInt32 inElement)
+ : AUElement(audioUnit), mIndex(inElement)
+{
+}
+
+SynthElement::~SynthElement()
+{
+}
+
+SynthGroupElement::SynthGroupElement(AUInstrumentBase *audioUnit, UInt32 inElement, MIDIControlHandler *inHandler)
+ : SynthElement(audioUnit, inElement),
+ mCurrentAbsoluteFrame(-1),
+ mMidiControlHandler(inHandler),
+ mSustainIsOn(false), mSostenutoIsOn(false), mOutputBus(0), mGroupID(kUnassignedGroup)
+{
+ for (UInt32 i=0; i<kNumberOfSoundingNoteStates; ++i)
+ mNoteList[i].mState = (SynthNoteState) i;
+}
+
+SynthGroupElement::~SynthGroupElement()
+{
+ delete mMidiControlHandler;
+}
+
+void SynthGroupElement::SetGroupID (MusicDeviceGroupID inGroup)
+{
+ // can't re-assign a group once its been assigned
+ if (mGroupID != kUnassignedGroup) throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement);
+ mGroupID = inGroup;
+}
+
+void SynthGroupElement::Reset()
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::Reset\n");
+#endif
+ mMidiControlHandler->Reset();
+ for (UInt32 i=0; i<kNumberOfSoundingNoteStates; ++i)
+ mNoteList[i].Empty();
+}
+
+SynthPartElement::SynthPartElement(AUInstrumentBase *audioUnit, UInt32 inElement)
+ : SynthElement(audioUnit, inElement)
+{
+}
+
+// Return the SynthNote with the given inNoteID, if found. If unreleasedOnly is true, only look for
+// attacked and sostenutoed notes, otherwise search all states. Return state of found note via outNoteState.
+
+SynthNote *SynthGroupElement::GetNote(NoteInstanceID inNoteID, bool unreleasedOnly, UInt32 *outNoteState)
+{
+#if DEBUG_PRINT_RENDER
+ printf("SynthGroupElement::GetNote %d, unreleased = %d\n", inNoteID, unreleasedOnly);
+#endif
+ const UInt32 lastNoteState = unreleasedOnly ?
+ (mSostenutoIsOn ? kNoteState_Sostenutoed : kNoteState_Attacked)
+ : kNoteState_Released;
+ SynthNote *note = NULL;
+ // Search for notes in each successive state
+ for (UInt32 noteState = kNoteState_Attacked; noteState <= lastNoteState; ++noteState)
+ {
+ if (outNoteState) *outNoteState = noteState; // even if we find nothing
+ note = mNoteList[noteState].mHead;
+ while (note && note->mNoteID != inNoteID)
+ {
+#if DEBUG_PRINT_RENDER
+ printf(" checking %p id: %d\n", note, note->mNoteID);
+#endif
+ note = note->mNext;
+ }
+ if (note)
+ {
+#if DEBUG_PRINT_RENDER
+ printf(" found %p\n", note);
+#endif
+ break;
+ }
+ }
+ return note;
+}
+
+void SynthGroupElement::NoteOn(SynthNote *note,
+ SynthPartElement *part,
+ NoteInstanceID inNoteID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams)
+{
+#if DEBUG_PRINT_NOTE
+ printf("SynthGroupElement::NoteOn %d\n", inNoteID);
+#endif
+ // TODO: CONSIDER FIXING this to not need to initialize mCurrentAbsoluteFrame to -1.
+ UInt64 absoluteFrame = (mCurrentAbsoluteFrame == -1) ? inOffsetSampleFrame : mCurrentAbsoluteFrame + inOffsetSampleFrame;
+ if (note->AttackNote(part, this, inNoteID, absoluteFrame, inOffsetSampleFrame, inParams)) {
+ mNoteList[kNoteState_Attacked].AddNote(note);
+ }
+}
+
+void SynthGroupElement::NoteOff(NoteInstanceID inNoteID, UInt32 inFrame)
+{
+#if DEBUG_PRINT_NOTE
+ printf("SynthGroupElement::NoteOff %d\n", inNoteID);
+#endif
+ UInt32 noteState = kNoteState_Attacked;
+ SynthNote *note = GetNote(inNoteID, true, &noteState); // asking for unreleased only
+ if (note)
+ {
+#if DEBUG_PRINT_NOTE
+ printf(" old note state: %d\n", note->mState);
+#endif
+ if (noteState == kNoteState_Attacked)
+ {
+ mNoteList[noteState].RemoveNote(note);
+ if (mSustainIsOn) {
+ mNoteList[kNoteState_ReleasedButSustained].AddNote(note);
+ } else {
+ note->Release(inFrame);
+ mNoteList[kNoteState_Released].AddNote(note);
+ }
+#if DEBUG_PRINT_NOTE
+ printf(" new note state: %d\n", note->mState);
+#endif
+ }
+ else /* if (noteState == kNoteState_Sostenutoed) */
+ {
+ mNoteList[kNoteState_Sostenutoed].RemoveNote(note);
+ mNoteList[kNoteState_ReleasedButSostenutoed].AddNote(note);
+ }
+ }
+}
+
+void SynthGroupElement::NoteEnded(SynthNote *inNote, UInt32 inFrame)
+{
+#if DEBUG_PRINT_NOTE
+ printf("SynthGroupElement::NoteEnded: id %d state %d\n", inNote->mNoteID, inNote->mState);
+#endif
+ if (inNote->IsSounding()) {
+ SynthNoteList *list = &mNoteList[inNote->GetState()];
+ list->RemoveNote(inNote);
+ }
+
+ GetAUInstrument()->AddFreeNote(inNote);
+}
+
+void SynthGroupElement::NoteFastReleased(SynthNote *inNote)
+{
+#if DEBUG_PRINT_NOTE
+ printf("SynthGroupElement::NoteFastReleased id %d state %d\n", inNote->mNoteID, inNote->mState);
+#endif
+ if (inNote->IsActive()) {
+ mNoteList[inNote->GetState()].RemoveNote(inNote);
+ GetAUInstrument()->DecNumActiveNotes();
+ mNoteList[kNoteState_FastReleased].AddNote(inNote);
+ }
+ else {
+ Assert(true, "ASSERT FAILED: Attempting to fast-release non-active note");
+ }
+}
+
+bool SynthGroupElement::ChannelMessage(UInt16 controllerID, UInt16 inValue)
+{
+ bool handled = true;
+#if DEBUG_PRINT
+ printf("SynthGroupElement::ChannelMessage(0x%x, %u)\n", controllerID, inValue);
+#endif
+ // Sustain and sostenuto are "pedal events", and are handled during render cycle
+ if (controllerID <= kMidiController_RPN_MSB && controllerID != kMidiController_Sustain && controllerID != kMidiController_Sostenuto)
+ handled = mMidiControlHandler->SetController(controllerID, UInt8(inValue));
+ else
+ {
+ switch (controllerID)
+ {
+ case kMidiMessage_ProgramChange:
+ handled = mMidiControlHandler->SetProgramChange(inValue);
+ break;
+ case kMidiMessage_PitchWheel:
+ handled = mMidiControlHandler->SetPitchWheel(inValue);
+ break;
+ case kMidiMessage_ChannelPressure:
+#if DEBUG_PRINT
+ printf("SynthGroupElement::ChannelMessage: Channel Pressure %u\n", inValue);
+#endif
+ handled = mMidiControlHandler->SetChannelPressure(UInt8(inValue));
+ break;
+ case kMidiMessage_PolyPressure:
+ { UInt8 inKey = inValue >> 7;
+ UInt8 val = inValue & 0x7f;
+ handled = mMidiControlHandler->SetPolyPressure(inKey, val);
+ break;
+ }
+ default:
+ handled = false;
+ break;
+ }
+ }
+ return handled;
+}
+
+void SynthGroupElement::SostenutoOn(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::SostenutoOn\n");
+#endif
+ if (!mSostenutoIsOn) {
+ mMidiControlHandler->SetController(kMidiController_Sostenuto, 127);
+ mSostenutoIsOn = true;
+ mNoteList[kNoteState_Sostenutoed].TransferAllFrom(&mNoteList[kNoteState_Attacked], inFrame);
+ }
+}
+
+void SynthGroupElement::SostenutoOff(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::SostenutoOff\n");
+#endif
+ if (mSostenutoIsOn) {
+ mMidiControlHandler->SetController(kMidiController_Sostenuto, 0);
+ mSostenutoIsOn = false;
+ mNoteList[kNoteState_Attacked].TransferAllFrom(&mNoteList[kNoteState_Sostenutoed], inFrame);
+ if (mSustainIsOn)
+ mNoteList[kNoteState_ReleasedButSustained].TransferAllFrom(&mNoteList[kNoteState_ReleasedButSostenutoed], inFrame);
+ else
+ mNoteList[kNoteState_Released].TransferAllFrom(&mNoteList[kNoteState_ReleasedButSostenutoed], inFrame);
+ }
+}
+
+
+void SynthGroupElement::SustainOn(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+// printf("SynthGroupElement::SustainOn\n");
+#endif
+ if (!mSustainIsOn) {
+ mMidiControlHandler->SetController(kMidiController_Sustain, 127);
+ mSustainIsOn = true;
+ }
+}
+
+void SynthGroupElement::SustainOff(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+// printf("SynthGroupElement::SustainOff\n");
+#endif
+ if (mSustainIsOn) {
+ mMidiControlHandler->SetController(kMidiController_Sustain, 0);
+ mSustainIsOn = false;
+
+ mNoteList[kNoteState_Released].TransferAllFrom(&mNoteList[kNoteState_ReleasedButSustained], inFrame);
+ }
+}
+
+void SynthGroupElement::AllNotesOff(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::AllNotesOff\n");
+#endif
+ SynthNote *note;
+ for (UInt32 i=0 ; i<=kNoteState_Sostenutoed; ++i)
+ {
+ UInt32 newState = (i == kNoteState_Attacked) ?
+ kNoteState_Released : kNoteState_ReleasedButSostenutoed;
+ note = mNoteList[i].mHead;
+ while (note)
+ {
+ SynthNote *nextNote = note->mNext;
+
+ mNoteList[i].RemoveNote(note);
+ note->Release(inFrame);
+ mNoteList[newState].AddNote(note);
+
+ note = nextNote;
+ }
+ }
+}
+
+void SynthGroupElement::AllSoundOff(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::AllSoundOff\n");
+#endif
+ SynthNote *note;
+
+ for (UInt32 i=0 ; i<kNumberOfActiveNoteStates; ++i)
+ {
+ note = mNoteList[i].mHead;
+ while (note)
+ {
+ SynthNote *nextNote = note->mNext;
+
+ mNoteList[i].RemoveNote(note);
+ note->FastRelease(inFrame);
+ mNoteList[kNoteState_FastReleased].AddNote(note);
+ GetAUInstrument()->DecNumActiveNotes();
+ note = nextNote;
+ }
+ }
+}
+
+void SynthGroupElement::ResetAllControllers(UInt32 inFrame)
+{
+#if DEBUG_PRINT
+ printf("SynthGroupElement::ResetAllControllers\n");
+#endif
+ mMidiControlHandler->Reset();
+}
+
+OSStatus SynthGroupElement::Render(SInt64 inAbsoluteSampleFrame, UInt32 inNumberFrames, AUScope &outputs)
+{
+ // Avoid duplicate calls at same sample offset
+ if (inAbsoluteSampleFrame != mCurrentAbsoluteFrame)
+ {
+ mCurrentAbsoluteFrame = inAbsoluteSampleFrame;
+ AudioBufferList* buffArray[16];
+ UInt32 numOutputs = outputs.GetNumberOfElements();
+ for (UInt32 outBus = 0; outBus < numOutputs && outBus < 16; ++outBus)
+ {
+ buffArray[outBus] = &GetAudioUnit()->GetOutput(outBus)->GetBufferList();
+ }
+
+ for (UInt32 i=0 ; i<kNumberOfSoundingNoteStates; ++i)
+ {
+ SynthNote *note = mNoteList[i].mHead;
+ while (note)
+ {
+#if DEBUG_PRINT_RENDER
+ printf("SynthGroupElement::Render: state %d, note %p\n", i, note);
+#endif
+ SynthNote *nextNote = note->mNext;
+
+ OSStatus err = note->Render(inAbsoluteSampleFrame, inNumberFrames, buffArray, numOutputs);
+ if (err) return err;
+
+ note = nextNote;
+ }
+ }
+ }
+ return noErr;
+}
+
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h
new file mode 100644
index 0000000000..4ca3643106
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h
@@ -0,0 +1,227 @@
+/*
+ File: SynthElement.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __SynthElement__
+#define __SynthElement__
+
+#include <AudioUnit/AudioUnit.h>
+#include "MusicDeviceBase.h"
+#include "SynthNoteList.h"
+#include "MIDIControlHandler.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+class AUInstrumentBase;
+
+class SynthElement : public AUElement
+{
+public:
+ SynthElement(AUInstrumentBase *audioUnit, UInt32 inElement);
+ virtual ~SynthElement();
+
+ UInt32 GetIndex() const { return mIndex; }
+
+ AUInstrumentBase* GetAUInstrument() { return (AUInstrumentBase*)GetAudioUnit(); }
+
+private:
+ UInt32 mIndex;
+};
+
+class MidiControls : public MIDIControlHandler
+{
+ enum { kMaxControls = 128 };
+public:
+ MidiControls();
+ virtual ~MidiControls() {}
+ virtual void Reset();
+ virtual bool SetProgramChange(UInt16 inProgram) { mProgramChange = inProgram; return true; }
+ virtual bool SetPitchWheel(UInt16 inValue) {
+ mPitchBend = inValue;
+ mFPitchBend = (float)(((SInt16)mPitchBend - 8192) / 8192.);
+ return true;
+ }
+ virtual bool SetChannelPressure(UInt8 inValue) { mMonoPressure = inValue; return true; }
+ virtual bool SetPolyPressure(UInt8 inKey, UInt8 inValue) {
+ mPolyPressure[inKey] = inValue;
+ return true;
+ }
+ virtual bool SetController(UInt8 inControllerNumber, UInt8 inValue) {
+ if (inControllerNumber < kMaxControls) {
+ mControls[inControllerNumber] = inValue;
+ return true;
+ }
+ return false;
+ }
+ virtual bool SetSysex(void *inSysexMsg) { return false; }
+
+ virtual float GetPitchBend() const { return mFPitchBend * mFPitchBendDepth; }
+
+ SInt16 GetHiResControl(UInt32 inIndex) const
+ {
+ return ((mControls[inIndex] & 127) << 7) | (mControls[inIndex + 32] & 127);
+ }
+
+ float GetControl(UInt32 inIndex) const
+ {
+ if (inIndex < 32) {
+ return (float)(mControls[inIndex] + (mControls[inIndex + 32] / 127.));
+ } else {
+ return (float)mControls[inIndex];
+ }
+ }
+
+
+private:
+
+ UInt8 mControls[128];
+ UInt8 mPolyPressure[128];
+ UInt8 mMonoPressure;
+ UInt8 mProgramChange;
+ UInt16 mPitchBend;
+ UInt16 mActiveRPN;
+ UInt16 mActiveNRPN;
+ UInt16 mActiveRPValue;
+ UInt16 mActiveNRPValue;
+
+ UInt16 mPitchBendDepth;
+ float mFPitchBendDepth;
+ float mFPitchBend;
+
+ void SetHiResControl(UInt32 inIndex, UInt8 inMSB, UInt8 inLSB)
+ {
+ mControls[inIndex] = inMSB;
+ mControls[inIndex + 32] = inLSB;
+ }
+
+};
+
+
+class SynthGroupElement : public SynthElement
+{
+public:
+ enum {
+ kUnassignedGroup = 0xFFFFFFFF
+ };
+
+ SynthGroupElement(AUInstrumentBase *audioUnit, UInt32 inElement, MIDIControlHandler *inHandler);
+ virtual ~SynthGroupElement();
+
+ virtual void NoteOn(SynthNote *note, SynthPartElement *part, NoteInstanceID inNoteID, UInt32 inOffsetSampleFrame, const MusicDeviceNoteParams &inParams);
+ virtual void NoteOff(NoteInstanceID inNoteID, UInt32 inOffsetSampleFrame);
+ void SustainOn(UInt32 inFrame);
+ void SustainOff(UInt32 inFrame);
+ void SostenutoOn(UInt32 inFrame);
+ void SostenutoOff(UInt32 inFrame);
+
+ void NoteEnded(SynthNote *inNote, UInt32 inFrame);
+ void NoteFastReleased(SynthNote *inNote);
+
+ virtual bool ChannelMessage(UInt16 controlID, UInt16 controlValue);
+ virtual void AllNotesOff(UInt32 inFrame);
+ virtual void AllSoundOff(UInt32 inFrame);
+ void ResetAllControllers(UInt32 inFrame);
+
+ SynthNote * GetNote(NoteInstanceID inNoteID, bool unreleasedOnly=false, UInt32 *outNoteState=NULL);
+
+ void Reset();
+
+ virtual OSStatus Render(SInt64 inAbsoluteSampleFrame, UInt32 inNumberFrames, AUScope &outputs);
+
+ float GetPitchBend() const { return mMidiControlHandler->GetPitchBend(); }
+ SInt64 GetCurrentAbsoluteFrame() const { return mCurrentAbsoluteFrame; }
+
+ MusicDeviceGroupID GroupID () const { return mGroupID; }
+ virtual void SetGroupID (MusicDeviceGroupID inGroup);
+
+ MIDIControlHandler * GetMIDIControlHandler() const { return mMidiControlHandler; }
+
+protected:
+ SInt64 mCurrentAbsoluteFrame;
+ SynthNoteList mNoteList[kNumberOfSoundingNoteStates];
+ MIDIControlHandler *mMidiControlHandler;
+
+private:
+ friend class AUInstrumentBase;
+ friend class AUMonotimbralInstrumentBase;
+ friend class AUMultitimbralInstrumentBase;
+
+ bool mSustainIsOn;
+ bool mSostenutoIsOn;
+ UInt32 mOutputBus;
+ MusicDeviceGroupID mGroupID;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+struct SynthKeyZone
+{
+ UInt8 mLoNote;
+ UInt8 mHiNote;
+ UInt8 mLoVelocity;
+ UInt8 mHiVelocity;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const UInt32 kUnlimitedPolyphony = 0xFFFFFFFF;
+
+class SynthPartElement : public SynthElement
+{
+public:
+ SynthPartElement(AUInstrumentBase *audioUnit, UInt32 inElement);
+
+ UInt32 GetGroupIndex() const { return mGroupIndex; }
+ bool InRange(Float32 inNote, Float32 inVelocity);
+
+ UInt32 GetMaxPolyphony() const { return mMaxPolyphony; }
+ void SetMaxPolyphony(UInt32 inMaxPolyphony) { mMaxPolyphony = inMaxPolyphony; }
+
+private:
+ UInt32 mGroupIndex;
+ UInt32 mPatchIndex;
+ UInt32 mMaxPolyphony;
+ SynthKeyZone mKeyZone;
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h
new file mode 100644
index 0000000000..9c27aee04f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h
@@ -0,0 +1,145 @@
+/*
+ File: SynthEvent.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+/* You can either fill in code here or remove this and create or add new files. */
+
+#ifndef __SynthEvent__
+#define __SynthEvent__
+
+#include <AudioUnit/AudioUnit.h>
+#include <CoreAudio/CoreAudio.h>
+#include "MusicDeviceBase.h"
+#include <stdexcept>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+class SynthEvent
+{
+public:
+ enum {
+ kEventType_NoteOn = 1,
+ kEventType_NoteOff = 2,
+ kEventType_SustainOn = 3,
+ kEventType_SustainOff = 4,
+ kEventType_SostenutoOn = 5,
+ kEventType_SostenutoOff = 6,
+ kEventType_AllNotesOff = 7,
+ kEventType_AllSoundOff = 8,
+ kEventType_ResetAllControllers = 9
+ };
+
+
+ SynthEvent() {}
+ ~SynthEvent() {}
+
+ void Set(
+ UInt32 inEventType,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams* inNoteParams
+ )
+ {
+ mEventType = inEventType;
+ mGroupID = inGroupID;
+ mNoteID = inNoteID;
+ mOffsetSampleFrame = inOffsetSampleFrame;
+
+ if (inNoteParams)
+ {
+ UInt32 paramSize = offsetof(MusicDeviceNoteParams, mControls) + (inNoteParams->argCount-2)*sizeof(NoteParamsControlValue);
+ mNoteParams = inNoteParams->argCount > 3
+ ? (MusicDeviceNoteParams*)malloc(paramSize)
+ : &mSmallNoteParams;
+ memcpy(mNoteParams, inNoteParams, paramSize);
+ }
+ else
+ mNoteParams = NULL;
+ }
+
+
+ void Free()
+ {
+ if (mNoteParams)
+ {
+ if (mNoteParams->argCount > 3)
+ free(mNoteParams);
+ mNoteParams = NULL;
+ }
+ }
+
+ UInt32 GetEventType() const { return mEventType; }
+ MusicDeviceGroupID GetGroupID() const { return mGroupID; }
+ NoteInstanceID GetNoteID() const { return mNoteID; }
+ UInt32 GetOffsetSampleFrame() const { return mOffsetSampleFrame; }
+
+ MusicDeviceNoteParams* GetParams() const { return mNoteParams; }
+
+ UInt32 GetArgCount() const { return mNoteParams->argCount; }
+ UInt32 NumberParameters() const { return mNoteParams->argCount - 2; }
+
+ Float32 GetNote() const { return mNoteParams->mPitch; }
+ Float32 GetVelocity() const { return mNoteParams->mVelocity; }
+
+ NoteParamsControlValue GetParameter(UInt32 inIndex) const
+ {
+ if (inIndex >= NumberParameters())
+ throw std::runtime_error("index out of range");
+ return mNoteParams->mControls[inIndex];
+ }
+
+private:
+ UInt32 mEventType;
+ MusicDeviceGroupID mGroupID;
+ NoteInstanceID mNoteID;
+ UInt32 mOffsetSampleFrame;
+ MusicDeviceNoteParams* mNoteParams;
+ MusicDeviceNoteParams mSmallNoteParams; // inline a small one to eliminate malloc for the simple case.
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp
new file mode 100644
index 0000000000..96a24d33c2
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp
@@ -0,0 +1,140 @@
+/*
+ File: SynthNote.cpp
+ Abstract: SynthNote.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "SynthNote.h"
+#include "SynthElement.h"
+#include "AUInstrumentBase.h"
+
+bool SynthNote::AttackNote(
+ SynthPartElement * inPart,
+ SynthGroupElement * inGroup,
+ NoteInstanceID inNoteID,
+ UInt64 inAbsoluteSampleFrame,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams)
+{
+#if DEBUG_PRINT
+ printf("SynthNote::AttackNote %lu %lu abs frame %llu rel frame %lu\n", (UInt32)inGroup->GroupID(), (UInt32)inNoteID, inAbsoluteSampleFrame, inOffsetSampleFrame);
+#endif
+ mPart = inPart;
+ mGroup = inGroup;
+ mNoteID = inNoteID;
+
+ mAbsoluteStartFrame = inAbsoluteSampleFrame;
+ mRelativeStartFrame = inOffsetSampleFrame;
+ mRelativeReleaseFrame = -1;
+ mRelativeKillFrame = -1;
+
+ mPitch = inParams.mPitch;
+ mVelocity = inParams.mVelocity;
+
+
+ return Attack(inParams);
+}
+
+
+void SynthNote::Reset()
+{
+ mPart = 0;
+ mGroup = 0;
+ mAbsoluteStartFrame = 0;
+ mRelativeStartFrame = 0;
+ mRelativeReleaseFrame = 0;
+ mRelativeKillFrame = 0;
+}
+
+void SynthNote::Kill(UInt32 inFrame)
+{
+ mRelativeKillFrame = inFrame;
+}
+
+void SynthNote::Release(UInt32 inFrame)
+{
+ mRelativeReleaseFrame = inFrame;
+}
+
+void SynthNote::FastRelease(UInt32 inFrame)
+{
+ mRelativeReleaseFrame = inFrame;
+}
+
+double SynthNote::TuningA() const
+{
+ return 440.0;
+}
+
+double SynthNote::Frequency()
+{
+ return TuningA() * pow(2., (mPitch - 69. + GetPitchBend()) / 12.);
+}
+
+double SynthNote::SampleRate()
+{
+ return GetAudioUnit()->GetOutput(0)->GetStreamFormat().mSampleRate;
+}
+
+AUInstrumentBase* SynthNote::GetAudioUnit() const
+{
+ return (AUInstrumentBase*)mGroup->GetAudioUnit();
+}
+
+Float32 SynthNote::GetGlobalParameter(AudioUnitParameterID inParamID) const
+{
+ return mGroup->GetAudioUnit()->Globals()->GetParameter(inParamID);
+}
+
+void SynthNote::NoteEnded(UInt32 inFrame)
+{
+ mGroup->NoteEnded(this, inFrame);
+ mNoteID = 0xFFFFFFFF;
+}
+
+float SynthNote::GetPitchBend() const
+{
+ return mGroup->GetPitchBend();
+}
+
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h
new file mode 100644
index 0000000000..cec6377217
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h
@@ -0,0 +1,187 @@
+/*
+ File: SynthNote.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __SynthNote__
+#define __SynthNote__
+
+#include <AudioUnit/AudioUnit.h>
+#include <CoreAudio/CoreAudio.h>
+#include "MusicDeviceBase.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+enum SynthNoteState {
+ kNoteState_Attacked = 0,
+ kNoteState_Sostenutoed = 1,
+ kNoteState_ReleasedButSostenutoed = 2,
+ kNoteState_ReleasedButSustained = 3,
+ kNoteState_Released = 4,
+ kNoteState_FastReleased = 5,
+ kNoteState_Free = 6,
+ kNumberOfActiveNoteStates = 5,
+ kNumberOfSoundingNoteStates = 6,
+ kNumberOfNoteStates = 7,
+ kNoteState_Unset = kNumberOfNoteStates
+};
+
+/*
+ This table describes the state transitions for SynthNotes
+
+ EVENT CURRENT STATE NEW STATE
+ note on free attacked
+ note off attacked (and sustain on) released but sustained
+ note off attacked released
+ note off sostenutoed released but sostenutoed
+ sustain on -- no changes --
+ sustain off released but sustained released
+ sostenuto on attacked sostenutoed
+ sostenuto off sostenutoed attacked
+ sostenuto off released but sostenutoed (and sustain on) released but sustained
+ sostenuto off released but sostenutoed released
+ end of note any state free
+ soft voice stealing any state fast released
+ hard voice stealing any state free
+
+ soft voice stealing happens when there is a note on event and NumActiveNotes > MaxActiveNotes
+ hard voice stealing happens when there is a note on event and NumActiveNotes == NumNotes (no free notes)
+ voice stealing removes the quietest note in the highest numbered state that has sounding notes.
+*/
+
+class SynthGroupElement;
+class SynthPartElement;
+class AUInstrumentBase;
+
+struct SynthNote
+{
+ SynthNote() :
+ mPrev(0), mNext(0), mPart(0), mGroup(0),
+ mNoteID(0xffffffff),
+ mState(kNoteState_Unset),
+ mAbsoluteStartFrame(0),
+ mRelativeStartFrame(0),
+ mRelativeReleaseFrame(-1),
+ mRelativeKillFrame(-1),
+ mPitch(0.0f),
+ mVelocity(0.0f)
+ {
+ }
+
+ virtual ~SynthNote() {}
+
+ virtual void Reset();
+ //! Returns true if active note resulted from this call, otherwise false
+ virtual bool AttackNote(
+ SynthPartElement * inPart,
+ SynthGroupElement * inGroup,
+ NoteInstanceID inNoteID,
+ UInt64 inAbsoluteSampleFrame,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams &inParams
+ );
+
+ virtual OSStatus Render(UInt64 inAbsoluteSampleFrame, UInt32 inNumFrames, AudioBufferList** inBufferList, UInt32 inOutBusCount) = 0;
+ //! Returns true if active note resulted from this call, otherwise false
+ virtual bool Attack(const MusicDeviceNoteParams &inParams) = 0;
+ virtual void Kill(UInt32 inFrame); // voice is being stolen.
+ virtual void Release(UInt32 inFrame);
+ virtual void FastRelease(UInt32 inFrame);
+ virtual Float32 Amplitude() = 0; // used for finding quietest note for voice stealing.
+
+ virtual void NoteEnded(UInt32 inFrame);
+
+ SynthGroupElement* GetGroup() const { return mGroup; }
+ SynthPartElement* GetPart() const { return mPart; }
+
+ AUInstrumentBase* GetAudioUnit() const;
+
+ Float32 GetGlobalParameter(AudioUnitParameterID inParamID) const;
+
+ NoteInstanceID GetNoteID() const { return mNoteID; }
+ SynthNoteState GetState() const { return mState; }
+ UInt8 GetMidiKey() const { return (UInt8) mPitch; }
+ UInt8 GetMidiVelocity() const { return (UInt8) mVelocity; }
+
+ Boolean IsSounding() const { return mState < kNumberOfSoundingNoteStates; }
+ Boolean IsActive() const { return mState < kNumberOfActiveNoteStates; }
+ UInt64 GetAbsoluteStartFrame() const { return mAbsoluteStartFrame; }
+ SInt32 GetRelativeStartFrame() const { return mRelativeStartFrame; }
+ SInt32 GetRelativeReleaseFrame() const { return mRelativeReleaseFrame; }
+ SInt32 GetRelativeKillFrame() const { return mRelativeKillFrame; }
+
+ void ListRemove() { mPrev = mNext = 0; } // only use when lists will be reset.
+
+ float GetPitchBend() const;
+ double TuningA() const;
+
+ Float32 GetPitch() const { return mPitch; } // returns raw pitch from MusicDeviceNoteParams
+ virtual double Frequency(); // returns the frequency of note + pitch bend.
+ virtual double SampleRate();
+
+ // linked list pointers
+ SynthNote *mPrev;
+ SynthNote *mNext;
+
+ friend class SynthGroupElement;
+ friend struct SynthNoteList;
+protected:
+ void SetState(SynthNoteState inState) { mState = inState; }
+private:
+ SynthPartElement* mPart;
+ SynthGroupElement* mGroup;
+
+ NoteInstanceID mNoteID;
+ SynthNoteState mState;
+ UInt64 mAbsoluteStartFrame;
+ SInt32 mRelativeStartFrame;
+ SInt32 mRelativeReleaseFrame;
+ SInt32 mRelativeKillFrame;
+
+ Float32 mPitch;
+ Float32 mVelocity;
+};
+
+#endif
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp
new file mode 100644
index 0000000000..849abd266b
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp
@@ -0,0 +1,93 @@
+/*
+ File: SynthNoteList.cpp
+ Abstract: SynthNoteList.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "SynthNoteList.h"
+#include <stdexcept>
+
+void SynthNoteList::SanityCheck() const
+{
+ if (mState >= kNoteState_Unset) {
+ throw std::runtime_error("SanityCheck: mState is bad");
+ }
+
+ if (mHead == NULL) {
+ if (mTail != NULL)
+ throw std::runtime_error("SanityCheck: mHead is NULL but not mTail");
+ return;
+ }
+ if (mTail == NULL) {
+ throw std::runtime_error("SanityCheck: mTail is NULL but not mHead");
+ }
+
+ if (mHead->mPrev) {
+ throw std::runtime_error("SanityCheck: mHead has a mPrev");
+ }
+ if (mTail->mNext) {
+ throw std::runtime_error("SanityCheck: mTail has a mNext");
+ }
+
+ SynthNote *note = mHead;
+ while (note)
+ {
+ if (note->mState != mState)
+ throw std::runtime_error("SanityCheck: note in wrong state");
+ if (note->mNext) {
+ if (note->mNext->mPrev != note)
+ throw std::runtime_error("SanityCheck: bad link 1");
+ } else {
+ if (mTail != note)
+ throw std::runtime_error("SanityCheck: note->mNext is nil, but mTail != note");
+ }
+ if (note->mPrev) {
+ if (note->mPrev->mNext != note)
+ throw std::runtime_error("SanityCheck: bad link 2");
+ } else {
+ if (mHead != note)
+ throw std::runtime_error("SanityCheck: note->mPrev is nil, but mHead != note");
+ }
+ note = note->mNext;
+ }
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h
new file mode 100644
index 0000000000..47a3593018
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h
@@ -0,0 +1,232 @@
+/*
+ File: SynthNoteList.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __SynthNoteList__
+#define __SynthNoteList__
+
+#include "SynthNote.h"
+
+#if DEBUG
+#ifndef DEBUG_PRINT
+ #define DEBUG_PRINT 0
+#endif
+ #define USE_SANITY_CHECK 0
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+struct SynthNoteList
+{
+ SynthNoteList() : mState(kNoteState_Unset), mHead(0), mTail(0) {}
+
+ bool NotEmpty() const { return mHead != NULL; }
+ bool IsEmpty() const { return mHead == NULL; }
+ void Empty() {
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ mHead = mTail = NULL;
+ }
+
+ UInt32 Length() const {
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ UInt32 length = 0;
+ for (SynthNote* note = mHead; note; note = note->mNext)
+ length++;
+ return length;
+ };
+
+ void AddNote(SynthNote *inNote)
+ {
+#if DEBUG_PRINT
+ printf("AddNote(inNote=%p) to state: %lu\n", inNote, mState);
+#endif
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ inNote->SetState(mState);
+ inNote->mNext = mHead;
+ inNote->mPrev = NULL;
+
+ if (mHead) { mHead->mPrev = inNote; mHead = inNote; }
+ else mHead = mTail = inNote;
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ }
+
+ void RemoveNote(SynthNote *inNote)
+ {
+#if DEBUG_PRINT
+ printf("RemoveNote(inNote=%p) from state: %lu\n", inNote, mState);
+#endif
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ if (inNote->mPrev) inNote->mPrev->mNext = inNote->mNext;
+ else mHead = inNote->mNext;
+
+ if (inNote->mNext) inNote->mNext->mPrev = inNote->mPrev;
+ else mTail = inNote->mPrev;
+
+ inNote->mPrev = 0;
+ inNote->mNext = 0;
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ }
+
+ void TransferAllFrom(SynthNoteList *inNoteList, UInt32 inFrame)
+ {
+#if DEBUG_PRINT
+ printf("TransferAllFrom: from state %lu into state %lu\n", inNoteList->mState, mState);
+#endif
+#if USE_SANITY_CHECK
+ SanityCheck();
+ inNoteList->SanityCheck();
+#endif
+ if (!inNoteList->mTail) return;
+
+ if (mState == kNoteState_Released)
+ {
+ for (SynthNote* note = inNoteList->mHead; note; note = note->mNext)
+ {
+#if DEBUG_PRINT
+ printf("TransferAllFrom: releasing note %p\n", note);
+#endif
+ note->Release(inFrame);
+ note->SetState(mState);
+ }
+ }
+ else
+ {
+ for (SynthNote* note = inNoteList->mHead; note; note = note->mNext)
+ {
+ note->SetState(mState);
+ }
+ }
+
+ inNoteList->mTail->mNext = mHead;
+
+ if (mHead) mHead->mPrev = inNoteList->mTail;
+ else mTail = inNoteList->mTail;
+
+ mHead = inNoteList->mHead;
+
+ inNoteList->mHead = NULL;
+ inNoteList->mTail = NULL;
+#if USE_SANITY_CHECK
+ SanityCheck();
+ inNoteList->SanityCheck();
+#endif
+ }
+
+ SynthNote* FindOldestNote()
+ {
+#if DEBUG_PRINT
+ printf("FindOldestNote\n");
+#endif
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ UInt64 minStartFrame = -1;
+ SynthNote* oldestNote = NULL;
+ for (SynthNote* note = mHead; note; note = note->mNext)
+ {
+ if (note->mAbsoluteStartFrame < minStartFrame)
+ {
+ oldestNote = note;
+ minStartFrame = note->mAbsoluteStartFrame;
+ }
+ }
+ return oldestNote;
+ }
+
+ SynthNote* FindMostQuietNote()
+ {
+#if DEBUG_PRINT
+ printf("FindMostQuietNote\n");
+#endif
+ Float32 minAmplitude = 1e9f;
+ UInt64 minStartFrame = -1;
+ SynthNote* mostQuietNote = NULL;
+ for (SynthNote* note = mHead; note; note = note->mNext)
+ {
+ Float32 amp = note->Amplitude();
+#if DEBUG_PRINT
+ printf(" amp %g minAmplitude %g\n", amp, minAmplitude);
+#endif
+ if (amp < minAmplitude)
+ {
+ mostQuietNote = note;
+ minAmplitude = amp;
+ minStartFrame = note->mAbsoluteStartFrame;
+ }
+ else if (amp == minAmplitude && note->mAbsoluteStartFrame < minStartFrame)
+ {
+ // use earliest start time as a tie breaker
+ mostQuietNote = note;
+ minStartFrame = note->mAbsoluteStartFrame;
+ }
+ }
+#if USE_SANITY_CHECK
+ SanityCheck();
+#endif
+ return mostQuietNote;
+ }
+
+ void SanityCheck() const;
+
+ SynthNoteState mState;
+ SynthNote * mHead;
+ SynthNote * mTail;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h
new file mode 100644
index 0000000000..741be00fe0
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h
@@ -0,0 +1,88 @@
+/*
+ File: AUViewLocalizedStringKeys.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUViewLocalizedStringKeys_h__
+#define __AUViewLocalizedStringKeys_h__
+
+// ACCESS POINT:
+#define kLocalizedStringBundle_AUView CFSTR("com.apple.audio.units.Components")
+#define kLocalizedStringTable_AUView CFSTR("CustomUI")
+
+// UNLOCALIZED STRINGS:
+ #define kAUViewUnlocalizedString_TitleSeparator CFSTR(": ")
+
+// Generic View:
+ #define kAUViewLocalizedStringKey_AudioUnit CFSTR("Audio Unit")
+ #define kAUViewLocalizedStringKey_Manufacturer CFSTR("Manufacturer")
+
+ #define kAUViewLocalizedStringKey_FactoryPreset CFSTR("Factory Preset")
+
+ #define kAUViewLocalizedStringKey_Properties CFSTR("Properties")
+ #define kAUViewLocalizedStringKey_Parameters CFSTR("Parameters")
+
+ #define kAUViewLocalizedStringKey_Standard CFSTR("Standard")
+ #define kAUViewLocalizedStringKey_Expert CFSTR("Expert")
+
+// AULoadCPU:
+ #define kAUViewLocalizedStringKey_RestrictCPULoad CFSTR("Restrict CPU Load")
+ #define kAUViewLocalizedStringKey_PercentSymbol CFSTR("%")
+ #define kAUViewLocalizedStringKey_NotApplicable CFSTR("n/a")
+
+// AUDiskStreamingCheckbox:
+ #define kAUViewLocalizedStringKey_StreamFromDisk CFSTR("Stream From Disk")
+
+// AURenderQualityPopup:
+ #define kAUViewLocalizedStringKey_RenderQuality CFSTR("Render Quality")
+ #define kAUViewLocalizedStringKey_Maximum CFSTR("Maximum")
+ #define kAUViewLocalizedStringKey_High CFSTR("High")
+ #define kAUViewLocalizedStringKey_Medium CFSTR("Medium")
+ #define kAUViewLocalizedStringKey_Low CFSTR("Low")
+ #define kAUViewLocalizedStringKey_Minimum CFSTR("Minimum")
+
+// AUChannelLayoutPopUp:
+ #define kAUViewLocalizedStringKey_AudioChannelLayout CFSTR("Audio Channel Layout")
+
+#endif //__AUViewLocalizedStringKeys_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp
new file mode 100644
index 0000000000..010082fc3f
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp
@@ -0,0 +1,466 @@
+/*
+ File: AUEffectBase.cpp
+ Abstract: AUEffectBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUEffectBase.h"
+
+/*
+ This class does not deal as well as it should with N-M effects...
+
+ The problem areas are (if the channels don't match):
+ ProcessInPlace if the channels don't match - there will be problems if InputChan != OutputChan
+ Bypass - its just passing the buffers through when not processing them
+
+ This will be fixed in a future update...
+*/
+
+//_____________________________________________________________________________
+//
+AUEffectBase::AUEffectBase( AudioComponentInstance audioUnit,
+ bool inProcessesInPlace ) :
+ AUBase(audioUnit, 1, 1), // 1 in bus, 1 out bus
+ mBypassEffect(false),
+ mParamSRDep (false),
+ mProcessesInPlace(inProcessesInPlace),
+ mMainOutput(NULL), mMainInput(NULL)
+#if TARGET_OS_IPHONE
+ , mOnlyOneKernel(false)
+#endif
+{
+}
+
+//_____________________________________________________________________________
+//
+AUEffectBase::~AUEffectBase()
+{
+ Cleanup();
+}
+
+//_____________________________________________________________________________
+//
+void AUEffectBase::Cleanup()
+{
+ for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end(); ++it)
+ delete *it;
+
+ mKernelList.clear();
+ mMainOutput = NULL;
+ mMainInput = NULL;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUEffectBase::Initialize()
+{
+ // get our current numChannels for input and output
+ SInt16 auNumInputs = (SInt16) GetInput(0)->GetStreamFormat().mChannelsPerFrame;
+ SInt16 auNumOutputs = (SInt16) GetOutput(0)->GetStreamFormat().mChannelsPerFrame;
+
+ // does the unit publish specific information about channel configurations?
+ const AUChannelInfo *auChannelConfigs = NULL;
+ UInt32 numIOconfigs = SupportedNumChannels(&auChannelConfigs);
+
+ if ((numIOconfigs > 0) && (auChannelConfigs != NULL))
+ {
+ bool foundMatch = false;
+ for (UInt32 i = 0; (i < numIOconfigs) && !foundMatch; ++i)
+ {
+ SInt16 configNumInputs = auChannelConfigs[i].inChannels;
+ SInt16 configNumOutputs = auChannelConfigs[i].outChannels;
+ if ((configNumInputs < 0) && (configNumOutputs < 0))
+ {
+ // unit accepts any number of channels on input and output
+ if (((configNumInputs == -1) && (configNumOutputs == -2))
+ || ((configNumInputs == -2) && (configNumOutputs == -1)))
+ {
+ foundMatch = true;
+ // unit accepts any number of channels on input and output IFF they are the same number on both scopes
+ }
+ else if (((configNumInputs == -1) && (configNumOutputs == -1)) && (auNumInputs == auNumOutputs))
+ {
+ foundMatch = true;
+ // unit has specified a particular number of channels on both scopes
+ }
+ else
+ continue;
+ }
+ else
+ {
+ // the -1 case on either scope is saying that the unit doesn't care about the
+ // number of channels on that scope
+ bool inputMatch = (auNumInputs == configNumInputs) || (configNumInputs == -1);
+ bool outputMatch = (auNumOutputs == configNumOutputs) || (configNumOutputs == -1);
+ if (inputMatch && outputMatch)
+ foundMatch = true;
+ }
+ }
+ if (!foundMatch)
+ return kAudioUnitErr_FormatNotSupported;
+ }
+ else
+ {
+ // there is no specifically published channel info
+ // so for those kinds of effects, the assumption is that the channels (whatever their number)
+ // should match on both scopes
+ if ((auNumOutputs != auNumInputs) || (auNumOutputs == 0))
+ {
+ return kAudioUnitErr_FormatNotSupported;
+ }
+ }
+
+ MaintainKernels();
+
+ mMainOutput = GetOutput(0);
+ mMainInput = GetInput(0);
+
+ const CAStreamBasicDescription& format = GetStreamFormat(kAudioUnitScope_Output, 0);
+ format.IdentifyCommonPCMFormat(mCommonPCMFormat, NULL);
+ mBytesPerFrame = format.mBytesPerFrame;
+
+ return noErr;
+}
+
+OSStatus AUEffectBase::Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end(); ++it) {
+ AUKernelBase *kernel = *it;
+ if (kernel != NULL)
+ kernel->Reset();
+ }
+
+ return AUBase::Reset(inScope, inElement);
+}
+
+OSStatus AUEffectBase::GetPropertyInfo (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ if (inScope == kAudioUnitScope_Global) {
+ switch (inID) {
+ case kAudioUnitProperty_BypassEffect:
+ outWritable = true;
+ outDataSize = sizeof (UInt32);
+ return noErr;
+ case kAudioUnitProperty_InPlaceProcessing:
+ outWritable = true;
+ outDataSize = sizeof (UInt32);
+ return noErr;
+ }
+ }
+ return AUBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+}
+
+
+OSStatus AUEffectBase::GetProperty (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ if (inScope == kAudioUnitScope_Global) {
+ switch (inID) {
+ case kAudioUnitProperty_BypassEffect:
+ *((UInt32*)outData) = (IsBypassEffect() ? 1 : 0);
+ return noErr;
+ case kAudioUnitProperty_InPlaceProcessing:
+ *((UInt32*)outData) = (mProcessesInPlace ? 1 : 0);
+ return noErr;
+ }
+ }
+ return AUBase::GetProperty (inID, inScope, inElement, outData);
+}
+
+
+OSStatus AUEffectBase::SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ if (inScope == kAudioUnitScope_Global) {
+ switch (inID) {
+ case kAudioUnitProperty_BypassEffect:
+ {
+ if (inDataSize < sizeof(UInt32))
+ return kAudioUnitErr_InvalidPropertyValue;
+
+ bool tempNewSetting = *((UInt32*)inData) != 0;
+ // we're changing the state of bypass
+ if (tempNewSetting != IsBypassEffect())
+ {
+ if (!tempNewSetting && IsBypassEffect() && IsInitialized()) // turning bypass off and we're initialized
+ Reset(0, 0);
+ SetBypassEffect (tempNewSetting);
+ }
+ return noErr;
+ }
+ case kAudioUnitProperty_InPlaceProcessing:
+ mProcessesInPlace = (*((UInt32*)inData) != 0);
+ return noErr;
+ }
+ }
+ return AUBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
+}
+
+
+void AUEffectBase::MaintainKernels()
+{
+#if TARGET_OS_IPHONE
+ UInt32 nKernels = mOnlyOneKernel ? 1 : GetNumberOfChannels();
+#else
+ UInt32 nKernels = GetNumberOfChannels();
+#endif
+
+ if (mKernelList.size() < nKernels) {
+ mKernelList.reserve(nKernels);
+ for (UInt32 i = (UInt32)mKernelList.size(); i < nKernels; ++i)
+ mKernelList.push_back(NewKernel());
+ } else {
+ while (mKernelList.size() > nKernels) {
+ AUKernelBase *kernel = mKernelList.back();
+ delete kernel;
+ mKernelList.pop_back();
+ }
+ }
+
+ for(unsigned int i = 0; i < nKernels; i++ )
+ {
+ if(mKernelList[i]) {
+ mKernelList[i]->SetChannelNum (i);
+ }
+ }
+}
+
+bool AUEffectBase::StreamFormatWritable( AudioUnitScope scope,
+ AudioUnitElement element)
+{
+ return IsInitialized() ? false : true;
+}
+
+OSStatus AUEffectBase::ChangeStreamFormat( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inPrevFormat,
+ const CAStreamBasicDescription & inNewFormat)
+{
+ OSStatus result = AUBase::ChangeStreamFormat(inScope, inElement, inPrevFormat, inNewFormat);
+ if (result == noErr)
+ {
+ // for the moment this only dependency we know about
+ // where a parameter's range may change is with the sample rate
+ // and effects are only publishing parameters in the global scope!
+ if (GetParamHasSampleRateDependency() && fnotequal(inPrevFormat.mSampleRate, inNewFormat.mSampleRate))
+ PropertyChanged(kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0);
+ }
+
+ return result;
+}
+
+
+// ____________________________________________________________________________
+//
+// This method is called (potentially repeatedly) by ProcessForScheduledParams()
+// in order to perform the actual DSP required for this portion of the entire buffer
+// being processed. The entire buffer can be divided up into smaller "slices"
+// according to the timestamps on the scheduled parameters...
+//
+OSStatus AUEffectBase::ProcessScheduledSlice( void *inUserData,
+ UInt32 inStartFrameInBuffer,
+ UInt32 inSliceFramesToProcess,
+ UInt32 inTotalBufferFrames )
+{
+ ScheduledProcessParams &sliceParams = *((ScheduledProcessParams*)inUserData);
+
+ AudioUnitRenderActionFlags &actionFlags = *sliceParams.actionFlags;
+ AudioBufferList &inputBufferList = *sliceParams.inputBufferList;
+ AudioBufferList &outputBufferList = *sliceParams.outputBufferList;
+
+ UInt32 channelSize = inSliceFramesToProcess * mBytesPerFrame;
+ // fix the size of the buffer we're operating on before we render this slice of time
+ for(unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
+ inputBufferList.mBuffers[i].mDataByteSize = inputBufferList.mBuffers[i].mNumberChannels * channelSize;
+ }
+
+ for(unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
+ outputBufferList.mBuffers[i].mDataByteSize = outputBufferList.mBuffers[i].mNumberChannels * channelSize;
+ }
+ // process the buffer
+ OSStatus result = ProcessBufferLists(actionFlags, inputBufferList, outputBufferList, inSliceFramesToProcess );
+
+ // we just partially processed the buffers, so increment the data pointers to the next part of the buffer to process
+ for(unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
+ inputBufferList.mBuffers[i].mData =
+ (char *)inputBufferList.mBuffers[i].mData + inputBufferList.mBuffers[i].mNumberChannels * channelSize;
+ }
+
+ for(unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
+ outputBufferList.mBuffers[i].mData =
+ (char *)outputBufferList.mBuffers[i].mData + outputBufferList.mBuffers[i].mNumberChannels * channelSize;
+ }
+
+ return result;
+}
+
+// ____________________________________________________________________________
+//
+
+OSStatus AUEffectBase::Render( AudioUnitRenderActionFlags &ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 nFrames)
+{
+ if (!HasInput(0))
+ return kAudioUnitErr_NoConnection;
+
+ OSStatus result = noErr;
+
+ result = mMainInput->PullInput(ioActionFlags, inTimeStamp, 0 /* element */, nFrames);
+
+ if (result == noErr)
+ {
+ if(ProcessesInPlace() && mMainOutput->WillAllocateBuffer())
+ {
+ mMainOutput->SetBufferList(mMainInput->GetBufferList() );
+ }
+
+ if (ShouldBypassEffect())
+ {
+ // leave silence bit alone
+
+ if(!ProcessesInPlace() )
+ {
+ mMainInput->CopyBufferContentsTo (mMainOutput->GetBufferList());
+ }
+ }
+ else
+ {
+ if(mParamList.size() == 0 )
+ {
+ // this will read/write silence bit
+ result = ProcessBufferLists(ioActionFlags, mMainInput->GetBufferList(), mMainOutput->GetBufferList(), nFrames);
+ }
+ else
+ {
+ // deal with scheduled parameters...
+
+ AudioBufferList &inputBufferList = mMainInput->GetBufferList();
+ AudioBufferList &outputBufferList = mMainOutput->GetBufferList();
+
+ ScheduledProcessParams processParams;
+ processParams.actionFlags = &ioActionFlags;
+ processParams.inputBufferList = &inputBufferList;
+ processParams.outputBufferList = &outputBufferList;
+
+ // divide up the buffer into slices according to scheduled params then
+ // do the DSP for each slice (ProcessScheduledSlice() called for each slice)
+ result = ProcessForScheduledParams( mParamList,
+ nFrames,
+ &processParams );
+
+
+ // fixup the buffer pointers to how they were before we started
+ UInt32 channelSize = nFrames * mBytesPerFrame;
+ for(unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
+ UInt32 size = inputBufferList.mBuffers[i].mNumberChannels * channelSize;
+ inputBufferList.mBuffers[i].mData = (char *)inputBufferList.mBuffers[i].mData - size;
+ inputBufferList.mBuffers[i].mDataByteSize = size;
+ }
+
+ for(unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
+ UInt32 size = outputBufferList.mBuffers[i].mNumberChannels * channelSize;
+ outputBufferList.mBuffers[i].mData = (char *)outputBufferList.mBuffers[i].mData - size;
+ outputBufferList.mBuffers[i].mDataByteSize = size;
+ }
+ }
+ }
+
+ if ( (ioActionFlags & kAudioUnitRenderAction_OutputIsSilence) && !ProcessesInPlace() )
+ {
+ AUBufferList::ZeroBuffer(mMainOutput->GetBufferList() );
+ }
+ }
+
+ return result;
+}
+
+
+OSStatus AUEffectBase::ProcessBufferLists(
+ AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioBufferList & inBuffer,
+ AudioBufferList & outBuffer,
+ UInt32 inFramesToProcess )
+{
+ if (ShouldBypassEffect())
+ return noErr;
+
+ // interleaved (or mono)
+ switch (mCommonPCMFormat) {
+ case CAStreamBasicDescription::kPCMFormatFloat32 :
+ ProcessBufferListsT<Float32>(ioActionFlags, inBuffer, outBuffer, inFramesToProcess);
+ break;
+ case CAStreamBasicDescription::kPCMFormatFixed824 :
+ ProcessBufferListsT<SInt32>(ioActionFlags, inBuffer, outBuffer, inFramesToProcess);
+ break;
+ case CAStreamBasicDescription::kPCMFormatInt16 :
+ ProcessBufferListsT<SInt16>(ioActionFlags, inBuffer, outBuffer, inFramesToProcess);
+ break;
+ default :
+ throw CAException(kAudio_UnimplementedError);
+ }
+
+ return noErr;
+}
+
+Float64 AUEffectBase::GetSampleRate()
+{
+ return GetOutput(0)->GetStreamFormat().mSampleRate;
+}
+
+UInt32 AUEffectBase::GetNumberOfChannels()
+{
+ return GetOutput(0)->GetStreamFormat().mChannelsPerFrame;
+}
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.h
new file mode 100644
index 0000000000..13ba96b393
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUEffectBase.h
@@ -0,0 +1,377 @@
+/*
+ File: AUEffectBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUEffectBase_h__
+#define __AUEffectBase_h__
+
+#include "AUBase.h"
+#include "AUSilentTimeout.h"
+#include "CAException.h"
+
+class AUKernelBase;
+
+// Base class for an effect with one input stream, one output stream,
+// any number of channels.
+ /*! @class AUEffectBase */
+class AUEffectBase : public AUBase {
+public:
+ /*! @ctor AUEffectBase */
+ AUEffectBase( AudioComponentInstance audioUnit,
+ bool inProcessesInPlace = true );
+ /*! @dtor ~AUEffectBase */
+ ~AUEffectBase();
+
+ /*! @method Initialize */
+ virtual OSStatus Initialize();
+
+ /*! @method Cleanup */
+ virtual void Cleanup();
+
+
+ /*! @method Reset */
+ virtual OSStatus Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ /*! @method GetPropertyInfo */
+ virtual OSStatus GetPropertyInfo (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ /*! @method GetProperty */
+ virtual OSStatus GetProperty (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+
+ /*! @method SetProperty */
+ virtual OSStatus SetProperty(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+
+ /*! @method StreamFormatWritable */
+ virtual bool StreamFormatWritable (AudioUnitScope scope,
+ AudioUnitElement element);
+
+ /*! @method ChangeStreamFormat */
+ virtual OSStatus ChangeStreamFormat (
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inPrevFormat,
+ const CAStreamBasicDescription & inNewFormat);
+
+ /*! @method Render */
+ virtual OSStatus Render(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames);
+
+ // our virtual methods
+
+ // If your unit processes N to N channels, and there are no interactions between channels,
+ // it can override NewKernel to create a mono processing object per channel. Otherwise,
+ // don't override NewKernel, and instead, override ProcessBufferLists.
+ /*! @method NewKernel */
+ virtual AUKernelBase * NewKernel() { return NULL; }
+
+ /*! @method ProcessBufferLists */
+ virtual OSStatus ProcessBufferLists(
+ AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioBufferList & inBuffer,
+ AudioBufferList & outBuffer,
+ UInt32 inFramesToProcess );
+
+ // convenience format accessors (use output 0's format)
+ /*! @method GetSampleRate */
+ Float64 GetSampleRate();
+
+ /*! @method GetNumberOfChannels */
+ UInt32 GetNumberOfChannels();
+
+ // convenience wrappers for accessing parameters in the global scope
+ /*! @method SetParameter */
+ using AUBase::SetParameter;
+ void SetParameter( AudioUnitParameterID paramID,
+ AudioUnitParameterValue value)
+ {
+ Globals()->SetParameter(paramID, value);
+ }
+
+ /*! @method GetParameter */
+ using AUBase::GetParameter;
+ AudioUnitParameterValue GetParameter( AudioUnitParameterID paramID )
+ {
+ return Globals()->GetParameter(paramID );
+ }
+
+ /*! @method CanScheduleParameters */
+ virtual bool CanScheduleParameters() const { return true; }
+
+ /*! @method IsBypassEffect */
+ // This is used for the property value - to reflect to the UI if an effect is bypassed
+ bool IsBypassEffect () { return mBypassEffect; }
+
+protected:
+
+ /*! @method MaintainKernels */
+ void MaintainKernels();
+
+ /*! @method ShouldBypassEffect */
+ // This is used in the render call to see if an effect is bypassed
+ // It can return a different status than IsBypassEffect (though it MUST take that into account)
+ virtual bool ShouldBypassEffect () { return IsBypassEffect(); }
+
+public:
+ /*! @method SetBypassEffect */
+ virtual void SetBypassEffect (bool inFlag) { mBypassEffect = inFlag; }
+
+ /*! @method SetParamHasSampleRateDependency */
+ void SetParamHasSampleRateDependency (bool inFlag)
+ {
+ mParamSRDep = inFlag;
+ }
+
+ /*! @method GetParamHasSampleRateDependency */
+ bool GetParamHasSampleRateDependency () const { return mParamSRDep; }
+
+ struct ScheduledProcessParams // pointer passed in as void* userData param for ProcessScheduledSlice()
+ {
+ AudioUnitRenderActionFlags *actionFlags;
+ AudioBufferList *inputBufferList;
+ AudioBufferList *outputBufferList;
+ };
+
+ virtual OSStatus ProcessScheduledSlice( void *inUserData,
+ UInt32 inStartFrameInBuffer,
+ UInt32 inSliceFramesToProcess,
+ UInt32 inTotalBufferFrames );
+
+
+ bool ProcessesInPlace() const {return mProcessesInPlace;};
+ void SetProcessesInPlace(bool inProcessesInPlace) {mProcessesInPlace = inProcessesInPlace;};
+
+ typedef std::vector<AUKernelBase *> KernelList;
+
+
+
+protected:
+ /*! @var mKernelList */
+ KernelList mKernelList;
+
+ AUKernelBase* GetKernel(UInt32 index) { return mKernelList[index]; }
+
+ /*! @method IsInputSilent */
+ bool IsInputSilent (AudioUnitRenderActionFlags inActionFlags, UInt32 inFramesToProcess)
+ {
+ bool inputSilent = (inActionFlags & kAudioUnitRenderAction_OutputIsSilence) != 0;
+
+ // take latency and tail time into account when propagating the silent bit
+ UInt32 silentTimeoutFrames = UInt32(GetSampleRate() * (GetLatency() + GetTailTime()));
+ mSilentTimeout.Process (inFramesToProcess, silentTimeoutFrames, inputSilent);
+ return inputSilent;
+ }
+
+#if TARGET_OS_IPHONE
+ void SetOnlyOneKernel(bool inUseOnlyOneKernel) { mOnlyOneKernel = inUseOnlyOneKernel; } // set in ctor of subclass that wants it.
+#endif
+
+ template <typename T>
+ void ProcessBufferListsT(
+ AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioBufferList & inBuffer,
+ AudioBufferList & outBuffer,
+ UInt32 inFramesToProcess );
+
+ CAStreamBasicDescription::CommonPCMFormat GetCommonPCMFormat() const { return mCommonPCMFormat; }
+
+
+private:
+ /*! @var mBypassEffect */
+ bool mBypassEffect;
+ /*! @var mParamSRDep */
+ bool mParamSRDep;
+
+ /*! @var mProcessesInplace */
+ bool mProcessesInPlace;
+
+ /*! @var mSilentTimeout */
+ AUSilentTimeout mSilentTimeout;
+
+ /*! @var mMainOutput */
+ AUOutputElement * mMainOutput;
+
+ /*! @var mMainInput */
+ AUInputElement * mMainInput;
+
+#if TARGET_OS_IPHONE
+ /*! @var mOnlyOneKernel */
+ bool mOnlyOneKernel;
+#endif
+
+ /*! @var mCommonPCMFormat */
+ CAStreamBasicDescription::CommonPCMFormat mCommonPCMFormat;
+ UInt32 mBytesPerFrame;
+};
+
+
+// Base class for a "kernel", an object that performs DSP on one channel of an interleaved stream.
+ /*! @class AUKernelBase */
+class AUKernelBase {
+public:
+ /*! @ctor AUKernelBase */
+ AUKernelBase(AUEffectBase *inAudioUnit ) :
+ mAudioUnit(inAudioUnit) { }
+
+ /*! @dtor ~AUKernelBase */
+ virtual ~AUKernelBase() { }
+
+ /*! @method Reset */
+ virtual void Reset() { }
+
+ /*! @method Process */
+ virtual void Process( const Float32 * inSourceP,
+ Float32 * inDestP,
+ UInt32 inFramesToProcess,
+ UInt32 inNumChannels,
+ bool & ioSilence) { throw CAException(kAudio_UnimplementedError ); }
+
+ /*! @method Process */
+ virtual void Process( const SInt32 * inSourceP,
+ SInt32 * inDestP,
+ UInt32 inFramesToProcess,
+ UInt32 inNumChannels,
+ bool & ioSilence) { throw CAException(kAudio_UnimplementedError ); }
+
+ /*! @method Process */
+ virtual void Process( const SInt16 * inSourceP,
+ SInt16 * inDestP,
+ UInt32 inFramesToProcess,
+ UInt32 inNumChannels,
+ bool & ioSilence) { throw CAException(kAudio_UnimplementedError ); }
+
+ /*! @method GetSampleRate */
+ Float64 GetSampleRate()
+ {
+ return mAudioUnit->GetSampleRate();
+ }
+
+ /*! @method GetParameter */
+ AudioUnitParameterValue GetParameter (AudioUnitParameterID paramID)
+ {
+ return mAudioUnit->GetParameter(paramID);
+ }
+
+ void SetChannelNum (UInt32 inChan) { mChannelNum = inChan; }
+ UInt32 GetChannelNum () { return mChannelNum; }
+
+protected:
+ /*! @var mAudioUnit */
+ AUEffectBase * mAudioUnit;
+ UInt32 mChannelNum;
+
+};
+
+template <typename T>
+void AUEffectBase::ProcessBufferListsT(
+ AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioBufferList & inBuffer,
+ AudioBufferList & outBuffer,
+ UInt32 inFramesToProcess )
+{
+ bool ioSilence;
+
+ bool silentInput = IsInputSilent (ioActionFlags, inFramesToProcess);
+ ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
+
+ // call the kernels to handle either interleaved or deinterleaved
+ if (inBuffer.mNumberBuffers == 1) {
+ if (inBuffer.mBuffers[0].mNumberChannels == 0)
+ throw CAException(kAudio_ParamError);
+
+ for (UInt32 channel = 0; channel < mKernelList.size(); ++channel) {
+ AUKernelBase *kernel = mKernelList[channel];
+
+ if (kernel == NULL) continue;
+ ioSilence = silentInput;
+
+ // process each interleaved channel individually
+ kernel->Process(
+ (const T *)inBuffer.mBuffers[0].mData + channel,
+ (T *)outBuffer.mBuffers[0].mData + channel,
+ inFramesToProcess,
+ inBuffer.mBuffers[0].mNumberChannels,
+ ioSilence);
+
+ if (!ioSilence)
+ ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence;
+ }
+ } else {
+ for (UInt32 channel = 0; channel < mKernelList.size(); ++channel) {
+ AUKernelBase *kernel = mKernelList[channel];
+
+ if (kernel == NULL) continue;
+
+ ioSilence = silentInput;
+ const AudioBuffer *srcBuffer = &inBuffer.mBuffers[channel];
+ AudioBuffer *destBuffer = &outBuffer.mBuffers[channel];
+
+ kernel->Process(
+ (const T *)srcBuffer->mData,
+ (T *)destBuffer->mData,
+ inFramesToProcess,
+ 1,
+ ioSilence);
+
+ if (!ioSilence)
+ ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence;
+ }
+ }
+}
+
+
+#endif // __AUEffectBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp
new file mode 100644
index 0000000000..e5e358d685
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp
@@ -0,0 +1,495 @@
+/*
+ File: AUMIDIBase.cpp
+ Abstract: AUMIDIBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUMIDIBase.h"
+#include <CoreMIDI/CoreMIDI.h>
+#include "CAXException.h"
+
+//temporaray location
+enum
+{
+ kMidiMessage_NoteOff = 0x80,
+ kMidiMessage_NoteOn = 0x90,
+ kMidiMessage_PolyPressure = 0xA0,
+ kMidiMessage_ControlChange = 0xB0,
+ kMidiMessage_ProgramChange = 0xC0,
+ kMidiMessage_ChannelPressure = 0xD0,
+ kMidiMessage_PitchWheel = 0xE0,
+
+ kMidiController_AllSoundOff = 120,
+ kMidiController_ResetAllControllers = 121,
+ kMidiController_AllNotesOff = 123
+};
+
+AUMIDIBase::AUMIDIBase(AUBase* inBase)
+ : mAUBaseInstance (*inBase)
+{
+#if CA_AUTO_MIDI_MAP
+ mMapManager = new CAAUMIDIMapManager();
+#endif
+}
+
+AUMIDIBase::~AUMIDIBase()
+{
+#if CA_AUTO_MIDI_MAP
+ if (mMapManager)
+ delete mMapManager;
+#endif
+}
+
+#if TARGET_API_MAC_OSX
+OSStatus AUMIDIBase::DelegateGetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus result = noErr;
+
+ switch (inID) {
+#if !TARGET_OS_IPHONE
+ case kMusicDeviceProperty_MIDIXMLNames:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ if (GetXMLNames(NULL) == noErr) {
+ outDataSize = sizeof(CFURLRef);
+ outWritable = false;
+ } else
+ result = kAudioUnitErr_InvalidProperty;
+ break;
+#endif
+#if CA_AUTO_MIDI_MAP
+ case kAudioUnitProperty_AllParameterMIDIMappings:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ outWritable = true;
+ outDataSize = sizeof (AUParameterMIDIMapping)*mMapManager->NumMaps();
+ result = noErr;
+ break;
+
+ case kAudioUnitProperty_HotMapParameterMIDIMapping:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ outWritable = true;
+ outDataSize = sizeof (AUParameterMIDIMapping);
+ result = noErr;
+ break;
+
+ case kAudioUnitProperty_AddParameterMIDIMapping:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ outWritable = true;
+ outDataSize = sizeof (AUParameterMIDIMapping);
+ result = noErr;
+ break;
+
+ case kAudioUnitProperty_RemoveParameterMIDIMapping:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ outWritable = true;
+ outDataSize = sizeof (AUParameterMIDIMapping);
+ result = noErr;
+ break;
+#endif
+
+ default:
+ result = kAudioUnitErr_InvalidProperty;
+ break;
+ }
+ return result;
+
+#if CA_AUTO_MIDI_MAP || (!TARGET_OS_IPHONE)
+InvalidScope:
+ return kAudioUnitErr_InvalidScope;
+InvalidElement:
+ return kAudioUnitErr_InvalidElement;
+#endif
+}
+
+OSStatus AUMIDIBase::DelegateGetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ OSStatus result;
+
+ switch (inID) {
+#if !TARGET_OS_IPHONE
+ case kMusicDeviceProperty_MIDIXMLNames:
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ result = GetXMLNames((CFURLRef *)outData);
+ break;
+#endif
+#if CA_AUTO_MIDI_MAP
+ case kAudioUnitProperty_AllParameterMIDIMappings:{
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ AUParameterMIDIMapping* maps = (static_cast<AUParameterMIDIMapping*>(outData));
+ mMapManager->GetMaps(maps);
+// printf ("GETTING MAPS\n");
+// mMapManager->Print();
+ result = noErr;
+ break;
+ }
+
+ case kAudioUnitProperty_HotMapParameterMIDIMapping:{
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ AUParameterMIDIMapping * map = (static_cast<AUParameterMIDIMapping*>(outData));
+ mMapManager->GetHotParameterMap (*map);
+ result = noErr;
+ break;
+ }
+#endif
+
+ default:
+ result = kAudioUnitErr_InvalidProperty;
+ break;
+ }
+ return result;
+
+#if CA_AUTO_MIDI_MAP || (!TARGET_OS_IPHONE)
+InvalidScope:
+ return kAudioUnitErr_InvalidScope;
+InvalidElement:
+ return kAudioUnitErr_InvalidElement;
+#endif
+}
+
+OSStatus AUMIDIBase::DelegateSetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ OSStatus result;
+
+ switch (inID) {
+#if CA_AUTO_MIDI_MAP
+ case kAudioUnitProperty_AddParameterMIDIMapping:{
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ AUParameterMIDIMapping * maps = (AUParameterMIDIMapping*)inData;
+ mMapManager->SortedInsertToParamaterMaps (maps, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance);
+ mAUBaseInstance.PropertyChanged (kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0);
+ result = noErr;
+ break;
+ }
+
+ case kAudioUnitProperty_RemoveParameterMIDIMapping:{
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ AUParameterMIDIMapping * maps = (AUParameterMIDIMapping*)inData;
+ bool didChange;
+ mMapManager->SortedRemoveFromParameterMaps(maps, (inDataSize / sizeof(AUParameterMIDIMapping)), didChange);
+ if (didChange)
+ mAUBaseInstance.PropertyChanged (kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0);
+ result = noErr;
+ break;
+ }
+
+ case kAudioUnitProperty_HotMapParameterMIDIMapping:{
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ AUParameterMIDIMapping & map = *((AUParameterMIDIMapping*)inData);
+ mMapManager->SetHotMapping (map);
+ result = noErr;
+ break;
+ }
+ case kAudioUnitProperty_AllParameterMIDIMappings:{
+ ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
+ ca_require(inElement == 0, InvalidElement);
+ AUParameterMIDIMapping * mappings = (AUParameterMIDIMapping*)inData;
+ mMapManager->ReplaceAllMaps (mappings, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance);
+ result = noErr;
+ break;
+ }
+#endif
+
+ default:
+ result = kAudioUnitErr_InvalidProperty;
+ break;
+ }
+ return result;
+#if CA_AUTO_MIDI_MAP
+ InvalidScope:
+ return kAudioUnitErr_InvalidScope;
+ InvalidElement:
+ return kAudioUnitErr_InvalidElement;
+#endif
+}
+
+
+
+#endif //TARGET_API_MAC_OSX
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#pragma mark ____MidiDispatch
+
+
+inline const Byte * NextMIDIEvent(const Byte *event, const Byte *end)
+{
+ Byte c = *event;
+ switch (c >> 4) {
+ default: // data byte -- assume in sysex
+ while ((*++event & 0x80) == 0 && event < end)
+ ;
+ break;
+ case 0x8:
+ case 0x9:
+ case 0xA:
+ case 0xB:
+ case 0xE:
+ event += 3;
+ break;
+ case 0xC:
+ case 0xD:
+ event += 2;
+ break;
+ case 0xF:
+ switch (c) {
+ case 0xF0:
+ while ((*++event & 0x80) == 0 && event < end)
+ ;
+ break;
+ case 0xF1:
+ case 0xF3:
+ event += 2;
+ break;
+ case 0xF2:
+ event += 3;
+ break;
+ default:
+ ++event;
+ break;
+ }
+ }
+ return (event >= end) ? end : event;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUMIDIBase::HandleMIDIPacketList
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+OSStatus AUMIDIBase::HandleMIDIPacketList(const MIDIPacketList *pktlist)
+{
+ if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
+
+ int nPackets = pktlist->numPackets;
+ const MIDIPacket *pkt = pktlist->packet;
+
+ while (nPackets-- > 0) {
+ const Byte *event = pkt->data, *packetEnd = event + pkt->length;
+ long startFrame = (long)pkt->timeStamp;
+ while (event < packetEnd) {
+ Byte status = event[0];
+ if (status & 0x80) {
+ // really a status byte (not sysex continuation)
+ HandleMidiEvent(status & 0xF0, status & 0x0F, event[1], event[2], static_cast<UInt32>(startFrame));
+ // note that we're generating a bogus channel number for system messages (0xF0-FF)
+ }
+ event = NextMIDIEvent(event, packetEnd);
+ }
+ pkt = reinterpret_cast<const MIDIPacket *>(packetEnd);
+ }
+ return noErr;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AUMIDIBase::HandleMidiEvent
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+OSStatus AUMIDIBase::HandleMidiEvent(UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
+{
+ if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
+
+#if CA_AUTO_MIDI_MAP
+// you potentially have a choice to make here - if a param mapping matches, do you still want to process the
+// MIDI event or not. The default behaviour is to continue on with the MIDI event.
+ if (mMapManager->HandleHotMapping (status, channel, data1, mAUBaseInstance)) {
+ mAUBaseInstance.PropertyChanged (kAudioUnitProperty_HotMapParameterMIDIMapping, kAudioUnitScope_Global, 0);
+ }
+ else {
+ mMapManager->FindParameterMapEventMatch(status, channel, data1, data2, inStartFrame, mAUBaseInstance);
+ }
+#endif
+
+ OSStatus result = noErr;
+
+ switch(status)
+ {
+ case kMidiMessage_NoteOn:
+ if(data2)
+ {
+ result = HandleNoteOn(channel, data1, data2, inStartFrame);
+ }
+ else
+ {
+ // zero velocity translates to note off
+ result = HandleNoteOff(channel, data1, data2, inStartFrame);
+ }
+ break;
+
+ case kMidiMessage_NoteOff:
+ result = HandleNoteOff(channel, data1, data2, inStartFrame);
+ break;
+
+ default:
+ result = HandleNonNoteEvent (status, channel, data1, data2, inStartFrame);
+ break;
+ }
+
+ return result;
+}
+
+OSStatus AUMIDIBase::HandleNonNoteEvent (UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
+{
+ OSStatus result = noErr;
+
+ switch (status)
+ {
+ case kMidiMessage_PitchWheel:
+ result = HandlePitchWheel(channel, data1, data2, inStartFrame);
+ break;
+
+ case kMidiMessage_ProgramChange:
+ result = HandleProgramChange(channel, data1);
+ break;
+
+ case kMidiMessage_ChannelPressure:
+ result = HandleChannelPressure(channel, data1, inStartFrame);
+ break;
+
+ case kMidiMessage_ControlChange:
+ {
+ switch (data1) {
+ case kMidiController_AllNotesOff:
+ result = HandleAllNotesOff(channel);
+ break;
+
+ case kMidiController_ResetAllControllers:
+ result = HandleResetAllControllers(channel);
+ break;
+
+ case kMidiController_AllSoundOff:
+ result = HandleAllSoundOff(channel);
+ break;
+
+ default:
+ result = HandleControlChange(channel, data1, data2, inStartFrame);
+ break;
+ }
+ break;
+ }
+ case kMidiMessage_PolyPressure:
+ result = HandlePolyPressure (channel, data1, data2, inStartFrame);
+ break;
+ }
+ return result;
+}
+
+OSStatus AUMIDIBase::SysEx (const UInt8 * inData,
+ UInt32 inLength)
+{
+ if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
+
+ return HandleSysEx(inData, inLength );
+}
+
+
+
+#if TARGET_OS_MAC
+ #if __LP64__
+ // comp instance, parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index + 1];
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
+ #endif
+#elif TARGET_OS_WIN32
+ // (no comp instance), parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index];
+#endif
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+OSStatus AUMIDIBase::ComponentEntryDispatch( ComponentParameters * params,
+ AUMIDIBase * This)
+{
+ if (This == NULL) return kAudio_ParamError;
+
+ OSStatus result;
+
+ switch (params->what) {
+ case kMusicDeviceMIDIEventSelect:
+ {
+ PARAM(UInt32, pbinStatus, 0, 4);
+ PARAM(UInt32, pbinData1, 1, 4);
+ PARAM(UInt32, pbinData2, 2, 4);
+ PARAM(UInt32, pbinOffsetSampleFrame, 3, 4);
+ result = This->MIDIEvent(pbinStatus, pbinData1, pbinData2, pbinOffsetSampleFrame);
+ }
+ break;
+ case kMusicDeviceSysExSelect:
+ {
+ PARAM(const UInt8 *, pbinData, 0, 2);
+ PARAM(UInt32, pbinLength, 1, 2);
+ result = This->SysEx(pbinData, pbinLength);
+ }
+ break;
+
+ default:
+ result = badComponentSelector;
+ break;
+ }
+
+ return result;
+}
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h
new file mode 100644
index 0000000000..40c6a77695
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h
@@ -0,0 +1,213 @@
+/*
+ File: AUMIDIBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUMIDIBase_h__
+#define __AUMIDIBase_h__
+
+#include "AUBase.h"
+
+#if CA_AUTO_MIDI_MAP
+ #include "CAAUMIDIMapManager.h"
+#endif
+
+struct MIDIPacketList;
+
+// ________________________________________________________________________
+// MusicDeviceBase
+//
+ /*! @class AUMIDIBase */
+class AUMIDIBase {
+public:
+ // this is NOT a copy constructor!
+ /*! @ctor AUMIDIBase */
+ AUMIDIBase(AUBase* inBase);
+ /*! @dtor ~AUMIDIBase */
+ virtual ~AUMIDIBase();
+
+ /*! @method MIDIEvent */
+ virtual OSStatus MIDIEvent( UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame)
+ {
+ UInt32 strippedStatus = inStatus & 0xf0;
+ UInt32 channel = inStatus & 0x0f;
+
+ return HandleMidiEvent(strippedStatus, channel, inData1, inData2, inOffsetSampleFrame);
+ }
+
+ /*! @method HandleMIDIPacketList */
+ OSStatus HandleMIDIPacketList(const MIDIPacketList *pktlist);
+
+ /*! @method SysEx */
+ virtual OSStatus SysEx( const UInt8 * inData,
+ UInt32 inLength);
+
+#if TARGET_API_MAC_OSX
+ /*! @method DelegateGetPropertyInfo */
+ virtual OSStatus DelegateGetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ /*! @method DelegateGetProperty */
+ virtual OSStatus DelegateGetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+
+ /*! @method DelegateSetProperty */
+ virtual OSStatus DelegateSetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+#endif
+
+protected:
+ // MIDI dispatch
+ /*! @method HandleMidiEvent */
+ virtual OSStatus HandleMidiEvent( UInt8 inStatus,
+ UInt8 inChannel,
+ UInt8 inData1,
+ UInt8 inData2,
+ UInt32 inStartFrame);
+
+ /*! @method HandleNonNoteEvent */
+ virtual OSStatus HandleNonNoteEvent ( UInt8 status,
+ UInt8 channel,
+ UInt8 data1,
+ UInt8 data2,
+ UInt32 inStartFrame);
+
+#if TARGET_API_MAC_OSX
+ /*! @method GetXMLNames */
+ virtual OSStatus GetXMLNames(CFURLRef *outNameDocument)
+ { return kAudioUnitErr_InvalidProperty; } // if not overridden, it's unsupported
+#endif
+
+// channel messages
+ /*! @method HandleNoteOn */
+ virtual OSStatus HandleNoteOn( UInt8 inChannel,
+ UInt8 inNoteNumber,
+ UInt8 inVelocity,
+ UInt32 inStartFrame) { return noErr; }
+
+ /*! @method HandleNoteOff */
+ virtual OSStatus HandleNoteOff( UInt8 inChannel,
+ UInt8 inNoteNumber,
+ UInt8 inVelocity,
+ UInt32 inStartFrame) { return noErr; }
+
+ /*! @method HandleControlChange */
+ virtual OSStatus HandleControlChange( UInt8 inChannel,
+ UInt8 inController,
+ UInt8 inValue,
+ UInt32 inStartFrame) { return noErr; }
+
+ /*! @method HandlePitchWheel */
+ virtual OSStatus HandlePitchWheel( UInt8 inChannel,
+ UInt8 inPitch1,
+ UInt8 inPitch2,
+ UInt32 inStartFrame) { return noErr; }
+
+ /*! @method HandleChannelPressure */
+ virtual OSStatus HandleChannelPressure( UInt8 inChannel,
+ UInt8 inValue,
+ UInt32 inStartFrame) { return noErr; }
+
+ /*! @method HandleProgramChange */
+ virtual OSStatus HandleProgramChange( UInt8 inChannel,
+ UInt8 inValue) { return noErr; }
+
+ /*! @method HandlePolyPressure */
+ virtual OSStatus HandlePolyPressure( UInt8 inChannel,
+ UInt8 inKey,
+ UInt8 inValue,
+ UInt32 inStartFrame) { return noErr; }
+
+ /*! @method HandleResetAllControllers */
+ virtual OSStatus HandleResetAllControllers(UInt8 inChannel) { return noErr; }
+
+ /*! @method HandleAllNotesOff */
+ virtual OSStatus HandleAllNotesOff( UInt8 inChannel) { return noErr; }
+
+ /*! @method HandleAllSoundOff */
+ virtual OSStatus HandleAllSoundOff( UInt8 inChannel) { return noErr; }
+
+
+//System messages
+ /*! @method HandleSysEx */
+ virtual OSStatus HandleSysEx( const UInt8 * inData,
+ UInt32 inLength ) { return noErr; }
+
+#if CA_AUTO_MIDI_MAP
+ /* map manager */
+ CAAUMIDIMapManager *GetMIDIMapManager() {return mMapManager;};
+
+#endif
+
+
+private:
+ /*! @var mAUBaseInstance */
+ AUBase & mAUBaseInstance;
+
+#if CA_AUTO_MIDI_MAP
+ /* map manager */
+ CAAUMIDIMapManager * mMapManager;
+#endif
+
+public:
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ // component dispatcher
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch( ComponentParameters *params,
+ AUMIDIBase *This);
+#endif
+};
+
+#endif // __AUMIDIBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp
new file mode 100644
index 0000000000..dfe307c9eb
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp
@@ -0,0 +1,164 @@
+/*
+ File: AUMIDIEffectBase.cpp
+ Abstract: AUMIDIEffectBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUMIDIEffectBase.h"
+
+// compatibility with older OS SDK releases
+typedef OSStatus
+(*TEMP_MusicDeviceMIDIEventProc)( void * inComponentStorage,
+ UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame);
+
+static OSStatus AUMIDIEffectBaseMIDIEvent(void * inComponentStorage,
+ UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame);
+
+AUMIDIEffectBase::AUMIDIEffectBase( AudioComponentInstance inInstance,
+ bool inProcessesInPlace )
+ : AUEffectBase(inInstance, inProcessesInPlace),
+ AUMIDIBase(this)
+{
+}
+
+OSStatus AUMIDIEffectBase::GetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus result;
+
+ result = AUEffectBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = AUMIDIBase::DelegateGetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+
+ return result;
+}
+
+OSStatus AUMIDIEffectBase::GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ OSStatus result;
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ if (inID == kAudioUnitProperty_FastDispatch) {
+ if (inElement == kMusicDeviceMIDIEventSelect) {
+ *(TEMP_MusicDeviceMIDIEventProc *)outData = AUMIDIEffectBaseMIDIEvent;
+ return noErr;
+ }
+ return kAudioUnitErr_InvalidElement;
+ }
+#endif
+
+ result = AUEffectBase::GetProperty (inID, inScope, inElement, outData);
+
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = AUMIDIBase::DelegateGetProperty (inID, inScope, inElement, outData);
+
+ return result;
+}
+
+OSStatus AUMIDIEffectBase::SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+
+ OSStatus result = AUEffectBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
+
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = AUMIDIBase::DelegateSetProperty (inID, inScope, inElement, inData, inDataSize);
+
+ return result;
+}
+
+
+#if !TARGET_OS_IPHONE
+OSStatus AUMIDIEffectBase::ComponentEntryDispatch(ComponentParameters * params,
+ AUMIDIEffectBase * This)
+{
+ if (This == NULL) return paramErr;
+
+ OSStatus result;
+
+ switch (params->what) {
+ case kMusicDeviceMIDIEventSelect:
+ case kMusicDeviceSysExSelect:
+ result = AUMIDIBase::ComponentEntryDispatch (params, This);
+ break;
+ default:
+ result = AUEffectBase::ComponentEntryDispatch(params, This);
+ break;
+ }
+
+ return result;
+}
+#endif
+
+// fast dispatch
+static OSStatus AUMIDIEffectBaseMIDIEvent(void * inComponentStorage,
+ UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame)
+{
+ OSStatus result = noErr;
+ try {
+ AUMIDIEffectBase *This = static_cast<AUMIDIEffectBase *>(inComponentStorage);
+ if (This == NULL) return paramErr;
+ result = This->AUMIDIBase::MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
+ }
+ COMPONENT_CATCH
+ return result;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h
new file mode 100644
index 0000000000..b38f506d6c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h
@@ -0,0 +1,104 @@
+/*
+ File: AUMIDIEffectBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUMIDIEffectBase_h__
+#define __AUMIDIEffectBase_h__
+
+#include "AUMIDIBase.h"
+#include "AUEffectBase.h"
+
+// ________________________________________________________________________
+// AUMIDIEffectBase
+//
+ /*! @class AUMIDIEffectBase */
+class AUMIDIEffectBase : public AUEffectBase, public AUMIDIBase {
+public:
+ /*! @ctor AUMIDIEffectBase */
+ AUMIDIEffectBase( AudioComponentInstance inInstance,
+ bool inProcessesInPlace = false );
+ /*! @method MIDIEvent */
+ virtual OSStatus MIDIEvent(UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame)
+ {
+ return AUMIDIBase::MIDIEvent (inStatus, inData1, inData2, inOffsetSampleFrame);
+ }
+
+ /*! @method SysEx */
+ virtual OSStatus SysEx(const UInt8 * inData,
+ UInt32 inLength)
+ {
+ return AUMIDIBase::SysEx (inData, inLength);
+ }
+
+ /*! @method GetPropertyInfo */
+ virtual OSStatus GetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ /*! @method GetProperty */
+ virtual OSStatus GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+ /*! @method SetProperty */
+ virtual OSStatus SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+#if !TARGET_OS_IPHONE
+ // component dispatcher
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch( ComponentParameters * params,
+ AUMIDIEffectBase * This);
+#endif
+};
+
+#endif // __AUMIDIEffectBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp
new file mode 100644
index 0000000000..591c43ab8c
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp
@@ -0,0 +1,76 @@
+/*
+ File: AUOutputBase.cpp
+ Abstract: AUOutputBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+#include "AUOutputBase.h"
+
+OSStatus AUOutputBase::ComponentEntryDispatch(ComponentParameters *params, AUOutputBase *This)
+{
+ if (This == NULL) return paramErr;
+
+ OSStatus result;
+
+ switch (params->what) {
+ case kAudioOutputUnitStartSelect:
+ {
+ result = This->Start();
+ }
+ break;
+
+ case kAudioOutputUnitStopSelect:
+ {
+ result = This->Stop();
+ }
+ break;
+
+ default:
+ result = badComponentSelector;
+ break;
+ }
+
+ return result;
+}
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.h
new file mode 100644
index 0000000000..8e5399b911
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUOutputBase.h
@@ -0,0 +1,82 @@
+/*
+ File: AUOutputBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUOutputBase_h__
+#define __AUOutputBase_h__
+
+#include "AUBase.h"
+
+// ________________________________________________________________________
+// AUOutputBase
+// this is now a mix-in rather than an AUBase subclass
+
+ /*! @class AUOutputBase */
+class AUOutputBase {
+public:
+ /*! @ctor AUOutputBase */
+ AUOutputBase(AUBase *inBase) : mAUBaseInstance(*inBase) { }
+ virtual ~AUOutputBase() { }
+
+ // additional component entry points
+ /*! @method Start */
+ virtual OSStatus Start() = 0;
+
+ /*! @method Stop */
+ virtual OSStatus Stop() = 0;
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ // component dispatcher
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch( ComponentParameters * params,
+ AUOutputBase * This);
+#endif
+
+private:
+ /*! @var mAUBaseInstance */
+ AUBase & mAUBaseInstance;
+};
+
+#endif // __AUOutputBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp
new file mode 100644
index 0000000000..f1e2f248ab
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp
@@ -0,0 +1,706 @@
+/*
+ File: AUPannerBase.cpp
+ Abstract: AUPannerBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUPannerBase.h"
+#include "CABundleLocker.h"
+#include <AudioToolbox/AudioToolbox.h>
+#include <Accelerate/Accelerate.h>
+
+static bool sLocalized = false;
+
+static CFStringRef kPanner_Azimuth_Name = CFSTR("azimuth");
+static CFStringRef kPanner_Elevation_Name = CFSTR("elevation");
+static CFStringRef kPanner_Distance_Name = CFSTR("distance");
+
+static CFStringRef kPanner_CoordScale_Name = CFSTR("coordinate scale");
+static CFStringRef kPanner_RefDistance_Name = CFSTR("reference distance");
+static CFStringRef kPanner_Gain_Name = CFSTR("gain");
+
+static Float32 kPannerParamDefault_Azimuth = 0.;
+static Float32 kPannerParamDefault_Elevation = 0.;
+static Float32 kPannerParamDefault_Distance = 1.;
+
+static Float32 kPannerParamDefault_CoordScale = 10.;
+static Float32 kPannerParamDefault_RefDistance = 1.;
+static Float32 kPannerParamDefault_Gain = 1.;
+
+//_____________________________________________________________________________
+//
+AUPannerBase::AUPannerBase(AudioComponentInstance inAudioUnit)
+ : AUBase(inAudioUnit, 1, 1), mBypassEffect(false)
+{
+ {
+ CABundleLocker lock;
+ if (!sLocalized)
+ {
+ CFBundleRef bundle = CFBundleGetBundleWithIdentifier( CFSTR("com.apple.audio.units.Components") );
+ if (bundle != NULL)
+ {
+ kPanner_Azimuth_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Azimuth_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_Elevation_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Elevation_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_Distance_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Distance_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+
+ kPanner_CoordScale_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_CoordScale_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_RefDistance_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_RefDistance_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+ kPanner_Gain_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Gain_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
+
+ }
+
+ sLocalized = true;
+ }
+ }
+
+ CreateElements();
+
+ SetParameter(kPannerParam_Azimuth, kPannerParamDefault_Azimuth);
+ SetParameter(kPannerParam_Elevation, kPannerParamDefault_Elevation);
+ SetParameter(kPannerParam_Distance, kPannerParamDefault_Distance);
+
+ SetParameter(kPannerParam_CoordScale, kPannerParamDefault_CoordScale);
+ SetParameter(kPannerParam_RefDistance, kPannerParamDefault_RefDistance);
+ SetParameter(kPannerParam_Gain, kPannerParamDefault_Gain);
+}
+
+//_____________________________________________________________________________
+//
+AUPannerBase::~AUPannerBase()
+{
+ Cleanup();
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Initialize */
+OSStatus AUPannerBase::Initialize()
+{
+ OSStatus err = noErr;
+ AllocBypassMatrix();
+ err = UpdateBypassMatrix();
+ return err;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method AllocBypassMatrix */
+void AUPannerBase::AllocBypassMatrix()
+{
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ mBypassMatrix.alloc(inChannels * outChannels, true);
+}
+
+static AudioChannelLayoutTag DefaultTagForNumberOfChannels(UInt32 inNumberChannels)
+{
+ switch (inNumberChannels) {
+ case 1: return kAudioChannelLayoutTag_Mono;
+ case 2: return kAudioChannelLayoutTag_Stereo;
+ case 4: return kAudioChannelLayoutTag_Quadraphonic;
+ case 5: return kAudioChannelLayoutTag_AudioUnit_5_0;
+ case 6: return kAudioChannelLayoutTag_AudioUnit_6_0;
+ case 7: return kAudioChannelLayoutTag_AudioUnit_7_0;
+ case 8: return kAudioChannelLayoutTag_AudioUnit_8;
+
+ default: return 0xFFFF0000 | inNumberChannels;
+ }
+}
+
+//_____________________________________________________________________________
+//
+/*! @method UpdateBypassMatrix */
+OSStatus AUPannerBase::SetDefaultChannelLayoutsIfNone()
+{
+ OSStatus err = noErr;
+
+ // if layout has not been set, then guess layout from number of channels
+ UInt32 inChannels = GetNumberOfInputChannels();
+ AudioChannelLayout inputLayoutSubstitute;
+ const AudioChannelLayout* inputLayout = &GetInputLayout();
+ if (inputLayout == NULL || inputLayout->mChannelLayoutTag == 0) {
+ inputLayout = &inputLayoutSubstitute;
+ inputLayoutSubstitute.mNumberChannelDescriptions = 0;
+ inputLayoutSubstitute.mChannelBitmap = 0;
+ inputLayoutSubstitute.mChannelLayoutTag = DefaultTagForNumberOfChannels(inChannels);
+
+ mInputLayout = &inputLayoutSubstitute;
+ err = SetAudioChannelLayout(kAudioUnitScope_Input, 0, &GetInputLayout());
+ if (err) return err;
+ }
+
+ // if layout has not been set, then guess layout from number of channels
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ AudioChannelLayout outputLayoutSubstitute;
+ const AudioChannelLayout* outputLayout = &GetOutputLayout();
+ if (outputLayout == NULL || outputLayout->mChannelLayoutTag == 0) {
+ outputLayout = &outputLayoutSubstitute;
+ outputLayoutSubstitute.mNumberChannelDescriptions = 0;
+ outputLayoutSubstitute.mChannelBitmap = 0;
+ outputLayoutSubstitute.mChannelLayoutTag = DefaultTagForNumberOfChannels(outChannels);
+
+ mOutputLayout = &outputLayoutSubstitute;
+ err = SetAudioChannelLayout(kAudioUnitScope_Output, 0, &GetOutputLayout());
+ if (err) return err;
+ }
+
+ return err;
+}
+
+
+
+OSStatus AUPannerBase::UpdateBypassMatrix()
+{
+ OSStatus err = SetDefaultChannelLayoutsIfNone();
+ if (err) return err;
+
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+
+ const AudioChannelLayout* inoutACL[2];
+
+ inoutACL[0] = &GetInputLayout();
+ inoutACL[1] = &GetOutputLayout();
+
+ mBypassMatrix.alloc(inChannels * outChannels, true);
+
+ UInt32 propSize = inChannels * outChannels * sizeof(Float32);
+
+ err = AudioFormatGetProperty(kAudioFormatProperty_MatrixMixMap, sizeof(inoutACL), inoutACL, &propSize, mBypassMatrix());
+ if (err) {
+ // if there is an error, use a diagonal matrix.
+ Float32* bypass = mBypassMatrix();
+ for (UInt32 chan = 0; chan < std::min(inChannels, outChannels); ++chan)
+ {
+ float *amp = bypass + (chan * outChannels + chan);
+ *amp = 1.;
+ }
+ }
+
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Cleanup */
+void AUPannerBase::Cleanup()
+{
+
+}
+
+
+//_____________________________________________________________________________
+//
+/*! @method Reset */
+OSStatus AUPannerBase::Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ return AUBase::Reset(inScope, inElement);
+}
+
+//_____________________________________________________________________________
+//
+/*! @method GetParameterInfo */
+OSStatus AUPannerBase::GetParameterInfo( AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ AudioUnitParameterInfo &outParameterInfo )
+{
+ OSStatus result = noErr;
+
+ outParameterInfo.flags = kAudioUnitParameterFlag_IsWritable
+ + kAudioUnitParameterFlag_IsReadable;
+
+ if (inScope == kAudioUnitScope_Global) {
+
+ switch(inParameterID)
+ {
+ case kPannerParam_Azimuth:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Azimuth_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Degrees;
+ outParameterInfo.minValue = -180.;
+ outParameterInfo.maxValue = 180;
+ outParameterInfo.defaultValue = kPannerParamDefault_Azimuth;
+ break;
+
+ case kPannerParam_Elevation:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Elevation_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Degrees;
+ outParameterInfo.minValue = -90.;
+ outParameterInfo.maxValue = 90;
+ outParameterInfo.defaultValue = kPannerParamDefault_Elevation;
+ break;
+
+ case kPannerParam_Distance:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Distance_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
+ outParameterInfo.minValue = 0.0;
+ outParameterInfo.maxValue = 1.;
+ outParameterInfo.defaultValue = kPannerParamDefault_Distance;
+ outParameterInfo.flags += kAudioUnitParameterFlag_IsHighResolution;
+ //outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
+ break;
+
+ case kPannerParam_CoordScale:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_CoordScale_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Meters;
+ outParameterInfo.minValue = 0.01;
+ outParameterInfo.maxValue = 1000.;
+ outParameterInfo.defaultValue = kPannerParamDefault_CoordScale;
+ outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
+ break;
+
+ case kPannerParam_RefDistance:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_RefDistance_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Meters;
+ outParameterInfo.minValue = 0.01;
+ outParameterInfo.maxValue = 1000.;
+ outParameterInfo.defaultValue = kPannerParamDefault_RefDistance;
+ outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
+ break;
+
+ case kPannerParam_Gain:
+ AUBase::FillInParameterName (outParameterInfo, kPanner_Gain_Name, false);
+ outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
+ outParameterInfo.minValue = 0.;
+ outParameterInfo.maxValue = 1.;
+ outParameterInfo.defaultValue = kPannerParamDefault_Gain;
+ break;
+
+ default:
+ result = kAudioUnitErr_InvalidParameter;
+ break;
+ }
+ } else {
+ result = kAudioUnitErr_InvalidParameter;
+ }
+
+ return result;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::GetParameter( AudioUnitParameterID inParamID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ Float32 & outValue)
+{
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ outValue = Globals()->GetParameter(inParamID);
+
+ return noErr;
+}
+
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::SetParameter( AudioUnitParameterID inParamID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ Float32 inValue,
+ UInt32 inBufferOffsetInFrames)
+{
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ Globals()->SetParameter(inParamID, inValue);
+
+ return noErr;
+}
+
+
+
+//_____________________________________________________________________________
+//
+/*! @method GetPropertyInfo */
+OSStatus AUPannerBase::GetPropertyInfo (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus err = noErr;
+ switch (inID) {
+ case kAudioUnitProperty_BypassEffect:
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ outWritable = true;
+ outDataSize = sizeof (UInt32);
+ break;
+ default:
+ err = AUBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);
+ }
+ return err;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method GetProperty */
+OSStatus AUPannerBase::GetProperty (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ OSStatus err = noErr;
+ switch (inID)
+ {
+ case kAudioUnitProperty_BypassEffect:
+ if (inScope != kAudioUnitScope_Global)
+ return kAudioUnitErr_InvalidScope;
+
+ *((UInt32*)outData) = (IsBypassEffect() ? 1 : 0);
+ break;
+ default:
+ err = AUBase::GetProperty(inID, inScope, inElement, outData);
+ }
+ return err;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method SetProperty */
+OSStatus AUPannerBase::SetProperty(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+{
+ switch (inID)
+ {
+ case kAudioUnitProperty_BypassEffect:
+ if (inDataSize < sizeof(UInt32))
+ return kAudioUnitErr_InvalidPropertyValue;
+ bool tempNewSetting = *((UInt32*)inData) != 0;
+ // we're changing the state of bypass
+ if (tempNewSetting != IsBypassEffect())
+ {
+ if (!tempNewSetting && IsBypassEffect() && IsInitialized()) // turning bypass off and we're initialized
+ Reset(0, 0);
+ SetBypassEffect (tempNewSetting);
+ }
+ return noErr;
+ }
+ return AUBase::SetProperty(inID, inScope, inElement, inData, inDataSize);
+}
+
+
+//_____________________________________________________________________________
+//
+/*! @method StreamFormatWritable */
+bool AUPannerBase::StreamFormatWritable (AudioUnitScope scope,
+ AudioUnitElement element)
+{
+ return true;
+}
+
+//_____________________________________________________________________________
+//
+/*! @method ChangeStreamFormat */
+OSStatus AUPannerBase::ChangeStreamFormat (
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inPrevFormat,
+ const CAStreamBasicDescription & inNewFormat)
+{
+ if (inScope == kAudioUnitScope_Input && !InputChannelConfigIsSupported(inNewFormat.NumberChannels()))
+ return kAudioUnitErr_FormatNotSupported;
+
+ if (inScope == kAudioUnitScope_Output && !OutputChannelConfigIsSupported(inNewFormat.NumberChannels()))
+ return kAudioUnitErr_FormatNotSupported;
+
+ if (inNewFormat.NumberChannels() != inPrevFormat.NumberChannels())
+ RemoveAudioChannelLayout(inScope, inElement);
+
+ return AUBase::ChangeStreamFormat(inScope, inElement, inPrevFormat, inNewFormat);
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Render */
+OSStatus AUPannerBase::Render(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames)
+{
+ if (IsBypassEffect())
+ return BypassRender(ioActionFlags, inTimeStamp, inNumberFrames);
+ else
+ return PannerRender(ioActionFlags, inTimeStamp, inNumberFrames);
+}
+
+//_____________________________________________________________________________
+//
+/*! @method Render */
+OSStatus AUPannerBase::BypassRender(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames)
+{
+ AudioUnitRenderActionFlags xflags = 0;
+ OSStatus result = PullInput(0, xflags, inTimeStamp, inNumberFrames);
+ if (result) return false;
+ bool isSilent = xflags & kAudioUnitRenderAction_OutputIsSilence;
+
+ AudioBufferList& outputBufferList = GetOutput(0)->GetBufferList();
+ AUBufferList::ZeroBuffer(outputBufferList);
+
+ if (!isSilent)
+ {
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ Float32* bypass = mBypassMatrix();
+ for (UInt32 outChan = 0; outChan < outChannels; ++outChan)
+ {
+ float* outData = GetOutput(0)->GetChannelData(outChan);
+
+ for (UInt32 inChan = 0; inChan < inChannels; ++inChan)
+ {
+ float* inData = GetInput(0)->GetChannelData(inChan);
+ float *amp = bypass + (inChan * outChannels + outChan);
+ vDSP_vsma(inData, 1, amp, outData, 1, outData, 1, inNumberFrames);
+ }
+ }
+ }
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+UInt32 AUPannerBase::GetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayout * outLayoutPtr,
+ Boolean & outWritable)
+{
+ SetDefaultChannelLayoutsIfNone();
+
+ outWritable = true;
+
+ CAAudioChannelLayout* caacl = NULL;
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ caacl = &mInputLayout;
+ break;
+ case kAudioUnitScope_Output:
+ caacl = &mOutputLayout;
+ break;
+ default:
+ COMPONENT_THROW(kAudioUnitErr_InvalidScope);
+ }
+
+ if (inElement != 0)
+ COMPONENT_THROW(kAudioUnitErr_InvalidElement);
+
+ UInt32 size = caacl->IsValid() ? caacl->Size() : 0;
+ if (size > 0 && outLayoutPtr)
+ memcpy(outLayoutPtr, &caacl->Layout(), size);
+
+ return size;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::RemoveAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ CAAudioChannelLayout* caacl = NULL;
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ caacl = &mInputLayout;
+ break;
+ case kAudioUnitScope_Output:
+ caacl = &mOutputLayout;
+ break;
+ default:
+ return kAudioUnitErr_InvalidScope;
+ }
+
+ if (inElement != 0)
+ return kAudioUnitErr_InvalidElement;
+
+ *caacl = NULL;
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+OSStatus AUPannerBase::SetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const AudioChannelLayout * inLayout)
+{
+ if (!inLayout)
+ return RemoveAudioChannelLayout(inScope, inElement);
+
+ if (!ChannelLayoutTagIsSupported(inScope, inElement, inLayout->mChannelLayoutTag))
+ return kAudioUnitErr_FormatNotSupported;
+
+ CAAudioChannelLayout* caacl = NULL;
+ UInt32 currentChannels;
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ caacl = &mInputLayout;
+ currentChannels = GetNumberOfInputChannels();
+ break;
+ case kAudioUnitScope_Output:
+ caacl = &mOutputLayout;
+ currentChannels = GetNumberOfOutputChannels();
+ break;
+ default:
+ return kAudioUnitErr_InvalidScope;
+ }
+
+ if (inElement != 0)
+ return kAudioUnitErr_InvalidElement;
+
+ UInt32 numChannelsInLayout = CAAudioChannelLayout::NumberChannels(*inLayout);
+ if (currentChannels != numChannelsInLayout)
+ return kAudioUnitErr_InvalidPropertyValue;
+
+ *caacl = inLayout;
+ if (IsInitialized())
+ UpdateBypassMatrix();
+
+ return noErr;
+}
+
+//_____________________________________________________________________________
+//
+UInt32 AUPannerBase::GetChannelLayoutTags( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag* outTags)
+{
+ switch (inScope)
+ {
+ case kAudioUnitScope_Input:
+ if (outTags) {
+ outTags[0] = kAudioChannelLayoutTag_Mono;
+ outTags[1] = kAudioChannelLayoutTag_Stereo;
+ outTags[2] = kAudioChannelLayoutTag_Ambisonic_B_Format;
+ }
+ return 3;
+ case kAudioUnitScope_Output:
+ if (outTags) {
+ outTags[0] = kAudioChannelLayoutTag_Stereo;
+ outTags[1] = kAudioChannelLayoutTag_Quadraphonic;
+ outTags[2] = kAudioChannelLayoutTag_AudioUnit_5_0;
+ outTags[3] = kAudioChannelLayoutTag_AudioUnit_6_0;
+ outTags[4] = kAudioChannelLayoutTag_AudioUnit_7_0;
+ outTags[5] = kAudioChannelLayoutTag_AudioUnit_7_0_Front;
+ outTags[6] = kAudioChannelLayoutTag_AudioUnit_8;
+ }
+ return 7;
+ default: {
+ OSStatus err = kAudioUnitErr_InvalidScope;
+ throw err;
+ }
+ }
+}
+
+
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::ChannelConfigIsSupported()
+{
+ UInt32 inChannels = GetNumberOfInputChannels();
+ UInt32 outChannels = GetNumberOfOutputChannels();
+ const AUChannelInfo* cinfo = NULL;
+ UInt32 numConfigs = SupportedNumChannels(&cinfo);
+ for (UInt32 i = 0; i < numConfigs; ++i)
+ {
+ if (cinfo[i].inChannels == (SInt16)inChannels && cinfo[i].outChannels == (SInt16)outChannels)
+ return true;
+ }
+ return false;
+}
+
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::InputChannelConfigIsSupported(UInt32 inNumberChannels)
+{
+ const AUChannelInfo* cinfo = NULL;
+ UInt32 numConfigs = SupportedNumChannels(&cinfo);
+ for (UInt32 i = 0; i < numConfigs; ++i)
+ {
+ if (cinfo[i].inChannels == (SInt16)inNumberChannels)
+ return true;
+ }
+ return false;
+}
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::OutputChannelConfigIsSupported(UInt32 inNumberChannels)
+{
+ const AUChannelInfo* cinfo = NULL;
+ UInt32 numConfigs = SupportedNumChannels(&cinfo);
+ for (UInt32 i = 0; i < numConfigs; ++i)
+ {
+ if (cinfo[i].outChannels == (SInt16)inNumberChannels)
+ return true;
+ }
+ return false;
+}
+
+//_____________________________________________________________________________
+//
+bool AUPannerBase::ChannelLayoutTagIsSupported( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag inTag)
+{
+ UInt32 numTags = GetChannelLayoutTags(inScope, inElement, NULL);
+ CAAutoFree<AudioChannelLayoutTag> tags(numTags);
+ GetChannelLayoutTags(inScope, inElement, tags());
+
+ for (UInt32 i = 0; i < numTags; ++i)
+ {
+ if (tags[i] == inTag)
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.h
new file mode 100644
index 0000000000..3184830523
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/AUPannerBase.h
@@ -0,0 +1,272 @@
+/*
+ File: AUPannerBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUPannerBase_h__
+#define __AUPannerBase_h__
+
+#include "AUBase.h"
+#include <math.h>
+#include "CAAutoDisposer.h"
+#include "CAAudioChannelLayout.h"
+
+
+/*! @class AUPannerBase */
+class AUPannerBase : public AUBase
+{
+public:
+/*! @ctor AUPannerBase */
+ AUPannerBase(AudioComponentInstance inAudioUnit);
+/*! @dtor ~AUPannerBase */
+ virtual ~AUPannerBase();
+
+ /*! @method Initialize */
+ virtual OSStatus Initialize();
+
+ /*! @method Cleanup */
+ virtual void Cleanup();
+
+
+ /*! @method Reset */
+ virtual OSStatus Reset( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ /*! @method CanScheduleParameters */
+ virtual bool CanScheduleParameters() const { return false; }
+
+ /*! @method GetParameterInfo */
+ virtual OSStatus GetParameterInfo( AudioUnitScope inScope,
+ AudioUnitParameterID inParameterID,
+ AudioUnitParameterInfo &outParameterInfo );
+
+
+ /*! @method GetPropertyInfo */
+ virtual OSStatus GetPropertyInfo (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ /*! @method GetProperty */
+ virtual OSStatus GetProperty (AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+
+ /*! @method SetProperty */
+ virtual OSStatus SetProperty(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+
+
+ /*! @method StreamFormatWritable */
+ virtual bool StreamFormatWritable (AudioUnitScope scope,
+ AudioUnitElement element);
+
+ /*! @method ChangeStreamFormat */
+ virtual OSStatus ChangeStreamFormat (
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const CAStreamBasicDescription & inPrevFormat,
+ const CAStreamBasicDescription & inNewFormat);
+
+
+ /*! @method IsBypassEffect */
+ // This is used for the property value - to reflect to the UI if an effect is bypassed
+ bool IsBypassEffect () { return mBypassEffect; }
+
+ /*! @method SetBypassEffect */
+ virtual void SetBypassEffect (bool inFlag) { mBypassEffect = inFlag; }
+
+
+ /*! @method Render */
+ virtual OSStatus Render(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames);
+
+ /*! @method Render */
+ virtual OSStatus PannerRender(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames) = 0;
+
+ /*! @method BypassRender */
+ virtual OSStatus BypassRender(AudioUnitRenderActionFlags & ioActionFlags,
+ const AudioTimeStamp & inTimeStamp,
+ UInt32 inNumberFrames);
+
+
+ /*! @method GetAudioChannelLayout */
+ virtual UInt32 GetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayout * outLayoutPtr,
+ Boolean & outWritable);
+
+ /*! @method SetAudioChannelLayout */
+ virtual OSStatus SetAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const AudioChannelLayout * inLayout);
+
+ /*! @method RemoveAudioChannelLayout */
+ virtual OSStatus RemoveAudioChannelLayout( AudioUnitScope inScope,
+ AudioUnitElement inElement);
+
+ /*! @method GetChannelLayoutTags */
+ virtual UInt32 GetChannelLayoutTags( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag* outTags);
+
+ /*! @method GetNumberOfInputChannels */
+ UInt32 GetNumberOfInputChannels() { return ((AUIOElement*)Inputs().SafeGetElement(0))->NumberChannels(); };
+ /*! @method GetNumberOfOutputChannels */
+ UInt32 GetNumberOfOutputChannels() { return ((AUIOElement*)Outputs().SafeGetElement(0))->NumberChannels(); }
+
+ /*! @method GetParameter */
+ virtual OSStatus GetParameter( AudioUnitParameterID inParamID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ Float32 & outValue);
+
+ /*! @method SetParameter */
+ virtual OSStatus SetParameter( AudioUnitParameterID inParamID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ Float32 inValue,
+ UInt32 inBufferOffsetInFrames);
+
+ // convenience wrappers for accessing parameters in the global scope
+ /*! @method SetParameter */
+ void SetParameter( UInt32 inParamID,
+ Float32 inValue)
+ {
+ OSStatus err = SetParameter(inParamID, kAudioUnitScope_Global, 0, inValue, 0);
+ if (err) throw err;
+ }
+
+ /*! @method GetParameter */
+ Float32 GetParameter( UInt32 inParamID )
+ {
+ Float32 outValue = 0.;
+ OSStatus err = GetParameter(inParamID, kAudioUnitScope_Global, 0, outValue);
+ if (err) throw err;
+ return outValue;
+ }
+
+ /*! @method InputChannelConfigIsSupported */
+ bool InputChannelConfigIsSupported(UInt32 inNumberChannels);
+ /*! @method OutputChannelConfigIsSupported */
+ bool OutputChannelConfigIsSupported(UInt32 inNumberChannels);
+ /*! @method ChannelConfigIsSupported */
+ bool ChannelConfigIsSupported();
+
+ /*! @method SupportsTail */
+ virtual bool SupportsTail () { return true; }
+ /*! @method GetTailTime */
+ virtual Float64 GetTailTime() { return 0; }
+
+
+ /*! @method GetGain */
+ Float32 GetGain() { return GetParameter(kPannerParam_Gain); }
+ /*! @method GetTailTime */
+ Float32 GetAzimuth() { return GetParameter(kPannerParam_Azimuth); }
+ /*! @method GetElevation */
+ Float32 GetElevation() { return GetParameter(kPannerParam_Elevation); }
+ /*! @method GetDistance */
+ Float32 GetDistance() { return GetParameter(kPannerParam_Distance); }
+ /*! @method GetCoordScale */
+ Float32 GetCoordScale() { return GetParameter(kPannerParam_CoordScale); }
+ /*! @method GetRefDistance */
+ Float32 GetRefDistance() { return GetParameter(kPannerParam_RefDistance); }
+
+ /*! @method SetGain */
+ void SetGain(Float32 inValue) { SetParameter(kPannerParam_Gain, inValue); }
+ /*! @method SetAzimuth */
+ void SetAzimuth(Float32 inValue) { SetParameter(kPannerParam_Azimuth, inValue); }
+ /*! @method SetElevation */
+ void SetElevation(Float32 inValue) { SetParameter(kPannerParam_Elevation, inValue); }
+ /*! @method SetDistance */
+ void SetDistance(Float32 inValue) { SetParameter(kPannerParam_Distance, inValue); }
+ /*! @method SetCoordScale */
+ void SetCoordScale(Float32 inValue) { SetParameter(kPannerParam_CoordScale, inValue); }
+ /*! @method SetRefDistance */
+ void SetRefDistance(Float32 inValue) { SetParameter(kPannerParam_RefDistance, inValue); }
+
+protected:
+ /*! @method ShouldBypassEffect */
+ // This is used in the render call to see if an effect is bypassed
+ // It can return a different status than IsBypassEffect (though it MUST take that into account)
+ virtual bool ShouldBypassEffect () { return IsBypassEffect(); }
+
+ /*! @method AllocBypassMatrix */
+ void AllocBypassMatrix();
+
+ /*! @method UpdateBypassMatrix */
+ OSStatus UpdateBypassMatrix();
+
+ /*! @method SetDefaultChannelLayoutsIfNone */
+ OSStatus SetDefaultChannelLayoutsIfNone();
+
+ /*! @method ChannelLayoutTagIsSupported */
+ bool ChannelLayoutTagIsSupported( AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ AudioChannelLayoutTag inTag);
+
+ const AudioChannelLayout& GetInputLayout() const { return mInputLayout.Layout(); }
+ const AudioChannelLayout& GetOutputLayout() const { return mOutputLayout.Layout(); }
+
+private:
+
+ /*! @var UpdateBypassMatrix */
+ bool mBypassEffect;
+ /*! @var mBypassMatrix */
+ CAAutoFree<Float32> mBypassMatrix;
+ /*! @var mInputLayout */
+ CAAudioChannelLayout mInputLayout;
+ /*! @var mOutputLayout */
+ CAAudioChannelLayout mOutputLayout;
+};
+
+#endif /* __AUPannerBase_h__ */
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp
new file mode 100644
index 0000000000..28e4d366bc
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp
@@ -0,0 +1,354 @@
+/*
+ File: MusicDeviceBase.cpp
+ Abstract: MusicDeviceBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "MusicDeviceBase.h"
+
+// compatibility with older OS SDK releases
+typedef OSStatus
+(*TEMP_MusicDeviceMIDIEventProc)( void * inComponentStorage,
+ UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame);
+
+typedef OSStatus
+(*TEMP_MusicDeviceStartNoteProc)( void * inComponentStorage,
+ MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams * inParams);
+
+typedef OSStatus
+(*TEMP_MusicDeviceStopNoteProc)(void * inComponentStorage,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame);
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+
+static OSStatus MusicDeviceBaseMIDIEvent(void * inComponentStorage,
+ UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame);
+
+static OSStatus MusicDeviceBaseStartNote( void * inComponentStorage,
+ MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams * inParams);
+
+static OSStatus MusicDeviceBaseStopNote(void * inComponentStorage,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame);
+
+#endif
+
+MusicDeviceBase::MusicDeviceBase(AudioComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups)
+ : AUBase(inInstance, numInputs, numOutputs, numGroups),
+ AUMIDIBase(this)
+{
+}
+
+OSStatus MusicDeviceBase::GetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable)
+{
+ OSStatus result;
+
+ switch (inID)
+ {
+#if !TARGET_OS_IPHONE
+ case kMusicDeviceProperty_InstrumentCount:
+ if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
+ outDataSize = sizeof(UInt32);
+ outWritable = false;
+ result = noErr;
+ break;
+#endif
+ default:
+ result = AUBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = AUMIDIBase::DelegateGetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
+ break;
+ }
+ return result;
+}
+
+OSStatus MusicDeviceBase::GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData)
+{
+ OSStatus result;
+
+ switch (inID)
+ {
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ case kAudioUnitProperty_FastDispatch:
+ if (!IsCMgrObject()) return kAudioUnitErr_InvalidProperty;
+ if (inElement == kMusicDeviceMIDIEventSelect) {
+ *(TEMP_MusicDeviceMIDIEventProc *)outData = MusicDeviceBaseMIDIEvent;
+ return noErr;
+ }
+ else if (inElement == kMusicDeviceStartNoteSelect) {
+ *(TEMP_MusicDeviceStartNoteProc *)outData = MusicDeviceBaseStartNote;
+ return noErr;
+ }
+ else if (inElement == kMusicDeviceStopNoteSelect) {
+ *(TEMP_MusicDeviceStopNoteProc *)outData = MusicDeviceBaseStopNote;
+ return noErr;
+ }
+ return kAudioUnitErr_InvalidElement;
+#endif
+
+#if !TARGET_OS_IPHONE
+ case kMusicDeviceProperty_InstrumentCount:
+ if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
+ return GetInstrumentCount (*(UInt32*)outData);
+#endif
+ default:
+ result = AUBase::GetProperty (inID, inScope, inElement, outData);
+
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = AUMIDIBase::DelegateGetProperty (inID, inScope, inElement, outData);
+ }
+
+ return result;
+}
+
+
+OSStatus MusicDeviceBase::SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize)
+
+{
+
+ OSStatus result = AUBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
+
+ if (result == kAudioUnitErr_InvalidProperty)
+ result = AUMIDIBase::DelegateSetProperty (inID, inScope, inElement, inData, inDataSize);
+
+ return result;
+}
+
+// For a MusicDevice that doesn't support separate instruments (ie. is mono-timbral)
+// then this call should return an instrument count of zero and noErr
+OSStatus MusicDeviceBase::GetInstrumentCount (UInt32 &outInstCount) const
+{
+ outInstCount = 0;
+ return noErr;
+}
+
+OSStatus MusicDeviceBase::HandleNoteOn( UInt8 inChannel,
+ UInt8 inNoteNumber,
+ UInt8 inVelocity,
+ UInt32 inStartFrame)
+{
+ MusicDeviceNoteParams params;
+ params.argCount = 2;
+ params.mPitch = inNoteNumber;
+ params.mVelocity = inVelocity;
+ return StartNote (kMusicNoteEvent_UseGroupInstrument, inChannel, NULL, inStartFrame, params);
+}
+
+OSStatus MusicDeviceBase::HandleNoteOff( UInt8 inChannel,
+ UInt8 inNoteNumber,
+ UInt8 inVelocity,
+ UInt32 inStartFrame)
+{
+ return StopNote (inChannel, inNoteNumber, inStartFrame);
+}
+
+OSStatus
+MusicDeviceBase::HandleStartNoteMessage (MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams * inParams)
+{
+ if (inParams == NULL || outNoteInstanceID == NULL) return kAudio_ParamError;
+
+ if (!IsInitialized()) return kAudioUnitErr_Uninitialized;
+
+ return StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
+}
+
+#if TARGET_OS_MAC
+ #if __LP64__
+ // comp instance, parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index + 1];
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
+ #endif
+#elif TARGET_OS_WIN32
+ // (no comp instance), parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index];
+#endif
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+OSStatus MusicDeviceBase::ComponentEntryDispatch( ComponentParameters * params,
+ MusicDeviceBase * This)
+{
+ if (This == NULL) return kAudio_ParamError;
+
+ OSStatus result;
+
+ switch (params->what) {
+ case kMusicDeviceMIDIEventSelect:
+ case kMusicDeviceSysExSelect:
+ {
+ result = AUMIDIBase::ComponentEntryDispatch (params, This);
+ }
+ break;
+ case kMusicDevicePrepareInstrumentSelect:
+ {
+ PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
+ result = This->PrepareInstrument(inInstrument);
+ }
+ break;
+ case kMusicDeviceReleaseInstrumentSelect:
+ {
+ PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
+ result = This->ReleaseInstrument(inInstrument);
+ }
+ break;
+ case kMusicDeviceStartNoteSelect:
+ {
+ PARAM(MusicDeviceInstrumentID, pbinInstrument, 0, 5);
+ PARAM(MusicDeviceGroupID, pbinGroupID, 1, 5);
+ PARAM(NoteInstanceID *, pboutNoteInstanceID, 2, 5);
+ PARAM(UInt32, pbinOffsetSampleFrame, 3, 5);
+ PARAM(const MusicDeviceNoteParams *, pbinParams, 4, 5);
+ result = This->HandleStartNoteMessage(pbinInstrument, pbinGroupID, pboutNoteInstanceID, pbinOffsetSampleFrame, pbinParams);
+ }
+ break;
+ case kMusicDeviceStopNoteSelect:
+ {
+ PARAM(MusicDeviceGroupID, pbinGroupID, 0, 3);
+ PARAM(NoteInstanceID, pbinNoteInstanceID, 1, 3);
+ PARAM(UInt32, pbinOffsetSampleFrame, 2, 3);
+ result = This->StopNote(pbinGroupID, pbinNoteInstanceID, pbinOffsetSampleFrame);
+ }
+ break;
+
+ default:
+ result = AUBase::ComponentEntryDispatch(params, This);
+ break;
+ }
+
+ return result;
+}
+#endif
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+
+// fast dispatch
+static OSStatus MusicDeviceBaseMIDIEvent(void * inComponentStorage,
+ UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame)
+{
+ OSStatus result = noErr;
+ try {
+ MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
+ if (This == NULL) return kAudio_ParamError;
+ result = This->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+OSStatus MusicDeviceBaseStartNote( void * inComponentStorage,
+ MusicDeviceInstrumentID inInstrument,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID * outNoteInstanceID,
+ UInt32 inOffsetSampleFrame,
+ const MusicDeviceNoteParams * inParams)
+{
+ OSStatus result = noErr;
+ try {
+ if (inParams == NULL || outNoteInstanceID == NULL) return kAudio_ParamError;
+ MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
+ if (This == NULL) return kAudio_ParamError;
+ result = This->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+OSStatus MusicDeviceBaseStopNote(void * inComponentStorage,
+ MusicDeviceGroupID inGroupID,
+ NoteInstanceID inNoteInstanceID,
+ UInt32 inOffsetSampleFrame)
+{
+ OSStatus result = noErr;
+ try {
+ MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
+ if (This == NULL) return kAudio_ParamError;
+ result = This->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
+ }
+ COMPONENT_CATCH
+ return result;
+}
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h
new file mode 100644
index 0000000000..4850b8f0cb
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h
@@ -0,0 +1,126 @@
+/*
+ File: MusicDeviceBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __MusicDeviceBase_h__
+#define __MusicDeviceBase_h__
+
+#include "AUMIDIBase.h"
+
+// ________________________________________________________________________
+// MusicDeviceBase
+//
+
+/*! @class MusicDeviceBase */
+class MusicDeviceBase : public AUBase, public AUMIDIBase {
+public:
+ /*! @ctor MusicDeviceBase */
+ MusicDeviceBase( AudioComponentInstance inInstance,
+ UInt32 numInputs,
+ UInt32 numOutputs,
+ UInt32 numGroups = 0);
+
+
+ virtual OSStatus MIDIEvent( UInt32 inStatus,
+ UInt32 inData1,
+ UInt32 inData2,
+ UInt32 inOffsetSampleFrame)
+ {
+ return AUMIDIBase::MIDIEvent (inStatus, inData1, inData2, inOffsetSampleFrame);
+ }
+
+ /*! @method SysEx */
+ virtual OSStatus SysEx( const UInt8 * inData,
+ UInt32 inLength)
+ {
+ return AUMIDIBase::SysEx (inData, inLength);
+ }
+
+ /*! @method GetPropertyInfo */
+ virtual OSStatus GetPropertyInfo(AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ UInt32 & outDataSize,
+ Boolean & outWritable);
+
+ /*! @method GetProperty */
+ virtual OSStatus GetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ void * outData);
+
+ /*! @method SetProperty */
+ virtual OSStatus SetProperty( AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement,
+ const void * inData,
+ UInt32 inDataSize);
+
+ /*! @method HandleNoteOn */
+ virtual OSStatus HandleNoteOn( UInt8 inChannel,
+ UInt8 inNoteNumber,
+ UInt8 inVelocity,
+ UInt32 inStartFrame);
+
+ /*! @method HandleNoteOff */
+ virtual OSStatus HandleNoteOff( UInt8 inChannel,
+ UInt8 inNoteNumber,
+ UInt8 inVelocity,
+ UInt32 inStartFrame);
+
+ /*! @method GetInstrumentCount */
+ virtual OSStatus GetInstrumentCount ( UInt32 &outInstCount) const;
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ // component dispatcher
+ /*! @method ComponentEntryDispatch */
+ static OSStatus ComponentEntryDispatch( ComponentParameters * params,
+ MusicDeviceBase * This);
+#endif
+private:
+ OSStatus HandleStartNoteMessage (MusicDeviceInstrumentID inInstrument, MusicDeviceGroupID inGroupID, NoteInstanceID *outNoteInstanceID, UInt32 inOffsetSampleFrame, const MusicDeviceNoteParams *inParams);
+};
+
+#endif // __MusicDeviceBase_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp
new file mode 100644
index 0000000000..2316807138
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp
@@ -0,0 +1,125 @@
+/*
+ File: AUBaseHelper.cpp
+ Abstract: AUBaseHelper.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUBaseHelper.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnitProperties.h>
+#else
+ #include <AudioUnitProperties.h>
+#endif
+
+OSStatus GetFileRefPath (CFDictionaryRef parent, CFStringRef frKey, CFStringRef * fPath)
+{
+ static CFStringRef kFRString = CFSTR (kAUPresetExternalFileRefs);
+
+ const void* frVal = CFDictionaryGetValue(parent, kFRString);
+ if (!frVal) return kAudioUnitErr_InvalidPropertyValue;
+
+ const void* frString = CFDictionaryGetValue ((CFDictionaryRef)frVal, frKey);
+ if (!frString) return kAudioUnitErr_InvalidPropertyValue;
+
+ if (fPath)
+ *fPath = (CFStringRef)frString;
+
+ return noErr;
+}
+
+CFMutableDictionaryRef CreateFileRefDict (CFStringRef fKey, CFStringRef fPath, CFMutableDictionaryRef fileRefDict)
+{
+ if (!fileRefDict)
+ fileRefDict = CFDictionaryCreateMutable (NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ CFDictionarySetValue (fileRefDict, fKey, fPath);
+
+ return fileRefDict;
+}
+
+#if TARGET_OS_MAC
+// check if the URL can be accessed for reading/writing. Returns 0 if yes, or the error value.
+int AccessURLAsset(const CFURLRef inURL, int mode)
+{
+ char path[PATH_MAX];
+ if (CFURLGetFileSystemRepresentation(inURL, TRUE, (UInt8 *)path, PATH_MAX) == FALSE)
+ return kAudio_FileNotFoundError;
+ // check whether we have access
+ int ret = access(path, mode);
+// syslog(LOG_CRIT, "access() error is %d for \"%s\".\n", ret, path);
+ if (ret == 0) return 0;
+ switch (errno) {
+ case EACCES:
+ case EPERM:
+ return -54; /*permission denied error*/
+ case ENOENT:
+ case ENOTDIR:
+ case ELOOP:
+ return kAudio_FileNotFoundError;
+ default:
+ return errno;
+ }
+}
+#endif
+
+#if DEBUG
+//_____________________________________________________________________________
+//
+void PrintAUParamEvent (AudioUnitParameterEvent& event, FILE* f)
+{
+ bool isRamp = event.eventType == kParameterEvent_Ramped;
+ fprintf (f, "\tParamID=%ld,Scope=%ld,Element=%ld\n", (long)event.parameter, (long)event.scope, (long)event.element);
+ fprintf (f, "\tEvent Type:%s,", (isRamp ? "ramp" : "immediate"));
+ if (isRamp)
+ fprintf (f, "start=%ld,dur=%ld,startValue=%f,endValue=%f\n",
+ (long)event.eventValues.ramp.startBufferOffset, (long)event.eventValues.ramp.durationInFrames,
+ event.eventValues.ramp.startValue, event.eventValues.ramp.endValue);
+ else
+ fprintf (f, "start=%ld,value=%f\n",
+ (long)event.eventValues.immediate.bufferOffset,
+ event.eventValues.immediate.value);
+ fprintf (f, "- - - - - - - - - - - - - - - -\n");
+}
+#endif
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.h
new file mode 100644
index 0000000000..310a8df620
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBaseHelper.h
@@ -0,0 +1,75 @@
+/*
+ File: AUBaseHelper.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUBaseHelper_h__
+#define __AUBaseHelper_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreFoundation/CoreFoundation.h>
+ #include <AudioUnit/AUComponent.h>
+#else
+ #include <CoreFoundation.h>
+ #include <AUComponent.h>
+#endif
+
+#include "AUBase.h"
+
+// helpers for dealing with the file-references dictionary in an AUPreset
+OSStatus GetFileRefPath (CFDictionaryRef parent, CFStringRef frKey, CFStringRef * fPath);
+
+// if fileRefDict is NULL, this call creates one
+// if not NULL, then the key value is added to it
+CFMutableDictionaryRef CreateFileRefDict (CFStringRef fKey, CFStringRef fPath, CFMutableDictionaryRef fileRefDict);
+
+int AccessURLAsset(const CFURLRef inURL, int mode);
+
+#if DEBUG
+ void PrintAUParamEvent (AudioUnitParameterEvent& event, FILE* f);
+#endif
+
+
+
+#endif // __AUBaseHelper_h__ \ No newline at end of file
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.cpp
new file mode 100644
index 0000000000..36bb41fa58
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.cpp
@@ -0,0 +1,219 @@
+/*
+ File: AUBuffer.cpp
+ Abstract: AUBuffer.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUBuffer.h"
+#include <stdlib.h>
+
+AUBufferList::~AUBufferList()
+{
+ Deallocate();
+ if (mPtrs)
+ free(mPtrs);
+}
+
+// a * b + c
+static UInt32 SafeMultiplyAddUInt32(UInt32 a, UInt32 b, UInt32 c)
+{
+ if (a == 0 || b == 0) return c; // prevent zero divide
+
+ if (a > (0xFFFFFFFF - c) / b)
+ throw std::bad_alloc();
+
+ return a * b + c;
+}
+
+void AUBufferList::Allocate(const CAStreamBasicDescription &format, UInt32 nFrames)
+{
+ UInt32 nStreams;
+ if (format.IsInterleaved()) {
+ nStreams = 1;
+ } else {
+ nStreams = format.mChannelsPerFrame;
+ }
+
+ // careful -- the I/O thread could be running!
+ if (nStreams > mAllocatedStreams) {
+ size_t theHeaderSize = sizeof(AudioBufferList) - sizeof(AudioBuffer);
+ mPtrs = (AudioBufferList *)CA_realloc(mPtrs,
+ SafeMultiplyAddUInt32(nStreams, sizeof(AudioBuffer), theHeaderSize));
+ mAllocatedStreams = nStreams;
+ }
+ UInt32 bytesPerStream = SafeMultiplyAddUInt32(nFrames, format.mBytesPerFrame, 0xF) & ~0xF;
+ UInt32 nBytes = SafeMultiplyAddUInt32(nStreams, bytesPerStream, 0);
+ if (nBytes > mAllocatedBytes) {
+ if (mExternalMemory) {
+ mExternalMemory = false;
+ mMemory = NULL;
+ }
+ mMemory = (Byte *)CA_realloc(mMemory, nBytes);
+ mAllocatedBytes = nBytes;
+ }
+ mAllocatedFrames = nFrames;
+ mPtrState = kPtrsInvalid;
+}
+
+void AUBufferList::Deallocate()
+{
+ mAllocatedStreams = 0;
+ mAllocatedFrames = 0;
+ mAllocatedBytes = 0;
+// this causes a world of hurt if someone upstream disconnects during I/O (SysSoundGraph)
+/* if (mPtrs) {
+ printf("deallocating bufferlist %08X\n", int(mPtrs));
+ free(mPtrs);
+ mPtrs = NULL;
+ } */
+ if (mMemory) {
+ if (mExternalMemory)
+ mExternalMemory = false;
+ else
+ free(mMemory);
+ mMemory = NULL;
+ }
+ mPtrState = kPtrsInvalid;
+}
+
+AudioBufferList & AUBufferList::PrepareBuffer(const CAStreamBasicDescription &format, UInt32 nFrames)
+{
+ if (nFrames > mAllocatedFrames)
+ COMPONENT_THROW(kAudioUnitErr_TooManyFramesToProcess);
+
+ UInt32 nStreams;
+ UInt32 channelsPerStream;
+ if (format.IsInterleaved()) {
+ nStreams = 1;
+ channelsPerStream = format.mChannelsPerFrame;
+ } else {
+ nStreams = format.mChannelsPerFrame;
+ channelsPerStream = 1;
+ if (nStreams > mAllocatedStreams)
+ COMPONENT_THROW(kAudioUnitErr_FormatNotSupported);
+ }
+
+ AudioBufferList *abl = mPtrs;
+ abl->mNumberBuffers = nStreams;
+ AudioBuffer *buf = abl->mBuffers;
+ Byte *mem = mMemory;
+ UInt32 streamInterval = (mAllocatedFrames * format.mBytesPerFrame + 0xF) & ~0xF;
+ UInt32 bytesPerBuffer = nFrames * format.mBytesPerFrame;
+ for ( ; nStreams--; ++buf) {
+ buf->mNumberChannels = channelsPerStream;
+ buf->mData = mem;
+ buf->mDataByteSize = bytesPerBuffer;
+ mem += streamInterval;
+ }
+ if (UInt32(mem - mMemory) > mAllocatedBytes)
+ COMPONENT_THROW(kAudioUnitErr_TooManyFramesToProcess);
+ mPtrState = kPtrsToMyMemory;
+ return *mPtrs;
+}
+
+AudioBufferList & AUBufferList::PrepareNullBuffer(const CAStreamBasicDescription &format, UInt32 nFrames)
+{
+ UInt32 nStreams;
+ UInt32 channelsPerStream;
+ if (format.IsInterleaved()) {
+ nStreams = 1;
+ channelsPerStream = format.mChannelsPerFrame;
+ } else {
+ nStreams = format.mChannelsPerFrame;
+ channelsPerStream = 1;
+ if (nStreams > mAllocatedStreams)
+ COMPONENT_THROW(kAudioUnitErr_FormatNotSupported);
+ }
+ AudioBufferList *abl = mPtrs;
+ abl->mNumberBuffers = nStreams;
+ AudioBuffer *buf = abl->mBuffers;
+ UInt32 bytesPerBuffer = nFrames * format.mBytesPerFrame;
+ for ( ; nStreams--; ++buf) {
+ buf->mNumberChannels = channelsPerStream;
+ buf->mData = NULL;
+ buf->mDataByteSize = bytesPerBuffer;
+ }
+ mPtrState = kPtrsToExternalMemory;
+ return *mPtrs;
+}
+
+// this should NOT be called while I/O is in process
+void AUBufferList::UseExternalBuffer(const CAStreamBasicDescription &format, const AudioUnitExternalBuffer &buf)
+{
+ UInt32 alignedSize = buf.size & ~0xF;
+ if (mMemory != NULL && alignedSize >= mAllocatedBytes) {
+ // don't accept the buffer if we already have one and it's big enough
+ // if we don't already have one, we don't need one
+ Byte *oldMemory = mMemory;
+ mMemory = buf.buffer;
+ mAllocatedBytes = alignedSize;
+ // from Allocate(): nBytes = nStreams * nFrames * format.mBytesPerFrame;
+ // thus: nFrames = nBytes / (nStreams * format.mBytesPerFrame)
+ mAllocatedFrames = mAllocatedBytes / (format.NumberChannelStreams() * format.mBytesPerFrame);
+ mExternalMemory = true;
+ free(oldMemory);
+ }
+}
+
+#if DEBUG
+void AUBufferList::PrintBuffer(const char *label, int subscript, const AudioBufferList &abl, UInt32 nFrames, bool asFloats)
+{
+ printf(" %s [%d] 0x%08lX:\n", label, subscript, long(&abl));
+ const AudioBuffer *buf = abl.mBuffers;
+ for (UInt32 i = 0; i < abl.mNumberBuffers; ++buf, ++i) {
+ printf(" [%2d] %5dbytes %dch @ %p: ", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData);
+ if (buf->mData != NULL) {
+ UInt32 nSamples = nFrames * buf->mNumberChannels;
+ for (UInt32 j = 0; j < nSamples; ++j) {
+ if (nSamples > 16 && (j % 16) == 0)
+ printf("\n\t");
+ if (asFloats)
+ printf(" %6.3f", ((float *)buf->mData)[j]);
+ else
+ printf(" %08X", (unsigned)((UInt32 *)buf->mData)[j]);
+ }
+ }
+ printf("\n");
+ }
+}
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.h
new file mode 100644
index 0000000000..64ea4c3971
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUBuffer.h
@@ -0,0 +1,267 @@
+/*
+ File: AUBuffer.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUBuffer_h__
+#define __AUBuffer_h__
+
+#include <TargetConditionals.h>
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioUnit/AudioUnit.h>
+#else
+ #include <AudioUnit.h>
+#endif
+
+#include <string.h>
+#include "CAStreamBasicDescription.h"
+#include "CAAutoDisposer.h"
+#include "CADebugMacros.h"
+
+// make this usable outside the stricter context of AudiUnits
+#ifndef COMPONENT_THROW
+ #define COMPONENT_THROW(err) \
+ do { DebugMessage(#err); throw static_cast<OSStatus>(err); } while (0)
+#endif
+
+
+ /*! @class AUBufferList */
+class AUBufferList {
+ enum EPtrState {
+ kPtrsInvalid,
+ kPtrsToMyMemory,
+ kPtrsToExternalMemory
+ };
+public:
+ /*! @ctor AUBufferList */
+ AUBufferList() : mPtrState(kPtrsInvalid), mExternalMemory(false), mPtrs(NULL), mMemory(NULL),
+ mAllocatedStreams(0), mAllocatedFrames(0), mAllocatedBytes(0) { }
+ /*! @dtor ~AUBufferList */
+ ~AUBufferList();
+
+ /*! @method PrepareBuffer */
+ AudioBufferList & PrepareBuffer(const CAStreamBasicDescription &format, UInt32 nFrames);
+ /*! @method PrepareNullBuffer */
+ AudioBufferList & PrepareNullBuffer(const CAStreamBasicDescription &format, UInt32 nFrames);
+
+ /*! @method SetBufferList */
+ AudioBufferList & SetBufferList(const AudioBufferList &abl) {
+ if (mAllocatedStreams < abl.mNumberBuffers)
+ COMPONENT_THROW(-1);
+ mPtrState = kPtrsToExternalMemory;
+ memcpy(mPtrs, &abl, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl);
+ return *mPtrs;
+ }
+
+ /*! @method SetBuffer */
+ void SetBuffer(UInt32 index, const AudioBuffer &ab) {
+ if (mPtrState == kPtrsInvalid || index >= mPtrs->mNumberBuffers)
+ COMPONENT_THROW(-1);
+ mPtrState = kPtrsToExternalMemory;
+ mPtrs->mBuffers[index] = ab;
+ }
+
+ /*! @method InvalidateBufferList */
+ void InvalidateBufferList() { mPtrState = kPtrsInvalid; }
+
+ /*! @method GetBufferList */
+ AudioBufferList & GetBufferList() const {
+ if (mPtrState == kPtrsInvalid)
+ COMPONENT_THROW(-1);
+ return *mPtrs;
+ }
+
+ /*! @method CopyBufferListTo */
+ void CopyBufferListTo(AudioBufferList &abl) const {
+ if (mPtrState == kPtrsInvalid)
+ COMPONENT_THROW(-1);
+ memcpy(&abl, mPtrs, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl);
+ }
+
+ /*! @method CopyBufferContentsTo */
+ void CopyBufferContentsTo(AudioBufferList &abl) const {
+ if (mPtrState == kPtrsInvalid)
+ COMPONENT_THROW(-1);
+ const AudioBuffer *srcbuf = mPtrs->mBuffers;
+ AudioBuffer *destbuf = abl.mBuffers;
+
+ for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++srcbuf, ++destbuf) {
+ if (i >= mPtrs->mNumberBuffers) // duplicate last source to additional outputs [4341137]
+ --srcbuf;
+ if (destbuf->mData != srcbuf->mData)
+ memmove(destbuf->mData, srcbuf->mData, srcbuf->mDataByteSize);
+ destbuf->mDataByteSize = srcbuf->mDataByteSize;
+ }
+ }
+
+ /*! @method Allocate */
+ void Allocate(const CAStreamBasicDescription &format, UInt32 nFrames);
+ /*! @method Deallocate */
+ void Deallocate();
+
+ /*! @method UseExternalBuffer */
+ void UseExternalBuffer(const CAStreamBasicDescription &format, const AudioUnitExternalBuffer &buf);
+
+ // AudioBufferList utilities
+ /*! @method ZeroBuffer */
+ static void ZeroBuffer(AudioBufferList &abl) {
+ AudioBuffer *buf = abl.mBuffers;
+ for (UInt32 i = abl.mNumberBuffers ; i--; ++buf)
+ memset(buf->mData, 0, buf->mDataByteSize);
+ }
+#if DEBUG
+ /*! @method PrintBuffer */
+ static void PrintBuffer(const char *label, int subscript, const AudioBufferList &abl, UInt32 nFrames = 8, bool asFloats = true);
+#endif
+
+ /*! @method GetAllocatedFrames */
+ UInt32 GetAllocatedFrames() const { return mAllocatedFrames; }
+
+private:
+ /*! @ctor AUBufferList */
+ AUBufferList(AUBufferList &) { } // prohibit copy constructor
+
+ /*! @var mPtrState */
+ EPtrState mPtrState;
+ /*! @var mExternalMemory */
+ bool mExternalMemory;
+ /*! @var mPtrs */
+ AudioBufferList * mPtrs;
+ /*! @var mMemory */
+ Byte * mMemory;
+ /*! @var mAllocatedStreams */
+ UInt32 mAllocatedStreams;
+ /*! @var mAllocatedFrames */
+ UInt32 mAllocatedFrames;
+ /*! @var mAllocatedBytes */
+ UInt32 mAllocatedBytes;
+};
+
+
+// Allocates an array of samples (type T), to be optimally aligned for the processor
+ /*! @class TAUBuffer */
+template <class T>
+class TAUBuffer {
+public:
+ enum {
+ kAlignInterval = 0x10,
+ kAlignMask = kAlignInterval - 1
+ };
+
+ /*! @ctor TAUBuffer.0 */
+ TAUBuffer() : mMemObject(NULL), mAlignedBuffer(NULL), mBufferSizeBytes(0)
+ {
+ }
+
+ /*! @ctor TAUBuffer.1 */
+ TAUBuffer(UInt32 numElems, UInt32 numChannels) : mMemObject(NULL), mAlignedBuffer(NULL),
+ mBufferSizeBytes(0)
+ {
+ Allocate(numElems, numChannels);
+ }
+
+ /*! @dtor ~TAUBuffer */
+ ~TAUBuffer()
+ {
+ Deallocate();
+ }
+
+ /*! @method Allocate */
+ void Allocate(UInt32 numElems) // can also re-allocate
+ {
+ UInt32 reqSize = numElems * sizeof(T);
+
+ if (mMemObject != NULL && reqSize == mBufferSizeBytes)
+ return; // already allocated
+
+ mBufferSizeBytes = reqSize;
+ mMemObject = CA_realloc(mMemObject, reqSize);
+ UInt32 misalign = (uintptr_t)mMemObject & kAlignMask;
+ if (misalign) {
+ mMemObject = CA_realloc(mMemObject, reqSize + kAlignMask);
+ mAlignedBuffer = (T *)((char *)mMemObject + kAlignInterval - misalign);
+ } else
+ mAlignedBuffer = (T *)mMemObject;
+ }
+
+ /*! @method Deallocate */
+ void Deallocate()
+ {
+ if (mMemObject == NULL) return; // so this method has no effect if we're using
+ // an external buffer
+
+ free(mMemObject);
+ mMemObject = NULL;
+ mAlignedBuffer = NULL;
+ mBufferSizeBytes = 0;
+ }
+
+ /*! @method AllocateClear */
+ void AllocateClear(UInt32 numElems) // can also re-allocate
+ {
+ Allocate(numElems);
+ Clear();
+ }
+
+ /*! @method Clear */
+ void Clear()
+ {
+ memset(mAlignedBuffer, 0, mBufferSizeBytes);
+ }
+
+ // accessors
+
+ /*! @method operator T *()@ */
+ operator T *() { return mAlignedBuffer; }
+
+private:
+ /*! @var mMemObject */
+ void * mMemObject; // null when using an external buffer
+ /*! @var mAlignedBuffer */
+ T * mAlignedBuffer; // always valid once allocated
+ /*! @var mBufferSizeBytes */
+ UInt32 mBufferSizeBytes;
+};
+
+#endif // __AUBuffer_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h
new file mode 100644
index 0000000000..f628a915e1
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h
@@ -0,0 +1,155 @@
+/*
+ File: AUInputFormatConverter.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUInputFormatConverter_h__
+#define __AUInputFormatConverter_h__
+
+#include "FormatConverterClient.h"
+#include "AUTimestampGenerator.h"
+
+// ____________________________________________________________________________
+// AUInputFormatConverter
+//
+// Subclass of FormatConverterClient that applies a format conversion
+// to an input of an AudioUnit.
+ /*! @class AUInputFormatConverter */
+class AUInputFormatConverter : public FormatConverterClient {
+public:
+ /*! @ctor AUInputFormatConverter */
+ AUInputFormatConverter(AUBase *hostAU, int inputBus) :
+ mHost(hostAU),
+ mHostBus(inputBus),
+ mPreviousSilentFrames(0x1000)
+ {
+#if DEBUG
+ mTimestampGenerator.mVerbosity = 0;
+ strcpy(mTimestampGenerator.mDebugName, "AUConverter");
+#endif
+ }
+
+ // need to subsequently call Initialize, with the desired formats
+
+ /*! @dtor ~AUInputFormatConverter */
+ ~AUInputFormatConverter()
+ {
+ }
+
+ virtual OSStatus Initialize(const AudioStreamBasicDescription &src, const AudioStreamBasicDescription &dest)
+ {
+ OSStatus err = FormatConverterClient::Initialize(src, dest);
+ if (err) return err;
+ mIsPCMToPCM = (src.mFormatID == kAudioFormatLinearPCM) && (dest.mFormatID == kAudioFormatLinearPCM);
+ mHasSRC = (fnonzero(src.mSampleRate) && fnonzero(dest.mSampleRate) && fnotequal(src.mSampleRate, dest.mSampleRate));
+ return ca_noErr;
+ }
+
+ virtual OSStatus Reset()
+ {
+ mPreviousSilentFrames = 0x1000;
+ mTimestampGenerator.Reset();
+ return FormatConverterClient::Reset();
+ }
+
+ void SetStartInputTimeAtZero(bool b)
+ {
+ mTimestampGenerator.SetStartInputAtZero(b);
+ }
+
+ /*! @method FillComplexBuffer */
+ OSStatus AUFillComplexBuffer(const AudioTimeStamp & inTimeStamp,
+ UInt32 & ioOutputDataPacketSize,
+ AudioBufferList & outOutputData,
+ AudioStreamPacketDescription* outPacketDescription,
+ bool& outSilence)
+ {
+ mTimestampGenerator.AddOutputTime(inTimeStamp, ioOutputDataPacketSize, mOutputFormat.mSampleRate);
+ mSilentOutput = true;
+ OSStatus err = FillComplexBuffer(ioOutputDataPacketSize, outOutputData, outPacketDescription);
+ if (mSilentOutput) {
+ if (!mIsPCMToPCM || (mHasSRC && mPreviousSilentFrames < 32))
+ mSilentOutput = false;
+ mPreviousSilentFrames += ioOutputDataPacketSize;
+ } else
+ mPreviousSilentFrames = 0;
+ outSilence = mSilentOutput;
+ return err;
+ }
+
+ /*! @method FormatConverterInputProc */
+ virtual OSStatus FormatConverterInputProc(
+ UInt32 & ioNumberDataPackets,
+ AudioBufferList & ioData,
+ AudioStreamPacketDescription** outDataPacketDescription)
+ {
+ OSStatus err = ca_noErr;
+
+ AudioUnitRenderActionFlags actionFlags = 0;
+ AUInputElement *input = mHost->GetInput(mHostBus);
+ *ioNumberDataPackets = std::min(*ioNumberDataPackets, This->mHost->GetMaxFramesPerSlice());
+ const AudioTimeStamp &inputTime = mTimestampGenerator.GenerateInputTime(ioNumberDataPackets, mInputFormat.mSampleRate);
+ err = input->PullInput(actionFlags, inputTime, mHostBus, ioNumberDataPackets);
+ if (!err) {
+ input->CopyBufferListTo(ioData);
+ if (!(actionFlags & kAudioUnitRenderAction_OutputIsSilence))
+ mSilentOutput = false;
+ }
+ return err;
+ }
+
+protected:
+ /*! @var mHost */
+ AUBase * mHost;
+ /*! @var mHostBus */
+ int mHostBus;
+
+ AUTimestampGenerator mTimestampGenerator;
+ bool mIsPCMToPCM;
+ bool mHasSRC;
+ bool mSilentOutput;
+ UInt32 mPreviousSilentFrames;
+};
+
+#endif // __AUInputFormatConverter_h__
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUMIDIDefs.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUMIDIDefs.h
new file mode 100644
index 0000000000..e83c0e7e8d
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUMIDIDefs.h
@@ -0,0 +1,138 @@
+/*
+ File: AUMIDIDefs.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUMIDIDefs_h__
+#define __AUMIDIDefs_h__
+
+#if !defined(__TMidiMessage) /* DAS HACK */
+enum
+{
+ kMidiMessage_NoteOff = 0x80,
+ kMidiMessage_NoteOn = 0x90,
+ kMidiMessage_PolyPressure = 0xA0,
+ kMidiMessage_ControlChange = 0xB0,
+ kMidiMessage_ProgramChange = 0xC0,
+ kMidiMessage_ChannelPressure = 0xD0,
+ kMidiMessage_PitchWheel = 0xE0,
+ kMidiMessage_SysEx = 0xF0,
+ kMidiMessage_SysEx_End = 0xF7,
+ kMidiMessage_MetaEvent = 0xFF
+};
+#endif
+
+enum
+{
+ kMidiController_BankSelect = 0,
+ kMidiController_ModWheel = 1,
+ kMidiController_Breath = 2,
+ kMidiController_Foot = 4,
+ kMidiController_PortamentoTime = 5,
+ kMidiController_DataEntry = 6,
+ kMidiController_Volume = 7,
+ kMidiController_Balance = 8,
+ kMidiController_Pan = 10,
+ kMidiController_Expression = 11,
+
+ // these controls have a (0-63) == off, (64-127) == on
+ kMidiController_Sustain = 64, //hold1
+ kMidiController_Portamento = 65,
+ kMidiController_Sostenuto = 66,
+ kMidiController_Soft = 67,
+ kMidiController_LegatoPedal = 68,
+ kMidiController_Hold2Pedal = 69,
+ kMidiController_FilterResonance = 71,
+ kMidiController_ReleaseTime = 72,
+ kMidiController_AttackTime = 73,
+ kMidiController_Brightness = 74,
+ kMidiController_DecayTime = 75,
+ kMidiController_VibratoRate = 76,
+ kMidiController_VibratoDepth = 77,
+ kMidiController_VibratoDelay = 78,
+
+ // these controls have a 0-127 range and in MIDI they have no LSB (so fractional values are lost in MIDI)
+ kMidiController_ReverbLevel = 91,
+ kMidiController_ChorusLevel = 93,
+
+ kMidiController_RPN_LSB = 100,
+ kMidiController_RPN_MSB = 101,
+
+ kMidiController_AllSoundOff = 120,
+ kMidiController_ResetAllControllers = 121,
+ kMidiController_AllNotesOff = 123,
+ kMidiController_OmniModeOff = 124,
+ kMidiController_OmniModeOn = 125,
+ kMidiController_MonoModeOn = 126,
+ kMidiController_MonoModeOff = 127
+};
+
+// RPN values
+enum
+{
+ kMidiControllerValue_RPNPitchBendSensitivity = 0,
+ kMidiControllerValue_RPNChannelFineTuning = 1,
+ kMidiControllerValue_RPNChannelCoarseTuning = 2,
+ kMidiControllerValue_RPNModDepthRange = 5,
+ kMidiControllerValue_RPNNull = 0x3fff //! 0x7f/0x7f
+};
+
+// GM2 Sound Bank Constants
+enum
+{
+ kGM2MelodicBank = 0x7900,
+ kGM2PercussionBank = 0x7800,
+ kGSPercussionBank = 0x7f00,
+ kXGSFXBank = 0x7E00,
+ kXGPercussionBank = kGSPercussionBank,
+ kBankMSBMask = 0xff00
+};
+
+enum
+{
+ kMSBController_MidPoint = 0x40
+};
+
+#endif // __AUMIDIDefs_h__
+
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUSilentTimeout.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUSilentTimeout.h
new file mode 100644
index 0000000000..9fbd3e1f23
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUSilentTimeout.h
@@ -0,0 +1,93 @@
+/*
+ File: AUSilentTimeout.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUSilentTimeout
+#define __AUSilentTimeout
+
+class AUSilentTimeout
+{
+public:
+ AUSilentTimeout()
+ : mTimeoutCounter(0),
+ mResetTimer(true)
+ {};
+
+ void Process(UInt32 inFramesToProcess, UInt32 inTimeoutLimit, bool &ioSilence )
+ {
+ if(ioSilence )
+ {
+ if(mResetTimer )
+ {
+ mTimeoutCounter = inTimeoutLimit;
+ mResetTimer = false;
+ }
+
+ if(mTimeoutCounter > 0 )
+ {
+ mTimeoutCounter -= inFramesToProcess;
+ ioSilence = false;
+ }
+ }
+ else
+ {
+ // signal to reset the next time we receive silence
+ mResetTimer = true;
+ }
+ }
+
+ void Reset()
+ {
+ mResetTimer = true;
+ };
+
+
+
+private:
+ SInt32 mTimeoutCounter;
+ bool mResetTimer;
+};
+
+#endif // __AUSilentTimeout
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp
new file mode 100644
index 0000000000..7c57a81ede
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp
@@ -0,0 +1,203 @@
+/*
+ File: AUTimestampGenerator.cpp
+ Abstract: AUTimestampGenerator.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AUTimestampGenerator.h"
+#include "CAMath.h"
+
+#if DEBUG
+static double DebugHostTime(const AudioTimeStamp &ts)
+{
+ static UInt64 baseHostTime = 0;
+ if (!(ts.mFlags & kAudioTimeStampHostTimeValid))
+ return -1.;
+ if (baseHostTime == 0)
+ baseHostTime = ts.mHostTime;
+ return double(SInt64(ts.mHostTime) - SInt64(baseHostTime)) * CAHostTimeBase::GetInverseFrequency();
+}
+#endif
+
+void AUTimestampGenerator::AddOutputTime(const AudioTimeStamp &inTimeStamp, Float64 expectedDeltaFrames, double outputSampleRate, double rateScalarAdj)
+{
+ mState.mRateScalarAdj = rateScalarAdj;
+ mState.mLastOutputTime = mState.mCurrentOutputTime;
+ mState.mInputSampleTimeForOutputPull = mState.mNextInputSampleTime;
+ mState.mCurrentOutputTime = inTimeStamp;
+
+ if (mState.mBypassed)
+ return;
+
+ if (mState.mHostTimeDiscontinuityCorrection && !(mState.mCurrentOutputTime.mFlags & kAudioTimeStampHostTimeValid) && (mState.mLastOutputTime.mFlags & kAudioTimeStampHostTimeValid)) {
+ // no host time here but we had one last time, interpolate one
+ double rateScalar = (mState.mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid) ? mState.mCurrentOutputTime.mRateScalar : 1.0;
+ Float64 deltaSamples = mState.mCurrentOutputTime.mSampleTime - mState.mLastOutputTime.mSampleTime;
+ mState.mCurrentOutputTime.mHostTime = mState.mLastOutputTime.mHostTime +
+ UInt64(CAHostTimeBase::GetFrequency() * deltaSamples * rateScalar / outputSampleRate);
+ mState.mCurrentOutputTime.mFlags |= kAudioTimeStampHostTimeValid;
+#if DEBUG
+ if (mVerbosity > 1)
+ printf("synthesized host time: %.3f (%.3f + %.f smp @ %.f Hz, rs %.3f\n", DebugHostTime(mState.mCurrentOutputTime), DebugHostTime(mState.mLastOutputTime), deltaSamples, outputSampleRate, rateScalar);
+#endif
+ }
+ // copy rate scalar
+ if (rateScalarAdj != 1.0) {
+ if (mState.mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid)
+ mState.mCurrentOutputTime.mRateScalar *= rateScalarAdj;
+ else {
+ mState.mCurrentOutputTime.mRateScalar = rateScalarAdj;
+ mState.mCurrentOutputTime.mFlags |= kAudioTimeStampRateScalarValid;
+ }
+ }
+
+ if (mFirstTime) {
+ mFirstTime = false;
+ mState.mDiscontinuous = false;
+ mState.mDiscontinuityDeltaSamples = 0.;
+ if (!mState.mStartInputAtZero) {
+ mState.mNextInputSampleTime = mState.mCurrentOutputTime.mSampleTime;
+ mState.mInputSampleTimeForOutputPull = mState.mNextInputSampleTime;
+ }
+ } else {
+ mState.mDiscontinuous = fnotequal(mState.mCurrentOutputTime.mSampleTime, mState.mNextOutputSampleTime);
+ mState.mDiscontinuityDeltaSamples = mState.mCurrentOutputTime.mSampleTime - mState.mNextOutputSampleTime;
+ // time should never go backwards...
+ if (mState.mDiscontinuityDeltaSamples < 0.)
+ mState.mDiscontinuityDeltaSamples = 0.;
+#if DEBUG
+ if (mVerbosity > 1)
+ if (mState.mDiscontinuous)
+ printf("%-20.20s: *** DISCONTINUOUS, got " TSGFMT ", expected " TSGFMT "\n", mDebugName, (SInt64)mState.mCurrentOutputTime.mSampleTime, (SInt64)mState.mNextOutputSampleTime);
+#endif
+ }
+ mState.mNextOutputSampleTime = mState.mCurrentOutputTime.mSampleTime + expectedDeltaFrames;
+}
+
+const AudioTimeStamp & AUTimestampGenerator::GenerateInputTime(Float64 framesToAdvance, double inputSampleRate, bool advanceHostTime)
+{
+ if (mState.mBypassed)
+ return mState.mCurrentOutputTime;
+
+ double inputSampleTime;
+
+ mState.mCurrentInputTime.mFlags = kAudioTimeStampSampleTimeValid;
+ double rateScalar = 1.0;
+
+ // propagate rate scalar
+ if (mState.mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid) {
+ mState.mCurrentInputTime.mFlags |= kAudioTimeStampRateScalarValid;
+ mState.mCurrentInputTime.mRateScalar = rateScalar = mState.mCurrentOutputTime.mRateScalar;
+ }
+
+ // propagate host time and sample time
+ if (mState.mCurrentOutputTime.mFlags & kAudioTimeStampHostTimeValid) {
+ mState.mCurrentInputTime.mFlags |= kAudioTimeStampHostTimeValid;
+ if (advanceHostTime) {
+ Float64 deltaSamples = mState.mNextInputSampleTime - mState.mInputSampleTimeForOutputPull;
+ Float64 deltaSeconds = (deltaSamples / inputSampleRate) * mState.mRateScalarAdj;
+ UInt64 deltaHostTime = (UInt64)(deltaSeconds * CAHostTimeBase::GetFrequency());
+ mState.mCurrentInputTime.mHostTime = mState.mCurrentOutputTime.mHostTime + deltaHostTime;
+ } else {
+ mState.mCurrentInputTime.mHostTime = mState.mCurrentOutputTime.mHostTime;
+ }
+ if (mState.mHostTimeDiscontinuityCorrection && mState.mDiscontinuous && (mState.mLastOutputTime.mFlags & kAudioTimeStampHostTimeValid)) {
+ // we had a discontinuous output time, need to resync by interpolating
+ // a sample time that is appropriate to the host time
+ UInt64 deltaHostTime = mState.mCurrentOutputTime.mHostTime - mState.mLastOutputTime.mHostTime;
+ double deltaSeconds = double(deltaHostTime) * CAHostTimeBase::GetInverseFrequency();
+ // samples/second * seconds = samples
+ double deltaSamples = floor(inputSampleRate / rateScalar * deltaSeconds + 0.5);
+ double lastInputSampleTime = mState.mCurrentInputTime.mSampleTime;
+ inputSampleTime = lastInputSampleTime + deltaSamples;
+#if DEBUG
+ if (mVerbosity > 1)
+ printf("%-20.20s: adjusted input time: " TSGFMT " -> " TSGFMT " (SR=%.3f, rs=%.3f)\n", mDebugName, (SInt64)lastInputSampleTime, (SInt64)inputSampleTime, inputSampleRate, rateScalar);
+#endif
+ mState.mDiscontinuous = false;
+ } else {
+ inputSampleTime = mState.mNextInputSampleTime;
+ }
+ } else {
+ // we don't know the host time, so we can't do much
+ inputSampleTime = mState.mNextInputSampleTime;
+ }
+
+ if (!mState.mHostTimeDiscontinuityCorrection && fnonzero(mState.mDiscontinuityDeltaSamples))
+ {
+ // we had a discontinuous output time, need to resync by propagating the
+ // detected discontinuity, taking the rate scalar adjustment into account
+ inputSampleTime += floor(mState.mDiscontinuityDeltaSamples / mState.mRateScalarAdj + 0.5);
+
+#if DEBUG
+ if (mVerbosity > 1)
+ printf("%-20.20s: adjusted input time: %.0f -> %.0f (SR=%.3f, rs=%.3f, delta=%.0f)\n", mDebugName, mState.mNextInputSampleTime, inputSampleTime, inputSampleRate, mState.mRateScalarAdj, mState.mDiscontinuityDeltaSamples);
+#endif
+
+ mState.mDiscontinuityDeltaSamples = 0.;
+ }
+
+
+ // propagate word clock
+ if (mState.mCurrentOutputTime.mFlags & kAudioTimeStampWordClockTimeValid) {
+ mState.mCurrentInputTime.mFlags |= kAudioTimeStampWordClockTimeValid;
+ mState.mCurrentInputTime.mWordClockTime = mState.mCurrentOutputTime.mWordClockTime;
+ }
+
+ // propagate SMPTE time
+ if (mState.mCurrentOutputTime.mFlags & kAudioTimeStampSMPTETimeValid) {
+ mState.mCurrentInputTime.mFlags |= kAudioTimeStampSMPTETimeValid;
+ mState.mCurrentInputTime.mSMPTETime = mState.mCurrentOutputTime.mSMPTETime;
+ }
+
+ // store the input sample time and expected next input time
+ mState.mCurrentInputTime.mSampleTime = inputSampleTime;
+ mState.mNextInputSampleTime = inputSampleTime + framesToAdvance;
+
+#if DEBUG
+ if (mVerbosity > 0) {
+ printf("%-20.20s: out = " TSGFMT " (%10.3fs) in = " TSGFMT " (%10.3fs) delta = " TSGFMT " advance = " TSGFMT "\n", mDebugName, (SInt64)mState.mCurrentOutputTime.mSampleTime, DebugHostTime(mState.mCurrentOutputTime), (SInt64)inputSampleTime, DebugHostTime(mState.mCurrentInputTime), (SInt64)(mState.mCurrentOutputTime.mSampleTime - inputSampleTime), (SInt64)framesToAdvance);
+ }
+#endif
+ return mState.mCurrentInputTime;
+}
diff --git a/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h
new file mode 100644
index 0000000000..cfd8456dfb
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h
@@ -0,0 +1,163 @@
+/*
+ File: AUTimestampGenerator.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AUTimestampGenerator_h__
+#define __AUTimestampGenerator_h__
+
+#include <math.h>
+#include "CAHostTimeBase.h"
+#include <stdio.h>
+
+#define TSGFMT "0x%10qx"
+//#define TSGFMT "%10qd"
+
+// This class generates a continuously increasing series of timestamps based
+// on a series of potentially discontinuous timestamps (as can be delivered from
+// CoreAudio in the event of an overload or major engine change).
+// N.B.: "output" = downstream (source) timestamp
+// "input" = upstream (derived) timestamp
+class AUTimestampGenerator {
+public:
+ AUTimestampGenerator(bool hostTimeDiscontinuityCorrection = false)
+ {
+ mState.mStartInputAtZero = true;
+ mState.mBypassed = false;
+ mState.mHostTimeDiscontinuityCorrection = hostTimeDiscontinuityCorrection;
+#if DEBUG
+ mVerbosity = 0;
+ snprintf(mDebugName, sizeof(mDebugName), "tsg @ %p", this);
+#endif
+ // CAHostTimeBase should be used instead of the calls in <CoreAudio/HostTime.h>
+ // we make this call here to ensure that this is initialized, otherwise the first time
+ // you do actually call CAHostTimeBase to do work, can be on the render thread, and lead to unwanted VM faults
+ CAHostTimeBase::GetFrequency();
+ Reset();
+ }
+
+ void SetStartInputAtZero(bool b) { mState.mStartInputAtZero = b; }
+ bool GetStartInputAtZero() const { return mState.mStartInputAtZero; }
+
+ // bypassing is intended for a narrow special case. the upstream sample time will always be the same as the downstream time.
+ void SetBypassed(bool b) { mState.mBypassed = b; }
+ bool GetBypassed() const { return mState.mBypassed; }
+
+ // Call this to reset the timeline.
+ void Reset()
+ {
+ mState.mCurrentInputTime.mSampleTime = 0.;
+ mState.mNextInputSampleTime = 0.;
+ mState.mCurrentOutputTime.mSampleTime = 0.;
+ mState.mNextOutputSampleTime = 0.;
+ mState.mLastOutputTime.mFlags = 0;
+ mState.mRateScalarAdj = 1.;
+
+ mFirstTime = true;
+#if DEBUG
+ if (mVerbosity)
+ printf("%-20.20s: Reset\n", mDebugName);
+#endif
+ }
+
+ // Call this once per render cycle with the downstream timestamp.
+ // expectedDeltaFrames is the expected difference between the current and NEXT
+ // downstream timestamps.
+ // sampleRate is the OUTPUT sample rate.
+ void AddOutputTime(const AudioTimeStamp &inTimeStamp, Float64 expectedDeltaFrames, double outputSampleRate, double rateScalarAdj=1.0);
+
+ // Call this once per render cycle to obtain the upstream timestamp.
+ // framesToAdvance is the number of frames the input timeline is to be
+ // advanced during this render cycle.
+ // sampleRate is the INPUT sample rate.
+ const AudioTimeStamp & GenerateInputTime(Float64 framesToAdvance, double inputSampleRate, bool advanceHostTime = false);
+
+ // this can be called to override the setting of the next input sample time in GenerateInputTime
+ void Advance(Float64 framesToAdvance)
+ {
+#if DEBUG
+ if (mVerbosity > 1)
+ printf("%-20.20s: ADVANCE in = " TSGFMT " advance = " TSGFMT "\n", mDebugName, (SInt64)mState.mCurrentInputTime.mSampleTime, (SInt64)framesToAdvance);
+#endif
+ mState.mNextInputSampleTime = mState.mCurrentInputTime.mSampleTime + framesToAdvance;
+ }
+
+ struct State {
+ AudioTimeStamp mCurrentInputTime;
+ Float64 mNextInputSampleTime;
+ Float64 mNextOutputSampleTime;
+ Float64 mInputSampleTimeForOutputPull;
+
+ AudioTimeStamp mLastOutputTime;
+ AudioTimeStamp mCurrentOutputTime;
+
+ bool mStartInputAtZero; // if true, input timeline starts at 0, else it starts
+ // synced with the output timeline
+ bool mDiscontinuous;
+ bool mBypassed;
+ Float64 mDiscontinuityDeltaSamples;
+
+ double mRateScalarAdj;
+
+ bool mHostTimeDiscontinuityCorrection; // If true, propagate timestamp discontinuities using host time.
+ };
+
+ void GetState(State& outState) const { outState = mState; }
+ void SetState(State const& inState) { mState = inState; mFirstTime = false; }
+
+private:
+
+ struct State mState;
+
+ bool mFirstTime;
+
+#if DEBUG
+public:
+ int mVerbosity;
+ char mDebugName[64];
+#endif
+};
+
+
+#endif // __AUTimestampGenerator_h__