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);
792 case kAudioUnitProperty_BypassEffect:
794 ASSERT_SCOPE(kAudioUnitScope_Global);
796 *pDataSize =
sizeof(UInt32);
803 case kAudioUnitProperty_LastRenderError:
805 ASSERT_SCOPE(kAudioUnitScope_Global);
806 *pDataSize =
sizeof(OSStatus);
809 *((OSStatus*) pData) = noErr;
813 case kAudioUnitProperty_SetRenderCallback:
815 ASSERT_INPUT_OR_GLOBAL_SCOPE;
816 if (element >= mInBuses.GetSize())
818 return kAudioUnitErr_InvalidProperty;
820 *pDataSize =
sizeof(AURenderCallbackStruct);
824 case kAudioUnitProperty_FactoryPresets:
826 *pDataSize =
sizeof(CFArrayRef);
835 CFMutableArrayRef presetArray = CFArrayCreateMutable(kCFAllocatorDefault, n, &kCFAUPresetArrayCallBacks);
837 if (presetArray == NULL)
838 return coreFoundationUnknownErr;
840 for (i = 0; i < n; ++i)
843 CFAUPresetRef newPreset = CFAUPresetCreate(kCFAllocatorDefault, i, presetName.Get());
845 if (newPreset != NULL)
847 CFArrayAppendValue(presetArray, newPreset);
848 CFAUPresetRelease(newPreset);
852 *((CFMutableArrayRef*) pData) = presetArray;
856 NO_OP(kAudioUnitProperty_ContextName);
857 NO_OP(kAudioUnitProperty_RenderQuality);
858 case kAudioUnitProperty_HostCallbacks:
860 ASSERT_SCOPE(kAudioUnitScope_Global);
861 *pDataSize =
sizeof(HostCallbackInfo);
865 NO_OP(kAudioUnitProperty_InPlaceProcessing);
866 case kAudioUnitProperty_ElementName:
868 *pDataSize =
sizeof(CFStringRef);
877 case kAudioUnitScope_Input:
882 GetBusName(ERoute::kInput, (
int) element, nIn, busName);
883 *(CFStringRef*) pData = MakeCFString(busName.Get());
887 return kAudioUnitErr_InvalidElement;
889 case kAudioUnitScope_Output:
894 GetBusName(ERoute::kOutput, (
int) element, nOut, busName);
895 *(CFStringRef*) pData = MakeCFString(busName.Get());
899 return kAudioUnitErr_InvalidElement;
902 return kAudioUnitErr_InvalidScope;
905 return kAudioUnitErr_InvalidProperty;
907 case kAudioUnitProperty_CocoaUI:
911 *pDataSize =
sizeof(AudioUnitCocoaViewInfo);
914 AudioUnitCocoaViewInfo* pViewInfo = (AudioUnitCocoaViewInfo*) pData;
915 CFStrLocal bundleID(mBundleID.Get());
916 CFBundleRef pBundle = CFBundleGetBundleWithIdentifier(bundleID.Get());
917 CFURLRef url = CFBundleCopyBundleURL(pBundle);
918 pViewInfo->mCocoaAUViewBundleLocation = url;
919 pViewInfo->mCocoaAUViewClass[0] = CFStringCreateWithCString(0, mCocoaViewFactoryClassName.Get(), kCFStringEncodingUTF8);
923 return kAudioUnitErr_InvalidProperty;
925#pragma mark - kAudioUnitProperty_SupportedChannelLayoutTags
926 case kAudioUnitProperty_SupportedChannelLayoutTags:
930 UInt32 numLayouts = GetChannelLayoutTags(scope, element, NULL);
934 *pDataSize = numLayouts *
sizeof(AudioChannelLayoutTag);
947 AudioChannelLayoutTag* ptr = pData ?
static_cast<AudioChannelLayoutTag*
>(pData) : NULL;
949 if (GetChannelLayoutTags(scope, element, ptr))
955 return kAudioUnitErr_InvalidProperty;
957 case kAudioUnitProperty_ParameterIDName:
959 *pDataSize =
sizeof(AudioUnitParameterIDName);
960 if (pData && scope == kAudioUnitScope_Global)
962 AudioUnitParameterIDName* pIDName = (AudioUnitParameterIDName*) pData;
963 char cStr[MAX_PARAM_NAME_LEN];
965 strcpy(cStr, GetParam(pIDName->inID)->GetName());
967 if (pIDName->inDesiredLength != kAudioUnitParameterName_Full)
969 int n = std::min<int>(MAX_PARAM_NAME_LEN - 1, pIDName->inDesiredLength);
972 pIDName->outName = CFStringCreateWithCString(0, cStr, kCFStringEncodingUTF8);
976 case kAudioUnitProperty_ParameterClumpName:
978 *pDataSize =
sizeof (AudioUnitParameterNameInfo);
979 if (pData && scope == kAudioUnitScope_Global)
981 AudioUnitParameterNameInfo* parameterNameInfo = (AudioUnitParameterNameInfo*) pData;
982 int clumpId = parameterNameInfo->inID;
985 return kAudioUnitErr_PropertyNotInUse;
987 parameterNameInfo->outName = CFStringCreateWithCString(0,
GetParamGroupName(clumpId-1), kCFStringEncodingUTF8);
991 case kAudioUnitProperty_CurrentPreset:
992 case kAudioUnitProperty_PresentPreset:
994 *pDataSize =
sizeof(AUPreset);
998 AUPreset* pAUPreset = (AUPreset*) pData;
1001 pAUPreset->presetName = CFStringCreateWithCString(0, name, kCFStringEncodingUTF8);
1005 NO_OP(kAudioUnitProperty_OfflineRender);
1006 case kAudioUnitProperty_ParameterStringFromValue:
1008 *pDataSize =
sizeof(AudioUnitParameterStringFromValue);
1009 if (pData && scope == kAudioUnitScope_Global)
1011 AudioUnitParameterStringFromValue* pSFV = (AudioUnitParameterStringFromValue*) pData;
1013 GetParam(pSFV->inParamID)->GetDisplay(*(pSFV->inValue),
false, mParamDisplayStr);
1015 pSFV->outString = MakeCFString((
const char*) mParamDisplayStr.Get());
1019 case kAudioUnitProperty_ParameterValueFromString:
1021 *pDataSize =
sizeof(AudioUnitParameterValueFromString);
1024 AudioUnitParameterValueFromString* pVFS = (AudioUnitParameterValueFromString*) pData;
1025 if (scope == kAudioUnitScope_Global)
1027 CStrLocal cStr(pVFS->inString);
1029 const double v = GetParam(pVFS->inParamID)->StringToValue(cStr.Get());
1031 pVFS->outValue = (AudioUnitParameterValue) v;
1036 NO_OP(kAudioUnitProperty_IconLocation);
1037 NO_OP(kAudioUnitProperty_PresentationLatency);
1038 NO_OP(kAudioUnitProperty_DependentParameters);
1039 case kMusicDeviceProperty_InstrumentCount:
1041 ASSERT_SCOPE(kAudioUnitScope_Global);
1044 *pDataSize =
sizeof(UInt32);
1047 *((UInt32*) pData) = 1;
1053 return kAudioUnitErr_InvalidProperty;
1057 NO_OP(kAudioUnitProperty_AUHostIdentifier);
1058 case kAudioUnitProperty_MIDIOutputCallbackInfo:
1062 *pWriteable =
false;
1063 *pDataSize =
sizeof(CFArrayRef);
1067 CFStringRef outputName = CFSTR(
"midiOut");
1068 CFArrayRef array = CFArrayCreate(kCFAllocatorDefault, (
const void**) &outputName, 1,
nullptr);
1069 CFRelease(outputName);
1070 *((CFArrayRef*) pData) = array;
1074 case kAudioUnitProperty_MIDIOutputCallback:
1079 *pDataSize =
sizeof(AUMIDIOutputCallbackStruct);
1084 NO_OP(kAudioUnitProperty_InputSamplesInOutput);
1085 NO_OP(kAudioUnitProperty_ClassInfoFromDocument);
1086 case kAudioUnitProperty_SupportsMPE:
1090 *pWriteable =
false;
1091 *pDataSize =
sizeof(UInt32);
1095 *((UInt32*) pData) = (
DoesMPE() ? 1 : 0);
1101 return kAudioUnitErr_InvalidProperty;
1106OSStatus IPlugAU::SetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element,
1107 UInt32* pDataSize,
const void* pData)
1109 Trace(TRACELOC,
"(%d:%s):(%d:%s):%d", propID, AUPropertyStr(propID), scope, AUScopeStr(scope), element);
1111 InformListeners(propID, scope);
1115 case kAudioUnitProperty_ClassInfo:
1117 return SetState(*((CFPropertyListRef*) pData));
1119 case kAudioUnitProperty_MakeConnection:
1121 ASSERT_INPUT_OR_GLOBAL_SCOPE;
1122 AudioUnitConnection* pAUC = (AudioUnitConnection*) pData;
1123 if (pAUC->destInputNumber >= mInBusConnections.GetSize())
1125 return kAudioUnitErr_InvalidProperty;
1127 InputBusConnection* pInBusConn = mInBusConnections.Get(pAUC->destInputNumber);
1128 memset(pInBusConn, 0,
sizeof(InputBusConnection));
1129 bool negotiatedOK =
true;
1130 if (pAUC->sourceAudioUnit)
1132 AudioStreamBasicDescription srcASBD;
1133 UInt32 size =
sizeof(AudioStreamBasicDescription);
1135 (AudioUnitGetProperty(pAUC->sourceAudioUnit, kAudioUnitProperty_StreamFormat,
1136 kAudioUnitScope_Output, pAUC->sourceOutputNumber, &srcASBD, &size) == noErr);
1138 (SetProperty(kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
1139 pAUC->destInputNumber, &size, &srcASBD) == noErr);
1142 pInBusConn->mUpstreamUnit = pAUC->sourceAudioUnit;
1143 pInBusConn->mUpstreamBusIdx = pAUC->sourceOutputNumber;
1145 AudioUnitRenderProc srcRenderProc;
1146 size =
sizeof(AudioUnitRenderProc);
1147 if (AudioUnitGetProperty(pAUC->sourceAudioUnit, kAudioUnitProperty_FastDispatch, kAudioUnitScope_Global, kAudioUnitRenderSelect,
1148 &srcRenderProc, &size) == noErr)
1151 pInBusConn->mUpstreamRenderProc = srcRenderProc;
1152 pInBusConn->mUpstreamObj = GetComponentInstanceStorage(pAUC->sourceAudioUnit);
1160 AssessInputConnections();
1161 return (negotiatedOK ? noErr : (
int) kAudioUnitErr_InvalidProperty);
1163 case kAudioUnitProperty_SampleRate:
1165 SetSampleRate(*((Float64*) pData));
1169 NO_OP(kAudioUnitProperty_ParameterList);
1170 NO_OP(kAudioUnitProperty_ParameterInfo);
1171 NO_OP(kAudioUnitProperty_FastDispatch);
1172 NO_OP(kAudioUnitProperty_CPULoad);
1173 case kAudioUnitProperty_StreamFormat:
1175 AudioStreamBasicDescription* pASBD = (AudioStreamBasicDescription*) pData;
1176 int nHostChannels = pASBD->mChannelsPerFrame;
1177 BusChannels* pBus = GetBus(scope, element);
1180 return kAudioUnitErr_InvalidProperty;
1182 pBus->mNHostChannels = 0;
1186 bool connectionOK = (nHostChannels > 0);
1187 connectionOK &= CheckLegalIO(scope, element, nHostChannels);
1188 connectionOK &= (pASBD->mFormatID == kAudioFormatLinearPCM && pASBD->mFormatFlags & kAudioFormatFlagsCanonical);
1190 Trace(TRACELOC,
"%d:%d:%s:%s:%s",
1191 nHostChannels, pBus->mNPlugChannels,
1192 (pASBD->mFormatID == kAudioFormatLinearPCM ?
"linearPCM" :
"notLinearPCM"),
1193 (pASBD->mFormatFlags & kAudioFormatFlagsCanonical ?
"canonicalFormat" :
"notCanonicalFormat"),
1194 (connectionOK ?
"connectionOK" :
"connectionNotOK"));
1199 pBus->mNHostChannels = nHostChannels;
1200 if (pASBD->mSampleRate > 0.0)
1202 SetSampleRate(pASBD->mSampleRate);
1207 pBus->mNHostChannels = pBus->mNPlugChannels;
1209 AssessInputConnections();
1210 return (connectionOK ? noErr : (
int) kAudioUnitErr_InvalidProperty);
1212 NO_OP(kAudioUnitProperty_ElementCount);
1213 NO_OP(kAudioUnitProperty_Latency);
1214 NO_OP(kAudioUnitProperty_SupportedNumChannels);
1215 case kAudioUnitProperty_MaximumFramesPerSlice:
1217 SetBlockSize(*((UInt32*) pData));
1218 ResizeScratchBuffers();
1222 NO_OP(kAudioUnitProperty_SetExternalBuffer);
1223 NO_OP(kAudioUnitProperty_ParameterValueStrings);
1224 NO_OP(kAudioUnitProperty_GetUIComponentList);
1225 NO_OP(kAudioUnitProperty_AudioChannelLayout);
1226 NO_OP(kAudioUnitProperty_TailTime);
1227 case kAudioUnitProperty_BypassEffect:
1229 const bool bypassed = *((UInt32*) pData) != 0;
1230 SetBypassed(bypassed);
1237 NO_OP(kAudioUnitProperty_LastRenderError);
1238 case kAudioUnitProperty_SetRenderCallback:
1240 ASSERT_SCOPE(kAudioUnitScope_Input);
1241 if (element >= mInBusConnections.GetSize())
1243 return kAudioUnitErr_InvalidProperty;
1245 InputBusConnection* pInBusConn = mInBusConnections.Get(element);
1246 memset(pInBusConn, 0,
sizeof(InputBusConnection));
1247 AURenderCallbackStruct* pCS = (AURenderCallbackStruct*) pData;
1248 if (pCS->inputProc != 0)
1250 pInBusConn->mUpstreamRenderCallback = *pCS;
1252 AssessInputConnections();
1255 NO_OP(kAudioUnitProperty_FactoryPresets);
1257 case kAudioUnitProperty_ContextName:
1259 CFStringRef inStr = *(CFStringRef*) pData;
1260 CFIndex bufferSize = CFStringGetLength(inStr) + 1;
1261 char buffer[bufferSize];
1262 if (CFStringGetCString(inStr, buffer, bufferSize, kCFStringEncodingUTF8))
1264 mTrackName.Set(buffer);
1268 NO_OP(kAudioUnitProperty_RenderQuality);
1269 case kAudioUnitProperty_HostCallbacks:
1271 ASSERT_SCOPE(kAudioUnitScope_Global);
1272 memcpy(&mHostCallbacks, pData,
sizeof(HostCallbackInfo));
1275 NO_OP(kAudioUnitProperty_InPlaceProcessing);
1276 NO_OP(kAudioUnitProperty_ElementName);
1277 NO_OP(kAudioUnitProperty_CocoaUI);
1278 NO_OP(kAudioUnitProperty_SupportedChannelLayoutTags);
1279 NO_OP(kAudioUnitProperty_ParameterIDName);
1280 NO_OP(kAudioUnitProperty_ParameterClumpName);
1281 case kAudioUnitProperty_CurrentPreset:
1282 case kAudioUnitProperty_PresentPreset:
1284 int presetIdx = ((AUPreset*) pData)->presetNumber;
1288 case kAudioUnitProperty_OfflineRender:
1290 const bool renderingOffline = (*((UInt32*) pData) != 0);
1291 SetRenderingOffline(renderingOffline);
1294 NO_OP(kAudioUnitProperty_ParameterStringFromValue);
1295 NO_OP(kAudioUnitProperty_ParameterValueFromString);
1296 NO_OP(kAudioUnitProperty_IconLocation);
1297 NO_OP(kAudioUnitProperty_PresentationLatency);
1298 NO_OP(kAudioUnitProperty_DependentParameters);
1299 case kAudioUnitProperty_AUHostIdentifier:
1303 AUHostIdentifier* pHostID = (AUHostIdentifier*) pData;
1304 CStrLocal hostStr(pHostID->hostName);
1305 int version = (pHostID->hostVersion.majorRev << 16)
1306 + ((pHostID->hostVersion.minorAndBugRev & 0xF0) << 4)
1307 + ((pHostID->hostVersion.minorAndBugRev & 0x0F));
1308 SetHost(hostStr.Get(), version);
1312 NO_OP(kAudioUnitProperty_MIDIOutputCallbackInfo);
1313 case kAudioUnitProperty_MIDIOutputCallback:
1315 mMidiCallback = *((AUMIDIOutputCallbackStruct*) pData);
1318 NO_OP(kAudioUnitProperty_InputSamplesInOutput);
1319 NO_OP(kAudioUnitProperty_ClassInfoFromDocument)
1322 return kAudioUnitErr_InvalidProperty;
1328const char* IPlugAU::AUInputTypeStr(
int type)
1330 switch ((IPlugAU::EAUInputType) type)
1332 case IPlugAU::eDirectFastProc:
return "DirectFastProc";
1333 case IPlugAU::eDirectNoFastProc:
return "DirectNoFastProc";
1334 case IPlugAU::eRenderCallback:
return "RenderCallback";
1335 case IPlugAU::eNotConnected:
1336 default:
return "NotConnected";
1340int IPlugAU::NHostChannelsConnected(WDL_PtrList<BusChannels>* pBuses,
int excludeIdx)
1343 int nCh = 0, n = pBuses->GetSize();
1345 for (
int i = 0; i < n; ++i)
1347 if (i != excludeIdx)
1349 int nHostChannels = pBuses->Get(i)->mNHostChannels;
1350 if (nHostChannels >= 0)
1352 nCh += nHostChannels;
1366bool IPlugAU::CheckLegalIO(AudioUnitScope scope,
int busIdx,
int nChannels)
1368 if (scope == kAudioUnitScope_Input)
1370 int nIn = std::max(NHostChannelsConnected(&mInBuses, busIdx), 0);
1371 int nOut = (mActive ? NHostChannelsConnected(&mOutBuses) : -1);
1372 return LegalIO(nIn + nChannels, nOut);
1376 int nIn = (mActive ? NHostChannelsConnected(&mInBuses) : -1);
1377 int nOut = std::max(NHostChannelsConnected(&mOutBuses, busIdx), 0);
1378 return LegalIO(nIn, nOut + nChannels);
1382bool IPlugAU::CheckLegalIO()
1384 int nIn = NHostChannelsConnected(&mInBuses);
1385 int nOut = NHostChannelsConnected(&mOutBuses);
1386 return ((!nIn && !nOut) ||
LegalIO(nIn, nOut));
1389void IPlugAU::AssessInputConnections()
1392 SetChannelConnections(ERoute::kInput, 0,
MaxNChannels(ERoute::kInput),
false);
1394 int nIn = mInBuses.GetSize();
1395 for (
int i = 0; i < nIn; ++i)
1397 BusChannels* pInBus = mInBuses.Get(i);
1398 InputBusConnection* pInBusConn = mInBusConnections.Get(i);
1401 if (pInBusConn->mUpstreamRenderProc && pInBusConn->mUpstreamObj)
1404 pInBusConn->mInputType = eDirectFastProc;
1406 else if (pInBusConn->mUpstreamUnit)
1409 pInBusConn->mInputType = eDirectNoFastProc;
1411 else if (pInBusConn->mUpstreamRenderCallback.inputProc)
1414 pInBusConn->mInputType = eRenderCallback;
1418 pInBusConn->mInputType = eNotConnected;
1420 pInBus->mConnected = (pInBusConn->mInputType != eNotConnected);
1422 int startChannelIdx = pInBus->mPlugChannelStartIdx;
1423 if (pInBus->mConnected)
1427 if (pInBus->mNHostChannels < 0)
1431 Trace(TRACELOC,
"AssumeChannels:%d", pInBus->mNPlugChannels);
1432 pInBus->mNHostChannels = pInBus->mNPlugChannels;
1434 int nConnected = pInBus->mNHostChannels;
1435 int nUnconnected = std::max(pInBus->mNPlugChannels - nConnected, 0);
1436 SetChannelConnections(ERoute::kInput, startChannelIdx, nConnected,
true);
1437 SetChannelConnections(ERoute::kInput, startChannelIdx + nConnected, nUnconnected,
false);
1440 Trace(TRACELOC,
"%d:%s:%d:%d:%d", i, AUInputTypeStr(pInBusConn->mInputType), startChannelIdx, pInBus->mNPlugChannels, pInBus->mNHostChannels);
1444OSStatus IPlugAU::GetState(CFPropertyListRef* ppPropList)
1450 CFMutableDictionaryRef pDict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1452 PutNumberInDict(pDict, kAUPresetVersionKey, &version, kCFNumberSInt32Type);
1453 PutNumberInDict(pDict, kAUPresetTypeKey, &(plugType), kCFNumberSInt32Type);
1454 PutNumberInDict(pDict, kAUPresetSubtypeKey, &(plugSubType), kCFNumberSInt32Type);
1455 PutNumberInDict(pDict, kAUPresetManufacturerKey, &(plugManID), kCFNumberSInt32Type);
1463 PutDataInDict(pDict, kAUPresetDataKey, &chunk);
1466 *ppPropList = pDict;
1471OSStatus IPlugAU::SetState(CFPropertyListRef pPropList)
1473 CFDictionaryRef pDict = (CFDictionaryRef) pPropList;
1474 int version, type, subtype, mfr;
1475 char presetName[64];
1476 if (!GetNumberFromDict(pDict, kAUPresetVersionKey, &version, kCFNumberSInt32Type) ||
1477 !GetNumberFromDict(pDict, kAUPresetTypeKey, &type, kCFNumberSInt32Type) ||
1478 !GetNumberFromDict(pDict, kAUPresetSubtypeKey, &subtype, kCFNumberSInt32Type) ||
1479 !GetNumberFromDict(pDict, kAUPresetManufacturerKey, &mfr, kCFNumberSInt32Type) ||
1480 !GetStrFromDict(pDict, kAUPresetNameKey, presetName) ||
1486 return kAudioUnitErr_InvalidPropertyValue;
1493 if (!GetDataFromDict(pDict, kAUPresetDataKey, &chunk))
1495 return kAudioUnitErr_InvalidPropertyValue;
1504 return kAudioUnitErr_InvalidPropertyValue;
1512OSStatus IPlugAU::GetProc(AudioUnitElement element, UInt32* pDataSize,
void* pData)
1514 Trace(TRACELOC,
"%s:(%d:%s)", (pData ?
"" :
"Info"), element, AUSelectStr(element));
1547 return kAudioUnitErr_InvalidElement;
1552OSStatus IPlugAU::GetParamProc(
void* pPlug, AudioUnitParameterID paramID, AudioUnitScope scope, AudioUnitElement element, AudioUnitParameterValue* pValue)
1554 Trace(TRACELOC,
"%d:(%d:%s):%d", paramID, scope, AUScopeStr(scope), element);
1556 ASSERT_SCOPE(kAudioUnitScope_Global);
1558 assert(_this != NULL);
1559 ENTER_PARAMS_MUTEX_STATIC
1560 *pValue = _this->GetParam(paramID)->Value();
1561 LEAVE_PARAMS_MUTEX_STATIC
1566OSStatus IPlugAU::SetParamProc(
void* pPlug, AudioUnitParameterID paramID, AudioUnitScope scope, AudioUnitElement element, AudioUnitParameterValue value, UInt32 offsetFrames)
1568 Trace(TRACELOC,
"%d:(%d:%s):%d", paramID, scope, AUScopeStr(scope), element);
1571 ASSERT_SCOPE(kAudioUnitScope_Global);
1573 ENTER_PARAMS_MUTEX_STATIC
1574 _this->GetParam(paramID)->Set(value);
1576 _this->OnParamChange(paramID, kHost);
1577 LEAVE_PARAMS_MUTEX_STATIC
1581static inline OSStatus RenderCallback(AURenderCallbackStruct* pCB, AudioUnitRenderActionFlags* pFlags,
const AudioTimeStamp* pTimestamp, UInt32 inputBusIdx, UInt32 nFrames, AudioBufferList* pOutBufList)
1584 return pCB->inputProc(pCB->inputProcRefCon, pFlags, pTimestamp, inputBusIdx, nFrames, pOutBufList);
1588OSStatus IPlugAU::RenderProc(
void* pPlug, AudioUnitRenderActionFlags* pFlags,
const AudioTimeStamp* pTimestamp,
1589 UInt32 outputBusIdx, UInt32 nFrames, AudioBufferList* pOutBufList)
1591 Trace(TRACELOC,
"%d:%d:%d", outputBusIdx, pOutBufList->mNumberBuffers, nFrames);
1595 _this->mLastRenderTimeStamp = *pTimestamp;
1597 if (!(pTimestamp->mFlags & kAudioTimeStampSampleTimeValid) || nFrames > _this->
GetBlockSize())
1599 return kAudioUnitErr_InvalidPropertyValue;
1602 int nRenderNotify = _this->mRenderNotify.GetSize();
1606 for (
int i = 0; i < nRenderNotify; ++i)
1608 AURenderCallbackStruct* pRN = _this->mRenderNotify.Get(i);
1609 AudioUnitRenderActionFlags flags = kAudioUnitRenderAction_PreRender;
1610 RenderCallback(pRN, &flags, pTimestamp, outputBusIdx, nFrames, pOutBufList);
1614 int lastConnectedOutputBus = -1;
1618 double renderSampleTime = pTimestamp->mSampleTime;
1621 if (renderSampleTime != _this->mLastRenderSampleTime)
1624 AudioBufferList* pInBufList = (AudioBufferList*) &bufList;
1626 int nIn = _this->mInBuses.GetSize();
1628 for (
int i = 0; i < nIn; ++i)
1630 BusChannels* pInBus = _this->mInBuses.Get(i);
1631 InputBusConnection* pInBusConn = _this->mInBusConnections.Get(i);
1633 if (pInBus->mConnected)
1635 pInBufList->mNumberBuffers = pInBus->mNHostChannels;
1637 for (
int b = 0; b < pInBufList->mNumberBuffers; ++b)
1639 AudioBuffer* pBuffer = &(pInBufList->mBuffers[b]);
1640 pBuffer->mNumberChannels = 1;
1641 pBuffer->mDataByteSize = nFrames *
sizeof(AudioSampleType);
1645 AudioUnitRenderActionFlags flags = 0;
1648 switch (pInBusConn->mInputType)
1650 case eDirectFastProc:
1652 r = pInBusConn->mUpstreamRenderProc(pInBusConn->mUpstreamObj, &flags, pTimestamp, pInBusConn->mUpstreamBusIdx, nFrames, pInBufList);
1655 case eDirectNoFastProc:
1657 r = AudioUnitRender(pInBusConn->mUpstreamUnit, &flags, pTimestamp, pInBusConn->mUpstreamBusIdx, nFrames, pInBufList);
1660 case eRenderCallback:
1662 AudioSampleType* pScratchInput = _this->mInScratchBuf.Get() + pInBus->mPlugChannelStartIdx * nFrames;
1664 for (
int b = 0; b < pInBufList->mNumberBuffers; ++b, pScratchInput += nFrames)
1666 pInBufList->mBuffers[b].mData = pScratchInput;
1669 r = RenderCallback(&(pInBusConn->mUpstreamRenderCallback), &flags, pTimestamp, i, nFrames, pInBufList);
1681 for (
int c = 0, chIdx = pInBus->mPlugChannelStartIdx; c < pInBus->mNHostChannels; ++c, ++chIdx)
1683 _this->AttachBuffers(ERoute::kInput, chIdx, 1, (AudioSampleType**) &(pInBufList->mBuffers[c].mData), nFrames);
1687 _this->mLastRenderSampleTime = renderSampleTime;
1690 BusChannels* pOutBus = _this->mOutBuses.Get(outputBusIdx);
1693 if (!(pOutBus->mConnected) || pOutBus->mNHostChannels != pOutBufList->mNumberBuffers)
1695 const int startChannelIdx = pOutBus->mPlugChannelStartIdx;
1696 const int nConnected = std::max(pOutBus->mNHostChannels,
static_cast<int>(pOutBufList->mNumberBuffers));
1697 const int nUnconnected = std::max(pOutBus->mNPlugChannels - nConnected, 0);
1699 assert(nConnected > -1);
1700 _this->SetChannelConnections(ERoute::kOutput, startChannelIdx, nConnected,
true);
1701 _this->SetChannelConnections(ERoute::kOutput, startChannelIdx + nConnected, nUnconnected,
false);
1702 pOutBus->mConnected =
true;
1705 for (
int c = 0, chIdx = pOutBus->mPlugChannelStartIdx; c < pOutBufList->mNumberBuffers; ++c, ++chIdx)
1707 if (!(pOutBufList->mBuffers[c].mData))
1708 pOutBufList->mBuffers[c].mData = _this->mOutScratchBuf.Get() + chIdx * nFrames;
1710 _this->AttachBuffers(ERoute::kOutput, chIdx, 1, (AudioSampleType**) &(pOutBufList->mBuffers[c].mData), nFrames);
1713 for(
int i = 0; i < _this->mOutBuses.GetSize(); i++)
1715 if(!_this->mOutBuses.Get(i)->mConnected)
1721 lastConnectedOutputBus++;
1726 if (_this->
IsMidiEffect() || outputBusIdx == lastConnectedOutputBus)
1728 int busIdx1based = outputBusIdx+1;
1730 if (busIdx1based < _this->mOutBuses.GetSize() )
1732 int totalNumChans = _this->mOutBuses.GetSize() * 2;
1733 int nConnected = busIdx1based * 2;
1734 _this->SetChannelConnections(ERoute::kOutput, nConnected, totalNumChans - nConnected,
false);
1739 _this->PassThroughBuffers((AudioSampleType) 0, nFrames);
1743 if(_this->mMidiMsgsFromEditor.ElementsAvailable())
1747 while (_this->mMidiMsgsFromEditor.Pop(msg))
1753 _this->PreProcess();
1754 ENTER_PARAMS_MUTEX_STATIC
1755 _this->ProcessBuffers((AudioSampleType) 0, nFrames);
1756 LEAVE_PARAMS_MUTEX_STATIC
1762 for (
int i = 0; i < nRenderNotify; ++i)
1764 AURenderCallbackStruct* pRN = _this->mRenderNotify.Get(i);
1765 AudioUnitRenderActionFlags flags = kAudioUnitRenderAction_PostRender;
1766 RenderCallback(pRN, &flags, pTimestamp, outputBusIdx, nFrames, pOutBufList);
1770 _this->OutputSysexFromEditor();
1775IPlugAU::BusChannels* IPlugAU::GetBus(AudioUnitScope scope, AudioUnitElement busIdx)
1777 if (scope == kAudioUnitScope_Input && busIdx < mInBuses.GetSize())
1779 return mInBuses.Get(busIdx);
1781 if (scope == kAudioUnitScope_Output && busIdx < mOutBuses.GetSize())
1783 return mOutBuses.Get(busIdx);
1786 if (scope == kAudioUnitScope_Global && mOutBuses.GetSize())
1788 return mOutBuses.Get(busIdx);
1793void IPlugAU::ClearConnections()
1795 int nInBuses = mInBuses.GetSize();
1796 for (
int i = 0; i < nInBuses; ++i)
1798 BusChannels* pInBus = mInBuses.Get(i);
1799 pInBus->mConnected =
false;
1800 pInBus->mNHostChannels = -1;
1801 InputBusConnection* pInBusConn = mInBusConnections.Get(i);
1802 memset(pInBusConn, 0,
sizeof(InputBusConnection));
1804 int nOutBuses = mOutBuses.GetSize();
1805 for (
int i = 0; i < nOutBuses; ++i)
1807 BusChannels* pOutBus = mOutBuses.Get(i);
1808 pOutBus->mConnected =
false;
1809 pOutBus->mNHostChannels = -1;
1813#pragma mark - IPlugAU Constructor
1815IPlugAU::IPlugAU(
const InstanceInfo& info,
const Config& config)
1819 Trace(TRACELOC,
"%s", config.pluginName);
1821 memset(&mHostCallbacks, 0,
sizeof(HostCallbackInfo));
1822 memset(&mMidiCallback, 0,
sizeof(AUMIDIOutputCallbackStruct));
1824 mCocoaViewFactoryClassName.Set(info.mCocoaViewFactoryClassName.Get());
1826 int maxNIBuses = MaxNBuses(ERoute::kInput);
1829 if(maxNIBuses == 1 && MaxNChannelsForBus(kInput, 0) == 0)
1834 const int maxNOBuses = MaxNBuses(ERoute::kOutput);
1838 PtrListInitialize(&mInBusConnections, maxNIBuses);
1839 PtrListInitialize(&mInBuses, maxNIBuses);
1844 for (
auto bus = 0; bus < maxNIBuses; bus++)
1846 BusChannels* pInBus = mInBuses.Get(bus);
1847 pInBus->mNHostChannels = -1;
1848 pInBus->mPlugChannelStartIdx = chansSoFar;
1849 pInBus->mNPlugChannels = std::abs(MaxNChannelsForBus(ERoute::kInput, bus));
1851 chansSoFar += pInBus->mNPlugChannels;
1854 PtrListInitialize(&mOutBuses, maxNOBuses);
1858 for (
auto bus = 0; bus < maxNOBuses; bus++)
1860 BusChannels* pOutBus = mOutBuses.Get(bus);
1861 pOutBus->mNHostChannels = -1;
1862 pOutBus->mPlugChannelStartIdx = chansSoFar;
1863 pOutBus->mNPlugChannels = std::abs(MaxNChannelsForBus(ERoute::kOutput, bus));
1865 chansSoFar += pOutBus->mNPlugChannels;
1868 AssessInputConnections();
1870 SetBlockSize(DEFAULT_BLOCK_SIZE);
1871 ResizeScratchBuffers();
1879 mRenderNotify.Empty(
true);
1880 mInBuses.Empty(
true);
1881 mOutBuses.Empty(
true);
1882 mInBusConnections.Empty(
true);
1883 mPropertyListeners.Empty(
true);
1886void IPlugAU::SendAUEvent(AudioUnitEventType type, AudioComponentInstance ci,
int idx)
1888 AudioUnitEvent auEvent;
1889 memset(&auEvent, 0,
sizeof(AudioUnitEvent));
1890 auEvent.mEventType = type;
1891 auEvent.mArgument.mParameter.mAudioUnit = ci;
1892 auEvent.mArgument.mParameter.mParameterID = idx;
1893 auEvent.mArgument.mParameter.mScope = kAudioUnitScope_Global;
1894 auEvent.mArgument.mParameter.mElement = 0;
1895 AUEventListenerNotify(0, 0, &auEvent);
1900 Trace(TRACELOC,
"%d", idx);
1901 SendAUEvent(kAudioUnitEvent_BeginParameterChangeGesture, mCI, idx);
1906 Trace(TRACELOC,
"%d:%f", idx, normalizedValue);
1907 SendAUEvent(kAudioUnitEvent_ParameterValueChange, mCI, idx);
1912 Trace(TRACELOC,
"%d", idx);
1913 SendAUEvent(kAudioUnitEvent_EndParameterChangeGesture, mCI, idx);
1919 InformListeners(kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global);
1924 InformListeners(kAudioUnitProperty_ParameterList, kAudioUnitScope_Global);
1925 InformListeners(kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global);
1928void IPlugAU::PreProcess()
1932 if (mHostCallbacks.beatAndTempoProc)
1934 double currentBeat = 0.0, tempo = 0.0;
1935 mHostCallbacks.beatAndTempoProc(mHostCallbacks.hostUserData, ¤tBeat, &tempo);
1938 timeInfo.mTempo = tempo;
1940 if (currentBeat >= 0.0)
1941 timeInfo.mPPQPos = currentBeat;
1944 if (mHostCallbacks.transportStateProc)
1946 double samplePos = 0.0, loopStartBeat=0.0, loopEndBeat=0.0;
1947 Boolean playing, changed, looping;
1948 mHostCallbacks.transportStateProc(mHostCallbacks.hostUserData, &playing, &changed, &samplePos, &looping, &loopStartBeat, &loopEndBeat);
1950 if (samplePos > 0.0)
1951 timeInfo.mSamplePos = samplePos;
1953 if (loopStartBeat > 0.0)
1954 timeInfo.mCycleStart = loopStartBeat;
1956 if (loopEndBeat > 0.0)
1957 timeInfo.mCycleEnd = loopEndBeat;
1959 timeInfo.mTransportIsRunning = playing;
1960 timeInfo.mTransportLoopEnabled = looping;
1963 UInt32 sampleOffsetToNextBeat = 0, tsDenom = 0;
1965 double currentMeasureDownBeat = 0.0;
1967 if (mHostCallbacks.musicalTimeLocationProc)
1969 mHostCallbacks.musicalTimeLocationProc(mHostCallbacks.hostUserData, &sampleOffsetToNextBeat, &tsNum, &tsDenom, ¤tMeasureDownBeat);
1971 timeInfo.mNumerator = (int) tsNum;
1972 timeInfo.mDenominator = (int) tsDenom;
1973 if (currentMeasureDownBeat>0.0)
1974 timeInfo.mLastBar=currentMeasureDownBeat;
1977 SetTimeInfo(timeInfo);
1980void IPlugAU::ResizeScratchBuffers()
1985 mInScratchBuf.Resize(NInputs);
1986 mOutScratchBuf.Resize(NOutputs);
1987 memset(mInScratchBuf.Get(), 0, NInputs *
sizeof(AudioSampleType));
1988 memset(mOutScratchBuf.Get(), 0, NOutputs *
sizeof(AudioSampleType));
1991void IPlugAU::InformListeners(AudioUnitPropertyID propID, AudioUnitScope scope)
1994 int i, n = mPropertyListeners.GetSize();
1996 for (i = 0; i < n; ++i)
1998 PropertyListener* pListener = mPropertyListeners.Get(i);
2000 if (pListener->mPropID == propID)
2002 pListener->mListenerProc(pListener->mProcArgs, mCI, propID, scope, 0);
2010 InformListeners(kAudioUnitProperty_Latency, kAudioUnitScope_Global);
2016 if(mMidiCallback.midiOutputCallback ==
nullptr)
2019 MIDIPacketList packetList;
2021 packetList.packet[0].data[0] = msg.mStatus;
2022 packetList.packet[0].data[1] = msg.mData1;
2023 packetList.packet[0].data[2] = msg.mData2;
2024 packetList.packet[0].length = 3;
2025 packetList.packet[0].timeStamp = msg.mOffset;
2026 packetList.numPackets = 1;
2028 if(mMidiCallback.midiOutputCallback)
2030 OSStatus status = mMidiCallback.midiOutputCallback(mMidiCallback.userData, &mLastRenderTimeStamp, 0, &packetList);
2032 if (status == noErr)
2041 bool result =
false;
2043 if(mMidiCallback.midiOutputCallback ==
nullptr)
2046 WDL_HeapBuf heapBuf;
2047 MIDIPacketList* pPktlist = (MIDIPacketList*) heapBuf.ResizeOK(msgs.GetSize() * 3);
2048 MIDIPacket* pPkt = MIDIPacketListInit(pPktlist);
2049 ByteCount listSize = heapBuf.GetSize();
2052 for (
int i = 0; i < msgs.GetSize(); ++i, ++pMsg)
2054 pPkt = MIDIPacketListAdd(pPktlist, listSize, pPkt, pMsg->mOffset , 1, &pMsg->mStatus);
2055 pPkt = MIDIPacketListAdd(pPktlist, listSize, pPkt, pMsg->mOffset , 1, &pMsg->mData1);
2056 pPkt = MIDIPacketListAdd(pPktlist, listSize, pPkt, pMsg->mOffset , 1, &pMsg->mData2);
2059 if(mMidiCallback.midiOutputCallback)
2061 OSStatus status = mMidiCallback.midiOutputCallback(mMidiCallback.userData, &mLastRenderTimeStamp, 0, pPktlist);
2063 if (status == noErr)
2072 bool result =
false;
2074 if(mMidiCallback.midiOutputCallback ==
nullptr)
2077 assert(sysEx.mSize <= 65536);
2079 WDL_HeapBuf heapBuf;
2080 MIDIPacketList* pPktlist = (MIDIPacketList*) heapBuf.ResizeOK(sysEx.mSize);
2081 MIDIPacket* pPkt = MIDIPacketListInit(pPktlist);
2083 ByteCount listSize = heapBuf.GetSize();
2084 ByteCount bytesLeft = listSize;
2087 ByteCount packetSize = listSize < 256 ? listSize : 256;
2088 pPkt = MIDIPacketListAdd(pPktlist, listSize, pPkt, sysEx.mOffset , packetSize, sysEx.mData);
2089 bytesLeft -= packetSize;
2092 assert(pPkt !=
nullptr);
2094 if(mMidiCallback.midiOutputCallback)
2096 OSStatus status = mMidiCallback.midiOutputCallback(mMidiCallback.userData, &mLastRenderTimeStamp, 0, pPktlist);
2098 if (status == noErr)
2105void IPlugAU::OutputSysexFromEditor()
2108 if(mSysExDataFromEditor.ElementsAvailable())
2110 while (mSysExDataFromEditor.Pop(mSysexBuf))
2112 ISysEx smsg {mSysexBuf.mOffset, mSysexBuf.mData, mSysexBuf.mSize};
2118#pragma mark - IPlugAU Dispatch
2120#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
2122static IPlugAU* GetPlug(
void *x)
2124 return (
IPlugAU*) &((AudioComponentPlugInInstance*) x)->mInstanceStorage;
2128OSStatus IPlugAU::AUMethodInitialize(
void* pSelf)
2130 return DoInitialize(GetPlug(pSelf));
2134OSStatus IPlugAU::AUMethodUninitialize(
void* pSelf)
2136 return DoUninitialize(GetPlug(pSelf));
2140OSStatus IPlugAU::AUMethodGetPropertyInfo(
void* pSelf, AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32* outDataSize, Boolean* outWritable)
2142 return DoGetPropertyInfo(GetPlug(pSelf), prop, scope, elem, outDataSize, outWritable);
2146OSStatus IPlugAU::AUMethodGetProperty(
void* pSelf, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
void* outData, UInt32* ioDataSize)
2148 return DoGetProperty(GetPlug(pSelf), inID, inScope, inElement, outData, ioDataSize);
2152OSStatus IPlugAU::AUMethodSetProperty(
void* pSelf, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
const void* inData, UInt32* inDataSize)
2154 return DoSetProperty(GetPlug(pSelf), inID, inScope, inElement, inData, inDataSize);
2158OSStatus IPlugAU::AUMethodAddPropertyListener(
void* pSelf, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* userData)
2160 return DoAddPropertyListener(GetPlug(pSelf), prop, proc, userData);
2164OSStatus IPlugAU::AUMethodRemovePropertyListener(
void* pSelf, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc)
2166 return DoRemovePropertyListener(GetPlug(pSelf), prop, proc);
2170OSStatus IPlugAU::AUMethodRemovePropertyListenerWithUserData(
void* pSelf, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* userData)
2172 return DoRemovePropertyListenerWithUserData(GetPlug(pSelf), prop, proc, userData);
2176OSStatus IPlugAU::AUMethodAddRenderNotify(
void* pSelf, AURenderCallback proc,
void* userData)
2178 return DoAddRenderNotify(GetPlug(pSelf), proc, userData);
2182OSStatus IPlugAU::AUMethodRemoveRenderNotify(
void* pSelf, AURenderCallback proc,
void* userData)
2184 return DoRemoveRenderNotify(GetPlug(pSelf), proc, userData);
2188OSStatus IPlugAU::AUMethodGetParameter(
void* pSelf, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue* value)
2190 return DoGetParameter(GetPlug(pSelf), param, scope, elem, value);
2194OSStatus IPlugAU::AUMethodSetParameter(
void* pSelf, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset)
2196 return DoSetParameter(GetPlug(pSelf), param, scope, elem, value, bufferOffset);
2200OSStatus IPlugAU::AUMethodScheduleParameters(
void* pSelf,
const AudioUnitParameterEvent *pEvent, UInt32 nEvents)
2202 return DoScheduleParameters(GetPlug(pSelf), pEvent, nEvents);
2206OSStatus IPlugAU::AUMethodRender(
void* pSelf, AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData)
2208 return DoRender(GetPlug(pSelf), ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
2212OSStatus IPlugAU::AUMethodReset(
void* pSelf, AudioUnitScope scope, AudioUnitElement elem)
2214 return DoReset(GetPlug(pSelf));
2218OSStatus IPlugAU::AUMethodMIDIEvent(
void* pSelf, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame)
2220 return DoMIDIEvent(GetPlug(pSelf), inStatus, inData1, inData2, inOffsetSampleFrame);
2224OSStatus IPlugAU::AUMethodSysEx(
void* pSelf,
const UInt8* inData, UInt32 inLength)
2226 return DoSysEx(GetPlug(pSelf), inData, inLength);
2231OSStatus IPlugAU::DoInitialize(
IPlugAU* _this)
2233 if (_this->
GetHost() == kHostUninit)
2235 CFBundleRef mainBundle = CFBundleGetMainBundle();
2236 CFStringRef
id =
nullptr;
2241 id = CFBundleGetIdentifier(mainBundle);
2242 CStrLocal versionStr((CFStringRef) CFBundleGetValueForInfoDictionaryKey(mainBundle, kCFBundleVersionKey));
2245 long ver = versionStr.Get() ? strtol(versionStr.Get(), &pStr, 10) : 0;
2246 long verRevMaj = versionStr.Get() && *pStr ? strtol(pStr + 1, &pStr, 10) : 0;
2247 long verRevMin = versionStr.Get() && *pStr ? strtol(pStr + 1, &pStr, 10) : 0;
2249 version = (int) (((ver & 0xFFFF) << 16) | ((verRevMaj & 0xFF) << 8) | (verRevMin & 0xFF));
2252 _this->
SetHost(
id ? CStrLocal(
id).Get() :
"", version);
2255 if (!(_this->CheckLegalIO()))
2257 return badComponentSelector;
2260 _this->mActive =
true;
2261 _this->OnParamReset(kReset);
2268OSStatus IPlugAU::DoUninitialize(
IPlugAU* _this)
2270 _this->mActive =
false;
2276OSStatus IPlugAU::DoGetPropertyInfo(
IPlugAU* _this, AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32* outDataSize, Boolean* outWritable)
2278 UInt32 dataSize = 0;
2281 outDataSize = &dataSize;
2286 outWritable = &writeable;
2288 *outWritable =
false;
2290 return _this->GetProperty(prop, scope, elem, outDataSize, outWritable, 0 );
2294OSStatus IPlugAU::DoGetProperty(
IPlugAU* _this, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
void* outData, UInt32 *ioDataSize)
2296 UInt32 dataSize = 0;
2299 ioDataSize = &dataSize;
2301 Boolean writeable =
false;
2303 return _this->GetProperty(inID, inScope, inElement, ioDataSize, &writeable, outData);
2307OSStatus IPlugAU::DoSetProperty(
IPlugAU* _this, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
const void* inData, UInt32* inDataSize)
2309 return _this->SetProperty(inID, inScope, inElement, inDataSize, inData);
2313OSStatus IPlugAU::DoAddPropertyListener(
IPlugAU* _this, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* userData)
2315 PropertyListener listener;
2316 listener.mPropID = prop;
2317 listener.mListenerProc = proc;
2318 listener.mProcArgs = userData;
2319 int i, n = _this->mPropertyListeners.GetSize();
2320 for (i = 0; i < n; ++i)
2322 PropertyListener* pListener = _this->mPropertyListeners.Get(i);
2323 if (listener.mPropID == pListener->mPropID && listener.mListenerProc == pListener->mListenerProc)
2328 PtrListAddFromStack(&(_this->mPropertyListeners), &listener);
2333OSStatus IPlugAU::DoRemovePropertyListener(
IPlugAU* _this, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc)
2335 PropertyListener listener;
2336 listener.mPropID = prop;
2337 listener.mListenerProc = proc;
2338 int i, n = _this->mPropertyListeners.GetSize();
2339 for (i = 0; i < n; ++i)
2341 PropertyListener* pListener = _this->mPropertyListeners.Get(i);
2342 if (listener.mPropID == pListener->mPropID && listener.mListenerProc == pListener->mListenerProc)
2344 _this->mPropertyListeners.Delete(i,
true);
2352OSStatus IPlugAU::DoRemovePropertyListenerWithUserData(
IPlugAU* _this, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* userData)
2354 PropertyListener listener;
2355 listener.mPropID = prop;
2356 listener.mListenerProc = proc;
2357 listener.mProcArgs = userData;
2358 int i, n = _this->mPropertyListeners.GetSize();
2359 for (i = 0; i < n; ++i)
2361 PropertyListener* pListener = _this->mPropertyListeners.Get(i);
2362 if (listener.mPropID == pListener->mPropID &&
2363 listener.mListenerProc == pListener->mListenerProc && listener.mProcArgs == pListener->mProcArgs)
2365 _this->mPropertyListeners.Delete(i,
true);
2373OSStatus IPlugAU::DoAddRenderNotify(
IPlugAU* _this, AURenderCallback proc,
void* userData)
2375 AURenderCallbackStruct acs;
2376 acs.inputProc = proc;
2377 acs.inputProcRefCon = userData;
2379 PtrListAddFromStack(&(_this->mRenderNotify), &acs);
2384OSStatus IPlugAU::DoRemoveRenderNotify(
IPlugAU* _this, AURenderCallback proc,
void* userData)
2387 AURenderCallbackStruct acs;
2388 acs.inputProc = proc;
2389 acs.inputProcRefCon = userData;
2391 int i, n = _this->mRenderNotify.GetSize();
2392 for (i = 0; i < n; ++i)
2394 AURenderCallbackStruct* pACS = _this->mRenderNotify.Get(i);
2395 if (acs.inputProc == pACS->inputProc)
2397 _this->mRenderNotify.Delete(i,
true);
2405OSStatus IPlugAU::DoGetParameter(
IPlugAU* _this, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue *value)
2408 return _this->GetParamProc(_this, param, scope, elem, value);
2412OSStatus IPlugAU::DoSetParameter(
IPlugAU* _this, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset)
2415 return _this->SetParamProc(_this, param, scope, elem, value, bufferOffset);
2419OSStatus IPlugAU::DoScheduleParameters(
IPlugAU* _this,
const AudioUnitParameterEvent *pEvent, UInt32 nEvents)
2422 for (
int i = 0; i < nEvents; ++i, ++pEvent)
2424 if (pEvent->eventType == kParameterEvent_Immediate)
2426 OSStatus r = SetParamProc(_this, pEvent->parameter, pEvent->scope, pEvent->element,
2427 pEvent->eventValues.immediate.value, pEvent->eventValues.immediate.bufferOffset);
2438OSStatus IPlugAU::DoRender(
IPlugAU* _this, AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData)
2440 return RenderProc(_this, ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
2444OSStatus IPlugAU::DoReset(
IPlugAU* _this)
2451OSStatus IPlugAU::DoMIDIEvent(
IPlugAU* _this, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame)
2456 msg.mStatus = inStatus;
2457 msg.mData1 = inData1;
2458 msg.mData2 = inData2;
2459 msg.mOffset = inOffsetSampleFrame;
2461 _this->mMidiMsgsFromProcessor.Push(msg);
2465 return badComponentSelector;
2469OSStatus IPlugAU::DoSysEx(
IPlugAU* _this,
const UInt8* inData, UInt32 inLength)
2474 sysex.mData = inData;
2475 sysex.mSize = inLength;
2481 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.
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
int MaxNChannels(ERoute direction) const
virtual void ProcessSysEx(ISysEx &msg)
Override this method to handle incoming MIDI System Exclusive (SysEx) messages.
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.