1 /*
2 * Carla Plugin Host
3 * Copyright (C) 2011-2019 Filipe Coelho <falktx@falktx.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
16 */
17
18 #include "CarlaEngineOsc.hpp"
19
20 #ifdef HAVE_LIBLO
21
22 #include "CarlaBackendUtils.hpp"
23 #include "CarlaEngine.hpp"
24 #include "CarlaPlugin.hpp"
25
26 CARLA_BACKEND_START_NAMESPACE
27
28 static const char* const kNullString = "";
29
30 // -----------------------------------------------------------------------
31
sendCallback(const EngineCallbackOpcode action,const uint pluginId,const int value1,const int value2,const int value3,const float valuef,const char * const valueStr) const32 void CarlaEngineOsc::sendCallback(const EngineCallbackOpcode action, const uint pluginId,
33 const int value1, const int value2, const int value3,
34 const float valuef, const char* const valueStr) const noexcept
35 {
36 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
37 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
38 carla_stdout("CarlaEngineOsc::sendCallback(%i:%s, %i, %i, %i, %i, %f, \"%s\")",
39 action, EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3,
40 static_cast<double>(valuef), valueStr);
41
42 char targetPath[std::strlen(fControlDataTCP.path)+4];
43 std::strcpy(targetPath, fControlDataTCP.path);
44 std::strcat(targetPath, "/cb");
45 try_lo_send(fControlDataTCP.target, targetPath, "iiiiifs",
46 action, pluginId, value1, value2, value3, static_cast<double>(valuef),
47 valueStr != nullptr ? valueStr : kNullString);
48 }
49
sendPluginInfo(const CarlaPluginPtr & plugin) const50 void CarlaEngineOsc::sendPluginInfo(const CarlaPluginPtr& plugin) const noexcept
51 {
52 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
53 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
54 CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
55 carla_stdout("CarlaEngineOsc::sendPluginInfo(%p)", plugin.get());
56
57 char bufRealName[STR_MAX+1], bufLabel[STR_MAX+1], bufMaker[STR_MAX+1], bufCopyright[STR_MAX+1];
58 carla_zeroChars(bufRealName, STR_MAX+1);
59 carla_zeroChars(bufLabel, STR_MAX+1);
60 carla_zeroChars(bufMaker, STR_MAX+1);
61 carla_zeroChars(bufCopyright, STR_MAX+1);
62
63 if (! plugin->getRealName(bufRealName))
64 bufRealName[0] = '\0';
65 if (! plugin->getLabel(bufLabel))
66 bufLabel[0] = '\0';
67 if (! plugin->getMaker(bufMaker))
68 bufMaker[0] = '\0';
69 if (! plugin->getCopyright(bufCopyright))
70 bufCopyright[0] = '\0';
71
72 const char* name = plugin->getName();
73 const char* filename = plugin->getFilename();
74 const char* iconName = plugin->getIconName();
75
76 if (name == nullptr)
77 name = kNullString;
78 if (filename == nullptr)
79 filename = kNullString;
80 if (iconName == nullptr)
81 iconName = kNullString;
82
83 char targetPath[std::strlen(fControlDataTCP.path)+6];
84 std::strcpy(targetPath, fControlDataTCP.path);
85 std::strcat(targetPath, "/info");
86 try_lo_send(fControlDataTCP.target, targetPath, "iiiihiisssssss",
87 static_cast<int32_t>(plugin->getId()),
88 static_cast<int32_t>(plugin->getType()),
89 static_cast<int32_t>(plugin->getCategory()),
90 static_cast<int32_t>(plugin->getHints()),
91 static_cast<int64_t>(plugin->getUniqueId()),
92 static_cast<int64_t>(plugin->getOptionsAvailable()),
93 static_cast<int64_t>(plugin->getOptionsEnabled()),
94 name, filename, iconName,
95 bufRealName, bufLabel, bufMaker, bufCopyright);
96 }
97
sendPluginPortCount(const CarlaPluginPtr & plugin) const98 void CarlaEngineOsc::sendPluginPortCount(const CarlaPluginPtr& plugin) const noexcept
99 {
100 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
101 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
102 CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
103 carla_stdout("CarlaEngineOsc::sendPluginPortCount(%p)", plugin.get());
104
105 uint32_t paramIns, paramOuts;
106 plugin->getParameterCountInfo(paramIns, paramOuts);
107
108 if (paramIns > 49)
109 paramIns = 49;
110 if (paramOuts > 49)
111 paramOuts = 49;
112
113 char targetPath[std::strlen(fControlDataTCP.path)+7];
114 std::strcpy(targetPath, fControlDataTCP.path);
115 std::strcat(targetPath, "/ports");
116 try_lo_send(fControlDataTCP.target, targetPath, "iiiiiiii",
117 static_cast<int32_t>(plugin->getId()),
118 static_cast<int32_t>(plugin->getAudioInCount()),
119 static_cast<int32_t>(plugin->getAudioOutCount()),
120 static_cast<int32_t>(plugin->getMidiInCount()),
121 static_cast<int32_t>(plugin->getMidiOutCount()),
122 static_cast<int32_t>(paramIns),
123 static_cast<int32_t>(paramOuts),
124 static_cast<int32_t>(plugin->getParameterCount()));
125 }
126
sendPluginParameterInfo(const CarlaPluginPtr & plugin,const uint32_t index) const127 void CarlaEngineOsc::sendPluginParameterInfo(const CarlaPluginPtr& plugin, const uint32_t index) const noexcept
128 {
129 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
130 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
131 CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
132 carla_debug("CarlaEngineOsc::sendPluginParameterInfo(%p, %u)", plugin.get(), index);
133
134 char bufName[STR_MAX+1], bufUnit[STR_MAX+1], bufComment[STR_MAX+1], bufGroupName[STR_MAX+1];
135 carla_zeroChars(bufName, STR_MAX+1);
136 carla_zeroChars(bufUnit, STR_MAX+1);
137 carla_zeroChars(bufComment, STR_MAX+1);
138 carla_zeroChars(bufGroupName, STR_MAX+1);
139
140 if (! plugin->getParameterName(index, bufName))
141 bufName[0] = '\0';
142 if (! plugin->getParameterUnit(index, bufUnit))
143 bufUnit[0] = '\0';
144 if (! plugin->getParameterComment(index, bufComment))
145 bufComment[0] = '\0';
146 if (! plugin->getParameterGroupName(index, bufGroupName))
147 bufGroupName[0] = '\0';
148
149 const ParameterData& paramData(plugin->getParameterData(index));
150 const ParameterRanges& paramRanges(plugin->getParameterRanges(index));
151
152 const int32_t pluginId = static_cast<int32_t>(plugin->getId());
153 const int32_t paramId = static_cast<int32_t>(index);
154
155 char targetPath[std::strlen(fControlDataTCP.path)+13];
156
157 std::strcpy(targetPath, fControlDataTCP.path);
158 std::strcat(targetPath, "/paramInfo");
159 try_lo_send(fControlDataTCP.target, targetPath, "iissss",
160 pluginId,
161 paramId,
162 bufName,
163 bufUnit,
164 bufComment,
165 bufGroupName);
166
167 std::strcpy(targetPath, fControlDataTCP.path);
168 std::strcat(targetPath, "/paramData");
169 try_lo_send(fControlDataTCP.target, targetPath, "iiiiiifff",
170 pluginId,
171 paramId,
172 static_cast<int32_t>(paramData.type),
173 static_cast<int32_t>(paramData.hints),
174 static_cast<int32_t>(paramData.midiChannel),
175 static_cast<int32_t>(paramData.mappedControlIndex),
176 static_cast<double>(paramData.mappedMinimum),
177 static_cast<double>(paramData.mappedMaximum),
178 static_cast<double>(plugin->getParameterValue(index)));
179
180 std::strcpy(targetPath, fControlDataTCP.path);
181 std::strcat(targetPath, "/paramRanges");
182 try_lo_send(fControlDataTCP.target, targetPath, "iiffffff",
183 pluginId,
184 paramId,
185 static_cast<double>(paramRanges.def),
186 static_cast<double>(paramRanges.min),
187 static_cast<double>(paramRanges.max),
188 static_cast<double>(paramRanges.step),
189 static_cast<double>(paramRanges.stepSmall),
190 static_cast<double>(paramRanges.stepLarge));
191 }
192
sendPluginDataCount(const CarlaPluginPtr & plugin) const193 void CarlaEngineOsc::sendPluginDataCount(const CarlaPluginPtr& plugin) const noexcept
194 {
195 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
196 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
197 CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
198 carla_stdout("CarlaEngineOsc::sendPluginDataCount(%p)", plugin.get());
199
200 char targetPath[std::strlen(fControlDataTCP.path)+7];
201 std::strcpy(targetPath, fControlDataTCP.path);
202 std::strcat(targetPath, "/count");
203 try_lo_send(fControlDataTCP.target, targetPath, "iiiiii",
204 static_cast<int32_t>(plugin->getId()),
205 static_cast<int32_t>(plugin->getProgramCount()),
206 static_cast<int32_t>(plugin->getMidiProgramCount()),
207 static_cast<int32_t>(plugin->getCustomDataCount()),
208 static_cast<int32_t>(plugin->getCurrentProgram()),
209 static_cast<int32_t>(plugin->getCurrentMidiProgram()));
210 }
211
sendPluginProgramCount(const CarlaPluginPtr & plugin) const212 void CarlaEngineOsc::sendPluginProgramCount(const CarlaPluginPtr& plugin) const noexcept
213 {
214 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
215 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
216 CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
217 carla_stdout("CarlaEngineOsc::sendPluginDataCount(%p)", plugin.get());
218
219 char targetPath[std::strlen(fControlDataTCP.path)+7];
220 std::strcpy(targetPath, fControlDataTCP.path);
221 std::strcat(targetPath, "/pcount");
222 try_lo_send(fControlDataTCP.target, targetPath, "iii",
223 static_cast<int32_t>(plugin->getId()),
224 static_cast<int32_t>(plugin->getProgramCount()),
225 static_cast<int32_t>(plugin->getMidiProgramCount()));
226 }
227
sendPluginProgram(const CarlaPluginPtr & plugin,const uint32_t index) const228 void CarlaEngineOsc::sendPluginProgram(const CarlaPluginPtr& plugin, const uint32_t index) const noexcept
229 {
230 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
231 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
232 carla_stdout("CarlaEngineOsc::sendPluginProgram(%p, %u)", plugin.get(), index);
233
234 char strBuf[STR_MAX+1];
235 carla_zeroChars(strBuf, STR_MAX+1);
236 if (! plugin->getProgramName(index, strBuf))
237 strBuf[0] = '\0';
238
239 char targetPath[std::strlen(fControlDataTCP.path)+6];
240 std::strcpy(targetPath, fControlDataTCP.path);
241 std::strcat(targetPath, "/prog");
242 try_lo_send(fControlDataTCP.target, targetPath, "iis",
243 static_cast<int32_t>(plugin->getId()), static_cast<int32_t>(index), strBuf);
244 }
245
sendPluginMidiProgram(const CarlaPluginPtr & plugin,const uint32_t index) const246 void CarlaEngineOsc::sendPluginMidiProgram(const CarlaPluginPtr& plugin, const uint32_t index) const noexcept
247 {
248 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
249 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
250 carla_stdout("CarlaEngineOsc::sendPluginProgram(%p, %u)", plugin.get(), index);
251
252 const MidiProgramData& mpdata(plugin->getMidiProgramData(index));
253 CARLA_SAFE_ASSERT_RETURN(mpdata.name != nullptr,);
254
255 char targetPath[std::strlen(fControlDataTCP.path)+7];
256 std::strcpy(targetPath, fControlDataTCP.path);
257 std::strcat(targetPath, "/mprog");
258 try_lo_send(fControlDataTCP.target, targetPath, "iiiis",
259 static_cast<int32_t>(plugin->getId()),
260 static_cast<int32_t>(index),
261 static_cast<int32_t>(mpdata.bank), static_cast<int32_t>(mpdata.program), mpdata.name);
262 }
263
sendPluginCustomData(const CarlaPluginPtr & plugin,const uint32_t index) const264 void CarlaEngineOsc::sendPluginCustomData(const CarlaPluginPtr& plugin, const uint32_t index) const noexcept
265 {
266 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
267 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
268 carla_stdout("CarlaEngineOsc::sendPluginCustomData(%p, %u)", plugin.get(), index);
269
270 const CustomData& cdata(plugin->getCustomData(index));
271 CARLA_SAFE_ASSERT_RETURN(cdata.isValid(),);
272
273 char targetPath[std::strlen(fControlDataTCP.path)+7];
274 std::strcpy(targetPath, fControlDataTCP.path);
275 std::strcat(targetPath, "/cdata");
276 try_lo_send(fControlDataTCP.target, targetPath, "iisss",
277 static_cast<int32_t>(plugin->getId()),
278 static_cast<int32_t>(index),
279 cdata.type, cdata.key, cdata.value);
280 }
281
sendPluginInternalParameterValues(const CarlaPluginPtr & plugin) const282 void CarlaEngineOsc::sendPluginInternalParameterValues(const CarlaPluginPtr& plugin) const noexcept
283 {
284 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
285 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
286 CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
287 carla_debug("CarlaEngineOsc::sendPluginInternalParameterValues(%p)", plugin.get());
288
289 #ifdef CARLA_PROPER_CPP11_SUPPORT
290 static_assert(PARAMETER_ACTIVE == -2 && PARAMETER_MAX == -9, "Incorrect data");
291 #endif
292
293 double iparams[7];
294
295 for (int32_t i = 0; i < 7; ++i)
296 iparams[i] = plugin->getInternalParameterValue(PARAMETER_ACTIVE - i);
297
298 char targetPath[std::strlen(fControlDataTCP.path)+9];
299 std::strcpy(targetPath, fControlDataTCP.path);
300 std::strcat(targetPath, "/iparams");
301 try_lo_send(fControlDataTCP.target, targetPath, "ifffffff",
302 static_cast<int32_t>(plugin->getId()),
303 iparams[0], // PARAMETER_ACTIVE
304 iparams[1], // PARAMETER_DRYWET
305 iparams[2], // PARAMETER_VOLUME
306 iparams[3], // PARAMETER_BALANCE_LEFT
307 iparams[4], // PARAMETER_BALANCE_RIGHT
308 iparams[5], // PARAMETER_PANNING
309 iparams[6] // PARAMETER_CTRL_CHANNEL
310 );
311 }
312
313 // -----------------------------------------------------------------------
314
sendPing() const315 void CarlaEngineOsc::sendPing() const noexcept
316 {
317 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
318 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
319
320 char targetPath[std::strlen(fControlDataTCP.path)+6];
321 std::strcpy(targetPath, fControlDataTCP.path);
322 std::strcat(targetPath, "/ping");
323 try_lo_send(fControlDataTCP.target, targetPath, "");
324 }
325
sendResponse(const int messageId,const char * const error) const326 void CarlaEngineOsc::sendResponse(const int messageId, const char* const error) const noexcept
327 {
328 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
329 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
330 carla_debug("CarlaEngineOsc::sendResponse()");
331
332 char targetPath[std::strlen(fControlDataTCP.path)+6];
333 std::strcpy(targetPath, fControlDataTCP.path);
334 std::strcat(targetPath, "/resp");
335 try_lo_send(fControlDataTCP.target, targetPath, "is", messageId, error);
336 }
337
sendExit() const338 void CarlaEngineOsc::sendExit() const noexcept
339 {
340 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
341 CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
342 carla_debug("CarlaEngineOsc::sendExit()");
343
344 char targetPath[std::strlen(fControlDataTCP.path)+6];
345 std::strcpy(targetPath, fControlDataTCP.path);
346 std::strcat(targetPath, "/exit");
347 try_lo_send(fControlDataTCP.target, targetPath, "");
348 }
349
350 // -----------------------------------------------------------------------
351
sendRuntimeInfo() const352 void CarlaEngineOsc::sendRuntimeInfo() const noexcept
353 {
354 CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.path != nullptr && fControlDataUDP.path[0] != '\0',);
355 CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.target != nullptr,);
356
357 const EngineTimeInfo timeInfo(fEngine->getTimeInfo());
358
359 char targetPath[std::strlen(fControlDataUDP.path)+9];
360 std::strcpy(targetPath, fControlDataUDP.path);
361 std::strcat(targetPath, "/runtime");
362 try_lo_send(fControlDataUDP.target, targetPath, "fiihiiif",
363 static_cast<double>(fEngine->getDSPLoad()),
364 static_cast<int32_t>(fEngine->getTotalXruns()),
365 timeInfo.playing ? 1 : 0,
366 static_cast<int64_t>(timeInfo.frame),
367 static_cast<int32_t>(timeInfo.bbt.bar),
368 static_cast<int32_t>(timeInfo.bbt.beat),
369 static_cast<int32_t>(timeInfo.bbt.tick),
370 timeInfo.bbt.beatsPerMinute);
371 }
372
sendParameterValue(const uint pluginId,const uint32_t index,const float value) const373 void CarlaEngineOsc::sendParameterValue(const uint pluginId, const uint32_t index, const float value) const noexcept
374 {
375 CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.path != nullptr && fControlDataUDP.path[0] != '\0',);
376 CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.target != nullptr,);
377
378 char targetPath[std::strlen(fControlDataUDP.path)+7];
379 std::strcpy(targetPath, fControlDataUDP.path);
380 std::strcat(targetPath, "/param");
381 try_lo_send(fControlDataUDP.target, targetPath, "iif",
382 static_cast<int32_t>(pluginId),
383 index,
384 static_cast<double>(value));
385 }
386
sendPeaks(const uint pluginId,const float peaks[4]) const387 void CarlaEngineOsc::sendPeaks(const uint pluginId, const float peaks[4]) const noexcept
388 {
389 CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.path != nullptr && fControlDataUDP.path[0] != '\0',);
390 CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.target != nullptr,);
391
392 char targetPath[std::strlen(fControlDataUDP.path)+7];
393 std::strcpy(targetPath, fControlDataUDP.path);
394 std::strcat(targetPath, "/peaks");
395 try_lo_send(fControlDataUDP.target, targetPath, "iffff", static_cast<int32_t>(pluginId),
396 static_cast<double>(peaks[0]),
397 static_cast<double>(peaks[1]),
398 static_cast<double>(peaks[2]),
399 static_cast<double>(peaks[3]));
400 }
401
402 // -----------------------------------------------------------------------
403
404 CARLA_BACKEND_END_NAMESPACE
405
406 #endif // HAVE_LIBLO
407