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