12 #include <CoreMIDI/CoreMIDI.h> 16 #include "dfx-au-utilities.h" 18 #include "IPlugAU_ioconfig.h" 20 using namespace iplug;
22 #pragma mark - CFString and CString Utilities 24 static inline CFStringRef MakeCFString(
const char* cStr)
26 return CFStringCreateWithCString(0, cStr, kCFStringEncodingUTF8);
29 class 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; }
51 struct 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 65 inline 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);
73 inline 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());
80 inline 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);
88 inline 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);
100 inline 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());
114 inline 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 130 typedef AudioStreamBasicDescription STREAM_DESC;
132 static 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;
154 static int PtrListAddFromStack(WDL_PtrList<C>* pList, C* pStackInstance)
157 memcpy(pNew, pStackInstance,
sizeof(C));
159 return pList->GetSize() - 1;
163 static int PtrListInitialize(WDL_PtrList<C>* pList,
int size)
165 for (
int i = 0; i < size; ++i)
168 memset(pNew, 0,
sizeof(C));
174 #if defined(__LP64__) 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 185 OSStatus 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;
391 #endif //AU_NO_COMPONENT_ENTRY 393 #pragma mark - GetChannelLayoutTags 395 UInt32 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++)
408 const IOConfig* pConfig = GetIOConfig(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; 458 OSStatus 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);
501 *((Float64*) pData) = GetSampleRate();
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))
635 for(
int i = 0; i< NParamGroups(); i++)
637 if(strcmp(paramGroupName, GetParamGroupName(i)) == 0)
642 clumpID = AddParamGroup(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;
673 MakeDefaultASBD(pASBD, GetSampleRate(), nChannels,
false);
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);
701 *((Float64*) pData) = (double) GetLatency() / GetSampleRate();
705 case kAudioUnitProperty_SupportedNumChannels:
707 ASSERT_SCOPE(kAudioUnitScope_Global);
708 int n = NIOConfigs();
709 *pDataSize = n *
sizeof(AUChannelInfo);
712 AUChannelInfo* pChInfo = (AUChannelInfo*) pData;
713 for (
int i = 0; i < n; ++i, ++pChInfo)
715 const IOConfig* pIO = GetIOConfig(i);
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);
740 *((UInt32*) pData) = GetBlockSize();
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 *pWriteable = GetTailSize() > 0;
785 *pDataSize =
sizeof(Float64);
789 *((Float64*) pData) = (double) GetTailSize() / GetSampleRate();
793 case kAudioUnitProperty_BypassEffect:
795 ASSERT_SCOPE(kAudioUnitScope_Global);
797 *pDataSize =
sizeof(UInt32);
800 *((UInt32*) pData) = (GetBypassed() ? 1 : 0);
804 case kAudioUnitProperty_LastRenderError:
806 ASSERT_SCOPE(kAudioUnitScope_Global);
807 *pDataSize =
sizeof(OSStatus);
810 *((OSStatus*) pData) = noErr;
814 case kAudioUnitProperty_SetRenderCallback:
816 ASSERT_INPUT_OR_GLOBAL_SCOPE;
817 if (element >= mInBuses.GetSize())
819 return kAudioUnitErr_InvalidProperty;
821 *pDataSize =
sizeof(AURenderCallbackStruct);
825 case kAudioUnitProperty_FactoryPresets:
827 *pDataSize =
sizeof(CFArrayRef);
833 int i, n = NPresets();
836 CFMutableArrayRef presetArray = CFArrayCreateMutable(kCFAllocatorDefault, n, &kCFAUPresetArrayCallBacks);
838 if (presetArray == NULL)
839 return coreFoundationUnknownErr;
841 for (i = 0; i < n; ++i)
843 CFStrLocal presetName(GetPresetName(i));
844 CFAUPresetRef newPreset = CFAUPresetCreate(kCFAllocatorDefault, i, presetName.Get());
846 if (newPreset != NULL)
848 CFArrayAppendValue(presetArray, newPreset);
849 CFAUPresetRelease(newPreset);
853 *((CFMutableArrayRef*) pData) = presetArray;
857 NO_OP(kAudioUnitProperty_ContextName);
858 NO_OP(kAudioUnitProperty_RenderQuality);
859 case kAudioUnitProperty_HostCallbacks:
861 ASSERT_SCOPE(kAudioUnitScope_Global);
862 *pDataSize =
sizeof(HostCallbackInfo);
866 NO_OP(kAudioUnitProperty_InPlaceProcessing);
867 case kAudioUnitProperty_ElementName:
869 *pDataSize =
sizeof(CFStringRef);
873 const int nIn = MaxNBuses(kInput);
874 const int nOut = MaxNBuses(kOutput);
878 case kAudioUnitScope_Input:
883 GetBusName(ERoute::kInput, (
int) element, nIn, busName);
884 *(CFStringRef*) pData = MakeCFString(busName.Get());
888 return kAudioUnitErr_InvalidElement;
890 case kAudioUnitScope_Output:
896 GetBusName(ERoute::kOutput, (
int) element, nOut, busName);
897 *(CFStringRef*) pData = MakeCFString(busName.Get());
901 return kAudioUnitErr_InvalidElement;
904 return kAudioUnitErr_InvalidScope;
907 return kAudioUnitErr_InvalidProperty;
909 case kAudioUnitProperty_CocoaUI:
913 *pDataSize =
sizeof(AudioUnitCocoaViewInfo);
916 AudioUnitCocoaViewInfo* pViewInfo = (AudioUnitCocoaViewInfo*) pData;
917 CFStrLocal bundleID(mBundleID.Get());
918 CFBundleRef pBundle = CFBundleGetBundleWithIdentifier(bundleID.Get());
919 CFURLRef url = CFBundleCopyBundleURL(pBundle);
920 pViewInfo->mCocoaAUViewBundleLocation = url;
921 pViewInfo->mCocoaAUViewClass[0] = CFStringCreateWithCString(0, mCocoaViewFactoryClassName.Get(), kCFStringEncodingUTF8);
925 return kAudioUnitErr_InvalidProperty;
927 #pragma mark - kAudioUnitProperty_SupportedChannelLayoutTags 928 case kAudioUnitProperty_SupportedChannelLayoutTags:
932 UInt32 numLayouts = GetChannelLayoutTags(scope, element, NULL);
936 *pDataSize = numLayouts *
sizeof(AudioChannelLayoutTag);
949 AudioChannelLayoutTag* ptr = pData ?
static_cast<AudioChannelLayoutTag*
>(pData) : NULL;
951 if (GetChannelLayoutTags(scope, element, ptr))
957 return kAudioUnitErr_InvalidProperty;
959 case kAudioUnitProperty_ParameterIDName:
961 *pDataSize =
sizeof(AudioUnitParameterIDName);
962 if (pData && scope == kAudioUnitScope_Global)
964 AudioUnitParameterIDName* pIDName = (AudioUnitParameterIDName*) pData;
965 char cStr[MAX_PARAM_NAME_LEN];
967 strcpy(cStr, GetParam(pIDName->inID)->GetName());
969 if (pIDName->inDesiredLength != kAudioUnitParameterName_Full)
971 int n = std::min<int>(MAX_PARAM_NAME_LEN - 1, pIDName->inDesiredLength);
974 pIDName->outName = CFStringCreateWithCString(0, cStr, kCFStringEncodingUTF8);
978 case kAudioUnitProperty_ParameterClumpName:
980 *pDataSize =
sizeof (AudioUnitParameterNameInfo);
981 if (pData && scope == kAudioUnitScope_Global)
983 AudioUnitParameterNameInfo* parameterNameInfo = (AudioUnitParameterNameInfo *) pData;
984 int clumpId = parameterNameInfo->inID;
987 return kAudioUnitErr_PropertyNotInUse;
989 parameterNameInfo->outName = CFStringCreateWithCString(0, GetParamGroupName(clumpId-1), kCFStringEncodingUTF8);
993 case kAudioUnitProperty_CurrentPreset:
994 case kAudioUnitProperty_PresentPreset:
996 *pDataSize =
sizeof(AUPreset);
1000 AUPreset* pAUPreset = (AUPreset*) pData;
1001 pAUPreset->presetNumber = GetCurrentPresetIdx();
1002 const char* name = GetPresetName(pAUPreset->presetNumber);
1003 pAUPreset->presetName = CFStringCreateWithCString(0, name, kCFStringEncodingUTF8);
1007 NO_OP(kAudioUnitProperty_OfflineRender);
1008 case kAudioUnitProperty_ParameterStringFromValue:
1010 *pDataSize =
sizeof(AudioUnitParameterStringFromValue);
1011 if (pData && scope == kAudioUnitScope_Global)
1013 AudioUnitParameterStringFromValue* pSFV = (AudioUnitParameterStringFromValue*) pData;
1015 GetParam(pSFV->inParamID)->GetDisplay(*(pSFV->inValue),
false, mParamDisplayStr);
1017 pSFV->outString = MakeCFString((
const char*) mParamDisplayStr.Get());
1021 case kAudioUnitProperty_ParameterValueFromString:
1023 *pDataSize =
sizeof(AudioUnitParameterValueFromString);
1026 AudioUnitParameterValueFromString* pVFS = (AudioUnitParameterValueFromString*) pData;
1027 if (scope == kAudioUnitScope_Global)
1029 CStrLocal cStr(pVFS->inString);
1031 const double v = GetParam(pVFS->inParamID)->StringToValue(cStr.Get());
1033 pVFS->outValue = (AudioUnitParameterValue) v;
1038 NO_OP(kAudioUnitProperty_IconLocation);
1039 NO_OP(kAudioUnitProperty_PresentationLatency);
1040 NO_OP(kAudioUnitProperty_DependentParameters);
1041 case kMusicDeviceProperty_InstrumentCount:
1043 ASSERT_SCOPE(kAudioUnitScope_Global);
1046 *pDataSize =
sizeof(UInt32);
1049 *((UInt32*) pData) = 1;
1055 return kAudioUnitErr_InvalidProperty;
1059 NO_OP(kAudioUnitProperty_AUHostIdentifier);
1060 case kAudioUnitProperty_MIDIOutputCallbackInfo:
1064 *pWriteable =
false;
1065 *pDataSize =
sizeof(CFArrayRef);
1069 CFStringRef outputName = CFSTR(
"midiOut");
1070 CFArrayRef array = CFArrayCreate(kCFAllocatorDefault, (
const void**) &outputName, 1,
nullptr);
1071 CFRelease(outputName);
1072 *((CFArrayRef*) pData) = array;
1076 case kAudioUnitProperty_MIDIOutputCallback:
1081 *pDataSize =
sizeof(AUMIDIOutputCallbackStruct);
1086 NO_OP(kAudioUnitProperty_InputSamplesInOutput);
1087 NO_OP(kAudioUnitProperty_ClassInfoFromDocument);
1088 case kAudioUnitProperty_SupportsMPE:
1092 *pWriteable =
false;
1093 *pDataSize =
sizeof(UInt32);
1097 *((UInt32*) pData) = (DoesMPE() ? 1 : 0);
1103 return kAudioUnitErr_InvalidProperty;
1108 OSStatus IPlugAU::SetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element,
1109 UInt32* pDataSize,
const void* pData)
1111 Trace(TRACELOC,
"(%d:%s):(%d:%s):%d", propID, AUPropertyStr(propID), scope, AUScopeStr(scope), element);
1113 InformListeners(propID, scope);
1117 case kAudioUnitProperty_ClassInfo:
1119 return SetState(*((CFPropertyListRef*) pData));
1121 case kAudioUnitProperty_MakeConnection:
1123 ASSERT_INPUT_OR_GLOBAL_SCOPE;
1124 AudioUnitConnection* pAUC = (AudioUnitConnection*) pData;
1125 if (pAUC->destInputNumber >= mInBusConnections.GetSize())
1127 return kAudioUnitErr_InvalidProperty;
1129 InputBusConnection* pInBusConn = mInBusConnections.Get(pAUC->destInputNumber);
1130 memset(pInBusConn, 0,
sizeof(InputBusConnection));
1131 bool negotiatedOK =
true;
1132 if (pAUC->sourceAudioUnit)
1134 AudioStreamBasicDescription srcASBD;
1135 UInt32 size =
sizeof(AudioStreamBasicDescription);
1137 (AudioUnitGetProperty(pAUC->sourceAudioUnit, kAudioUnitProperty_StreamFormat,
1138 kAudioUnitScope_Output, pAUC->sourceOutputNumber, &srcASBD, &size) == noErr);
1140 (SetProperty(kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
1141 pAUC->destInputNumber, &size, &srcASBD) == noErr);
1144 pInBusConn->mUpstreamUnit = pAUC->sourceAudioUnit;
1145 pInBusConn->mUpstreamBusIdx = pAUC->sourceOutputNumber;
1147 AudioUnitRenderProc srcRenderProc;
1148 size =
sizeof(AudioUnitRenderProc);
1149 if (AudioUnitGetProperty(pAUC->sourceAudioUnit, kAudioUnitProperty_FastDispatch, kAudioUnitScope_Global, kAudioUnitRenderSelect,
1150 &srcRenderProc, &size) == noErr)
1153 pInBusConn->mUpstreamRenderProc = srcRenderProc;
1154 pInBusConn->mUpstreamObj = GetComponentInstanceStorage(pAUC->sourceAudioUnit);
1162 AssessInputConnections();
1163 return (negotiatedOK ? noErr : (
int) kAudioUnitErr_InvalidProperty);
1165 case kAudioUnitProperty_SampleRate:
1167 SetSampleRate(*((Float64*) pData));
1171 NO_OP(kAudioUnitProperty_ParameterList);
1172 NO_OP(kAudioUnitProperty_ParameterInfo);
1173 NO_OP(kAudioUnitProperty_FastDispatch);
1174 NO_OP(kAudioUnitProperty_CPULoad);
1175 case kAudioUnitProperty_StreamFormat:
1177 AudioStreamBasicDescription* pASBD = (AudioStreamBasicDescription*) pData;
1178 int nHostChannels = pASBD->mChannelsPerFrame;
1179 BusChannels* pBus = GetBus(scope, element);
1182 return kAudioUnitErr_InvalidProperty;
1184 pBus->mNHostChannels = 0;
1188 bool connectionOK = (nHostChannels > 0);
1189 connectionOK &= CheckLegalIO(scope, element, nHostChannels);
1190 connectionOK &= (pASBD->mFormatID == kAudioFormatLinearPCM && pASBD->mFormatFlags & kAudioFormatFlagsCanonical);
1192 Trace(TRACELOC,
"%d:%d:%s:%s:%s",
1193 nHostChannels, pBus->mNPlugChannels,
1194 (pASBD->mFormatID == kAudioFormatLinearPCM ?
"linearPCM" :
"notLinearPCM"),
1195 (pASBD->mFormatFlags & kAudioFormatFlagsCanonical ?
"canonicalFormat" :
"notCanonicalFormat"),
1196 (connectionOK ?
"connectionOK" :
"connectionNotOK"));
1201 pBus->mNHostChannels = nHostChannels;
1202 if (pASBD->mSampleRate > 0.0)
1204 SetSampleRate(pASBD->mSampleRate);
1207 AssessInputConnections();
1208 return (connectionOK ? noErr : (
int) kAudioUnitErr_InvalidProperty);
1210 NO_OP(kAudioUnitProperty_ElementCount);
1211 NO_OP(kAudioUnitProperty_Latency);
1212 NO_OP(kAudioUnitProperty_SupportedNumChannels);
1213 case kAudioUnitProperty_MaximumFramesPerSlice:
1215 SetBlockSize(*((UInt32*) pData));
1216 ResizeScratchBuffers();
1220 NO_OP(kAudioUnitProperty_SetExternalBuffer);
1221 NO_OP(kAudioUnitProperty_ParameterValueStrings);
1222 NO_OP(kAudioUnitProperty_GetUIComponentList);
1223 NO_OP(kAudioUnitProperty_AudioChannelLayout);
1224 NO_OP(kAudioUnitProperty_TailTime);
1225 case kAudioUnitProperty_BypassEffect:
1227 const bool bypassed = *((UInt32*) pData) != 0;
1228 SetBypassed(bypassed);
1231 OnActivate(!bypassed);
1235 NO_OP(kAudioUnitProperty_LastRenderError);
1236 case kAudioUnitProperty_SetRenderCallback:
1238 ASSERT_SCOPE(kAudioUnitScope_Input);
1239 if (element >= mInBusConnections.GetSize())
1241 return kAudioUnitErr_InvalidProperty;
1243 InputBusConnection* pInBusConn = mInBusConnections.Get(element);
1244 memset(pInBusConn, 0,
sizeof(InputBusConnection));
1245 AURenderCallbackStruct* pCS = (AURenderCallbackStruct*) pData;
1246 if (pCS->inputProc != 0)
1248 pInBusConn->mUpstreamRenderCallback = *pCS;
1250 AssessInputConnections();
1253 NO_OP(kAudioUnitProperty_FactoryPresets);
1255 case kAudioUnitProperty_ContextName:
1257 CFStringRef inStr = *(CFStringRef *)pData;
1258 CFIndex bufferSize = CFStringGetLength(inStr) + 1;
1259 char buffer[bufferSize];
1260 if (CFStringGetCString(inStr, buffer, bufferSize, kCFStringEncodingUTF8))
1262 mTrackName.Set(buffer);
1266 NO_OP(kAudioUnitProperty_RenderQuality);
1267 case kAudioUnitProperty_HostCallbacks:
1269 ASSERT_SCOPE(kAudioUnitScope_Global);
1270 memcpy(&mHostCallbacks, pData,
sizeof(HostCallbackInfo));
1273 NO_OP(kAudioUnitProperty_InPlaceProcessing);
1274 NO_OP(kAudioUnitProperty_ElementName);
1275 NO_OP(kAudioUnitProperty_CocoaUI);
1276 NO_OP(kAudioUnitProperty_SupportedChannelLayoutTags);
1277 NO_OP(kAudioUnitProperty_ParameterIDName);
1278 NO_OP(kAudioUnitProperty_ParameterClumpName);
1279 case kAudioUnitProperty_CurrentPreset:
1280 case kAudioUnitProperty_PresentPreset:
1282 int presetIdx = ((AUPreset*) pData)->presetNumber;
1283 RestorePreset(presetIdx);
1286 case kAudioUnitProperty_OfflineRender:
1288 const bool renderingOffline = (*((UInt32*) pData) != 0);
1289 SetRenderingOffline(renderingOffline);
1292 NO_OP(kAudioUnitProperty_ParameterStringFromValue);
1293 NO_OP(kAudioUnitProperty_ParameterValueFromString);
1294 NO_OP(kAudioUnitProperty_IconLocation);
1295 NO_OP(kAudioUnitProperty_PresentationLatency);
1296 NO_OP(kAudioUnitProperty_DependentParameters);
1297 case kAudioUnitProperty_AUHostIdentifier:
1299 if (GetHost() == kHostUninit)
1301 AUHostIdentifier* pHostID = (AUHostIdentifier*) pData;
1302 CStrLocal hostStr(pHostID->hostName);
1303 int version = (pHostID->hostVersion.majorRev << 16)
1304 + ((pHostID->hostVersion.minorAndBugRev & 0xF0) << 4)
1305 + ((pHostID->hostVersion.minorAndBugRev & 0x0F));
1306 SetHost(hostStr.Get(), version);
1310 NO_OP(kAudioUnitProperty_MIDIOutputCallbackInfo);
1311 case kAudioUnitProperty_MIDIOutputCallback:
1313 mMidiCallback = *((AUMIDIOutputCallbackStruct*) pData);
1316 NO_OP(kAudioUnitProperty_InputSamplesInOutput);
1317 NO_OP(kAudioUnitProperty_ClassInfoFromDocument)
1320 return kAudioUnitErr_InvalidProperty;
1326 const char* IPlugAU::AUInputTypeStr(
int type)
1328 switch ((IPlugAU::EAUInputType) type)
1330 case IPlugAU::eDirectFastProc:
return "DirectFastProc";
1331 case IPlugAU::eDirectNoFastProc:
return "DirectNoFastProc";
1332 case IPlugAU::eRenderCallback:
return "RenderCallback";
1333 case IPlugAU::eNotConnected:
1334 default:
return "NotConnected";
1338 int IPlugAU::NHostChannelsConnected(WDL_PtrList<BusChannels>* pBuses,
int excludeIdx)
1341 int nCh = 0, n = pBuses->GetSize();
1343 for (
int i = 0; i < n; ++i)
1345 if (i != excludeIdx)
1347 int nHostChannels = pBuses->Get(i)->mNHostChannels;
1348 if (nHostChannels >= 0)
1350 nCh += nHostChannels;
1364 bool IPlugAU::CheckLegalIO(AudioUnitScope scope,
int busIdx,
int nChannels)
1366 if (scope == kAudioUnitScope_Input)
1368 int nIn = std::max(NHostChannelsConnected(&mInBuses, busIdx), 0);
1369 int nOut = (mActive ? NHostChannelsConnected(&mOutBuses) : -1);
1370 return LegalIO(nIn + nChannels, nOut);
1374 int nIn = (mActive ? NHostChannelsConnected(&mInBuses) : -1);
1375 int nOut = std::max(NHostChannelsConnected(&mOutBuses, busIdx), 0);
1376 return LegalIO(nIn, nOut + nChannels);
1380 bool IPlugAU::CheckLegalIO()
1382 int nIn = NHostChannelsConnected(&mInBuses);
1383 int nOut = NHostChannelsConnected(&mOutBuses);
1384 return ((!nIn && !nOut) || LegalIO(nIn, nOut));
1387 void IPlugAU::AssessInputConnections()
1390 SetChannelConnections(ERoute::kInput, 0, MaxNChannels(ERoute::kInput),
false);
1392 int nIn = mInBuses.GetSize();
1393 for (
int i = 0; i < nIn; ++i)
1395 BusChannels* pInBus = mInBuses.Get(i);
1396 InputBusConnection* pInBusConn = mInBusConnections.Get(i);
1399 if (pInBusConn->mUpstreamRenderProc && pInBusConn->mUpstreamObj)
1402 pInBusConn->mInputType = eDirectFastProc;
1404 else if (pInBusConn->mUpstreamUnit)
1407 pInBusConn->mInputType = eDirectNoFastProc;
1409 else if (pInBusConn->mUpstreamRenderCallback.inputProc)
1412 pInBusConn->mInputType = eRenderCallback;
1416 pInBusConn->mInputType = eNotConnected;
1418 pInBus->mConnected = (pInBusConn->mInputType != eNotConnected);
1420 int startChannelIdx = pInBus->mPlugChannelStartIdx;
1421 if (pInBus->mConnected)
1425 if (pInBus->mNHostChannels < 0)
1429 Trace(TRACELOC,
"AssumeChannels:%d", pInBus->mNPlugChannels);
1430 pInBus->mNHostChannels = pInBus->mNPlugChannels;
1432 int nConnected = pInBus->mNHostChannels;
1433 int nUnconnected = std::max(pInBus->mNPlugChannels - nConnected, 0);
1434 SetChannelConnections(ERoute::kInput, startChannelIdx, nConnected,
true);
1435 SetChannelConnections(ERoute::kInput, startChannelIdx + nConnected, nUnconnected,
false);
1438 Trace(TRACELOC,
"%d:%s:%d:%d:%d", i, AUInputTypeStr(pInBusConn->mInputType), startChannelIdx, pInBus->mNPlugChannels, pInBus->mNHostChannels);
1442 OSStatus IPlugAU::GetState(CFPropertyListRef* ppPropList)
1444 int plugType = GetAUPluginType();
1445 int plugSubType = GetUniqueID();
1446 int plugManID = GetMfrID();
1448 CFMutableDictionaryRef pDict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1449 int version = GetPluginVersion(
false);
1450 PutNumberInDict(pDict, kAUPresetVersionKey, &version, kCFNumberSInt32Type);
1451 PutNumberInDict(pDict, kAUPresetTypeKey, &(plugType), kCFNumberSInt32Type);
1452 PutNumberInDict(pDict, kAUPresetSubtypeKey, &(plugSubType), kCFNumberSInt32Type);
1453 PutNumberInDict(pDict, kAUPresetManufacturerKey, &(plugManID), kCFNumberSInt32Type);
1454 PutStrInDict(pDict, kAUPresetNameKey, GetPresetName(GetCurrentPresetIdx()));
1459 if (SerializeState(chunk))
1461 PutDataInDict(pDict, kAUPresetDataKey, &chunk);
1464 *ppPropList = pDict;
1469 OSStatus IPlugAU::SetState(CFPropertyListRef pPropList)
1471 CFDictionaryRef pDict = (CFDictionaryRef) pPropList;
1472 int version, type, subtype, mfr;
1473 char presetName[64];
1474 if (!GetNumberFromDict(pDict, kAUPresetVersionKey, &version, kCFNumberSInt32Type) ||
1475 !GetNumberFromDict(pDict, kAUPresetTypeKey, &type, kCFNumberSInt32Type) ||
1476 !GetNumberFromDict(pDict, kAUPresetSubtypeKey, &subtype, kCFNumberSInt32Type) ||
1477 !GetNumberFromDict(pDict, kAUPresetManufacturerKey, &mfr, kCFNumberSInt32Type) ||
1478 !GetStrFromDict(pDict, kAUPresetNameKey, presetName) ||
1480 type != GetAUPluginType() ||
1481 subtype != GetUniqueID() ||
1484 return kAudioUnitErr_InvalidPropertyValue;
1487 RestorePreset(presetName);
1491 if (!GetDataFromDict(pDict, kAUPresetDataKey, &chunk))
1493 return kAudioUnitErr_InvalidPropertyValue;
1500 if (!UnserializeState(chunk, 0))
1502 return kAudioUnitErr_InvalidPropertyValue;
1510 OSStatus IPlugAU::GetProc(AudioUnitElement element, UInt32* pDataSize,
void* pData)
1512 Trace(TRACELOC,
"%s:(%d:%s)", (pData ?
"" :
"Info"), element, AUSelectStr(element));
1545 return kAudioUnitErr_InvalidElement;
1550 OSStatus IPlugAU::GetParamProc(
void* pPlug, AudioUnitParameterID paramID, AudioUnitScope scope, AudioUnitElement element, AudioUnitParameterValue* pValue)
1552 Trace(TRACELOC,
"%d:(%d:%s):%d", paramID, scope, AUScopeStr(scope), element);
1554 ASSERT_SCOPE(kAudioUnitScope_Global);
1556 assert(_this != NULL);
1557 ENTER_PARAMS_MUTEX_STATIC
1558 *pValue = _this->GetParam(paramID)->Value();
1559 LEAVE_PARAMS_MUTEX_STATIC
1564 OSStatus IPlugAU::SetParamProc(
void* pPlug, AudioUnitParameterID paramID, AudioUnitScope scope, AudioUnitElement element, AudioUnitParameterValue value, UInt32 offsetFrames)
1566 Trace(TRACELOC,
"%d:(%d:%s):%d", paramID, scope, AUScopeStr(scope), element);
1569 ASSERT_SCOPE(kAudioUnitScope_Global);
1571 ENTER_PARAMS_MUTEX_STATIC
1572 _this->GetParam(paramID)->Set(value);
1574 _this->OnParamChange(paramID, kHost);
1575 LEAVE_PARAMS_MUTEX_STATIC
1579 static inline OSStatus RenderCallback(AURenderCallbackStruct* pCB, AudioUnitRenderActionFlags* pFlags,
const AudioTimeStamp* pTimestamp, UInt32 inputBusIdx, UInt32 nFrames, AudioBufferList* pOutBufList)
1582 return pCB->inputProc(pCB->inputProcRefCon, pFlags, pTimestamp, inputBusIdx, nFrames, pOutBufList);
1586 OSStatus IPlugAU::RenderProc(
void* pPlug, AudioUnitRenderActionFlags* pFlags,
const AudioTimeStamp* pTimestamp,
1587 UInt32 outputBusIdx, UInt32 nFrames, AudioBufferList* pOutBufList)
1589 Trace(TRACELOC,
"%d:%d:%d", outputBusIdx, pOutBufList->mNumberBuffers, nFrames);
1593 _this->mLastRenderTimeStamp = *pTimestamp;
1595 if (!(pTimestamp->mFlags & kAudioTimeStampSampleTimeValid) || nFrames > _this->
GetBlockSize())
1597 return kAudioUnitErr_InvalidPropertyValue;
1600 int nRenderNotify = _this->mRenderNotify.GetSize();
1604 for (
int i = 0; i < nRenderNotify; ++i)
1606 AURenderCallbackStruct* pRN = _this->mRenderNotify.Get(i);
1607 AudioUnitRenderActionFlags flags = kAudioUnitRenderAction_PreRender;
1608 RenderCallback(pRN, &flags, pTimestamp, outputBusIdx, nFrames, pOutBufList);
1612 int lastConnectedOutputBus = -1;
1616 double renderSampleTime = pTimestamp->mSampleTime;
1619 if (renderSampleTime != _this->mLastRenderSampleTime)
1622 AudioBufferList* pInBufList = (AudioBufferList*) &bufList;
1624 int nIn = _this->mInBuses.GetSize();
1626 for (
int i = 0; i < nIn; ++i)
1628 BusChannels* pInBus = _this->mInBuses.Get(i);
1629 InputBusConnection* pInBusConn = _this->mInBusConnections.Get(i);
1631 if (pInBus->mConnected)
1633 pInBufList->mNumberBuffers = pInBus->mNHostChannels;
1635 for (
int b = 0; b < pInBufList->mNumberBuffers; ++b)
1637 AudioBuffer* pBuffer = &(pInBufList->mBuffers[b]);
1638 pBuffer->mNumberChannels = 1;
1639 pBuffer->mDataByteSize = nFrames *
sizeof(AudioSampleType);
1643 AudioUnitRenderActionFlags flags = 0;
1646 switch (pInBusConn->mInputType)
1648 case eDirectFastProc:
1650 r = pInBusConn->mUpstreamRenderProc(pInBusConn->mUpstreamObj, &flags, pTimestamp, pInBusConn->mUpstreamBusIdx, nFrames, pInBufList);
1653 case eDirectNoFastProc:
1655 r = AudioUnitRender(pInBusConn->mUpstreamUnit, &flags, pTimestamp, pInBusConn->mUpstreamBusIdx, nFrames, pInBufList);
1658 case eRenderCallback:
1660 AudioSampleType* pScratchInput = _this->mInScratchBuf.Get() + pInBus->mPlugChannelStartIdx * nFrames;
1662 for (
int b = 0; b < pInBufList->mNumberBuffers; ++b, pScratchInput += nFrames)
1664 pInBufList->mBuffers[b].mData = pScratchInput;
1667 r = RenderCallback(&(pInBusConn->mUpstreamRenderCallback), &flags, pTimestamp, i, nFrames, pInBufList);
1679 for (
int c = 0, chIdx = pInBus->mPlugChannelStartIdx; c < pInBus->mNHostChannels; ++c, ++chIdx)
1681 _this->AttachBuffers(ERoute::kInput, chIdx, 1, (AudioSampleType**) &(pInBufList->mBuffers[c].mData), nFrames);
1685 _this->mLastRenderSampleTime = renderSampleTime;
1688 BusChannels* pOutBus = _this->mOutBuses.Get(outputBusIdx);
1691 if (!(pOutBus->mConnected) || pOutBus->mNHostChannels != pOutBufList->mNumberBuffers)
1693 const int startChannelIdx = pOutBus->mPlugChannelStartIdx;
1694 const int nConnected = std::max(pOutBus->mNHostChannels, static_cast<int>(pOutBufList->mNumberBuffers));
1695 const int nUnconnected = std::max(pOutBus->mNPlugChannels - nConnected, 0);
1697 assert(nConnected > -1);
1698 _this->SetChannelConnections(ERoute::kOutput, startChannelIdx, nConnected,
true);
1699 _this->SetChannelConnections(ERoute::kOutput, startChannelIdx + nConnected, nUnconnected,
false);
1700 pOutBus->mConnected =
true;
1703 for (
int c = 0, chIdx = pOutBus->mPlugChannelStartIdx; c < pOutBufList->mNumberBuffers; ++c, ++chIdx)
1705 if (!(pOutBufList->mBuffers[c].mData))
1706 pOutBufList->mBuffers[c].mData = _this->mOutScratchBuf.Get() + chIdx * nFrames;
1708 _this->AttachBuffers(ERoute::kOutput, chIdx, 1, (AudioSampleType**) &(pOutBufList->mBuffers[c].mData), nFrames);
1711 for(
int i = 0; i < _this->mOutBuses.GetSize(); i++)
1713 if(!_this->mOutBuses.Get(i)->mConnected)
1719 lastConnectedOutputBus++;
1724 if (_this->
IsMidiEffect() || outputBusIdx == lastConnectedOutputBus)
1726 int busIdx1based = outputBusIdx+1;
1728 if (busIdx1based < _this->mOutBuses.GetSize() )
1730 int totalNumChans = _this->mOutBuses.GetSize() * 2;
1731 int nConnected = busIdx1based * 2;
1732 _this->SetChannelConnections(ERoute::kOutput, nConnected, totalNumChans - nConnected,
false);
1737 _this->PassThroughBuffers((AudioSampleType) 0, nFrames);
1741 if(_this->mMidiMsgsFromEditor.ElementsAvailable())
1745 while (_this->mMidiMsgsFromEditor.Pop(msg))
1751 _this->PreProcess();
1753 _this->ProcessBuffers((AudioSampleType) 0, nFrames);
1760 for (
int i = 0; i < nRenderNotify; ++i)
1762 AURenderCallbackStruct* pRN = _this->mRenderNotify.Get(i);
1763 AudioUnitRenderActionFlags flags = kAudioUnitRenderAction_PostRender;
1764 RenderCallback(pRN, &flags, pTimestamp, outputBusIdx, nFrames, pOutBufList);
1768 _this->OutputSysexFromEditor();
1773 IPlugAU::BusChannels* IPlugAU::GetBus(AudioUnitScope scope, AudioUnitElement busIdx)
1775 if (scope == kAudioUnitScope_Input && busIdx < mInBuses.GetSize())
1777 return mInBuses.Get(busIdx);
1779 if (scope == kAudioUnitScope_Output && busIdx < mOutBuses.GetSize())
1781 return mOutBuses.Get(busIdx);
1784 if (scope == kAudioUnitScope_Global && mOutBuses.GetSize())
1786 return mOutBuses.Get(busIdx);
1791 void IPlugAU::ClearConnections()
1793 int nInBuses = mInBuses.GetSize();
1794 for (
int i = 0; i < nInBuses; ++i)
1796 BusChannels* pInBus = mInBuses.Get(i);
1797 pInBus->mConnected =
false;
1798 pInBus->mNHostChannels = -1;
1799 InputBusConnection* pInBusConn = mInBusConnections.Get(i);
1800 memset(pInBusConn, 0,
sizeof(InputBusConnection));
1802 int nOutBuses = mOutBuses.GetSize();
1803 for (
int i = 0; i < nOutBuses; ++i)
1805 BusChannels* pOutBus = mOutBuses.Get(i);
1806 pOutBus->mConnected =
false;
1807 pOutBus->mNHostChannels = -1;
1811 #pragma mark - IPlugAU Constructor 1813 IPlugAU::IPlugAU(
const InstanceInfo& info,
const Config& config)
1817 Trace(TRACELOC,
"%s", config.pluginName);
1819 memset(&mHostCallbacks, 0,
sizeof(HostCallbackInfo));
1820 memset(&mMidiCallback, 0,
sizeof(AUMIDIOutputCallbackStruct));
1822 mCocoaViewFactoryClassName.Set(info.mCocoaViewFactoryClassName.Get());
1824 int maxNIBuses = MaxNBuses(ERoute::kInput);
1827 if(maxNIBuses == 1 && MaxNChannelsForBus(kInput, 0) == 0)
1832 const int maxNOBuses = MaxNBuses(ERoute::kOutput);
1836 PtrListInitialize(&mInBusConnections, maxNIBuses);
1837 PtrListInitialize(&mInBuses, maxNIBuses);
1842 for (
auto bus = 0; bus < maxNIBuses; bus++)
1844 BusChannels* pInBus = mInBuses.Get(bus);
1845 pInBus->mNHostChannels = -1;
1846 pInBus->mPlugChannelStartIdx = chansSoFar;
1847 pInBus->mNPlugChannels = std::abs(MaxNChannelsForBus(ERoute::kInput, bus));
1849 chansSoFar += pInBus->mNPlugChannels;
1852 PtrListInitialize(&mOutBuses, maxNOBuses);
1856 for (
auto bus = 0; bus < maxNOBuses; bus++)
1858 BusChannels* pOutBus = mOutBuses.Get(bus);
1859 pOutBus->mNHostChannels = -1;
1860 pOutBus->mPlugChannelStartIdx = chansSoFar;
1861 pOutBus->mNPlugChannels = std::abs(MaxNChannelsForBus(ERoute::kOutput, bus));
1863 chansSoFar += pOutBus->mNPlugChannels;
1866 AssessInputConnections();
1868 SetBlockSize(DEFAULT_BLOCK_SIZE);
1869 ResizeScratchBuffers();
1876 mRenderNotify.Empty(
true);
1877 mInBuses.Empty(
true);
1878 mOutBuses.Empty(
true);
1879 mInBusConnections.Empty(
true);
1880 mPropertyListeners.Empty(
true);
1883 void IPlugAU::SendAUEvent(AudioUnitEventType type, AudioComponentInstance ci,
int idx)
1885 AudioUnitEvent auEvent;
1886 memset(&auEvent, 0,
sizeof(AudioUnitEvent));
1887 auEvent.mEventType = type;
1888 auEvent.mArgument.mParameter.mAudioUnit = ci;
1889 auEvent.mArgument.mParameter.mParameterID = idx;
1890 auEvent.mArgument.mParameter.mScope = kAudioUnitScope_Global;
1891 auEvent.mArgument.mParameter.mElement = 0;
1892 AUEventListenerNotify(0, 0, &auEvent);
1897 Trace(TRACELOC,
"%d", idx);
1898 SendAUEvent(kAudioUnitEvent_BeginParameterChangeGesture, mCI, idx);
1903 Trace(TRACELOC,
"%d:%f", idx, normalizedValue);
1904 SendAUEvent(kAudioUnitEvent_ParameterValueChange, mCI, idx);
1909 Trace(TRACELOC,
"%d", idx);
1910 SendAUEvent(kAudioUnitEvent_EndParameterChangeGesture, mCI, idx);
1916 InformListeners(kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global);
1921 InformListeners(kAudioUnitProperty_ParameterList, kAudioUnitScope_Global);
1922 InformListeners(kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global);
1925 void IPlugAU::PreProcess()
1929 if (mHostCallbacks.beatAndTempoProc)
1931 double currentBeat = 0.0, tempo = 0.0;
1932 mHostCallbacks.beatAndTempoProc(mHostCallbacks.hostUserData, ¤tBeat, &tempo);
1935 timeInfo.mTempo = tempo;
1937 if (currentBeat >= 0.0)
1938 timeInfo.mPPQPos = currentBeat;
1941 if (mHostCallbacks.transportStateProc)
1943 double samplePos = 0.0, loopStartBeat=0.0, loopEndBeat=0.0;
1944 Boolean playing, changed, looping;
1945 mHostCallbacks.transportStateProc(mHostCallbacks.hostUserData, &playing, &changed, &samplePos, &looping, &loopStartBeat, &loopEndBeat);
1947 if (samplePos > 0.0)
1948 timeInfo.mSamplePos = samplePos;
1950 if (loopStartBeat > 0.0)
1951 timeInfo.mCycleStart = loopStartBeat;
1953 if (loopEndBeat > 0.0)
1954 timeInfo.mCycleEnd = loopEndBeat;
1956 timeInfo.mTransportIsRunning = playing;
1957 timeInfo.mTransportLoopEnabled = looping;
1960 UInt32 sampleOffsetToNextBeat = 0, tsDenom = 0;
1962 double currentMeasureDownBeat = 0.0;
1964 if (mHostCallbacks.musicalTimeLocationProc)
1966 mHostCallbacks.musicalTimeLocationProc(mHostCallbacks.hostUserData, &sampleOffsetToNextBeat, &tsNum, &tsDenom, ¤tMeasureDownBeat);
1968 timeInfo.mNumerator = (int) tsNum;
1969 timeInfo.mDenominator = (int) tsDenom;
1970 if (currentMeasureDownBeat>0.0)
1971 timeInfo.mLastBar=currentMeasureDownBeat;
1974 SetTimeInfo(timeInfo);
1977 void IPlugAU::ResizeScratchBuffers()
1980 int NInputs = MaxNChannels(ERoute::kInput) * GetBlockSize();
1981 int NOutputs = MaxNChannels(ERoute::kOutput) * GetBlockSize();
1982 mInScratchBuf.Resize(NInputs);
1983 mOutScratchBuf.Resize(NOutputs);
1984 memset(mInScratchBuf.Get(), 0, NInputs *
sizeof(AudioSampleType));
1985 memset(mOutScratchBuf.Get(), 0, NOutputs *
sizeof(AudioSampleType));
1988 void IPlugAU::InformListeners(AudioUnitPropertyID propID, AudioUnitScope scope)
1991 int i, n = mPropertyListeners.GetSize();
1993 for (i = 0; i < n; ++i)
1995 PropertyListener* pListener = mPropertyListeners.Get(i);
1997 if (pListener->mPropID == propID)
1999 pListener->mListenerProc(pListener->mProcArgs, mCI, propID, scope, 0);
2007 int i, n = mPropertyListeners.GetSize();
2009 for (i = 0; i < n; ++i)
2011 PropertyListener* pListener = mPropertyListeners.Get(i);
2012 if (pListener->mPropID == kAudioUnitProperty_Latency)
2014 pListener->mListenerProc(pListener->mProcArgs, mCI, kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0);
2023 if(mMidiCallback.midiOutputCallback ==
nullptr)
2026 MIDIPacketList packetList;
2028 packetList.packet[0].data[0] = msg.mStatus;
2029 packetList.packet[0].data[1] = msg.mData1;
2030 packetList.packet[0].data[2] = msg.mData2;
2031 packetList.packet[0].length = 3;
2032 packetList.packet[0].timeStamp = msg.mOffset;
2033 packetList.numPackets = 1;
2035 if(mMidiCallback.midiOutputCallback)
2037 OSStatus status = mMidiCallback.midiOutputCallback(mMidiCallback.userData, &mLastRenderTimeStamp, 0, &packetList);
2039 if (status == noErr)
2048 bool result =
false;
2050 if(mMidiCallback.midiOutputCallback ==
nullptr)
2053 WDL_HeapBuf heapBuf;
2054 MIDIPacketList* pPktlist = (MIDIPacketList*) heapBuf.ResizeOK(msgs.GetSize() * 3);
2055 MIDIPacket* pPkt = MIDIPacketListInit(pPktlist);
2056 ByteCount listSize = heapBuf.GetSize();
2059 for (
int i = 0; i < msgs.GetSize(); ++i, ++pMsg)
2061 pPkt = MIDIPacketListAdd(pPktlist, listSize, pPkt, pMsg->mOffset , 1, &pMsg->mStatus);
2062 pPkt = MIDIPacketListAdd(pPktlist, listSize, pPkt, pMsg->mOffset , 1, &pMsg->mData1);
2063 pPkt = MIDIPacketListAdd(pPktlist, listSize, pPkt, pMsg->mOffset , 1, &pMsg->mData2);
2066 if(mMidiCallback.midiOutputCallback)
2068 OSStatus status = mMidiCallback.midiOutputCallback(mMidiCallback.userData, &mLastRenderTimeStamp, 0, pPktlist);
2070 if (status == noErr)
2079 bool result =
false;
2081 if(mMidiCallback.midiOutputCallback ==
nullptr)
2084 assert(sysEx.mSize <= 65536);
2086 WDL_HeapBuf heapBuf;
2087 MIDIPacketList* pPktlist = (MIDIPacketList*) heapBuf.ResizeOK(sysEx.mSize);
2088 MIDIPacket* pPkt = MIDIPacketListInit(pPktlist);
2090 ByteCount listSize = heapBuf.GetSize();
2091 ByteCount bytesLeft = listSize;
2094 ByteCount packetSize = listSize < 256 ? listSize : 256;
2095 pPkt = MIDIPacketListAdd(pPktlist, listSize, pPkt, sysEx.mOffset , packetSize, sysEx.mData);
2096 bytesLeft -= packetSize;
2099 assert(pPkt !=
nullptr);
2101 if(mMidiCallback.midiOutputCallback)
2103 OSStatus status = mMidiCallback.midiOutputCallback(mMidiCallback.userData, &mLastRenderTimeStamp, 0, pPktlist);
2105 if (status == noErr)
2112 void IPlugAU::OutputSysexFromEditor()
2115 if(mSysExDataFromEditor.ElementsAvailable())
2117 while (mSysExDataFromEditor.Pop(mSysexBuf))
2119 ISysEx smsg {mSysexBuf.mOffset, mSysexBuf.mData, mSysexBuf.mSize};
2125 #pragma mark - IPlugAU Dispatch 2127 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 2129 static IPlugAU* GetPlug(
void *x)
2131 return (
IPlugAU*) &((AudioComponentPlugInInstance *) x)->mInstanceStorage;
2135 OSStatus IPlugAU::AUMethodInitialize(
void* pSelf)
2137 return DoInitialize(GetPlug(pSelf));
2141 OSStatus IPlugAU::AUMethodUninitialize(
void* pSelf)
2143 return DoUninitialize(GetPlug(pSelf));
2147 OSStatus IPlugAU::AUMethodGetPropertyInfo(
void* pSelf, AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32* outDataSize, Boolean* outWritable)
2149 return DoGetPropertyInfo(GetPlug(pSelf), prop, scope, elem, outDataSize, outWritable);
2153 OSStatus IPlugAU::AUMethodGetProperty(
void* pSelf, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
void* outData, UInt32* ioDataSize)
2155 return DoGetProperty(GetPlug(pSelf), inID, inScope, inElement, outData, ioDataSize);
2159 OSStatus IPlugAU::AUMethodSetProperty(
void* pSelf, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
const void* inData, UInt32* inDataSize)
2161 return DoSetProperty(GetPlug(pSelf), inID, inScope, inElement, inData, inDataSize);
2165 OSStatus IPlugAU::AUMethodAddPropertyListener(
void* pSelf, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* userData)
2167 return DoAddPropertyListener(GetPlug(pSelf), prop, proc, userData);
2171 OSStatus IPlugAU::AUMethodRemovePropertyListener(
void* pSelf, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc)
2173 return DoRemovePropertyListener(GetPlug(pSelf), prop, proc);
2177 OSStatus IPlugAU::AUMethodRemovePropertyListenerWithUserData(
void* pSelf, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* userData)
2179 return DoRemovePropertyListenerWithUserData(GetPlug(pSelf), prop, proc, userData);
2183 OSStatus IPlugAU::AUMethodAddRenderNotify(
void* pSelf, AURenderCallback proc,
void* userData)
2185 return DoAddRenderNotify(GetPlug(pSelf), proc, userData);
2189 OSStatus IPlugAU::AUMethodRemoveRenderNotify(
void* pSelf, AURenderCallback proc,
void* userData)
2191 return DoRemoveRenderNotify(GetPlug(pSelf), proc, userData);
2195 OSStatus IPlugAU::AUMethodGetParameter(
void* pSelf, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue* value)
2197 return DoGetParameter(GetPlug(pSelf), param, scope, elem, value);
2201 OSStatus IPlugAU::AUMethodSetParameter(
void* pSelf, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset)
2203 return DoSetParameter(GetPlug(pSelf), param, scope, elem, value, bufferOffset);
2207 OSStatus IPlugAU::AUMethodScheduleParameters(
void* pSelf,
const AudioUnitParameterEvent *pEvent, UInt32 nEvents)
2209 return DoScheduleParameters(GetPlug(pSelf), pEvent, nEvents);
2213 OSStatus IPlugAU::AUMethodRender(
void* pSelf, AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData)
2215 return DoRender(GetPlug(pSelf), ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
2219 OSStatus IPlugAU::AUMethodReset(
void* pSelf, AudioUnitScope scope, AudioUnitElement elem)
2221 return DoReset(GetPlug(pSelf));
2225 OSStatus IPlugAU::AUMethodMIDIEvent(
void* pSelf, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame)
2227 return DoMIDIEvent(GetPlug(pSelf), inStatus, inData1, inData2, inOffsetSampleFrame);
2231 OSStatus IPlugAU::AUMethodSysEx(
void* pSelf,
const UInt8* inData, UInt32 inLength)
2233 return DoSysEx(GetPlug(pSelf), inData, inLength);
2238 OSStatus IPlugAU::DoInitialize(
IPlugAU* _this)
2240 if (_this->
GetHost() == kHostUninit)
2242 CFBundleRef mainBundle = CFBundleGetMainBundle();
2243 CFStringRef
id =
nullptr;
2248 id = CFBundleGetIdentifier(mainBundle);
2249 CStrLocal versionStr((CFStringRef) CFBundleGetValueForInfoDictionaryKey(mainBundle, kCFBundleVersionKey));
2252 long ver = versionStr.Get() ? strtol(versionStr.Get(), &pStr, 10) : 0;
2253 long verRevMaj = versionStr.Get() && *pStr ? strtol(pStr + 1, &pStr, 10) : 0;
2254 long verRevMin = versionStr.Get() && *pStr ? strtol(pStr + 1, &pStr, 10) : 0;
2256 version = (int) (((ver & 0xFFFF) << 16) | ((verRevMaj & 0xFF) << 8) | (verRevMin & 0xFF));
2259 _this->
SetHost(
id ? CStrLocal(
id).Get() :
"", version);
2262 if (!(_this->CheckLegalIO()))
2264 return badComponentSelector;
2267 _this->mActive =
true;
2268 _this->OnParamReset(kReset);
2275 OSStatus IPlugAU::DoUninitialize(
IPlugAU* _this)
2277 _this->mActive =
false;
2283 OSStatus IPlugAU::DoGetPropertyInfo(
IPlugAU* _this, AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32* outDataSize, Boolean* outWritable)
2285 UInt32 dataSize = 0;
2288 outDataSize = &dataSize;
2293 outWritable = &writeable;
2295 *outWritable =
false;
2297 return _this->GetProperty(prop, scope, elem, outDataSize, outWritable, 0 );
2301 OSStatus IPlugAU::DoGetProperty(
IPlugAU* _this, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
void* outData, UInt32 *ioDataSize)
2303 UInt32 dataSize = 0;
2306 ioDataSize = &dataSize;
2308 Boolean writeable =
false;
2310 return _this->GetProperty(inID, inScope, inElement, ioDataSize, &writeable, outData);
2314 OSStatus IPlugAU::DoSetProperty(
IPlugAU* _this, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
const void* inData, UInt32* inDataSize)
2316 return _this->SetProperty(inID, inScope, inElement, inDataSize, inData);
2320 OSStatus IPlugAU::DoAddPropertyListener(
IPlugAU* _this, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* userData)
2322 PropertyListener listener;
2323 listener.mPropID = prop;
2324 listener.mListenerProc = proc;
2325 listener.mProcArgs = userData;
2326 int i, n = _this->mPropertyListeners.GetSize();
2327 for (i = 0; i < n; ++i)
2329 PropertyListener* pListener = _this->mPropertyListeners.Get(i);
2330 if (listener.mPropID == pListener->mPropID && listener.mListenerProc == pListener->mListenerProc)
2335 PtrListAddFromStack(&(_this->mPropertyListeners), &listener);
2340 OSStatus IPlugAU::DoRemovePropertyListener(
IPlugAU* _this, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc)
2342 PropertyListener listener;
2343 listener.mPropID = prop;
2344 listener.mListenerProc = proc;
2345 int i, n = _this->mPropertyListeners.GetSize();
2346 for (i = 0; i < n; ++i)
2348 PropertyListener* pListener = _this->mPropertyListeners.Get(i);
2349 if (listener.mPropID == pListener->mPropID && listener.mListenerProc == pListener->mListenerProc)
2351 _this->mPropertyListeners.Delete(i,
true);
2359 OSStatus IPlugAU::DoRemovePropertyListenerWithUserData(
IPlugAU* _this, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc,
void* userData)
2361 PropertyListener listener;
2362 listener.mPropID = prop;
2363 listener.mListenerProc = proc;
2364 listener.mProcArgs = userData;
2365 int i, n = _this->mPropertyListeners.GetSize();
2366 for (i = 0; i < n; ++i)
2368 PropertyListener* pListener = _this->mPropertyListeners.Get(i);
2369 if (listener.mPropID == pListener->mPropID &&
2370 listener.mListenerProc == pListener->mListenerProc && listener.mProcArgs == pListener->mProcArgs)
2372 _this->mPropertyListeners.Delete(i,
true);
2380 OSStatus IPlugAU::DoAddRenderNotify(
IPlugAU* _this, AURenderCallback proc,
void* userData)
2382 AURenderCallbackStruct acs;
2383 acs.inputProc = proc;
2384 acs.inputProcRefCon = userData;
2386 PtrListAddFromStack(&(_this->mRenderNotify), &acs);
2391 OSStatus IPlugAU::DoRemoveRenderNotify(
IPlugAU* _this, AURenderCallback proc,
void* userData)
2394 AURenderCallbackStruct acs;
2395 acs.inputProc = proc;
2396 acs.inputProcRefCon = userData;
2398 int i, n = _this->mRenderNotify.GetSize();
2399 for (i = 0; i < n; ++i)
2401 AURenderCallbackStruct* pACS = _this->mRenderNotify.Get(i);
2402 if (acs.inputProc == pACS->inputProc)
2404 _this->mRenderNotify.Delete(i,
true);
2412 OSStatus IPlugAU::DoGetParameter(
IPlugAU* _this, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue *value)
2415 return _this->GetParamProc(_this, param, scope, elem, value);
2419 OSStatus IPlugAU::DoSetParameter(
IPlugAU* _this, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset)
2422 return _this->SetParamProc(_this, param, scope, elem, value, bufferOffset);
2426 OSStatus IPlugAU::DoScheduleParameters(
IPlugAU* _this,
const AudioUnitParameterEvent *pEvent, UInt32 nEvents)
2429 for (
int i = 0; i < nEvents; ++i, ++pEvent)
2431 if (pEvent->eventType == kParameterEvent_Immediate)
2433 OSStatus r = SetParamProc(_this, pEvent->parameter, pEvent->scope, pEvent->element,
2434 pEvent->eventValues.immediate.value, pEvent->eventValues.immediate.bufferOffset);
2445 OSStatus IPlugAU::DoRender(
IPlugAU* _this, AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData)
2447 return RenderProc(_this, ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
2451 OSStatus IPlugAU::DoReset(
IPlugAU* _this)
2458 OSStatus IPlugAU::DoMIDIEvent(
IPlugAU* _this, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame)
2463 msg.mStatus = inStatus;
2464 msg.mData1 = inData1;
2465 msg.mData2 = inData2;
2466 msg.mOffset = inOffsetSampleFrame;
2468 _this->mMidiMsgsFromProcessor.Push(msg);
2472 return badComponentSelector;
2476 OSStatus IPlugAU::DoSysEx(
IPlugAU* _this,
const UInt8* inData, UInt32 inLength)
2481 sysex.mData = inData;
2482 sysex.mSize = inLength;
2488 return badComponentSelector;
The base class of an IPlug plug-in, which interacts with the different plug-in APIs.
void InformHostOfPresetChange() override
Implemented by the API class, called by the UI (etc) when the plug-in initiates a program/preset chan...
Encapsulates a MIDI message and provides helper functions.
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...
int GetTotalNChannels(ERoute direction) const
Get the total number of channels across all direction buses for this IOConfig.
IPlug's parameter class.
virtual void SetLatency(int latency)
Call this if the latency of your plug-in changes after initialization (perhaps from OnReset() ) This ...
void PruneUninitializedPresets()
[AUV2 only] Removes any presets that weren't initialized
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...
An IOConfig is used to store bus info for each input/output configuration defined in the channel io s...
Manages a block of memory, for plug-in settings store/recall.
AudioUnit v2 API base class for an IPlug plug-in.
int NBuses(ERoute direction) const
ERoute
Used to identify whether a bus/channel connection is an input or an output.
void MakeNoteOffMsg(int noteNumber, int offset, int channel=0)
Make a Note Off message.
int Size() const
Returns the current size of the chunk.
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!...
virtual void ProcessSysEx(ISysEx &msg)
Override this method to handle incoming MIDI System Exclusive (SysEx) messages.
int Resize(int newSize)
Resizes the chunk.
void InformHostOfParameterDetailsChange() override
Implemented by the API class, call this if you update parameter labels and hopefully the host should ...
void SetLatency(int samples) override
Call this if the latency of your plug-in changes after initialization (perhaps from OnReset() ) This ...
bool ContainsWildcard(ERoute direction) const
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...
virtual void ProcessMidiMsg(const IMidiMsg &msg)
Override this method to handle incoming MIDI messages.
The base class for IPlug Audio Processing.
bool SendSysEx(const ISysEx &msg) override
Send a single MIDI System Exclusive (SysEx) message // TODO: info about what thread should this be ca...
virtual void OnReset()
Override this method in your plug-in class to do something prior to playback etc. ...
bool IsMidiEffect() const
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...
AudioUnit v2 API base class for an IPlug plug-in.
uint8_t * GetData()
Gets a ptr to the chunk data.
A struct for dealing with SysEx messages.
int GetPluginVersion(bool decimal) const
Get the plug-in version number.
void MakeNoteOnMsg(int noteNumber, int velocity, int offset, int channel=0)
Make a Note On message.
Encapsulates information about the host transport state.
void SetHost(const char *host, int version)
Called to set the name of the current host, if known (calls on to HostSpecificInit() and OnHostIdenti...
virtual void OnActivate(bool active)
Override OnActivate() which should be called by the API class when a plug-in is "switched on" by the ...
void InformHostOfParamChange(int idx, double normalizedValue) override
Implemented by the API class, called by the UI via SetParameterValue() with the value of a parameter ...