iPlug2 - C++ Audio Plug-in Framework
Loading...
Searching...
No Matches
IPlugAU.h
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the iPlug 2 library. Copyright (C) the iPlug 2 developers.
5
6 See LICENSE.txt for more info.
7
8 ==============================================================================
9*/
10
11#ifndef _IPLUGAPI_
12#define _IPLUGAPI_
13// Only load one API class!
14
20#include <CoreServices/CoreServices.h>
21#include <AudioUnit/AUComponent.h>
22#include <AudioUnit/AudioUnitProperties.h>
23#include <AudioToolbox/AudioUnitUtilities.h>
24#include <AvailabilityMacros.h>
25
26#include "IPlugAPIBase.h"
27#include "IPlugProcessor.h"
28
29BEGIN_IPLUG_NAMESPACE
30
31struct AudioComponentPlugInInstance
32{
33 AudioComponentPlugInInstance() = default;
34 AudioComponentPlugInInstance(const AudioComponentPlugInInstance&) = delete;
35 AudioComponentPlugInInstance& operator=(const AudioComponentPlugInInstance&) = delete;
36
37 AudioComponentPlugInInterface mPlugInInterface;
38 void* (*mConstruct)(void* pMemory, AudioComponentInstance ci);
39 void (*mDestruct)(void* pMemory);
40 void* mPad[2];
41 UInt32 mInstanceStorage;
42};
43
44static const AudioUnitPropertyID kIPlugObjectPropertyID = UINT32_MAX-100;
45
47struct InstanceInfo
48{
49 WDL_String mCocoaViewFactoryClassName;
50};
51
54class IPlugAU : public IPlugAPIBase
55 , public IPlugProcessor
56{
57 struct CStrLocal;
58 class CFStrLocal;
59public:
60 IPlugAU(const InstanceInfo& info, const Config& config);
61 ~IPlugAU();
62
63//IPlugAPIBase
64 void BeginInformHostOfParamChange(int idx) override;
65 void InformHostOfParamChange(int idx, double normalizedValue) override;
66 void EndInformHostOfParamChange(int idx) override;
67 void InformHostOfPresetChange() override;
69
71 virtual void GetTrackName(WDL_String& str) override { str = mTrackName; };
72
73//IPlugProcessor
74 bool SendMidiMsg(const IMidiMsg& msg) override;
75 bool SendMidiMsgs(WDL_TypedBuf<IMidiMsg>& msgs) override;
76 bool SendSysEx(const ISysEx& msg) override;
77 void SetLatency(int samples) override;
78
79//IPlugAU
80 void OutputSysexFromEditor();
81 void PreProcess();
82 void ResizeScratchBuffers();
83 static const char* AUInputTypeStr(int type);
84#ifndef AU_NO_COMPONENT_ENTRY
85 static OSStatus IPlugAUEntry(ComponentParameters* pParams, void* pPlug);
86#endif
87private:
88
89 enum EAUInputType
90 {
91 eNotConnected = 0,
92 eDirectFastProc,
93 eDirectNoFastProc,
94 eRenderCallback
95 };
96
97 struct BusChannels
98 {
99 bool mConnected;
100 int mNHostChannels;
101 int mNPlugChannels;
102 int mPlugChannelStartIdx;
103 };
104
105 struct BufferList
106 {
107 int mNumberBuffers;
108 AudioBuffer mBuffers[AU_MAX_IO_CHANNELS];
109 };
110
111 struct InputBusConnection
112 {
113 void* mUpstreamObj;
114 AudioUnit mUpstreamUnit;
115 int mUpstreamBusIdx;
116 AudioUnitRenderProc mUpstreamRenderProc;
117 AURenderCallbackStruct mUpstreamRenderCallback;
118 EAUInputType mInputType;
119 };
120
121 struct PropertyListener
122 {
123 AudioUnitPropertyID mPropID;
124 AudioUnitPropertyListenerProc mListenerProc;
125 void* mProcArgs;
126 };
127
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);
132 bool CheckLegalIO();
133 void AssessInputConnections();
134
135 UInt32 GetTagForNumChannels(int numChannels);
136 UInt32 GetChannelLayoutTags(AudioUnitScope scope, AudioUnitElement element, AudioChannelLayoutTag* pTags);
137
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);
142
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);
148
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);
152
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);
171
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);
190
191protected:
192
193#pragma mark - Utilities
194
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);
201
202private:
203
204#pragma mark -
205
206 bool mActive = false; // TODO: is this necessary? is it correct?
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>
221 friend class IPlugAUFactory;
222};
223
224IPlugAU* MakePlug(void* memory);
225
228template <class Plug, bool MIDIIn>
230{
231public:
232 static void* Construct(void* pMemory, AudioComponentInstance compInstance)
233 {
234 return MakePlug(pMemory);
235 }
236
237 static void Destruct(void* pMemory)
238 {
239 ((Plug*) pMemory)->~Plug();
240 }
241
242 static AudioComponentMethod Lookup(SInt16 selector)
243 {
244 using Method = AudioComponentMethod;
245
246 switch (selector)
247 {
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;
253
254 case kAudioUnitAddPropertyListenerSelect: return (Method)IPlugAU::AUMethodAddPropertyListener;
255 case kAudioUnitRemovePropertyListenerSelect: return (Method)IPlugAU::AUMethodRemovePropertyListener;
256 case kAudioUnitRemovePropertyListenerWithUserDataSelect:
257 return (Method)IPlugAU::AUMethodRemovePropertyListenerWithUserData;
258
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;
266
267 case kMusicDeviceMIDIEventSelect: return MIDIIn ? (Method)IPlugAU::AUMethodMIDIEvent : NULL;
268 case kMusicDeviceSysExSelect: return MIDIIn ? (Method)IPlugAU::AUMethodSysEx : NULL;
269
270 default:
271 break;
272 }
273 return NULL;
274 }
275
276 static OSStatus Open(void* pSelf, AudioUnit compInstance)
277 {
278 AudioComponentPlugInInstance* acpi = (AudioComponentPlugInInstance*) pSelf;
279 assert(acpi);
280
281 (*acpi->mConstruct)(&acpi->mInstanceStorage, compInstance);
282 IPlugAU* plug = (IPlugAU*) &acpi->mInstanceStorage;
283
284 plug->mCI = compInstance;
286
287 return noErr;
288 }
289
290 static OSStatus Close(void* pSelf)
291 {
292 AudioComponentPlugInInstance* acpi = (AudioComponentPlugInInstance*) pSelf;
293 assert(acpi);
294 (*acpi->mDestruct)(&acpi->mInstanceStorage);
295 free(pSelf);
296 return noErr;
297 }
298
299 static AudioComponentPlugInInterface* Factory(const AudioComponentDescription* pInDesc)
300 {
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;
312 }
313};
314
315END_IPLUG_NAMESPACE
316
317#endif
318
319
Manages a block of memory, for plug-in settings store/recall.
Definition: IPlugStructs.h:112
The base class of an IPlug plug-in, which interacts with the different plug-in APIs.
Definition: IPlugAPIBase.h:43
AudioUnit v2 Factory Class Template.
Definition: IPlugAU.h:230
AudioUnit v2 API base class for an IPlug plug-in.
Definition: IPlugAU.h:56
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...
Definition: IPlugAU.cpp:1898
void InformHostOfPresetChange() override
Implemented by the API class, called by the UI (etc) when the plug-in initiates a program/preset chan...
Definition: IPlugAU.cpp:1916
void InformHostOfParameterDetailsChange() override
Implemented by the API class, call this if you update parameter labels and hopefully the host should ...
Definition: IPlugAU.cpp:1922
void InformHostOfParamChange(int idx, double normalizedValue) override
Implemented by the API class, called by the UI via SetParameterValue() with the value of a parameter ...
Definition: IPlugAU.cpp:1904
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!
Definition: IPlugAU.cpp:2014
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...
Definition: IPlugAU.cpp:1910
virtual void GetTrackName(WDL_String &str) override
Get the name of the track that the plug-in is inserted on.
Definition: IPlugAU.h:71
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...
Definition: IPlugAU.cpp:2039
void SetLatency(int samples) override
Call this if the latency of your plug-in changes after initialization (perhaps from OnReset() ) This ...
Definition: IPlugAU.cpp:2007
bool SendSysEx(const ISysEx &msg) override
Send a single MIDI System Exclusive (SysEx) message // TODO: info about what thread should this be ca...
Definition: IPlugAU.cpp:2070
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.
Definition: IPlugMidi.h:31
A struct for dealing with SysEx messages.
Definition: IPlugMidi.h:539