12#include <CoreMIDI/CoreMIDI.h>
16#include "dfx-au-utilities.h"
18#include "IPlugAU_ioconfig.h"
22#pragma mark - CFString and CString Utilities
24static inline CFStringRef MakeCFString(
const char* cStr)
26 return CFStringCreateWithCString(0, cStr, kCFStringEncodingUTF8);
29class IPlugAU::CFStrLocal
32 CFStrLocal(
const char* cStr)
34 mCFStr = MakeCFString(cStr);
42 CFStrLocal(
const CFStrLocal&) =
delete;
43 CFStrLocal& operator=(
const CFStrLocal&) =
delete;
45 CFStringRef Get() {
return mCFStr; }
51struct IPlugAU::CStrLocal : WDL_TypedBuf<char>
53 CStrLocal(CFStringRef cfStr)
57 Resize((
int) CFStringGetLength(cfStr) + 1);
58 CFStringGetCString(cfStr, Get(), GetSize(), kCFStringEncodingUTF8);
63#pragma mark - Utilities
65inline void IPlugAU::PutNumberInDict(CFMutableDictionaryRef pDict,
const char* key,
void* pNumber, CFNumberType type)
67 CFStrLocal cfKey(key);
68 CFNumberRef pValue = CFNumberCreate(0, type, pNumber);
69 CFDictionarySetValue(pDict, cfKey.Get(), pValue);
73inline void IPlugAU::PutStrInDict(CFMutableDictionaryRef pDict,
const char* key,
const char* value)
75 CFStrLocal cfKey(key);
76 CFStrLocal cfValue(value);
77 CFDictionarySetValue(pDict, cfKey.Get(), cfValue.Get());
80inline void IPlugAU::PutDataInDict(CFMutableDictionaryRef pDict,
const char* key,
IByteChunk* pChunk)
82 CFStrLocal cfKey(key);
83 CFDataRef pData = CFDataCreate(0, pChunk->
GetData(), pChunk->
Size());
84 CFDictionarySetValue(pDict, cfKey.Get(), pData);
88inline bool IPlugAU::GetNumberFromDict(CFDictionaryRef pDict,
const char* key,
void* pNumber, CFNumberType type)
90 CFStrLocal cfKey(key);
91 CFNumberRef pValue = (CFNumberRef) CFDictionaryGetValue(pDict, cfKey.Get());
94 CFNumberGetValue(pValue, type, pNumber);
100inline bool IPlugAU::GetStrFromDict(CFDictionaryRef pDict,
const char* key,
char* value)
102 CFStrLocal cfKey(key);
103 CFStringRef pValue = (CFStringRef) CFDictionaryGetValue(pDict, cfKey.Get());
106 CStrLocal cStr(pValue);
107 strcpy(value, cStr.Get());
114inline bool IPlugAU::GetDataFromDict(CFDictionaryRef pDict,
const char* key,
IByteChunk* pChunk)
116 CFStrLocal cfKey(key);
117 CFDataRef pData = (CFDataRef) CFDictionaryGetValue(pDict, cfKey.Get());
120 CFIndex n = CFDataGetLength(pData);
122 memcpy(pChunk->
GetData(), CFDataGetBytePtr(pData), n);
128#define kAudioUnitRemovePropertyListenerWithUserDataSelect 0x0012
130typedef AudioStreamBasicDescription STREAM_DESC;
132static void MakeDefaultASBD(STREAM_DESC* pASBD,
double sampleRate,
int nChannels,
bool interleaved)
134 memset(pASBD, 0,
sizeof(STREAM_DESC));
135 pASBD->mSampleRate = sampleRate;
136 pASBD->mFormatID = kAudioFormatLinearPCM;
137 pASBD->mFormatFlags = kAudioFormatFlagsCanonical;
138 pASBD->mBitsPerChannel = 8 *
sizeof(AudioSampleType);
139 pASBD->mChannelsPerFrame = nChannels;
140 pASBD->mFramesPerPacket = 1;
141 int nBytes =
sizeof(AudioSampleType);
148 pASBD->mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
150 pASBD->mBytesPerPacket = pASBD->mBytesPerFrame = nBytes;
154static int PtrListAddFromStack(WDL_PtrList<C>* pList, C* pStackInstance)
157 memcpy(pNew, pStackInstance,
sizeof(C));
159 return pList->GetSize() - 1;
163static int PtrListInitialize(WDL_PtrList<C>* pList,
int size)
165 for (
int i = 0; i < size; ++i)
168 memset(pNew, 0,
sizeof(C));
175 #define GET_COMP_PARAM(TYPE, IDX, NUM) *((TYPE*)&(params->params[NUM - IDX]))
177 #define GET_COMP_PARAM(TYPE, IDX, NUM) *((TYPE*)&(params->params[IDX]))
180#define NO_OP(select) case select: return badComponentSelector;
182#ifndef AU_NO_COMPONENT_ENTRY
183#pragma mark - COMPONENT MANAGER ENTRY POINT
185OSStatus IPlugAU::IPlugAUEntry(ComponentParameters *params,
void* pPlug)
187 int select = params->what;
189 Trace(TRACELOC,
"(%d:%s)", select, AUSelectStr(select));
191 if (select == kComponentOpenSelect)
194 IPlugAU* _this = MakePlug(
nullptr);
197 _this->mCI = GET_COMP_PARAM(ComponentInstance, 0, 1);
198 SetComponentInstanceStorage(_this->mCI, (Handle) _this);
204 if (select == kComponentCloseSelect)
206 _this->ClearConnections();
213 case kComponentVersionSelect:
217 case kAudioUnitInitializeSelect:
219 return DoInitialize(_this);
221 case kAudioUnitUninitializeSelect:
223 return DoUninitialize(_this);
225 case kAudioUnitGetPropertyInfoSelect:
227 AudioUnitPropertyID propID = GET_COMP_PARAM(AudioUnitPropertyID, 4, 5);
228 AudioUnitScope scope = GET_COMP_PARAM(AudioUnitScope, 3, 5);
229 AudioUnitElement element = GET_COMP_PARAM(AudioUnitElement, 2, 5);
230 UInt32* pDataSize = GET_COMP_PARAM(UInt32*, 1, 5);
231 Boolean* pWriteable = GET_COMP_PARAM(Boolean*, 0, 5);
233 return _this->DoGetPropertyInfo(_this, propID, scope, element, pDataSize, pWriteable);
235 case kAudioUnitGetPropertySelect:
237 AudioUnitPropertyID propID = GET_COMP_PARAM(AudioUnitPropertyID, 4, 5);
238 AudioUnitScope scope = GET_COMP_PARAM(AudioUnitScope, 3, 5);
239 AudioUnitElement element = GET_COMP_PARAM(AudioUnitElement, 2, 5);
240 void* pData = GET_COMP_PARAM(
void*, 1, 5);
241 UInt32* pDataSize = GET_COMP_PARAM(UInt32*, 0, 5);
243 return _this->DoGetProperty(_this, propID, scope, element, pData, pDataSize);
245 case kAudioUnitSetPropertySelect:
247 AudioUnitPropertyID propID = GET_COMP_PARAM(AudioUnitPropertyID, 4, 5);
248 AudioUnitScope scope = GET_COMP_PARAM(AudioUnitScope, 3, 5);
249 AudioUnitElement element = GET_COMP_PARAM(AudioUnitElement, 2, 5);
250 const void* pData = GET_COMP_PARAM(
const void*, 1, 5);
251 UInt32* pDataSize = GET_COMP_PARAM(UInt32*, 0, 5);
253 return _this->DoSetProperty(_this, propID, scope, element, pData, pDataSize);
255 case kAudioUnitAddPropertyListenerSelect:
257 AudioUnitPropertyID propID = GET_COMP_PARAM(AudioUnitPropertyID, 2, 3);
258 AudioUnitPropertyListenerProc proc = GET_COMP_PARAM(AudioUnitPropertyListenerProc, 1, 3);
259 void* userData = GET_COMP_PARAM(
void*, 0, 3);
261 return _this->DoAddPropertyListener(_this, propID, proc, userData);
263 case kAudioUnitRemovePropertyListenerSelect:
265 AudioUnitPropertyID propID = GET_COMP_PARAM(AudioUnitPropertyID, 1, 2);
266 AudioUnitPropertyListenerProc proc = GET_COMP_PARAM(AudioUnitPropertyListenerProc, 0, 2);
268 return _this->DoRemovePropertyListener(_this, propID, proc);
270 case kAudioUnitRemovePropertyListenerWithUserDataSelect:
272 AudioUnitPropertyID propID = GET_COMP_PARAM(AudioUnitPropertyID, 2, 3);
273 AudioUnitPropertyListenerProc proc = GET_COMP_PARAM(AudioUnitPropertyListenerProc, 1, 3);
274 void* userData = GET_COMP_PARAM(
void*, 0, 3);
276 return _this->DoRemovePropertyListenerWithUserData(_this, propID, proc, userData);
278 case kAudioUnitAddRenderNotifySelect:
280 AURenderCallback proc = GET_COMP_PARAM(AURenderCallback, 1, 2);
281 void* userData = GET_COMP_PARAM(
void*, 0, 2);
282 return _this->DoAddRenderNotify(_this, proc, userData);
284 case kAudioUnitRemoveRenderNotifySelect:
286 AURenderCallback proc = GET_COMP_PARAM(AURenderCallback, 1, 2);
287 void* userData = GET_COMP_PARAM(
void*, 0, 2);
288 return _this->DoRemoveRenderNotify(_this, proc, userData);
290 case kAudioUnitGetParameterSelect:
292 AudioUnitParameterID paramID = GET_COMP_PARAM(AudioUnitParameterID, 3, 4);
293 AudioUnitScope scope = GET_COMP_PARAM(AudioUnitScope, 2, 4);
294 AudioUnitElement element = GET_COMP_PARAM(AudioUnitElement, 1, 4);
295 AudioUnitParameterValue* pValue = GET_COMP_PARAM(AudioUnitParameterValue*, 0, 4);
296 return _this->DoGetParameter(_this, paramID, scope, element, pValue);
298 case kAudioUnitSetParameterSelect:
300 AudioUnitParameterID paramID = GET_COMP_PARAM(AudioUnitParameterID, 4, 5);
301 AudioUnitScope scope = GET_COMP_PARAM(AudioUnitScope, 3, 5);
302 AudioUnitElement element = GET_COMP_PARAM(AudioUnitElement, 2, 5);
303 AudioUnitParameterValue value = GET_COMP_PARAM(AudioUnitParameterValue, 1, 5);
304 UInt32 offset = GET_COMP_PARAM(UInt32, 0, 5);
305 return _this->DoSetParameter(_this, paramID, scope, element, value, offset);
307 case kAudioUnitScheduleParametersSelect:
309 AudioUnitParameterEvent* pEvent = GET_COMP_PARAM(AudioUnitParameterEvent*, 1, 2);
310 UInt32 nEvents = GET_COMP_PARAM(UInt32, 0, 2);
311 return _this->DoScheduleParameters(_this, pEvent, nEvents);
313 case kAudioUnitRenderSelect:
315 AudioUnitRenderActionFlags* pFlags = GET_COMP_PARAM(AudioUnitRenderActionFlags*, 4, 5);
316 const AudioTimeStamp* pTimestamp = GET_COMP_PARAM(AudioTimeStamp*, 3, 5);
317 UInt32 outputBusIdx = GET_COMP_PARAM(UInt32, 2, 5);
318 UInt32 nFrames = GET_COMP_PARAM(UInt32, 1, 5);
319 AudioBufferList* pBufferList = GET_COMP_PARAM(AudioBufferList*, 0, 5);
320 return _this->DoRender(_this, pFlags, pTimestamp, outputBusIdx, nFrames, pBufferList);
322 case kAudioUnitResetSelect:
324 return _this->DoReset(_this);
326 case kMusicDeviceMIDIEventSelect:
328 return _this->DoMIDIEvent(_this, GET_COMP_PARAM(UInt32, 3, 4), GET_COMP_PARAM(UInt32, 2, 4), GET_COMP_PARAM(UInt32, 1, 4), GET_COMP_PARAM(UInt32, 0, 4));
330 case kMusicDeviceSysExSelect:
332 return _this->DoSysEx(_this, GET_COMP_PARAM(UInt8*, 1, 2), GET_COMP_PARAM(UInt32, 0, 2));
334 case kMusicDevicePrepareInstrumentSelect:
338 case kMusicDeviceReleaseInstrumentSelect:
342 case kMusicDeviceStartNoteSelect:
346 NoteInstanceID* pNoteID = GET_COMP_PARAM(NoteInstanceID*, 2, 5);
347 UInt32 offset = GET_COMP_PARAM(UInt32, 1, 5);
348 MusicDeviceNoteParams* pNoteParams = GET_COMP_PARAM(MusicDeviceNoteParams*, 0, 5);
349 int note = (int) pNoteParams->mPitch;
352 msg.
MakeNoteOnMsg(note, (
int) pNoteParams->mVelocity, offset);
355 case kMusicDeviceStopNoteSelect:
358 NoteInstanceID noteID = GET_COMP_PARAM(NoteInstanceID, 1, 3);
359 UInt32 offset = GET_COMP_PARAM(UInt32, 0, 3);
365 case kComponentCanDoSelect:
367 switch (params->params[0])
369 case kAudioUnitInitializeSelect:
370 case kAudioUnitUninitializeSelect:
371 case kAudioUnitGetPropertyInfoSelect:
372 case kAudioUnitGetPropertySelect:
373 case kAudioUnitSetPropertySelect:
374 case kAudioUnitAddPropertyListenerSelect:
375 case kAudioUnitRemovePropertyListenerSelect:
376 case kAudioUnitGetParameterSelect:
377 case kAudioUnitSetParameterSelect:
378 case kAudioUnitResetSelect:
379 case kAudioUnitRenderSelect:
380 case kAudioUnitAddRenderNotifySelect:
381 case kAudioUnitRemoveRenderNotifySelect:
382 case kAudioUnitScheduleParametersSelect:
388 default:
return badComponentSelector;
393#pragma mark - GetChannelLayoutTags
395UInt32 IPlugAU::GetChannelLayoutTags(AudioUnitScope scope, AudioUnitElement element, AudioChannelLayoutTag* tags)
399 case kAudioUnitScope_Input:
400 case kAudioUnitScope_Output:
404 WDL_TypedBuf<uint64_t> foundTags;
406 for(
auto configIdx = 0; configIdx <
NIOConfigs(); configIdx++)
410 for(
auto busIdx = 0; busIdx < pConfig->
NBuses(dir); busIdx++)
412 if(busIdx == element)
414 WDL_TypedBuf<uint64_t> busTypes;
415 GetAPIBusTypeForChannelIOConfig(configIdx, dir, busIdx, pConfig, &busTypes);
418 for (
auto tag = 0; tag < busTypes.GetSize(); tag++)
420 if(foundTags.Find(busTypes.Get()[tag]) == -1)
421 foundTags.Add(busTypes.Get()[tag]);
429 for (
auto v = 0; v < foundTags.GetSize(); v++)
431 tags[v] = (AudioChannelLayoutTag) foundTags.Get()[v];
439 return foundTags.GetSize();
448#define ASSERT_SCOPE(reqScope) if (scope != reqScope) { return kAudioUnitErr_InvalidProperty; }
449#define ASSERT_ELEMENT(numElements) if (element >= numElements) { return kAudioUnitErr_InvalidElement; }
450#define ASSERT_INPUT_OR_GLOBAL_SCOPE \
451 if (scope != kAudioUnitScope_Input && scope != kAudioUnitScope_Global) { \
452 return kAudioUnitErr_InvalidProperty; \
455#define NO_OP(propID) case propID: return kAudioUnitErr_InvalidProperty;
458OSStatus IPlugAU::GetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element,
459 UInt32* pDataSize, Boolean* pWriteable,
void* pData)
461 Trace(TRACELOC,
"%s(%d:%s):(%d:%s):%d", (pData ?
"" :
"info:"), propID, AUPropertyStr(propID), scope, AUScopeStr(scope), element);
465 case kIPlugObjectPropertyID:
467 *pDataSize =
sizeof (
void*);
470 ((
void**) pData)[0] = (
void*)
static_cast<IPlugAPIBase*
> (
this);
477 case kAudioUnitProperty_ClassInfo:
479 *pDataSize =
sizeof(CFPropertyListRef);
482 CFPropertyListRef* pList = (CFPropertyListRef*) pData;
484 return GetState(pList);
488 case kAudioUnitProperty_MakeConnection:
490 ASSERT_INPUT_OR_GLOBAL_SCOPE;
491 *pDataSize =
sizeof(AudioUnitConnection);
495 case kAudioUnitProperty_SampleRate:
497 *pDataSize =
sizeof(Float64);
505 case kAudioUnitProperty_ParameterList:
507 int n = (scope == kAudioUnitScope_Global ? NParams() : 0);
508 *pDataSize = n *
sizeof(AudioUnitParameterID);
511 AudioUnitParameterID* pParamID = (AudioUnitParameterID*) pData;
512 for (
int i = 0; i < n; ++i, ++pParamID)
514 *pParamID = (AudioUnitParameterID) i;
519 case kAudioUnitProperty_ParameterInfo:
521 ASSERT_SCOPE(kAudioUnitScope_Global);
522 ASSERT_ELEMENT(NParams());
523 *pDataSize =
sizeof(AudioUnitParameterInfo);
526 AudioUnitParameterInfo* pInfo = (AudioUnitParameterInfo*) pData;
527 memset(pInfo, 0,
sizeof(AudioUnitParameterInfo));
528 pInfo->flags = kAudioUnitParameterFlag_CFNameRelease |
529 kAudioUnitParameterFlag_HasCFNameString |
530 kAudioUnitParameterFlag_IsWritable |
531 kAudioUnitParameterFlag_IsReadable;
533 #ifndef IPLUG1_COMPATIBILITY
534 pInfo->flags |= kAudioUnitParameterFlag_IsHighResolution;
538 IParam* pParam = GetParam(element);
540 if (!pParam->GetCanAutomate()) pInfo->flags |= kAudioUnitParameterFlag_NonRealTime;
541 if (pParam->GetMeta()) pInfo->flags |= kAudioUnitParameterFlag_IsElementMeta;
542 if (pParam->NDisplayTexts()) pInfo->flags |= kAudioUnitParameterFlag_ValuesHaveStrings;
544 const char* paramName = pParam->GetName();
545 pInfo->cfNameString = CFStringCreateWithCString(0, pParam->GetName(), kCFStringEncodingUTF8);
546 strcpy(pInfo->name, paramName);
548 switch (pParam->Type())
550 case IParam::kTypeBool:
551 pInfo->unit = kAudioUnitParameterUnit_Boolean;
553 case IParam::kTypeEnum:
555 case IParam::kTypeInt:
556 pInfo->unit = kAudioUnitParameterUnit_Indexed;
560 switch (pParam->Unit())
562 case IParam::kUnitPercentage: pInfo->unit = kAudioUnitParameterUnit_Percent;
break;
563 case IParam::kUnitSeconds: pInfo->unit = kAudioUnitParameterUnit_Seconds;
break;
564 case IParam::kUnitMilliseconds: pInfo->unit = kAudioUnitParameterUnit_Milliseconds;
break;
565 case IParam::kUnitSamples: pInfo->unit = kAudioUnitParameterUnit_SampleFrames;
break;
566 case IParam::kUnitDB: pInfo->unit = kAudioUnitParameterUnit_Decibels;
break;
567 case IParam::kUnitLinearGain: pInfo->unit = kAudioUnitParameterUnit_LinearGain;
break;
568 case IParam::kUnitPan: pInfo->unit = kAudioUnitParameterUnit_Pan;
break;
569 case IParam::kUnitPhase: pInfo->unit = kAudioUnitParameterUnit_Phase;
break;
570 case IParam::kUnitDegrees: pInfo->unit = kAudioUnitParameterUnit_Degrees;
break;
571 case IParam::kUnitMeters: pInfo->unit = kAudioUnitParameterUnit_Meters;
break;
572 case IParam::kUnitRate: pInfo->unit = kAudioUnitParameterUnit_Rate;
break;
573 case IParam::kUnitRatio: pInfo->unit = kAudioUnitParameterUnit_Ratio;
break;
574 case IParam::kUnitFrequency: pInfo->unit = kAudioUnitParameterUnit_Hertz;
break;
575 case IParam::kUnitOctaves: pInfo->unit = kAudioUnitParameterUnit_Octaves;
break;
576 case IParam::kUnitCents: pInfo->unit = kAudioUnitParameterUnit_Cents;
break;
577 case IParam::kUnitAbsCents: pInfo->unit = kAudioUnitParameterUnit_AbsoluteCents;
break;
578 case IParam::kUnitSemitones: pInfo->unit = kAudioUnitParameterUnit_RelativeSemiTones;
break;
579 case IParam::kUnitMIDINote: pInfo->unit = kAudioUnitParameterUnit_MIDINoteNumber;
break;
580 case IParam::kUnitMIDICtrlNum: pInfo->unit = kAudioUnitParameterUnit_MIDIController;
break;
581 case IParam::kUnitBPM: pInfo->unit = kAudioUnitParameterUnit_BPM;
break;
582 case IParam::kUnitBeats: pInfo->unit = kAudioUnitParameterUnit_Beats;
break;
584 case IParam::kUnitCustom:
586 if (CStringHasContents(pParam->GetCustomUnit()))
588 pInfo->unit = kAudioUnitParameterUnit_CustomUnit;
589 pInfo->unitName = CFStringCreateWithCString(0, pParam->GetCustomUnit(), kCFStringEncodingUTF8);
593 pInfo->unit = kAudioUnitParameterUnit_Generic;
601 switch (pParam->DisplayType())
603 case IParam::kDisplayLinear:
605 case IParam::kDisplaySquared:
606 pInfo->flags |= kAudioUnitParameterFlag_DisplaySquared;
608 case IParam::kDisplaySquareRoot:
609 pInfo->flags |= kAudioUnitParameterFlag_DisplaySquareRoot;
611 case IParam::kDisplayCubed:
612 pInfo->flags |= kAudioUnitParameterFlag_DisplayCubed;
614 case IParam::kDisplayCubeRoot:
615 pInfo->flags |= kAudioUnitParameterFlag_DisplayCubeRoot;
617 case IParam::kDisplayExp:
618 pInfo->flags |= kAudioUnitParameterFlag_DisplayExponential;
620 case IParam::kDisplayLog:
621 pInfo->flags |= kAudioUnitParameterFlag_DisplayLogarithmic;
625 pInfo->minValue = pParam->GetMin();
626 pInfo->maxValue = pParam->GetMax();
627 pInfo->defaultValue = pParam->GetDefault();
629 const char* paramGroupName = pParam->GetGroup();
631 if (CStringHasContents(paramGroupName))
644 pInfo->flags = pInfo->flags | kAudioUnitParameterFlag_HasClump;
645 pInfo->clumpID = clumpID;
651 case kAudioUnitProperty_FastDispatch:
653 return GetProc(element, pDataSize, pData);
655 NO_OP(kAudioUnitProperty_CPULoad);
656 case kAudioUnitProperty_StreamFormat:
658 BusChannels* pBus = GetBus(scope, element);
661 return kAudioUnitErr_InvalidProperty;
663 *pDataSize =
sizeof(STREAM_DESC);
667 int nChannels = pBus->mNHostChannels;
670 nChannels = pBus->mNPlugChannels;
672 STREAM_DESC* pASBD = (STREAM_DESC*) pData;
677 case kAudioUnitProperty_ElementCount:
679 *pDataSize =
sizeof(UInt32);
684 if (scope == kAudioUnitScope_Input)
685 n = mInBuses.GetSize();
686 else if (scope == kAudioUnitScope_Output)
687 n = mOutBuses.GetSize();
688 else if (scope == kAudioUnitScope_Global)
691 *((UInt32*) pData) = n;
695 case kAudioUnitProperty_Latency:
697 ASSERT_SCOPE(kAudioUnitScope_Global);
698 *pDataSize =
sizeof(Float64);
705 case kAudioUnitProperty_SupportedNumChannels:
707 ASSERT_SCOPE(kAudioUnitScope_Global);
709 *pDataSize = n *
sizeof(AUChannelInfo);
712 AUChannelInfo* pChInfo = (AUChannelInfo*) pData;
713 for (
int i = 0; i < n; ++i, ++pChInfo)
718 pChInfo->inChannels = -1;
723 pChInfo->outChannels = -1;
727 Trace(TRACELOC,
"IO:%d:%d", pChInfo->inChannels, pChInfo->outChannels);
733 case kAudioUnitProperty_MaximumFramesPerSlice:
735 ASSERT_SCOPE(kAudioUnitScope_Global);
736 *pDataSize =
sizeof(UInt32);
744 NO_OP(kAudioUnitProperty_SetExternalBuffer);
745 case kAudioUnitProperty_ParameterValueStrings:
747 ASSERT_SCOPE(kAudioUnitScope_Global);
748 ASSERT_ELEMENT(NParams());
750 IParam* pParam = GetParam(element);
751 int n = pParam->NDisplayTexts();
756 return kAudioUnitErr_InvalidProperty;
758 *pDataSize =
sizeof(CFArrayRef);
761 CFMutableArrayRef nameArray = CFArrayCreateMutable(kCFAllocatorDefault, n, &kCFTypeArrayCallBacks);
762 for (
int i = 0; i < n; ++i)
764 const char* str = pParam->GetDisplayText(i);
765 CFStrLocal cfstr(str);
766 CFArrayAppendValue(nameArray, cfstr.Get());
768 *((CFArrayRef*) pData) = nameArray;
773 case kAudioUnitProperty_GetUIComponentList:
775 return kAudioUnitErr_InvalidProperty;
777 case kAudioUnitProperty_AudioChannelLayout:
779 return kAudioUnitErr_InvalidPropertyValue;
781 case kAudioUnitProperty_TailTime:
783 ASSERT_SCOPE(kAudioUnitScope_Global);
784 *pDataSize =
sizeof(Float64);
789 *((Float64*) pData) = std::numeric_limits<double>::infinity();
795 case kAudioUnitProperty_BypassEffect:
797 ASSERT_SCOPE(kAudioUnitScope_Global);
799 *pDataSize =
sizeof(UInt32);
806 case kAudioUnitProperty_LastRenderError:
808 ASSERT_SCOPE(kAudioUnitScope_Global);
809 *pDataSize =
sizeof(OSStatus);
812 *((OSStatus*) pData) = noErr;
816 case kAudioUnitProperty_SetRenderCallback:
818 ASSERT_INPUT_OR_GLOBAL_SCOPE;
819 if (element >= mInBuses.GetSize())
821 return kAudioUnitErr_InvalidProperty;
823 *pDataSize =
sizeof(AURenderCallbackStruct);
827 case kAudioUnitProperty_FactoryPresets:
829 *pDataSize =
sizeof(CFArrayRef);
838 CFMutableArrayRef presetArray = CFArrayCreateMutable(kCFAllocatorDefault, n, &kCFAUPresetArrayCallBacks);
840 if (presetArray == NULL)
841 return coreFoundationUnknownErr;
843 for (i = 0; i < n; ++i)
846 CFAUPresetRef newPreset = CFAUPresetCreate(kCFAllocatorDefault, i, presetName.Get());
848 if (newPreset != NULL)
850 CFArrayAppendValue(presetArray, newPreset);
851 CFAUPresetRelease(newPreset);
855 *((CFMutableArrayRef*) pData) = presetArray;
859 NO_OP(kAudioUnitProperty_ContextName);
860 NO_OP(kAudioUnitProperty_RenderQuality);
861 case kAudioUnitProperty_HostCallbacks:
863 ASSERT_SCOPE(kAudioUnitScope_Global);
864 *pDataSize =
sizeof(HostCallbackInfo);
868 NO_OP(kAudioUnitProperty_InPlaceProcessing);
869 case kAudioUnitProperty_ElementName:
871 *pDataSize =
sizeof(CFStringRef);
880 case kAudioUnitScope_Input:
885 GetBusName(ERoute::kInput, (
int) element, nIn, busName);
886 *(CFStringRef*) pData = MakeCFString(busName.Get());
890 return kAudioUnitErr_InvalidElement;
892 case kAudioUnitScope_Output:
897 GetBusName(ERoute::kOutput, (
int) element, nOut, busName);
898 *(CFStringRef*) pData = MakeCFString(busName.Get());
902 return kAudioUnitErr_InvalidElement;
905 return kAudioUnitErr_InvalidScope;
908 return kAudioUnitErr_InvalidProperty;
910 case kAudioUnitProperty_CocoaUI:
914 *pDataSize =
sizeof(AudioUnitCocoaViewInfo);
917 AudioUnitCocoaViewInfo* pViewInfo = (AudioUnitCocoaViewInfo*) pData;
918 CFStrLocal bundleID(mBundleID.Get());
919 CFBundleRef pBundle = CFBundleGetBundleWithIdentifier(bundleID.Get());
920 CFURLRef url = CFBundleCopyBundleURL(pBundle);
921 pViewInfo->mCocoaAUViewBundleLocation = url;
922 pViewInfo->mCocoaAUViewClass[0] = CFStringCreateWithCString(0, mCocoaViewFactoryClassName.Get(), kCFStringEncodingUTF8);
926 return kAudioUnitErr_InvalidProperty;
928#pragma mark - kAudioUnitProperty_SupportedChannelLayoutTags
929 case kAudioUnitProperty_SupportedChannelLayoutTags:
933 UInt32 numLayouts = GetChannelLayoutTags(scope, element, NULL);
937 *pDataSize = numLayouts *
sizeof(AudioChannelLayoutTag);
950 AudioChannelLayoutTag* ptr = pData ?
static_cast<AudioChannelLayoutTag*
>(pData) : NULL;
952 if (GetChannelLayoutTags(scope, element, ptr))
958 return kAudioUnitErr_InvalidProperty;
960 case kAudioUnitProperty_ParameterIDName:
962 *pDataSize =
sizeof(AudioUnitParameterIDName);
963 if (pData && scope == kAudioUnitScope_Global)
965 AudioUnitParameterIDName* pIDName = (AudioUnitParameterIDName*) pData;
966 char cStr[MAX_PARAM_NAME_LEN];
968 strcpy(cStr, GetParam(pIDName->inID)->GetName());
970 if (pIDName->inDesiredLength != kAudioUnitParameterName_Full)
972 int n = std::min<int>(MAX_PARAM_NAME_LEN - 1, pIDName->inDesiredLength);
975 pIDName->outName = CFStringCreateWithCString(0, cStr, kCFStringEncodingUTF8);
979 case kAudioUnitProperty_ParameterClumpName:
981 *pDataSize =
sizeof (AudioUnitParameterNameInfo);
982 if (pData && scope == kAudioUnitScope_Global)
984 AudioUnitParameterNameInfo* parameterNameInfo = (AudioUnitParameterNameInfo*) pData;
985 int clumpId = parameterNameInfo->inID;
988 return kAudioUnitErr_PropertyNotInUse;
990 parameterNameInfo->outName = CFStringCreateWithCString(0,
GetParamGroupName(clumpId-1), kCFStringEncodingUTF8);
994 case kAudioUnitProperty_CurrentPreset:
995 case kAudioUnitProperty_PresentPreset:
997 *pDataSize =
sizeof(AUPreset);
1001 AUPreset* pAUPreset = (AUPreset*) pData;
1004 pAUPreset->presetName = CFStringCreateWithCString(0, name, kCFStringEncodingUTF8);
1008 NO_OP(kAudioUnitProperty_OfflineRender);
1009 case kAudioUnitProperty_ParameterStringFromValue:
1011 *pDataSize =
sizeof(AudioUnitParameterStringFromValue);
1012 if (pData && scope == kAudioUnitScope_Global)
1014 AudioUnitParameterStringFromValue* pSFV = (AudioUnitParameterStringFromValue*) pData;
1016 GetParam(pSFV->inParamID)->GetDisplay(*(pSFV->inValue),
false, mParamDisplayStr);
1018 pSFV->outString = MakeCFString((
const char*) mParamDisplayStr.Get());
1022 case kAudioUnitProperty_ParameterValueFromString:
1024 *pDataSize =
sizeof(AudioUnitParameterValueFromString);
1027 AudioUnitParameterValueFromString* pVFS = (AudioUnitParameterValueFromString*) pData;
1028 if (scope == kAudioUnitScope_Global)
1030 CStrLocal cStr(pVFS->inString);
1032 const double v = GetParam(pVFS->inParamID)->StringToValue(cStr.Get());
1034 pVFS->outValue = (AudioUnitParameterValue) v;
1039 NO_OP(kAudioUnitProperty_IconLocation);
1040 NO_OP(kAudioUnitProperty_PresentationLatency);
1041 NO_OP(kAudioUnitProperty_DependentParameters);
1042 case kMusicDeviceProperty_InstrumentCount:
1044 ASSERT_SCOPE(kAudioUnitScope_Global);
1047 *pDataSize =
sizeof(UInt32);
1050 *((UInt32*) pData) = 1;
1056 return kAudioUnitErr_InvalidProperty;
1060 NO_OP(kAudioUnitProperty_AUHostIdentifier);
1061 case kAudioUnitProperty_MIDIOutputCallbackInfo:
1065 *pWriteable =
false;
1066 *pDataSize =
sizeof(CFArrayRef);
1070 CFStringRef outputName = CFSTR(
"midiOut");
1071 CFArrayRef array = CFArrayCreate(kCFAllocatorDefault, (
const void**) &outputName, 1,
nullptr);
1072 CFRelease(outputName);
1073 *((CFArrayRef*) pData) = array;
1077 case kAudioUnitProperty_MIDIOutputCallback:
1082 *pDataSize =
sizeof(AUMIDIOutputCallbackStruct);
1087 NO_OP(kAudioUnitProperty_InputSamplesInOutput);
1088 NO_OP(kAudioUnitProperty_ClassInfoFromDocument);
1089 case kAudioUnitProperty_SupportsMPE:
1093 *pWriteable =
false;
1094 *pDataSize =
sizeof(UInt32);
1098 *((UInt32*) pData) = (
DoesMPE() ? 1 : 0);
1104 return kAudioUnitErr_InvalidProperty;
1109OSStatus IPlugAU::SetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element,
1110 UInt32* pDataSize,
const void* pData)
1112 Trace(TRACELOC,
"(%d:%s):(%d:%s):%d", propID, AUPropertyStr(propID), scope, AUScopeStr(scope), element);
1114 InformListeners(propID, scope);
1118 case kAudioUnitProperty_ClassInfo:
1120 return SetState(*((CFPropertyListRef*) pData));
1122 case kAudioUnitProperty_MakeConnection:
1124 ASSERT_INPUT_OR_GLOBAL_SCOPE;
1125 AudioUnitConnection* pAUC = (AudioUnitConnection*) pData;
1126 if (pAUC->destInputNumber >= mInBusConnections.GetSize())
1128 return kAudioUnitErr_InvalidProperty;
1130 InputBusConnection* pInBusConn = mInBusConnections.Get(pAUC->destInputNumber);
1131 memset(pInBusConn, 0,
sizeof(InputBusConnection));
1132 bool negotiatedOK =
true;
1133 if (pAUC->sourceAudioUnit)
1135 AudioStreamBasicDescription srcASBD;
1136 UInt32 size =
sizeof(AudioStreamBasicDescription);
1138 (AudioUnitGetProperty(pAUC->sourceAudioUnit, kAudioUnitProperty_StreamFormat,
1139 kAudioUnitScope_Output, pAUC->sourceOutputNumber, &srcASBD, &size) == noErr);
1141 (SetProperty(kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
1142 pAUC->destInputNumber, &size, &srcASBD) == noErr);
1145 pInBusConn->mUpstreamUnit = pAUC->sourceAudioUnit;
1146 pInBusConn->mUpstreamBusIdx = pAUC->sourceOutputNumber;
1148 AudioUnitRenderProc srcRenderProc;
1149 size =
sizeof(AudioUnitRenderProc);
1150 if (AudioUnitGetProperty(pAUC->sourceAudioUnit, kAudioUnitProperty_FastDispatch, kAudioUnitScope_Global, kAudioUnitRenderSelect,
1151 &srcRenderProc, &size) == noErr)
1154 pInBusConn->mUpstreamRenderProc = srcRenderProc;
1155 pInBusConn->mUpstreamObj = GetComponentInstanceStorage(pAUC->sourceAudioUnit);
1163 AssessInputConnections();
1164 return (negotiatedOK ? noErr : (
int) kAudioUnitErr_InvalidProperty);
1166 case kAudioUnitProperty_SampleRate:
1168 SetSampleRate(*((Float64*) pData));
1172 NO_OP(kAudioUnitProperty_ParameterList);
1173 NO_OP(kAudioUnitProperty_ParameterInfo);
1174 NO_OP(kAudioUnitProperty_FastDispatch);
1175 NO_OP(kAudioUnitProperty_CPULoad);
1176 case kAudioUnitProperty_StreamFormat:
1178 AudioStreamBasicDescription* pASBD = (AudioStreamBasicDescription*) pData;
1179 int nHostChannels = pASBD->mChannelsPerFrame;
1180 BusChannels* pBus = GetBus(scope, element);
1183 return kAudioUnitErr_InvalidProperty;
1185 pBus->mNHostChannels = 0;
1189 bool connectionOK = (nHostChannels > 0);
1190 connectionOK &= CheckLegalIO(scope, element, nHostChannels);
1191 connectionOK &= (pASBD->mFormatID == kAudioFormatLinearPCM && pASBD->mFormatFlags & kAudioFormatFlagsCanonical);
1193 Trace(TRACELOC,
"%d:%d:%s:%s:%s",
1194 nHostChannels, pBus->mNPlugChannels,
1195 (pASBD->mFormatID == kAudioFormatLinearPCM ?
"linearPCM" :
"notLinearPCM"),
1196 (pASBD->mFormatFlags & kAudioFormatFlagsCanonical ?
"canonicalFormat" :
"notCanonicalFormat"),
1197 (connectionOK ?
"connectionOK" :
"connectionNotOK"));
1202 pBus->mNHostChannels = nHostChannels;
1203 if (pASBD->mSampleRate > 0.0)
1205 SetSampleRate(pASBD->mSampleRate);
1210 pBus->mNHostChannels = pBus->mNPlugChannels;
1212 AssessInputConnections();
1213 return (connectionOK ? noErr : (
int) kAudioUnitErr_InvalidProperty);
1215 NO_OP(kAudioUnitProperty_ElementCount);
1216 NO_OP(kAudioUnitProperty_Latency);
1217 NO_OP(kAudioUnitProperty_SupportedNumChannels);
1218 case kAudioUnitProperty_MaximumFramesPerSlice:
1220 SetBlockSize(*((UInt32*) pData));
1221 ResizeScratchBuffers();
1225 NO_OP(kAudioUnitProperty_SetExternalBuffer);
1226 NO_OP(kAudioUnitProperty_ParameterValueStrings);
1227 NO_OP(kAudioUnitProperty_GetUIComponentList);
1228 NO_OP(kAudioUnitProperty_AudioChannelLayout);
1229 NO_OP(kAudioUnitProperty_TailTime);
1230 case kAudioUnitProperty_BypassEffect:
1232 const bool bypassed = *((UInt32*) pData) != 0;
1233 SetBypassed(bypassed);
1240 NO_OP(kAudioUnitProperty_LastRenderError);
1241 case kAudioUnitProperty_SetRenderCallback:
1243 ASSERT_SCOPE(kAudioUnitScope_Input);
1244 if (element >= mInBusConnections.GetSize())
1246 return kAudioUnitErr_InvalidProperty;
1248 InputBusConnection* pInBusConn = mInBusConnections.Get(element);
1249 memset(pInBusConn, 0,
sizeof(InputBusConnection));
1250 AURenderCallbackStruct* pCS = (AURenderCallbackStruct*) pData;
1251 if (pCS->inputProc != 0)
1253 pInBusConn->mUpstreamRenderCallback = *pCS;
1255 AssessInputConnections();
1258 NO_OP(kAudioUnitProperty_FactoryPresets);
1260 case kAudioUnitProperty_ContextName:
1262 CFStringRef inStr = *(CFStringRef*) pData;
1263 CFIndex bufferSize = CFStringGetLength(inStr) + 1;
1264 char buffer[bufferSize];
1265 if (CFStringGetCString(inStr, buffer, bufferSize, kCFStringEncodingUTF8))
1267 mTrackName.Set(buffer);
1271 NO_OP(kAudioUnitProperty_RenderQuality);
1272 case kAudioUnitProperty_HostCallbacks:
1274 ASSERT_SCOPE(kAudioUnitScope_Global);
1275 memcpy(&mHostCallbacks, pData,
sizeof(HostCallbackInfo));
1278 NO_OP(kAudioUnitProperty_InPlaceProcessing);
1279 NO_OP(kAudioUnitProperty_ElementName);
1280 NO_OP(kAudioUnitProperty_CocoaUI);
1281 NO_OP(kAudioUnitProperty_SupportedChannelLayoutTags);
1282 NO_OP(kAudioUnitProperty_ParameterIDName);
1283 NO_OP(kAudioUnitProperty_ParameterClumpName);
1284 case kAudioUnitProperty_CurrentPreset:
1285 case kAudioUnitProperty_PresentPreset:
1287 int presetIdx = ((AUPreset*) pData)->presetNumber;
1291 case kAudioUnitProperty_OfflineRender:
1293 const bool renderingOffline = (*((UInt32*) pData) != 0);
1294 SetRenderingOffline(renderingOffline);
1297 NO_OP(kAudioUnitProperty_ParameterStringFromValue);
1298 NO_OP(kAudioUnitProperty_ParameterValueFromString);
1299 NO_OP(kAudioUnitProperty_IconLocation);
1300 NO_OP(kAudioUnitProperty_PresentationLatency);
1301 NO_OP(kAudioUnitProperty_DependentParameters);
1302 case kAudioUnitProperty_AUHostIdentifier:
1306 AUHostIdentifier* pHostID = (AUHostIdentifier*) pData;
1307 CStrLocal hostStr(pHostID->hostName);
1308 int version = (pHostID->hostVersion.majorRev << 16)
1309 + ((pHostID->hostVersion.minorAndBugRev & 0xF0) << 4)
1310 + ((pHostID->hostVersion.minorAndBugRev & 0x0F));
1311 SetHost(hostStr.Get(), version);
1315 NO_OP(kAudioUnitProperty_MIDIOutputCallbackInfo);
1316 case kAudioUnitProperty_MIDIOutputCallback:
1318 mMidiCallback = *((AUMIDIOutputCallbackStruct*) pData);
1321 NO_OP(kAudioUnitProperty_InputSamplesInOutput);
1322 NO_OP(kAudioUnitProperty_ClassInfoFromDocument)
1325 return kAudioUnitErr_InvalidProperty;
1331const char* IPlugAU::AUInputTypeStr(
int type)
1333 switch ((IPlugAU::EAUInputType) type)
1335 case IPlugAU::eDirectFastProc:
return "DirectFastProc";
1336 case IPlugAU::eDirectNoFastProc:
return "DirectNoFastProc";
1337 case IPlugAU::eRenderCallback:
return "RenderCallback";
1338 case IPlugAU::eNotConnected:
1339 default:
return "NotConnected";
1343int IPlugAU::NHostChannelsConnected(WDL_PtrList<BusChannels>* pBuses,
int excludeIdx)
1346 int nCh = 0, n = pBuses->GetSize();
1348 for (
int i = 0; i < n; ++i)
1350 if (i != excludeIdx)
1352 int nHostChannels = pBuses->Get(i)->mNHostChannels;
1353 if (nHostChannels >= 0)
1355 nCh += nHostChannels;
1369bool IPlugAU::CheckLegalIO(AudioUnitScope scope,
int busIdx,
int nChannels)
1371 if (scope == kAudioUnitScope_Input)
1373 int nIn = std::max(NHostChannelsConnected(&mInBuses, busIdx), 0);
1374 int nOut = (mActive ? NHostChannelsConnected(&mOutBuses) : -1);
1375 return LegalIO(nIn + nChannels, nOut);
1379 int nIn = (mActive ? NHostChannelsConnected(&mInBuses) : -1);
1380 int nOut = std::max(NHostChannelsConnected(&mOutBuses, busIdx), 0);
1381 return LegalIO(nIn, nOut + nChannels);
1385bool IPlugAU::CheckLegalIO()
1387 int nIn = NHostChannelsConnected(&mInBuses);
1388 int nOut = NHostChannelsConnected(&mOutBuses);
1389 return ((!nIn && !nOut) ||
LegalIO(nIn, nOut));
1392void IPlugAU::AssessInputConnections()
1395 SetChannelConnections(ERoute::kInput, 0,
MaxNChannels(ERoute::kInput),
false);
1397 int nIn = mInBuses.GetSize();
1398 for (
int i = 0; i < nIn; ++i)
1400 BusChannels* pInBus = mInBuses.Get(i);
1401 InputBusConnection* pInBusConn = mInBusConnections.Get(i);
1404 if (pInBusConn->mUpstreamRenderProc && pInBusConn->mUpstreamObj)
1407 pInBusConn->mInputType = eDirectFastProc;
1409 else if (pInBusConn->mUpstreamUnit)
1412 pInBusConn->mInputType = eDirectNoFastProc;
1414 else if (pInBusConn->mUpstreamRenderCallback.inputProc)
1417 pInBusConn->mInputType = eRenderCallback;
1421 pInBusConn->mInputType = eNotConnected;
1423 pInBus->mConnected = (pInBusConn->mInputType != eNotConnected);
1425 int startChannelIdx = pInBus->mPlugChannelStartIdx;
1426 if (pInBus->mConnected)
1430 if (pInBus->mNHostChannels < 0)
1434 Trace(TRACELOC,
"AssumeChannels:%d", pInBus->mNPlugChannels);
1435 pInBus->mNHostChannels = pInBus->mNPlugChannels;
1437 int nConnected = pInBus->mNHostChannels;
1438 int nUnconnected = std::max(pInBus->mNPlugChannels - nConnected, 0);
1439 SetChannelConnections(ERoute::kInput, startChannelIdx, nConnected,
true);
1440 SetChannelConnections(ERoute::kInput, startChannelIdx + nConnected, nUnconnected,
false);
1443 Trace(TRACELOC,
"%d:%s:%d:%d:%d", i, AUInputTypeStr(pInBusConn->mInputType), startChannelIdx, pInBus->mNPlugChannels, pInBus->mNHostChannels);
1447OSStatus IPlugAU::GetState(CFPropertyListRef* ppPropList)
1453 CFMutableDictionaryRef pDict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1455 PutNumberInDict(pDict, kAUPresetVersionKey, &version, kCFNumberSInt32Type);
1456 PutNumberInDict(pDict, kAUPresetTypeKey, &(plugType), kCFNumberSInt32Type);
1457 PutNumberInDict(pDict, kAUPresetSubtypeKey, &(plugSubType), kCFNumberSInt32Type);
1458 PutNumberInDict(pDict, kAUPresetManufacturerKey, &(plugManID), kCFNumberSInt32Type);
1466 PutDataInDict(pDict, kAUPresetDataKey, &chunk);
1469 *ppPropList = pDict;
1474OSStatus IPlugAU::SetState(CFPropertyListRef pPropList)
1476 CFDictionaryRef pDict = (CFDictionaryRef) pPropList;
1477 int version, type, subtype, mfr;
1478 char presetName[64];
1479 if (!GetNumberFromDict(pDict, kAUPresetVersionKey, &version, kCFNumberSInt32Type) ||
1480 !GetNumberFromDict(pDict, kAUPresetTypeKey, &type, kCFNumberSInt32Type) ||
1481 !GetNumberFromDict(pDict, kAUPresetSubtypeKey, &subtype, kCFNumberSInt32Type) ||
1482 !GetNumberFromDict(pDict, kAUPresetManufacturerKey, &mfr, kCFNumberSInt32Type) ||
1483 !GetStrFromDict(pDict, kAUPresetNameKey, presetName) ||
1489 return kAudioUnitErr_InvalidPropertyValue;
1496 if (!GetDataFromDict(pDict, kAUPresetDataKey, &chunk))
1498 return kAudioUnitErr_InvalidPropertyValue;
1507 return kAudioUnitErr_InvalidPropertyValue;
1515OSStatus IPlugAU::GetProc(AudioUnitElement element, UInt32* pDataSize,
void* pData)
1517 Trace(TRACELOC,
"%s:(%d:%s)", (pData ?
"" :
"Info"), element, AUSelectStr(element));
1550 return kAudioUnitErr_InvalidElement;
1555OSStatus IPlugAU::GetParamProc(
void* pPlug, AudioUnitParameterID paramID, AudioUnitScope scope, AudioUnitElement element, AudioUnitParameterValue* pValue)
1557 Trace(TRACELOC,
"%d:(%d:%s):%d", paramID, scope, AUScopeStr(scope), element);
1559 ASSERT_SCOPE(kAudioUnitScope_Global);
1561 assert(_this != NULL);
1562 ENTER_PARAMS_MUTEX_STATIC
1563 *pValue = _this->GetParam(paramID)->Value();
1564 LEAVE_PARAMS_MUTEX_STATIC
1569OSStatus IPlugAU::SetParamProc(
void* pPlug, AudioUnitParameterID paramID, AudioUnitScope scope, AudioUnitElement element, AudioUnitParameterValue value, UInt32 offsetFrames)
1571 Trace(TRACELOC,
"%d:(%d:%s):%d", paramID, scope, AUScopeStr(scope), element);
1574 ASSERT_SCOPE(kAudioUnitScope_Global);
1576 ENTER_PARAMS_MUTEX_STATIC
1577 _this->GetParam(paramID)->Set(value);
1579 _this->OnParamChange(paramID, kHost, offsetFrames);
1580 LEAVE_PARAMS_MUTEX_STATIC
1584static inline OSStatus RenderCallback(AURenderCallbackStruct* pCB, AudioUnitRenderActionFlags* pFlags,
const AudioTimeStamp* pTimestamp, UInt32 inputBusIdx, UInt32 nFrames, AudioBufferList* pOutBufList)
1587 return pCB->inputProc(pCB->inputProcRefCon, pFlags, pTimestamp, inputBusIdx, nFrames, pOutBufList);
1591OSStatus IPlugAU::RenderProc(
void* pPlug, AudioUnitRenderActionFlags* pFlags,
const AudioTimeStamp* pTimestamp,
1592 UInt32 outputBusIdx, UInt32 nFrames, AudioBufferList* pOutBufList)
1594 Trace(TRACELOC,
"%d:%d:%d", outputBusIdx, pOutBufList->mNumberBuffers, nFrames);
1598 _this->mLastRenderTimeStamp = *pTimestamp;
1600 if (!(pTimestamp->mFlags & kAudioTimeStampSampleTimeValid) || nFrames > _this->
GetBlockSize())
1602 return kAudioUnitErr_InvalidPropertyValue;
1605 int nRenderNotify = _this->mRenderNotify.GetSize();
1609 for (
int i = 0; i < nRenderNotify; ++i)
1611 AURenderCallbackStruct* pRN = _this->mRenderNotify.Get(i);
1612 AudioUnitRenderActionFlags flags = kAudioUnitRenderAction_PreRender;
1613 RenderCallback(pRN, &flags, pTimestamp, outputBusIdx, nFrames, pOutBufList);
1617 int lastConnectedOutputBus = -1;
1621 double renderSampleTime = pTimestamp->mSampleTime;
1624 if (renderSampleTime != _this->mLastRenderSampleTime)
1627 AudioBufferList* pInBufList = (AudioBufferList*) &bufList;
1629 int nIn = _this->mInBuses.GetSize();
1631 for (
int i = 0; i < nIn; ++i)
1633 BusChannels* pInBus = _this->mInBuses.Get(i);
1634 InputBusConnection* pInBusConn = _this->mInBusConnections.Get(i);
1636 if (pInBus->mConnected)
1638 pInBufList->mNumberBuffers = pInBus->mNHostChannels;
1640 for (
int b = 0; b < pInBufList->mNumberBuffers; ++b)
1642 AudioBuffer* pBuffer = &(pInBufList->mBuffers[b]);
1643 pBuffer->mNumberChannels = 1;
1644 pBuffer->mDataByteSize = nFrames *
sizeof(AudioSampleType);
1648 AudioUnitRenderActionFlags flags = 0;
1651 switch (pInBusConn->mInputType)
1653 case eDirectFastProc:
1655 r = pInBusConn->mUpstreamRenderProc(pInBusConn->mUpstreamObj, &flags, pTimestamp, pInBusConn->mUpstreamBusIdx, nFrames, pInBufList);
1658 case eDirectNoFastProc:
1660 r = AudioUnitRender(pInBusConn->mUpstreamUnit, &flags, pTimestamp, pInBusConn->mUpstreamBusIdx, nFrames, pInBufList);
1663 case eRenderCallback:
1665 AudioSampleType* pScratchInput = _this->mInScratchBuf.Get() + pInBus->mPlugChannelStartIdx * nFrames;
1667 for (
int b = 0; b < pInBufList->mNumberBuffers; ++b, pScratchInput += nFrames)
1669 pInBufList->mBuffers[b].mData = pScratchInput;
1672 r = RenderCallback(&(pInBusConn->mUpstreamRenderCallback), &flags, pTimestamp, i, nFrames, pInBufList);
1684 for (
int c = 0, chIdx = pInBus->mPlugChannelStartIdx; c < pInBus->mNHostChannels; ++c, ++chIdx)
1686 _this->AttachBuffers(ERoute::kInput, chIdx, 1, (AudioSampleType**) &(pInBufList->mBuffers[c].mData), nFrames);
1690 _this->mLastRenderSampleTime = renderSampleTime;
1693 BusChannels* pOutBus = _this->mOutBuses.Get(outputBusIdx);
1696 if (!(pOutBus->mConnected) || pOutBus->mNHostChannels != pOutBufList->mNumberBuffers)
1698 const int startChannelIdx = pOutBus->mPlugChannelStartIdx;
1699 const int nConnected = std::max(pOutBus->mNHostChannels,
static_cast<int>(pOutBufList->mNumberBuffers));
1700 const int nUnconnected = std::max(pOutBus->mNPlugChannels - nConnected, 0);
1702 assert(nConnected > -1);
1703 _this->SetChannelConnections(ERoute::kOutput, startChannelIdx, nConnected,
true);
1704 _this->SetChannelConnections(ERoute::kOutput, startChannelIdx + nConnected, nUnconnected,
false);
1705 pOutBus->mConnected =
true;
1708 for (
int c = 0, chIdx = pOutBus->mPlugChannelStartIdx; c < pOutBufList->mNumberBuffers; ++c, ++chIdx)
1710 if (!(pOutBufList->mBuffers[c].mData))
1711 pOutBufList->mBuffers[c].mData = _this->mOutScratchBuf.Get() + chIdx * nFrames;
1713 _this->AttachBuffers(ERoute::kOutput, chIdx, 1, (AudioSampleType**) &(pOutBufList->mBuffers[c].mData), nFrames);
1716 for(
int i = 0; i < _this->mOutBuses.GetSize(); i++)
1718 if(!_this->mOutBuses.Get(i)->mConnected)
1724 lastConnectedOutputBus++;
1729 if (_this->
IsMidiEffect() || outputBusIdx == lastConnectedOutputBus)
1731 int busIdx1based = outputBusIdx+1;
1733 if (busIdx1based < _this->mOutBuses.GetSize() )
1735 int totalNumChans = _this->mOutBuses.GetSize() * 2;
1736 int nConnected = busIdx1based * 2;
1737 _this->SetChannelConnections(ERoute::kOutput, nConnected, totalNumChans - nConnected,
false);
1742 _this->PassThroughBuffers((AudioSampleType) 0, nFrames);
1746 if(_this->mMidiMsgsFromEditor.ElementsAvailable())
1750 while (_this->mMidiMsgsFromEditor.Pop(msg))
1756 _this->PreProcess();
1757 ENTER_PARAMS_MUTEX_STATIC
1758 _this->ProcessBuffers((AudioSampleType) 0, nFrames);
1759 LEAVE_PARAMS_MUTEX_STATIC
1765 for (
int i = 0; i < nRenderNotify; ++i)
1767 AURenderCallbackStruct* pRN = _this->mRenderNotify.Get(i);
1768 AudioUnitRenderActionFlags flags = kAudioUnitRenderAction_PostRender;
1769 RenderCallback(pRN, &flags, pTimestamp, outputBusIdx, nFrames, pOutBufList);
1773 _this->OutputSysexFromEditor();
1778IPlugAU::BusChannels* IPlugAU::GetBus(AudioUnitScope scope, AudioUnitElement busIdx)
1780 if (scope == kAudioUnitScope_Input && busIdx < mInBuses.GetSize())
1782 return mInBuses.Get(busIdx);
1784 if (scope == kAudioUnitScope_Output && busIdx < mOutBuses.GetSize())
1786 return mOutBuses.Get(busIdx);
1789 if (scope == kAudioUnitScope_Global && mOutBuses.GetSize())
1791 return mOutBuses.Get(busIdx);
1796void IPlugAU::ClearConnections()
1798 int nInBuses = mInBuses.GetSize();
1799 for (
int i = 0; i < nInBuses; ++i)
1801 BusChannels* pInBus = mInBuses.Get(i);
1802 pInBus->mConnected =
false;
1803 pInBus->mNHostChannels = -1;
1804 InputBusConnection* pInBusConn = mInBusConnections.Get(i);
1805 memset(pInBusConn, 0,
sizeof(InputBusConnection));
1807 int nOutBuses = mOutBuses.GetSize();
1808 for (
int i = 0; i < nOutBuses; ++i)
1810 BusChannels* pOutBus = mOutBuses.Get(i);
1811 pOutBus->mConnected =
false;
1812 pOutBus->mNHostChannels = -1;
1816#pragma mark - IPlugAU Constructor
1818IPlugAU::IPlugAU(
const InstanceInfo& info,
const Config& config)
1822 Trace(TRACELOC,
"%s", config.pluginName);
1824 memset(&mHostCallbacks, 0,
sizeof(HostCallbackInfo));
1825 memset(&mMidiCallback, 0,
sizeof(AUMIDIOutputCallbackStruct));
1827 mCocoaViewFactoryClassName.Set(info.mCocoaViewFactoryClassName.Get());
1829 int maxNIBuses = MaxNBuses(ERoute::kInput);
1832 if(maxNIBuses == 1 && MaxNChannelsForBus(kInput, 0) == 0)
1837 const int maxNOBuses = MaxNBuses(ERoute::kOutput);
1841 PtrListInitialize(&mInBusConnections, maxNIBuses);
1842 PtrListInitialize(&mInBuses, maxNIBuses);
1847 for (
auto bus = 0; bus < maxNIBuses; bus++)
1849 BusChannels* pInBus = mInBuses.Get(bus);
1850 pInBus->mNHostChannels = -1;
1851 pInBus->mPlugChannelStartIdx = chansSoFar;
1852 pInBus->mNPlugChannels = std::abs(MaxNChannelsForBus(ERoute::kInput, bus));
1854 chansSoFar += pInBus->mNPlugChannels;
1857 PtrListInitialize(&mOutBuses, maxNOBuses);
1861 for (
auto bus = 0; bus < maxNOBuses; bus++)
1863 BusChannels* pOutBus = mOutBuses.Get(bus);
1864 pOutBus->mNHostChannels = -1;
1865 pOutBus->mPlugChannelStartIdx = chansSoFar;
1866 pOutBus->mNPlugChannels = std::abs(MaxNChannelsForBus(ERoute::kOutput, bus));
1868 chansSoFar += pOutBus->mNPlugChannels;
1871 AssessInputConnections();
1873 SetBlockSize(DEFAULT_BLOCK_SIZE);
1874 ResizeScratchBuffers();
1882 mRenderNotify.Empty(
true);
1883 mInBuses.Empty(
true);
1884 mOutBuses.Empty(
true);
1885 mInBusConnections.Empty(
true);
1886 mPropertyListeners.Empty(
true);
1889void IPlugAU::SendAUEvent(AudioUnitEventType type, AudioComponentInstance ci,
int idx)
1891 AudioUnitEvent auEvent;
1892 memset(&auEvent, 0,
sizeof(AudioUnitEvent));
1893 auEvent.mEventType = type;
1894 auEvent.mArgument.mParameter.mAudioUnit = ci;
1895 auEvent.mArgument.mParameter.mParameterID = idx;
1896 auEvent.mArgument.mParameter.mScope = kAudioUnitScope_Global;
1897 auEvent.mArgument.mParameter.mElement = 0;
1898 AUEventListenerNotify(0, 0, &auEvent);
1903 Trace(TRACELOC,
"%d", idx);
1904 SendAUEvent(kAudioUnitEvent_BeginParameterChangeGesture, mCI, idx);
1909 Trace(TRACELOC,
"%d:%f", idx, normalizedValue);
1910 SendAUEvent(kAudioUnitEvent_ParameterValueChange, mCI, idx);
1915 Trace(TRACELOC,
"%d", idx);
1916 SendAUEvent(kAudioUnitEvent_EndParameterChangeGesture, mCI, idx);
1922 InformListeners(kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global);
1927 InformListeners(kAudioUnitProperty_ParameterList, kAudioUnitScope_Global);
1928 InformListeners(kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global);
1931void IPlugAU::PreProcess()
1935 if (mHostCallbacks.beatAndTempoProc)
1937 double currentBeat = 0.0, tempo = 0.0;
1938 mHostCallbacks.beatAndTempoProc(mHostCallbacks.hostUserData, ¤tBeat, &tempo);
1941 timeInfo.mTempo = tempo;
1943 timeInfo.mPPQPos = currentBeat;
1946 if (mHostCallbacks.transportStateProc)
1948 double samplePos = 0.0, loopStartBeat=0.0, loopEndBeat=0.0;
1949 Boolean playing, changed, looping;
1950 mHostCallbacks.transportStateProc(mHostCallbacks.hostUserData, &playing, &changed, &samplePos, &looping, &loopStartBeat, &loopEndBeat);
1952 if (samplePos > 0.0)
1953 timeInfo.mSamplePos = samplePos;
1955 if (loopStartBeat > 0.0)
1956 timeInfo.mCycleStart = loopStartBeat;
1958 if (loopEndBeat > 0.0)
1959 timeInfo.mCycleEnd = loopEndBeat;
1961 timeInfo.mTransportIsRunning = playing;
1962 timeInfo.mTransportLoopEnabled = looping;
1965 UInt32 sampleOffsetToNextBeat = 0, tsDenom = 0;
1967 double currentMeasureDownBeat = 0.0;
1969 if (mHostCallbacks.musicalTimeLocationProc)
1971 mHostCallbacks.musicalTimeLocationProc(mHostCallbacks.hostUserData, &sampleOffsetToNextBeat, &tsNum, &tsDenom, ¤tMeasureDownBeat);
1973 timeInfo.mNumerator = (int) tsNum;
1974 timeInfo.mDenominator = (int) tsDenom;
1975 if (currentMeasureDownBeat>0.0)
1976 timeInfo.mLastBar=currentMeasureDownBeat;
1979 SetTimeInfo(timeInfo);
1982void IPlugAU::ResizeScratchBuffers()
1987 mInScratchBuf.Resize(NInputs);
1988 mOutScratchBuf.Resize(NOutputs);
1989 memset(mInScratchBuf.Get(), 0, NInputs *
sizeof(AudioSampleType));
1990 memset(mOutScratchBuf.Get(), 0, NOutputs *
sizeof(AudioSampleType));
1993void IPlugAU::InformListeners(AudioUnitPropertyID propID, AudioUnitScope scope)
1996 int i, n = mPropertyListeners.GetSize();
1998 for (i = 0; i < n; ++i)
2000 PropertyListener* pListener = mPropertyListeners.Get(i);
2002 if (pListener->mPropID == propID)
2004 pListener->mListenerProc(pListener->mProcArgs, mCI, propID, scope, 0);
2012 InformListeners(kAudioUnitProperty_Latency, kAudioUnitScope_Global);
2018 if(mMidiCallback.midiOutputCallback ==
nullptr)
2021 MIDIPacketList packetList;
2023 packetList.packet[0].data[0] = msg.mStatus;
2024 packetList.packet[0].data[1] = msg.mData1;
2025 packetList.packet[0].data[2] = msg.mData2;
2026 packetList.packet[0].length = 3;
2027 packetList.packet[0].timeStamp = msg.mOffset;
2028 packetList.numPackets = 1;
2030 if(mMidiCallback.midiOutputCallback)
2032 OSStatus status = mMidiCallback.midiOutputCallback(mMidiCallback.userData, &mLastRenderTimeStamp, 0, &packetList);
2034 if (status == noErr)
2043 bool result =
false;
2045 if(mMidiCallback.midiOutputCallback ==
nullptr)
2048 WDL_HeapBuf heapBuf;
2049 MIDIPacketList* pPktlist = (MIDIPacketList*) heapBuf.ResizeOK(msgs.GetSize() * 3);
2050 MIDIPacket* pPkt = MIDIPacketListInit(pPktlist);
2051 ByteCount listSize = heapBuf.GetSize();
2054 for (
int i = 0; i < msgs.GetSize(); ++i, ++pMsg)
2056 pPkt = MIDIPacketListAdd(pPktlist, listSize, pPkt, pMsg->mOffset , 1, &pMsg->mStatus);
2057 pPkt = MIDIPacketListAdd(pPktlist, listSize, pPkt, pMsg->mOffset , 1, &pMsg->mData1);
2058 pPkt = MIDIPacketListAdd(pPktlist, listSize, pPkt, pMsg->mOffset , 1, &pMsg->mData2);
2061 if(mMidiCallback.midiOutputCallback)
2063 OSStatus status = mMidiCallback.midiOutputCallback(mMidiCallback.userData, &mLastRenderTimeStamp, 0, pPktlist);
2065 if (status == noErr)
2074 bool result =
false;
2076 if(mMidiCallback.midiOutputCallback ==
nullptr)
2079 assert(sysEx.mSize <= 65536);
2081 WDL_HeapBuf heapBuf;
2082 MIDIPacketList* pPktlist = (MIDIPacketList*) heapBuf.ResizeOK(sysEx.mSize);
2083 MIDIPacket* pPkt = MIDIPacketListInit(pPktlist);
2085 ByteCount listSize = heapBuf.GetSize();
2086 ByteCount bytesLeft = listSize;
2089 ByteCount packetSize = listSize < 256 ? listSize : 256;
2090 pPkt = MIDIPacketListAdd(pPktlist, listSize, pPkt, sysEx.mOffset , packetSize, sysEx.mData);
2091 bytesLeft -= packetSize;
2094 assert(pPkt !=
nullptr);
2096 if(mMidiCallback.midiOutputCallback)
2098 OSStatus status = mMidiCallback.midiOutputCallback(mMidiCallback.userData, &mLastRenderTimeStamp, 0, pPktlist);
2100 if (status == noErr)
2107void IPlugAU::OutputSysexFromEditor()
2110 if(mSysExDataFromEditor.ElementsAvailable())
2112 while (mSysExDataFromEditor.Pop(mSysexBuf))
2114 ISysEx smsg {mSysexBuf.mOffset, mSysexBuf.mData, mSysexBuf.mSize};
2120#pragma mark - IPlugAU Dispatch
2122#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2124static IPlugAU* GetPlug(
void *x)
2126 return (
IPlugAU*) &((AudioComponentPlugInInstance*) x)->mInstanceStorage;
2130OSStatus IPlugAU::AUMethodInitialize(
void* pSelf)
2132 return DoInitialize(GetPlug(pSelf));
2136OSStatus IPlugAU::AUMethodUninitialize(
void* pSelf)
2138 return DoUninitialize(GetPlug(pSelf));
2142OSStatus IPlugAU::AUMethodGetPropertyInfo(
void* pSelf, AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32* outDataSize, Boolean* outWritable)
2144 return DoGetPropertyInfo(GetPlug(pSelf), prop, scope, elem, outDataSize, outWritable);
2148OSStatus IPlugAU::AUMethodGetProperty(
void* pSelf, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
void* outData, UInt32* ioDataSize)
2150 return DoGetProperty(GetPlug(pSelf), inID, inScope, inElement, outData, ioDataSize);
2154OSStatus IPlugAU::AUMethodSetProperty(
void* pSelf, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
const void* inData, UInt32* inDataSize)
2156 return DoSetProperty(GetPlug(pSelf), inID, inScope, inElement, inData, inDataSize);
2160OSStatus IPlugAU::AUMethodAddPropertyListener(
void* pSelf, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* userData)
2162 return DoAddPropertyListener(GetPlug(pSelf), prop, proc, userData);
2166OSStatus IPlugAU::AUMethodRemovePropertyListener(
void* pSelf, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc)
2168 return DoRemovePropertyListener(GetPlug(pSelf), prop, proc);
2172OSStatus IPlugAU::AUMethodRemovePropertyListenerWithUserData(
void* pSelf, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* userData)
2174 return DoRemovePropertyListenerWithUserData(GetPlug(pSelf), prop, proc, userData);
2178OSStatus IPlugAU::AUMethodAddRenderNotify(
void* pSelf, AURenderCallback proc,
void* userData)
2180 return DoAddRenderNotify(GetPlug(pSelf), proc, userData);
2184OSStatus IPlugAU::AUMethodRemoveRenderNotify(
void* pSelf, AURenderCallback proc,
void* userData)
2186 return DoRemoveRenderNotify(GetPlug(pSelf), proc, userData);
2190OSStatus IPlugAU::AUMethodGetParameter(
void* pSelf, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue* value)
2192 return DoGetParameter(GetPlug(pSelf), param, scope, elem, value);
2196OSStatus IPlugAU::AUMethodSetParameter(
void* pSelf, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset)
2198 return DoSetParameter(GetPlug(pSelf), param, scope, elem, value, bufferOffset);
2202OSStatus IPlugAU::AUMethodScheduleParameters(
void* pSelf,
const AudioUnitParameterEvent *pEvent, UInt32 nEvents)
2204 return DoScheduleParameters(GetPlug(pSelf), pEvent, nEvents);
2208OSStatus IPlugAU::AUMethodRender(
void* pSelf, AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData)
2210 return DoRender(GetPlug(pSelf), ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
2214OSStatus IPlugAU::AUMethodReset(
void* pSelf, AudioUnitScope scope, AudioUnitElement elem)
2216 return DoReset(GetPlug(pSelf));
2220OSStatus IPlugAU::AUMethodMIDIEvent(
void* pSelf, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame)
2222 return DoMIDIEvent(GetPlug(pSelf), inStatus, inData1, inData2, inOffsetSampleFrame);
2226OSStatus IPlugAU::AUMethodSysEx(
void* pSelf,
const UInt8* inData, UInt32 inLength)
2228 return DoSysEx(GetPlug(pSelf), inData, inLength);
2233OSStatus IPlugAU::DoInitialize(
IPlugAU* _this)
2235 if (_this->
GetHost() == kHostUninit)
2237 CFBundleRef mainBundle = CFBundleGetMainBundle();
2238 CFStringRef
id =
nullptr;
2243 id = CFBundleGetIdentifier(mainBundle);
2244 CStrLocal versionStr((CFStringRef) CFBundleGetValueForInfoDictionaryKey(mainBundle, kCFBundleVersionKey));
2247 long ver = versionStr.Get() ? strtol(versionStr.Get(), &pStr, 10) : 0;
2248 long verRevMaj = versionStr.Get() && *pStr ? strtol(pStr + 1, &pStr, 10) : 0;
2249 long verRevMin = versionStr.Get() && *pStr ? strtol(pStr + 1, &pStr, 10) : 0;
2251 version = (int) (((ver & 0xFFFF) << 16) | ((verRevMaj & 0xFF) << 8) | (verRevMin & 0xFF));
2254 _this->
SetHost(
id ? CStrLocal(
id).Get() :
"", version);
2257 if (!(_this->CheckLegalIO()))
2259 return badComponentSelector;
2262 _this->mActive =
true;
2263 _this->OnParamReset(kReset);
2270OSStatus IPlugAU::DoUninitialize(
IPlugAU* _this)
2272 _this->mActive =
false;
2278OSStatus IPlugAU::DoGetPropertyInfo(
IPlugAU* _this, AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32* outDataSize, Boolean* outWritable)
2280 UInt32 dataSize = 0;
2283 outDataSize = &dataSize;
2288 outWritable = &writeable;
2290 *outWritable =
false;
2292 return _this->GetProperty(prop, scope, elem, outDataSize, outWritable, 0 );
2296OSStatus IPlugAU::DoGetProperty(
IPlugAU* _this, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
void* outData, UInt32 *ioDataSize)
2298 UInt32 dataSize = 0;
2301 ioDataSize = &dataSize;
2303 Boolean writeable =
false;
2305 return _this->GetProperty(inID, inScope, inElement, ioDataSize, &writeable, outData);
2309OSStatus IPlugAU::DoSetProperty(
IPlugAU* _this, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
const void* inData, UInt32* inDataSize)
2311 return _this->SetProperty(inID, inScope, inElement, inDataSize, inData);
2315OSStatus IPlugAU::DoAddPropertyListener(
IPlugAU* _this, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* userData)
2317 PropertyListener listener;
2318 listener.mPropID = prop;
2319 listener.mListenerProc = proc;
2320 listener.mProcArgs = userData;
2321 int i, n = _this->mPropertyListeners.GetSize();
2322 for (i = 0; i < n; ++i)
2324 PropertyListener* pListener = _this->mPropertyListeners.Get(i);
2325 if (listener.mPropID == pListener->mPropID && listener.mListenerProc == pListener->mListenerProc)
2330 PtrListAddFromStack(&(_this->mPropertyListeners), &listener);
2335OSStatus IPlugAU::DoRemovePropertyListener(
IPlugAU* _this, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc)
2337 PropertyListener listener;
2338 listener.mPropID = prop;
2339 listener.mListenerProc = proc;
2340 int i, n = _this->mPropertyListeners.GetSize();
2341 for (i = 0; i < n; ++i)
2343 PropertyListener* pListener = _this->mPropertyListeners.Get(i);
2344 if (listener.mPropID == pListener->mPropID && listener.mListenerProc == pListener->mListenerProc)
2346 _this->mPropertyListeners.Delete(i,
true);
2354OSStatus IPlugAU::DoRemovePropertyListenerWithUserData(
IPlugAU* _this, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* userData)
2356 PropertyListener listener;
2357 listener.mPropID = prop;
2358 listener.mListenerProc = proc;
2359 listener.mProcArgs = userData;
2360 int i, n = _this->mPropertyListeners.GetSize();
2361 for (i = 0; i < n; ++i)
2363 PropertyListener* pListener = _this->mPropertyListeners.Get(i);
2364 if (listener.mPropID == pListener->mPropID &&
2365 listener.mListenerProc == pListener->mListenerProc && listener.mProcArgs == pListener->mProcArgs)
2367 _this->mPropertyListeners.Delete(i,
true);
2375OSStatus IPlugAU::DoAddRenderNotify(
IPlugAU* _this, AURenderCallback proc,
void* userData)
2377 AURenderCallbackStruct acs;
2378 acs.inputProc = proc;
2379 acs.inputProcRefCon = userData;
2381 PtrListAddFromStack(&(_this->mRenderNotify), &acs);
2386OSStatus IPlugAU::DoRemoveRenderNotify(
IPlugAU* _this, AURenderCallback proc,
void* userData)
2389 AURenderCallbackStruct acs;
2390 acs.inputProc = proc;
2391 acs.inputProcRefCon = userData;
2393 int i, n = _this->mRenderNotify.GetSize();
2394 for (i = 0; i < n; ++i)
2396 AURenderCallbackStruct* pACS = _this->mRenderNotify.Get(i);
2397 if (acs.inputProc == pACS->inputProc)
2399 _this->mRenderNotify.Delete(i,
true);
2407OSStatus IPlugAU::DoGetParameter(
IPlugAU* _this, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue *value)
2410 return _this->GetParamProc(_this, param, scope, elem, value);
2414OSStatus IPlugAU::DoSetParameter(
IPlugAU* _this, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset)
2417 return _this->SetParamProc(_this, param, scope, elem, value, bufferOffset);
2421OSStatus IPlugAU::DoScheduleParameters(
IPlugAU* _this,
const AudioUnitParameterEvent *pEvent, UInt32 nEvents)
2424 for (
int i = 0; i < nEvents; ++i, ++pEvent)
2426 if (pEvent->eventType == kParameterEvent_Immediate)
2428 OSStatus r = SetParamProc(_this, pEvent->parameter, pEvent->scope, pEvent->element,
2429 pEvent->eventValues.immediate.value, pEvent->eventValues.immediate.bufferOffset);
2440OSStatus IPlugAU::DoRender(
IPlugAU* _this, AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData)
2442 return RenderProc(_this, ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
2446OSStatus IPlugAU::DoReset(
IPlugAU* _this)
2453OSStatus IPlugAU::DoMIDIEvent(
IPlugAU* _this, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame)
2458 msg.mStatus = inStatus;
2459 msg.mData1 = inData1;
2460 msg.mData2 = inData2;
2461 msg.mOffset = inOffsetSampleFrame;
2463 _this->mMidiMsgsFromProcessor.Push(msg);
2467 return badComponentSelector;
2471OSStatus IPlugAU::DoSysEx(
IPlugAU* _this,
const UInt8* inData, UInt32 inLength)
2476 sysex.mData = inData;
2477 sysex.mSize = inLength;
2483 return badComponentSelector;
Manages a block of memory, for plug-in settings store/recall.
uint8_t * GetData()
Gets a ptr to the chunk data.
int Size() const
Returns the current size of the chunk.
int Resize(int newSize)
Resizes the chunk.
The base class of an IPlug plug-in, which interacts with the different plug-in APIs.
virtual void SendParameterValueFromAPI(int paramIdx, double value, bool normalized)
This is called from the plug-in API class in order to update UI controls linked to plug-in parameters...
void SetHost(const char *host, int version)
Called to set the name of the current host, if known (calls on to HostSpecificInit() and OnHostIdenti...
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...
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.
bool GetTailIsInfinite() const
const IOConfig * GetIOConfig(int idx) const
virtual void ProcessMidiMsg(const IMidiMsg &msg)
Override this method to handle incoming MIDI messages.
bool LegalIO(int NInputChans, int NOutputChans) const
Check if a certain configuration of input channels and output channels is allowed based on the channe...
virtual void GetBusName(ERoute direction, int busIdx, int nBuses, WDL_String &str) const
Get the name for a particular bus.
virtual void SetLatency(int latency)
Call this if the latency of your plug-in changes after initialization (perhaps from OnReset() ) This ...
bool IsMidiEffect() const
bool IsInstrument() const
int MaxNBuses(ERoute direction, int *pConfigIdxWithTheMostBuses=nullptr) const
Used to determine the maximum number of input or output buses based on what was specified in the chan...
int GetAUPluginType() const
double GetSampleRate() const
virtual void ProcessSysEx(const ISysEx &msg)
Override this method to handle incoming MIDI System Exclusive (SysEx) messages.
int MaxNChannels(ERoute direction) const
virtual void OnActivate(bool active)
Override OnActivate() which should be called by the API class when a plug-in is "switched on" by the ...
virtual void OnReset()
Override this method in your plug-in class to do something prior to playback etc.
virtual int UnserializeState(const IByteChunk &chunk, int startPos)
Override this method to unserialize custom state data, if your plugin does state chunks.
int GetPluginVersion(bool decimal) const
Get the plug-in version number.
virtual bool SerializeState(IByteChunk &chunk) const
Override this method to serialize custom state data, if your plugin does state chunks.
int AddParamGroup(const char *name)
Called to add a parameter group name, when a unique group name is discovered.
int GetCurrentPresetIdx() const
Get the index of the current, active preset.
bool RestorePreset(int idx)
Restore a preset by index.
const char * GetParamGroupName(int idx) const
Get the parameter group name as a particular index.
const char * GetPresetName(int idx) const
Get the name a preset.
void PruneUninitializedPresets()
[AUV2 only] Removes any presets that weren't initialized
int NPresets() const
Gets the number of factory presets.
ERoute
Used to identify whether a bus/channel connection is an input or an output.
Encapsulates information about the host transport state.
Encapsulates a MIDI message and provides helper functions.
void MakeNoteOnMsg(int noteNumber, int velocity, int offset, int channel=0)
Make a Note On message.
void MakeNoteOffMsg(int noteNumber, int offset, int channel=0)
Make a Note Off message.
An IOConfig is used to store bus info for each input/output configuration defined in the channel io s...
int NBuses(ERoute direction) const
int GetTotalNChannels(ERoute direction) const
Get the total number of channels across all direction buses for this IOConfig.
bool ContainsWildcard(ERoute direction) const
A struct for dealing with SysEx messages.