20#include <CoreServices/CoreServices.h>
21#include <AudioUnit/AUComponent.h>
22#include <AudioUnit/AudioUnitProperties.h>
23#include <AudioToolbox/AudioUnitUtilities.h>
24#include <AvailabilityMacros.h>
31struct AudioComponentPlugInInstance
33 AudioComponentPlugInInstance() =
default;
34 AudioComponentPlugInInstance(
const AudioComponentPlugInInstance&) =
delete;
35 AudioComponentPlugInInstance& operator=(
const AudioComponentPlugInInstance&) =
delete;
37 AudioComponentPlugInInterface mPlugInInterface;
38 void* (*mConstruct)(
void* pMemory, AudioComponentInstance ci);
39 void (*mDestruct)(
void* pMemory);
41 UInt32 mInstanceStorage;
44static const AudioUnitPropertyID kIPlugObjectPropertyID = UINT32_MAX-100;
49 WDL_String mCocoaViewFactoryClassName;
60 IPlugAU(
const InstanceInfo& info,
const Config& config);
71 virtual void GetTrackName(WDL_String& str)
override { str = mTrackName; };
75 bool SendMidiMsgs(WDL_TypedBuf<IMidiMsg>& msgs)
override;
80 void OutputSysexFromEditor();
82 void ResizeScratchBuffers();
83 static const char* AUInputTypeStr(
int type);
84#ifndef AU_NO_COMPONENT_ENTRY
85 static OSStatus IPlugAUEntry(ComponentParameters* pParams,
void* pPlug);
102 int mPlugChannelStartIdx;
108 AudioBuffer mBuffers[AU_MAX_IO_CHANNELS];
111 struct InputBusConnection
114 AudioUnit mUpstreamUnit;
116 AudioUnitRenderProc mUpstreamRenderProc;
117 AURenderCallbackStruct mUpstreamRenderCallback;
118 EAUInputType mInputType;
121 struct PropertyListener
123 AudioUnitPropertyID mPropID;
124 AudioUnitPropertyListenerProc mListenerProc;
128 int NHostChannelsConnected(WDL_PtrList<BusChannels>* pBuses,
int excludeIdx = -1);
129 void ClearConnections();
130 BusChannels* GetBus(AudioUnitScope scope, AudioUnitElement busIdx);
131 bool CheckLegalIO(AudioUnitScope scope,
int busIdx,
int nChannels);
133 void AssessInputConnections();
135 UInt32 GetTagForNumChannels(
int numChannels);
136 UInt32 GetChannelLayoutTags(AudioUnitScope scope, AudioUnitElement element, AudioChannelLayoutTag* pTags);
138#pragma mark - Component Manager Methods
139 OSStatus GetPropertyInfo(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element, UInt32* pDataSize, Boolean* pWriteable);
140 OSStatus GetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element, UInt32* pDataSize, Boolean* pWriteable,
void* pData);
141 OSStatus SetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element, UInt32* pDataSize,
const void* pData);
143 OSStatus GetProc(AudioUnitElement element, UInt32* pDataSize,
void* pData);
144 virtual OSStatus GetState(CFPropertyListRef* ppPropList);
145 virtual OSStatus SetState(CFPropertyListRef pPropList);
146 void InformListeners(AudioUnitPropertyID propID, AudioUnitScope scope);
147 void SendAUEvent(AudioUnitEventType type, AudioComponentInstance ci,
int idx);
149 static OSStatus GetParamProc(
void* pPlug, AudioUnitParameterID paramID, AudioUnitScope scope, AudioUnitElement element, AudioUnitParameterValue* pValue);
150 static OSStatus SetParamProc(
void* pPlug, AudioUnitParameterID paramID, AudioUnitScope scope, AudioUnitElement element, AudioUnitParameterValue value, UInt32 offsetFrames);
151 static OSStatus RenderProc(
void* pPlug, AudioUnitRenderActionFlags* pFlags,
const AudioTimeStamp* pTimestamp, UInt32 outputBusIdx, UInt32 nFrames, AudioBufferList* pBufferList);
153#pragma mark - Dispatch Methods
154 static OSStatus AUMethodInitialize(
void* pSelf);
155 static OSStatus AUMethodUninitialize(
void* pSelf);
156 static OSStatus AUMethodGetPropertyInfo(
void* pSelf, AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32* pOutDataSize, Boolean* pOutWritable);
157 static OSStatus AUMethodGetProperty(
void* pSelf, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
void* pOutData, UInt32* pIODataSize);
158 static OSStatus AUMethodSetProperty(
void* pSelf, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
const void* pInData, UInt32* pInDataSize);
159 static OSStatus AUMethodAddPropertyListener(
void* pSelf, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* pUserData);
160 static OSStatus AUMethodRemovePropertyListener(
void* pSelf, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc);
161 static OSStatus AUMethodRemovePropertyListenerWithUserData(
void* pSelf, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* pUserData);
162 static OSStatus AUMethodAddRenderNotify(
void* pSelf, AURenderCallback proc,
void* pUserData);
163 static OSStatus AUMethodRemoveRenderNotify(
void* pSelf, AURenderCallback proc,
void* pUserData);
164 static OSStatus AUMethodGetParameter(
void* pSelf, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue *value);
165 static OSStatus AUMethodSetParameter(
void* pSelf, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset);
166 static OSStatus AUMethodScheduleParameters(
void* pSelf,
const AudioUnitParameterEvent *pEvent, UInt32 nEvents);
167 static OSStatus AUMethodRender(
void* pSelf, AudioUnitRenderActionFlags* pIOActionFlags,
const AudioTimeStamp* pInTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList* pIOData);
168 static OSStatus AUMethodReset(
void* pSelf, AudioUnitScope scope, AudioUnitElement elem);
169 static OSStatus AUMethodMIDIEvent(
void* pSelf, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame);
170 static OSStatus AUMethodSysEx(
void* pSelf,
const UInt8* pInData, UInt32 inLength);
172#pragma mark - Implementation Methods
173 static OSStatus DoInitialize(
IPlugAU* pPlug);
174 static OSStatus DoUninitialize(
IPlugAU* pPlug);
175 static OSStatus DoGetPropertyInfo(
IPlugAU* pPlug, AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32 *pOutDataSize, Boolean* pOutWritable);
176 static OSStatus DoGetProperty(
IPlugAU* pPlug, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
void *pOutData, UInt32* pIODataSize);
177 static OSStatus DoSetProperty(
IPlugAU* pPlug, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
const void* pInData, UInt32* pInDataSize);
178 static OSStatus DoAddPropertyListener(
IPlugAU* pPlug, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* pUserData);
179 static OSStatus DoRemovePropertyListener(
IPlugAU* pPlug, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc);
180 static OSStatus DoRemovePropertyListenerWithUserData(
IPlugAU* pPlug, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* pUserData);
181 static OSStatus DoAddRenderNotify(
IPlugAU* pPlug, AURenderCallback proc,
void* pUserData);
182 static OSStatus DoRemoveRenderNotify(
IPlugAU* pPlug, AURenderCallback proc,
void* pUserData);
183 static OSStatus DoGetParameter(
IPlugAU* pPlug, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue* pValue);
184 static OSStatus DoSetParameter(
IPlugAU* pPlug, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset);
185 static OSStatus DoScheduleParameters(
IPlugAU* pPlug,
const AudioUnitParameterEvent *pEvent, UInt32 nEvents);
186 static OSStatus DoRender(
IPlugAU* pPlug, AudioUnitRenderActionFlags* pIOActionFlags,
const AudioTimeStamp* pInTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList* pIOData);
187 static OSStatus DoReset(
IPlugAU* pPlug);
188 static OSStatus DoMIDIEvent(
IPlugAU* pPlug, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame);
189 static OSStatus DoSysEx(
IPlugAU* pPlug,
const UInt8 *inData, UInt32 inLength);
193#pragma mark - Utilities
195 static void PutNumberInDict(CFMutableDictionaryRef pDict,
const char* key,
void* pNumber, CFNumberType type);
196 static void PutStrInDict(CFMutableDictionaryRef pDict,
const char* key,
const char* value);
197 static void PutDataInDict(CFMutableDictionaryRef pDict,
const char* key,
IByteChunk* pChunk);
198 static bool GetNumberFromDict(CFDictionaryRef pDict,
const char* key,
void* pNumber, CFNumberType type);
199 static bool GetStrFromDict(CFDictionaryRef pDict,
const char* key,
char* value);
200 static bool GetDataFromDict(CFDictionaryRef pDict,
const char* key,
IByteChunk* pChunk);
206 bool mActive =
false;
207 double mLastRenderSampleTime = -1.0;
208 WDL_String mCocoaViewFactoryClassName;
209 AudioComponentInstance mCI =
nullptr;
210 HostCallbackInfo mHostCallbacks;
211 WDL_PtrList<BusChannels> mInBuses, mOutBuses;
212 WDL_PtrList<InputBusConnection> mInBusConnections;
213 WDL_PtrList<PropertyListener> mPropertyListeners;
214 WDL_TypedBuf<AudioSampleType> mInScratchBuf;
215 WDL_TypedBuf<AudioSampleType> mOutScratchBuf;
216 WDL_PtrList<AURenderCallbackStruct> mRenderNotify;
217 AUMIDIOutputCallbackStruct mMidiCallback;
218 AudioTimeStamp mLastRenderTimeStamp;
219 WDL_String mTrackName;
220 template <
class Plug,
bool DoesMIDIIn>
224IPlugAU* MakePlug(
void* memory);
228template <
class Plug,
bool MIDIIn>
232 static void* Construct(
void* pMemory, AudioComponentInstance compInstance)
234 return MakePlug(pMemory);
237 static void Destruct(
void* pMemory)
239 ((Plug*) pMemory)->~Plug();
242 static AudioComponentMethod Lookup(SInt16 selector)
244 using Method = AudioComponentMethod;
248 case kAudioUnitInitializeSelect:
return (Method)IPlugAU::AUMethodInitialize;
249 case kAudioUnitUninitializeSelect:
return (Method)IPlugAU::AUMethodUninitialize;
250 case kAudioUnitGetPropertyInfoSelect:
return (Method)IPlugAU::AUMethodGetPropertyInfo;
251 case kAudioUnitGetPropertySelect:
return (Method)IPlugAU::AUMethodGetProperty;
252 case kAudioUnitSetPropertySelect:
return (Method)IPlugAU::AUMethodSetProperty;
254 case kAudioUnitAddPropertyListenerSelect:
return (Method)IPlugAU::AUMethodAddPropertyListener;
255 case kAudioUnitRemovePropertyListenerSelect:
return (Method)IPlugAU::AUMethodRemovePropertyListener;
256 case kAudioUnitRemovePropertyListenerWithUserDataSelect:
257 return (Method)IPlugAU::AUMethodRemovePropertyListenerWithUserData;
259 case kAudioUnitAddRenderNotifySelect:
return (Method)IPlugAU::AUMethodAddRenderNotify;
260 case kAudioUnitRemoveRenderNotifySelect:
return (Method)IPlugAU::AUMethodRemoveRenderNotify;
261 case kAudioUnitGetParameterSelect:
return (Method)IPlugAU::AUMethodGetParameter;
262 case kAudioUnitSetParameterSelect:
return (Method)IPlugAU::AUMethodSetParameter;
263 case kAudioUnitScheduleParametersSelect:
return (Method)IPlugAU::AUMethodScheduleParameters;
264 case kAudioUnitRenderSelect:
return (Method)IPlugAU::AUMethodRender;
265 case kAudioUnitResetSelect:
return (Method)IPlugAU::AUMethodReset;
267 case kMusicDeviceMIDIEventSelect:
return MIDIIn ? (Method)IPlugAU::AUMethodMIDIEvent : NULL;
268 case kMusicDeviceSysExSelect:
return MIDIIn ? (Method)IPlugAU::AUMethodSysEx : NULL;
276 static OSStatus Open(
void* pSelf, AudioUnit compInstance)
278 AudioComponentPlugInInstance* acpi = (AudioComponentPlugInInstance*) pSelf;
281 (*acpi->mConstruct)(&acpi->mInstanceStorage, compInstance);
284 plug->mCI = compInstance;
290 static OSStatus Close(
void* pSelf)
292 AudioComponentPlugInInstance* acpi = (AudioComponentPlugInInstance*) pSelf;
294 (*acpi->mDestruct)(&acpi->mInstanceStorage);
299 static AudioComponentPlugInInterface* Factory(
const AudioComponentDescription* pInDesc)
301 void *ptr = malloc(offsetof(AudioComponentPlugInInstance, mInstanceStorage) +
sizeof(Plug));
302 AudioComponentPlugInInstance* acpi =
reinterpret_cast<AudioComponentPlugInInstance*
>(ptr);
303 acpi->mPlugInInterface.Open = Open;
304 acpi->mPlugInInterface.Close = Close;
305 acpi->mPlugInInterface.Lookup = Lookup;
306 acpi->mPlugInInterface.reserved = NULL;
307 acpi->mConstruct = Construct;
308 acpi->mDestruct = Destruct;
309 acpi->mPad[0] = NULL;
310 acpi->mPad[1] = NULL;
311 return (AudioComponentPlugInInterface*)acpi;
Manages a block of memory, for plug-in settings store/recall.
The base class of an IPlug plug-in, which interacts with the different plug-in APIs.
AudioUnit v2 Factory Class Template.
AudioUnit v2 API base class for an IPlug plug-in.
void BeginInformHostOfParamChange(int idx) override
Implemented by the API class, called by the UI (or by a delegate) at the beginning of a parameter cha...
void InformHostOfPresetChange() override
Implemented by the API class, called by the UI (etc) when the plug-in initiates a program/preset chan...
void InformHostOfParameterDetailsChange() override
Implemented by the API class, call this if you update parameter labels and hopefully the host should ...
void InformHostOfParamChange(int idx, double normalizedValue) override
Implemented by the API class, called by the UI via SetParameterValue() with the value of a parameter ...
bool SendMidiMsg(const IMidiMsg &msg) override
Send a single MIDI message // TODO: info about what thread should this be called on or not called on!
void EndInformHostOfParamChange(int idx) override
Implemented by the API class, called by the UI (or by a delegate) at the end of a parameter change ge...
virtual void GetTrackName(WDL_String &str) override
Get the name of the track that the plug-in is inserted on.
bool SendMidiMsgs(WDL_TypedBuf< IMidiMsg > &msgs) override
Send a collection of MIDI messages // TODO: info about what thread should this be called on or not ca...
void SetLatency(int samples) override
Call this if the latency of your plug-in changes after initialization (perhaps from OnReset() ) This ...
bool SendSysEx(const ISysEx &msg) override
Send a single MIDI System Exclusive (SysEx) message // TODO: info about what thread should this be ca...
The base class for IPlug Audio Processing.
void PruneUninitializedPresets()
[AUV2 only] Removes any presets that weren't initialized
Encapsulates a MIDI message and provides helper functions.
A struct for dealing with SysEx messages.