iPlug2 - C++ Audio Plug-in Framework
IPlugWAM.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the iPlug 2 library. Copyright (C) the iPlug 2 developers.
5 
6  See LICENSE.txt for more info.
7 
8  ==============================================================================
9 */
10 
11 #include "IPlugWAM.h"
12 
13 using namespace iplug;
14 
15 IPlugWAM::IPlugWAM(const InstanceInfo& info, const Config& config)
16 : IPlugAPIBase(config, kAPIWAM)
17 , IPlugProcessor(config, kAPIWAM)
18 {
19  int nInputs = MaxNChannels(ERoute::kInput), nOutputs = MaxNChannels(ERoute::kOutput);
20 
21  SetChannelConnections(ERoute::kInput, 0, nInputs, true);
22  SetChannelConnections(ERoute::kOutput, 0, nOutputs, true);
23 }
24 
25 const char* IPlugWAM::init(uint32_t bufsize, uint32_t sr, void* pDesc)
26 {
27  DBGMSG("init\n");
28 
29  SetSampleRate(sr);
30  SetBlockSize(bufsize);
31 
32  DBGMSG("%i %i\n", sr, bufsize);
33 
34  WDL_String json;
35  json.Set("{\n");
36  json.AppendFormatted(8192, "\"audio\": { \"inputs\": [{ \"id\":0, \"channels\":%i }], \"outputs\": [{ \"id\":0, \"channels\":%i }] },\n", MaxNChannels(ERoute::kInput), MaxNChannels(ERoute::kOutput));
37  json.AppendFormatted(8192, "\"parameters\": [\n");
38 
39  for (int idx = 0; idx < NParams(); idx++)
40  {
41  IParam* pParam = GetParam(idx);
42  pParam->GetJSON(json, idx);
43 
44  if(idx < NParams()-1)
45  json.AppendFormatted(8192, ",\n");
46  else
47  json.AppendFormatted(8192, "\n");
48  }
49 
50  json.Append("]\n}");
51 
52  //TODO: correct place? - do we need a WAM reset message?
53  OnParamReset(kReset);
54  OnReset();
55  postMessage("StartIdleTimer", nullptr, nullptr);
56 
57  return json.Get();
58 }
59 
60 void IPlugWAM::onProcess(WAM::AudioBus* pAudio, void* pData)
61 {
62  const int blockSize = GetBlockSize();
63 
64  SetChannelConnections(ERoute::kInput, 0, MaxNChannels(ERoute::kInput), !IsInstrument()); //TODO: go elsewhere
65  SetChannelConnections(ERoute::kOutput, 0, MaxNChannels(ERoute::kOutput), true); //TODO: go elsewhere
66  AttachBuffers(ERoute::kInput, 0, NChannelsConnected(ERoute::kInput), pAudio->inputs, blockSize);
67  AttachBuffers(ERoute::kOutput, 0, NChannelsConnected(ERoute::kOutput), pAudio->outputs, blockSize);
68 
69  ENTER_PARAMS_MUTEX
70  ProcessBuffers((float) 0.0f, blockSize);
71  LEAVE_PARAMS_MUTEX
72 }
73 
74 void IPlugWAM::OnEditorIdleTick()
75 {
76  while(mParamChangeFromProcessor.ElementsAvailable())
77  {
78  ParamTuple p;
79  mParamChangeFromProcessor.Pop(p);
80  SendParameterValueFromDelegate(p.idx, p.value, false);
81  }
82 
83  while (mMidiMsgsFromProcessor.ElementsAvailable())
84  {
85  IMidiMsg msg;
86  mMidiMsgsFromProcessor.Pop(msg);
87  SendMidiMsgFromDelegate(msg);
88  }
89 
90  OnIdle();
91 }
92 
93 //WAM onMessageN
94 void IPlugWAM::onMessage(char* verb, char* res, double data)
95 {
96  if(strcmp(verb, "TICK") == 0) // special case for DSP OnIdle()
97  {
98  OnEditorIdleTick();
99  }
100  else if(strcmp(verb, "SMMFUI") == 0)
101  {
102  uint8_t data[3];
103  char* pChar = strtok(res, ":");
104  int i = 0;
105  while (pChar != nullptr) {
106  data[i++] = atoi(pChar);
107  pChar = strtok(nullptr, ":");
108  }
109 
110  IMidiMsg msg = {0, data[0], data[1], data[2]};
111  ProcessMidiMsg(msg); // TODO: should queue to mMidiMsgsFromEditor?
112  }
113  else if(strcmp(verb, "SAMFUI") == 0) // SAMFUI
114  {
115  int data[2] = {-1, -1};
116  char* pChar = strtok(res, ":");
117  int i = 0;
118  while (pChar != nullptr) {
119  data[i++] = atoi(pChar);
120  pChar = strtok(nullptr, ":");
121  }
122 
123  OnMessage(data[0], data[1], sizeof(double), reinterpret_cast<void*>(&data));
124  }
125 }
126 
127 //WAM onMessageS
128 void IPlugWAM::onMessage(char* verb, char* res, char* str)
129 {
130 }
131 
132 //WAM onMessageA
133 void IPlugWAM::onMessage(char* verb, char* res, void* pData, uint32_t size)
134 {
135  if(strcmp(verb, "SAMFUI") == 0)
136  {
137  int pos = 0;
138  IByteStream stream(pData, size);
139  int msgTag;
140  int ctrlTag;
141  int dataSize;
142  pos = stream.Get(&msgTag, pos);
143  pos = stream.Get(&ctrlTag, pos);
144  pos = stream.Get(&dataSize, pos);
145 
146  OnMessage(msgTag, ctrlTag, dataSize, stream.GetData() + (sizeof(int) * 3));
147  }
148  else if(strcmp(verb, "SSMFUI") == 0)
149  {
150  //TODO
151  }
152  else
153  {
154  DBGMSG("onMessageA not handled\n");
155  }
156 }
157 
158 void IPlugWAM::onMidi(byte status, byte data1, byte data2)
159 {
160 // DBGMSG("onMidi\n");
161  IMidiMsg msg = {0, status, data1, data2};
162  ProcessMidiMsg(msg); // onMidi is not called on HPT. We could queue things up, but just process the message straightaway for now
163  //mMidiMsgsFromProcessor.Push(msg);
164 
165  WDL_String dataStr;
166  dataStr.SetFormatted(16, "%i:%i:%i", msg.mStatus, msg.mData1, msg.mData2);
167 
168  // TODO: in the future this will be done via shared array buffer
169  // if onMidi ever gets called on HPT, should defer via queue
170  postMessage("SMMFD", dataStr.Get(), "");
171 }
172 
173 void IPlugWAM::onParam(uint32_t idparam, double value)
174 {
175 // DBGMSG("IPlugWAM:: onParam %i %f\n", idparam, value);
176  SetParameterValue(idparam, value);
177 }
178 
179 void IPlugWAM::onSysex(byte* pData, uint32_t size)
180 {
181  ISysEx sysex = {0 /* no offset */, pData, (int) size };
182  ProcessSysEx(sysex);
183 
184  WDL_String dataStr;
185  dataStr.SetFormatted(16, "%i", size);
186 
187  // TODO: in the future this will be done via shared array buffer
188  // if onSysex ever gets called on HPT, should defer via queue
189  postMessage("SSMFD", dataStr.Get(), "");
190 }
191 
192 void IPlugWAM::SendControlValueFromDelegate(int ctrlTag, double normalizedValue)
193 {
194  WDL_String propStr;
195  WDL_String dataStr;
196 
197  propStr.SetFormatted(16, "%i", ctrlTag);
198  dataStr.SetFormatted(16, "%f", normalizedValue);
199 
200  // TODO: in the future this will be done via shared array buffer
201  postMessage("SCVFD", propStr.Get(), dataStr.Get());
202 }
203 
204 void IPlugWAM::SendControlMsgFromDelegate(int ctrlTag, int msgTag, int dataSize, const void* pData)
205 {
206  WDL_String propStr;
207  propStr.SetFormatted(16, "%i:%i", ctrlTag, msgTag);
208 
209  // TODO: in the future this will be done via shared array buffer
210  postMessage("SCMFD", propStr.Get(), pData, (uint32_t) dataSize);
211 }
212 
213 void IPlugWAM::SendParameterValueFromDelegate(int paramIdx, double value, bool normalized)
214 {
215  WDL_String propStr;
216  WDL_String dataStr;
217  propStr.SetFormatted(16, "%i", paramIdx);
218  dataStr.SetFormatted(16, "%f", value);
219 
220  // TODO: in the future this will be done via shared array buffer
221  postMessage("SPVFD", propStr.Get(), dataStr.Get());
222 }
223 
224 void IPlugWAM::SendArbitraryMsgFromDelegate(int msgTag, int dataSize, const void* pData)
225 {
226  WDL_String propStr;
227  propStr.SetFormatted(16, "%i", msgTag);
228 
229  // TODO: in the future this will be done via shared array buffer
230  postMessage("SAMFD", propStr.Get(), pData, (uint32_t) dataSize);
231 }
232 
int MaxNChannels(ERoute direction) const
The base class of an IPlug plug-in, which interacts with the different plug-in APIs.
Definition: IPlugAPIBase.h:42
int GetBlockSize() const
Encapsulates a MIDI message and provides helper functions.
Definition: IPlugMidi.h:30
void GetJSON(WDL_String &json, int idx) const
Get a JSON description of the parameter.
IPlug&#39;s parameter class.
Manages a non-owned block of memory, for receiving arbitrary message byte streams.
Definition: IPlugStructs.h:267
bool IsInstrument() const
virtual void ProcessSysEx(ISysEx &msg)
Override this method to handle incoming MIDI System Exclusive (SysEx) messages.
In certain cases we need to queue parameter changes for transferral between threads.
Definition: IPlugStructs.h:32
virtual void ProcessMidiMsg(const IMidiMsg &msg)
Override this method to handle incoming MIDI messages.
The base class for IPlug Audio Processing.
virtual void OnReset()
Override this method in your plug-in class to do something prior to playback etc. ...
A struct for dealing with SysEx messages.
Definition: IPlugMidi.h:538
int NChannelsConnected(ERoute direction) const