12 #include "IPlugAAX_view_interface.h" 13 #include "AAX_CBinaryTaperDelegate.h" 14 #include "AAX_CBinaryDisplayDelegate.h" 15 #include "AAX_CStringDisplayDelegate.h" 16 #include "AAX_CLinearTaperDelegate.h" 19 #include "IPlugAAX_TaperDelegate.h" 20 #include "AAX_CNumberDisplayDelegate.h" 21 #include "AAX_CUnitDisplayDelegateDecorator.h" 23 using namespace iplug;
25 AAX_CEffectParameters *AAX_CALLBACK IPlugAAX::Create()
27 return MakePlug(InstanceInfo());
30 void AAX_CEffectGUI_IPLUG::CreateViewContents()
33 mPlug =
dynamic_cast<IPlugAAX*
>(GetEffectParameters());
36 void AAX_CEffectGUI_IPLUG::CreateViewContainer()
40 void* pWindow = GetViewContainerPtr();
42 if (pWindow && mPlug->HasUI())
44 mPlug->OpenWindow(pWindow);
46 IPlugAAXView_Interface* pViewInterface = (IPlugAAXView_Interface*) mPlug->GetAAXViewInterface();
49 pViewInterface->SetViewContainer(GetViewContainer());
53 void AAX_CEffectGUI_IPLUG::DeleteViewContainer()
58 AAX_Result AAX_CEffectGUI_IPLUG::GetViewSize(AAX_Point* pNewViewSize)
const 62 pNewViewSize->horz = (float) mPlug->GetEditorWidth();
63 pNewViewSize->vert = (float) mPlug->GetEditorHeight();
69 AAX_Result AAX_CEffectGUI_IPLUG::ParameterUpdated(AAX_CParamID paramID)
74 AAX_IEffectGUI* AAX_CALLBACK AAX_CEffectGUI_IPLUG::Create()
76 return new AAX_CEffectGUI_IPLUG;
79 AAX_Result AAX_CEffectGUI_IPLUG::SetControlHighlightInfo(AAX_CParamID paramID, AAX_CBoolean iIsHighlighted, AAX_EHighlightColor iColor)
81 IPlugAAXView_Interface* pViewInterface = (IPlugAAXView_Interface*) mPlug->GetAAXViewInterface();
85 int paramIdx = atoi(paramID) - kAAXParamIdxOffset;
87 pViewInterface->SetPTParameterHighlight(paramIdx, (
bool) iIsHighlighted, (
int) iColor);
91 return AAX_ERROR_INVALID_PARAMETER_ID;
94 #pragma mark IPlugAAX Construct 96 IPlugAAX::IPlugAAX(
const InstanceInfo& info,
const Config& config)
100 Trace(TRACELOC,
"%s%s", config.pluginName, config.channelIOStr);
102 SetChannelConnections(ERoute::kInput, 0, MaxNChannels(ERoute::kInput),
true);
103 SetChannelConnections(ERoute::kOutput, 0, MaxNChannels(ERoute::kOutput),
true);
105 if (MaxNChannels(ERoute::kInput))
107 mLatencyDelay = std::unique_ptr<NChanDelayLine<PLUG_SAMPLE_DST>>(
new NChanDelayLine<PLUG_SAMPLE_DST>(MaxNChannels(ERoute::kInput), MaxNChannels(ERoute::kOutput)));
108 mLatencyDelay->SetDelayTime(config.latency);
111 SetBlockSize(DEFAULT_BLOCK_SIZE);
113 mMaxNChansForMainInputBus = MaxNChannelsForBus(kInput, 0);
118 IPlugAAX::~IPlugAAX()
120 mParamIDs.Empty(
true);
123 AAX_Result IPlugAAX::EffectInit()
127 if (GetHost() == kHostUninit)
128 SetHost(
"ProTools", 0);
130 AAX_CString bypassID = NULL;
131 this->GetMasterBypassParameter(&bypassID);
132 mBypassParameter =
new AAX_CParameter<bool>(bypassID.CString(),
133 AAX_CString(
"Master Bypass"),
135 AAX_CBinaryTaperDelegate<bool>(),
136 AAX_CBinaryDisplayDelegate<bool>(
"bypass",
"on"),
138 mBypassParameter->SetNumberOfSteps(2);
139 mBypassParameter->SetType(AAX_eParameterType_Discrete);
140 mParameterManager.AddParameter(mBypassParameter);
142 for (
int i=0; i<NParams(); i++)
145 AAX_IParameter* pAAXParam =
nullptr;
147 WDL_String* pParamIDStr =
new WDL_String(
"_", 1);
148 pParamIDStr->SetFormatted(MAX_AAX_PARAMID_LEN,
"%i", i+kAAXParamIdxOffset);
149 mParamIDs.Add(pParamIDStr);
151 switch (pParam->
Type())
153 case IParam::kTypeDouble:
155 pAAXParam =
new AAX_CParameter<double>(pParamIDStr->Get(),
156 AAX_CString(pParam->
GetName()),
158 AAX_CIPlugTaperDelegate<double>(*pParam),
159 AAX_CUnitDisplayDelegateDecorator<double>(AAX_CNumberDisplayDelegate<double>(), AAX_CString(pParam->GetLabel())),
160 pParam->GetCanAutomate());
162 pAAXParam->SetNumberOfSteps(128);
163 pAAXParam->SetType(AAX_eParameterType_Continuous);
167 case IParam::kTypeInt:
169 pAAXParam =
new AAX_CParameter<int>(pParamIDStr->Get(),
170 AAX_CString(pParam->GetName()),
171 (
int)pParam->GetDefault(),
172 AAX_CLinearTaperDelegate<
int,1>((
int)pParam->GetMin(), (
int)pParam->GetMax()),
173 AAX_CUnitDisplayDelegateDecorator<
int>(AAX_CNumberDisplayDelegate<
int,0>(), AAX_CString(pParam->GetLabel())),
174 pParam->GetCanAutomate());
176 pAAXParam->SetNumberOfSteps(128);
177 pAAXParam->SetType(AAX_eParameterType_Continuous);
186 std::map<int, AAX_CString> displayTexts;
188 for (
int j=0; j<pParam->NDisplayTexts(); j++)
191 const char* text = pParam->GetDisplayTextAtIdx(j, &value);
193 displayTexts.insert(std::pair<int, AAX_CString>(value, AAX_CString(text)));
196 pAAXParam =
new AAX_CParameter<int>(pParamIDStr->Get(),
197 AAX_CString(pParam->GetName()),
198 (
int)pParam->GetDefault(),
199 AAX_CLinearTaperDelegate<
int,1>((
int) pParam->GetMin(), (
int) pParam->GetMax()),
200 AAX_CStringDisplayDelegate<
int>(displayTexts),
201 pParam->GetCanAutomate());
203 pAAXParam->SetNumberOfSteps(nTexts);
204 pAAXParam->SetType(AAX_eParameterType_Discrete);
212 mParameterManager.AddParameter(pAAXParam);
216 Controller()->GetSampleRate(&sr);
223 AAX_Result
IPlugAAX::UpdateParameterNormalizedValue(AAX_CParamID paramID,
double iValue, AAX_EUpdateSource iSource)
227 AAX_Result result = AAX_SUCCESS;
229 AAX_IParameter* pAAXParameter = mParameterManager.GetParameterByID(paramID);
231 if (pAAXParameter ==
nullptr)
232 return AAX_ERROR_INVALID_PARAMETER_ID;
235 pAAXParameter->UpdateNormalizedValue(iValue);
237 int paramIdx = atoi(paramID) - kAAXParamIdxOffset;
239 if ((paramIdx > kNoParameter) && (paramIdx < NParams()))
243 SendParameterValueFromAPI(paramIdx, iValue,
true);
244 OnParamChange(paramIdx, kHost);
249 result = mPacketDispatcher.SetDirty(paramID);
256 void IPlugAAX::RenderAudio(AAX_SIPlugRenderInfo* pRenderInfo,
const TParamValPair* inSynchronizedParamValues[], int32_t inNumSynchronizedParamValues)
262 mBypassParameter->GetValueAsBool(&bypass);
264 AAX_EStemFormat inFormat, outFormat;
265 Controller()->GetInputStemFormat(&inFormat);
266 Controller()->GetOutputStemFormat(&outFormat);
270 AAX_IMIDINode* pMidiIn = pRenderInfo->mInputNode;
271 AAX_CMidiStream* pMidiBuffer = pMidiIn->GetNodeBuffer();
272 AAX_CMidiPacket* pMidiPacket = pMidiBuffer->mBuffer;
273 uint32_t packets_count = pMidiBuffer->mBufferSize;
275 for (
auto i = 0; i<packets_count; i++, pMidiPacket++)
277 IMidiMsg msg(pMidiPacket->mTimestamp, pMidiPacket->mData[0], pMidiPacket->mData[1], pMidiPacket->mData[2]);
279 mMidiMsgsFromProcessor.Push(msg);
283 AAX_IMIDINode* pTransportNode = pRenderInfo->mTransportNode;
284 mTransport = pTransportNode->GetTransport();
286 int32_t numSamples = *(pRenderInfo->mNumSamples);
287 int32_t numInChannels = AAX_STEM_FORMAT_CHANNEL_COUNT(inFormat);
288 int32_t numOutChannels = AAX_STEM_FORMAT_CHANNEL_COUNT(outFormat);
290 if (numSamples > GetBlockSize())
292 SetBlockSize(numSamples);
298 SetChannelConnections(ERoute::kInput, 0, numInChannels,
true);
299 SetChannelConnections(ERoute::kInput, numInChannels, MaxNChannels(ERoute::kInput) - numInChannels,
false);
301 int sideChainChannel = HasSidechainInput() ? *pRenderInfo->mSideChainP : 0;
303 if (sideChainChannel)
305 SetChannelConnections(ERoute::kInput, mMaxNChansForMainInputBus, 1,
true);
306 AttachBuffers(ERoute::kInput, 0, numInChannels, pRenderInfo->mAudioInputs, numSamples);
307 AttachBuffers(ERoute::kInput, mMaxNChansForMainInputBus, 1, pRenderInfo->mAudioInputs + sideChainChannel, numSamples);
310 AttachBuffers(ERoute::kInput, 0, numInChannels, pRenderInfo->mAudioInputs, numSamples);
313 int maxNOutChans = MaxNChannels(ERoute::kOutput);
315 SetChannelConnections(ERoute::kOutput, 0, maxNOutChans,
true);
317 if (MaxNBuses(kOutput) == 1)
319 SetChannelConnections(ERoute::kOutput, numOutChannels, maxNOutChans - numOutChannels,
false);
320 AttachBuffers(ERoute::kOutput, 0, maxNOutChans, pRenderInfo->mAudioOutputs, numSamples);
324 AttachBuffers(ERoute::kOutput, 0, maxNOutChans, pRenderInfo->mAudioOutputs, numSamples);
328 PassThroughBuffers(0.0f, numSamples);
332 int64_t ppqPos, samplePos, cStart, cEnd;
335 mTransport->GetCurrentTempo(&timeInfo.mTempo);
336 mTransport->IsTransportPlaying(&timeInfo.mTransportIsRunning);
338 mTransport->GetCurrentMeter(&num, &denom);
339 timeInfo.mNumerator = (int) num;
340 timeInfo.mDenominator = (int) denom;
342 mTransport->GetCurrentTickPosition(&ppqPos);
343 timeInfo.mPPQPos = (double) ppqPos / 960000.0;
345 if(timeInfo.mPPQPos < 0)
346 timeInfo.mPPQPos = 0;
348 mTransport->GetCurrentNativeSampleLocation(&samplePos);
349 timeInfo.mSamplePos = (double) samplePos;
351 mTransport->GetCurrentLoopPosition(&timeInfo.mTransportLoopEnabled, &cStart, &cEnd);
352 timeInfo.mCycleStart = (double) cStart / 960000.0;
353 timeInfo.mCycleEnd = (double) cEnd / 960000.0;
355 SetTimeInfo(timeInfo);
360 while (mMidiMsgsFromEditor.Pop(msg))
366 ProcessBuffers(0.0f, numSamples);
373 AAX_IMIDINode* midiOut = pRenderInfo->mOutputNode;
378 if (!mMidiOutputQueue.Empty())
380 while (!mMidiOutputQueue.Empty())
382 IMidiMsg& msg = mMidiOutputQueue.Peek();
384 AAX_CMidiPacket packet;
386 packet.mIsImmediate =
true;
388 packet.mTimestamp = (uint32_t) msg.mOffset;
391 packet.mData[0] = msg.mStatus;
392 packet.mData[1] = msg.mData1;
393 packet.mData[2] = msg.mData2;
395 midiOut->PostMIDIPacket (&packet);
397 mMidiOutputQueue.Remove();
401 mMidiOutputQueue.Flush(numSamples);
404 if(mSysExDataFromEditor.ElementsAvailable())
406 while (mSysExDataFromEditor.Pop(mSysexBuf))
408 int numPackets = (int) ceil((
float) mSysexBuf.mSize/4.);
411 for (
int p = 0; p < numPackets; p++)
413 AAX_CMidiPacket packet;
415 packet.mTimestamp = (uint32_t) mSysexBuf.mOffset;
416 packet.mIsImmediate =
true;
420 while (b < 4 && bytesPos < mSysexBuf.mSize)
422 packet.mData[b++] = mSysexBuf.mData[bytesPos++];
425 packet.mLength = (uint32_t) b;
427 midiOut->PostMIDIPacket (&packet);
435 AAX_Result IPlugAAX::GetChunkIDFromIndex(int32_t index, AAX_CTypeID* pChunkID)
const 439 *pChunkID = AAX_CTypeID(0);
440 return AAX_ERROR_INVALID_CHUNK_INDEX;
443 *pChunkID = GetUniqueID();
448 AAX_Result IPlugAAX::GetChunkSize(AAX_CTypeID chunkID, uint32_t* pSize)
const 452 if (chunkID == GetUniqueID())
458 if (SerializeState(chunk))
460 *pSize = chunk.
Size();
468 return AAX_ERROR_INVALID_CHUNK_ID;
472 AAX_Result IPlugAAX::GetChunk(AAX_CTypeID chunkID, AAX_SPlugInChunk* pChunk)
const 476 if (chunkID == GetUniqueID())
482 if (SerializeState(chunk))
484 pChunk->fSize = chunk.
Size();
485 memcpy(pChunk->fData, chunk.
GetData(), chunk.
Size());
490 return AAX_ERROR_INVALID_CHUNK_ID;
493 AAX_Result IPlugAAX::SetChunk(AAX_CTypeID chunkID,
const AAX_SPlugInChunk* pChunk)
498 if (chunkID == GetUniqueID())
501 chunk.
PutBytes(pChunk->fData, pChunk->fSize);
504 pos = UnserializeState(chunk, pos);
506 for (
int i = 0; i< NParams(); i++)
515 return AAX_ERROR_INVALID_CHUNK_ID;
518 AAX_Result IPlugAAX::CompareActiveChunk(
const AAX_SPlugInChunk* pChunk, AAX_CBoolean* pIsEqual)
const 522 if (pChunk->fChunkID != GetUniqueID())
528 *pIsEqual = CompareState((
const unsigned char*) pChunk->fData, 0);
533 AAX_Result IPlugAAX::NotificationReceived (AAX_CTypeID type,
const void* pData, uint32_t size)
537 case AAX_eNotificationEvent_TrackNameChanged:
539 mTrackName.Set(static_cast<const AAX_IString*>(pData)->Get());
545 case AAX_eNotificationEvent_EnteringOfflineMode:
546 SetRenderingOffline(
true);
548 case AAX_eNotificationEvent_ExitingOfflineMode:
549 SetRenderingOffline(
false);
560 return AAX_CEffectParameters::NotificationReceived (type, pData, size);
566 TouchParameter(mParamIDs.Get(idx)->Get());
572 SetParameterNormalizedValue(mParamIDs.Get(idx)->Get(), normalizedValue);
578 ReleaseParameter(mParamIDs.Get(idx)->Get());
585 IPlugAAXView_Interface* pViewInterface = (IPlugAAXView_Interface*) GetAAXViewInterface();
586 AAX_Point oEffectViewSize;
588 oEffectViewSize.horz = (float) viewWidth;
589 oEffectViewSize.vert = (float) viewHeight;
591 if (pViewInterface && (viewWidth != GetEditorWidth() || viewHeight != GetEditorHeight()))
593 auto* viewContainer = pViewInterface->GetViewContainer();
596 viewContainer->SetViewSize(oEffectViewSize);
599 SetEditorSize(viewWidth, viewHeight);
607 Controller()->SetSignalLatency(latency);
614 mMidiOutputQueue.Add(msg);
The base class of an IPlug plug-in, which interacts with the different plug-in APIs.
const char * GetName() const
Returns the parameter's name.
int NDisplayTexts() const
Get the number of display texts for the parameter.
Encapsulates a MIDI message and provides helper functions.
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...
const IParam * GetParam(int valIdx=0) const
Get a const pointer to the IParam object (owned by the editor delegate class), associated with this c...
void InformHostOfParamChange(int idx, double normalizedValue) override
Implemented by the API class, called by the UI via SetParameterValue() with the value of a parameter ...
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 ...
bool EditorResize(int viewWidth, int viewHeight) override
Implementations call into the APIs resize hooks returns a bool to indicate whether the DAW or plugin ...
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!...
Manages a block of memory, for plug-in settings store/recall.
AAX API base class for an IPlug plug-in.
AAX API base class for an IPlug plug-in.
double GetNormalized() const
Returns the parameter's normalized value.
void SetNormalized(double normalizedValue)
Sets the parameter value from a normalized range (usually coming from the linked IControl) ...
double GetDefault(bool normalized=false) const
Returns the parameter's default value.
int Size() const
Returns the current size of the chunk.
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...
The base class for IPlug Audio Processing.
EParamType Type() const
Get the parameter's type.
uint8_t * GetData()
Gets a ptr to the chunk data.
int PutBytes(const void *pSrc, int nBytesToCopy)
Copies data into the chunk, placing it at the end, resizing if nessecary.
Encapsulates information about the host transport state.
void SetLatency(int samples) override
Call this if the latency of your plug-in changes after initialization (perhaps from OnReset() ) This ...