iPlug2 - C++ Audio Plug-in Framework
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 
29 BEGIN_IPLUG_NAMESPACE
30 
31 struct 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 
44 static const AudioUnitPropertyID kIPlugObjectPropertyID = UINT32_MAX-100;
45 
47 struct InstanceInfo
48 {
49  WDL_String mCocoaViewFactoryClassName;
50 };
51 
54 class IPlugAU : public IPlugAPIBase
55  , public IPlugProcessor
56 {
57  struct CStrLocal;
58  class CFStrLocal;
59 public:
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;
68  void InformHostOfParameterDetailsChange() 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
87 private:
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 
191 protected:
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 
202 private:
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 
224 IPlugAU* MakePlug(void* memory);
225 
228 template <class Plug, bool MIDIIn>
230 {
231 public:
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 
315 END_IPLUG_NAMESPACE
316 
317 #endif
318 
319 
The base class for IPlug Audio Processing.
The base class of an IPlug plug-in, which interacts with the different plug-in APIs.
Definition: IPlugAPIBase.h:42
Encapsulates a MIDI message and provides helper functions.
Definition: IPlugMidi.h:30
void PruneUninitializedPresets()
[AUV2 only] Removes any presets that weren&#39;t initialized
Manages a block of memory, for plug-in settings store/recall.
Definition: IPlugStructs.h:111
AudioUnit v2 Factory Class Template.
Definition: IPlugAU.h:229
The base class for IPlug Audio Processing.
The base class of an IPlug plug-in, which interacts with the different plug-in APIs.
virtual void GetTrackName(WDL_String &str) override
Get the name of the track that the plug-in is inserted on.
Definition: IPlugAU.h:71
AudioUnit v2 API base class for an IPlug plug-in.
Definition: IPlugAU.h:54
A struct for dealing with SysEx messages.
Definition: IPlugMidi.h:538