1 /*
2 * Carla Plugin, LADSPA/DSSI implementation
3 * Copyright (C) 2011-2020 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 "CarlaPluginInternal.hpp"
19 #include "CarlaEngineUtils.hpp"
20
21 #include "CarlaBackendUtils.hpp"
22 #include "CarlaLadspaUtils.hpp"
23 #include "CarlaDssiUtils.hpp"
24 #include "CarlaMathUtils.hpp"
25
26 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
27 # include "CarlaOscUtils.hpp"
28 # include "CarlaScopeUtils.hpp"
29 # include "CarlaThread.hpp"
30 # include "water/threads/ChildProcess.h"
31 using water::ChildProcess;
32 #endif
33
34 using water::String;
35 using water::StringArray;
36
37 #define CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \
38 /* check argument count */ \
39 if (argc != argcToCompare) \
40 { \
41 carla_stderr("CarlaPluginLADSPADSSI::%s() - argument count mismatch: %i != %i", \
42 __FUNCTION__, argc, argcToCompare); \
43 return; \
44 } \
45 if (argc > 0) \
46 { \
47 /* check for nullness */ \
48 if (types == nullptr || typesToCompare == nullptr) \
49 { \
50 carla_stderr("CarlaPluginLADSPADSSI::%s() - argument types are null", \
51 __FUNCTION__); \
52 return; \
53 } \
54 /* check argument types */ \
55 if (std::strcmp(types, typesToCompare) != 0) \
56 { \
57 carla_stderr("CarlaPluginLADSPADSSI::%s() - argument types mismatch: '%s' != '%s'", \
58 __FUNCTION__, types, typesToCompare); \
59 return; \
60 } \
61 }
62
63 CARLA_BACKEND_START_NAMESPACE
64
65 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
66 // -------------------------------------------------------------------
67 // Fallback data
68
69 static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr };
70
71 // -------------------------------------------------------------------
72
73 class CarlaThreadDSSIUI : public CarlaThread
74 {
75 public:
CarlaThreadDSSIUI(CarlaEngine * const engine,CarlaPlugin * const plugin,const CarlaOscData & oscData)76 CarlaThreadDSSIUI(CarlaEngine* const engine, CarlaPlugin* const plugin, const CarlaOscData& oscData) noexcept
77 : CarlaThread("CarlaThreadDSSIUI"),
78 kEngine(engine),
79 kPlugin(plugin),
80 fBinary(),
81 fLabel(),
82 fUiTitle(),
83 fOscData(oscData),
84 fProcess() {}
85
setData(const char * const binary,const char * const label,const char * const uiTitle)86 void setData(const char* const binary, const char* const label, const char* const uiTitle) noexcept
87 {
88 CARLA_SAFE_ASSERT_RETURN(binary != nullptr && binary[0] != '\0',);
89 CARLA_SAFE_ASSERT_RETURN(label != nullptr,);
90 CARLA_SAFE_ASSERT_RETURN(uiTitle != nullptr && uiTitle[0] != '\0',);
91 CARLA_SAFE_ASSERT(! isThreadRunning());
92
93 fBinary = binary;
94 fLabel = label;
95 fUiTitle = uiTitle;
96
97 if (fLabel.isEmpty())
98 fLabel = "\"\"";
99 }
100
setUITitle(const char * const uiTitle)101 void setUITitle(const char* const uiTitle) noexcept
102 {
103 CARLA_SAFE_ASSERT_RETURN(uiTitle != nullptr && uiTitle[0] != '\0',);
104
105 fUiTitle = uiTitle;
106 }
107
getProcessId() const108 uintptr_t getProcessId() const noexcept
109 {
110 CARLA_SAFE_ASSERT_RETURN(fProcess != nullptr, 0);
111
112 return (uintptr_t)fProcess->getPID();
113 }
114
run()115 void run()
116 {
117 carla_stdout("LADSPA/DSSI UI thread started");
118
119 if (fProcess == nullptr)
120 {
121 fProcess = new ChildProcess();
122 }
123 else if (fProcess->isRunning())
124 {
125 carla_stderr("CarlaThreadDSSI::run() - already running, giving up...");
126
127 fProcess->kill();
128 fProcess = nullptr;
129 kEngine->callback(true, true,
130 ENGINE_CALLBACK_UI_STATE_CHANGED,
131 kPlugin->getId(),
132 0,
133 0, 0, 0.0f, nullptr);
134 return;
135 }
136
137 String name(kPlugin->getName());
138 String filename(kPlugin->getFilename());
139
140 if (name.isEmpty())
141 name = "(none)";
142
143 if (filename.isEmpty())
144 filename = "\"\"";
145
146 StringArray arguments;
147
148 // binary
149 arguments.add(fBinary.buffer());
150
151 // osc-url
152 arguments.add(String(kEngine->getOscServerPathUDP()) + String("/") + String(kPlugin->getId()));
153
154 // filename
155 arguments.add(filename);
156
157 // label
158 arguments.add(fLabel.buffer());
159
160 // ui-title
161 arguments.add(fUiTitle.buffer());
162
163 bool started;
164
165 {
166 #ifdef CARLA_OS_LINUX
167 /*
168 * If the frontend uses winId parent, set LD_PRELOAD to auto-map the DSSI UI.
169 * If not, unset LD_PRELOAD.
170 */
171 const uintptr_t winId(kEngine->getOptions().frontendWinId);
172
173 // for CARLA_ENGINE_OPTION_FRONTEND_WIN_ID
174 char winIdStr[STR_MAX+1];
175 winIdStr[STR_MAX] = '\0';
176
177 // for LD_PRELOAD
178 CarlaString ldPreloadValue;
179
180 if (winId != 0)
181 {
182 std::snprintf(winIdStr, STR_MAX, P_UINTPTR, winId);
183 ldPreloadValue = (CarlaString(kEngine->getOptions().binaryDir)
184 + "/libcarla_interposer-x11.so");
185 }
186 else
187 {
188 winIdStr[0] = '\0';
189 }
190
191 const ScopedEngineEnvironmentLocker _seel(kEngine);
192 const CarlaScopedEnvVar _sev1("CARLA_ENGINE_OPTION_FRONTEND_WIN_ID", winIdStr[0] != '\0' ? winIdStr : nullptr);
193 const CarlaScopedEnvVar _sev2("LD_PRELOAD", ldPreloadValue.isNotEmpty() ? ldPreloadValue.buffer() : nullptr);
194 #endif // CARLA_OS_LINUX
195
196 // start the DSSI UI application
197 carla_stdout("starting DSSI UI...");
198 started = fProcess->start(arguments);
199 }
200
201 if (! started)
202 {
203 carla_stdout("failed!");
204 fProcess = nullptr;
205 return;
206 }
207
208 if (waitForOscGuiShow())
209 {
210 for (; fProcess->isRunning() && ! shouldThreadExit();)
211 carla_sleep(1);
212
213 // we only get here if UI was closed or thread asked to exit
214 if (fProcess->isRunning() && shouldThreadExit())
215 {
216 fProcess->waitForProcessToFinish(static_cast<int>(kEngine->getOptions().uiBridgesTimeout));
217
218 if (fProcess->isRunning())
219 {
220 carla_stdout("CarlaThreadDSSIUI::run() - UI refused to close, force kill now");
221 fProcess->kill();
222 }
223 else
224 {
225 carla_stdout("CarlaThreadDSSIUI::run() - UI auto-closed successfully");
226 }
227 }
228 else if (fProcess->getExitCodeAndClearPID() != 0)
229 carla_stderr("CarlaThreadDSSIUI::run() - UI crashed while running");
230 else
231 carla_stdout("CarlaThreadDSSIUI::run() - UI closed cleanly");
232 }
233 else
234 {
235 fProcess->kill();
236 carla_stdout("CarlaThreadDSSIUI::run() - GUI timeout");
237 }
238
239 fProcess = nullptr;
240 kEngine->callback(true, true,
241 ENGINE_CALLBACK_UI_STATE_CHANGED,
242 kPlugin->getId(),
243 0,
244 0, 0, 0.0f, nullptr);
245
246 carla_stdout("LADSPA/DSSI UI thread finished");
247 }
248
249 private:
250 CarlaEngine* const kEngine;
251 CarlaPlugin* const kPlugin;
252
253 CarlaString fBinary;
254 CarlaString fLabel;
255 CarlaString fUiTitle;
256
257 const CarlaOscData& fOscData;
258 CarlaScopedPointer<ChildProcess> fProcess;
259
waitForOscGuiShow()260 bool waitForOscGuiShow()
261 {
262 carla_stdout("CarlaThreadDSSIUI::waitForOscGuiShow()");
263 const uint uiBridgesTimeout = kEngine->getOptions().uiBridgesTimeout;
264
265 // wait for UI 'update' call
266 for (uint i=0; i < uiBridgesTimeout/100; ++i)
267 {
268 if (fOscData.target != nullptr)
269 {
270 carla_stdout("CarlaThreadDSSIUI::waitForOscGuiShow() - got response, asking UI to show itself now");
271 osc_send_show(fOscData);
272 return true;
273 }
274
275 if (fProcess != nullptr && fProcess->isRunning() && ! shouldThreadExit())
276 carla_msleep(100);
277 else
278 return false;
279 }
280
281 carla_stdout("CarlaThreadDSSIUI::waitForOscGuiShow() - Timeout while waiting for UI to respond"
282 "(waited %u msecs)", uiBridgesTimeout);
283 return false;
284 }
285
286 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThreadDSSIUI)
287 };
288 #endif
289
290 // -----------------------------------------------------
291
292 class CarlaPluginLADSPADSSI : public CarlaPlugin
293 {
294 public:
CarlaPluginLADSPADSSI(CarlaEngine * const engine,const uint id)295 CarlaPluginLADSPADSSI(CarlaEngine* const engine, const uint id) noexcept
296 : CarlaPlugin(engine, id),
297 fHandles(),
298 fDescriptor(nullptr),
299 fDssiDescriptor(nullptr),
300 fRdfDescriptor(nullptr),
301 fAudioInBuffers(nullptr),
302 fAudioOutBuffers(nullptr),
303 fExtraStereoBuffer(),
304 fParamBuffers(nullptr),
305 fLatencyIndex(-1),
306 fForcedStereoIn(false),
307 fForcedStereoOut(false),
308 fNeedsFixedBuffers(false),
309 fUsesCustomData(false)
310 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
311 , fOscData(),
312 fThreadUI(engine, this, fOscData),
313 fUiFilename(nullptr)
314 #endif
315 {
316 carla_debug("CarlaPluginLADSPADSSI::CarlaPluginLADSPADSSI(%p, %i)", engine, id);
317
318 carla_zeroPointers(fExtraStereoBuffer, 2);
319 }
320
~CarlaPluginLADSPADSSI()321 ~CarlaPluginLADSPADSSI() noexcept override
322 {
323 carla_debug("CarlaPluginLADSPADSSI::~CarlaPluginLADSPADSSI()");
324
325 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
326 // close UI
327 if (fUiFilename != nullptr)
328 {
329 showCustomUI(false);
330
331 delete[] fUiFilename;
332 fUiFilename = nullptr;
333 }
334 #endif
335
336 pData->singleMutex.lock();
337 pData->masterMutex.lock();
338
339 if (pData->client != nullptr && pData->client->isActive())
340 pData->client->deactivate(true);
341
342 if (pData->active)
343 {
344 deactivate();
345 pData->active = false;
346 }
347
348 if (fDescriptor != nullptr)
349 {
350 if (fDescriptor->cleanup != nullptr)
351 {
352 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
353 {
354 LADSPA_Handle const handle(it.getValue(nullptr));
355 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
356
357 try {
358 fDescriptor->cleanup(handle);
359 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI cleanup");
360 }
361 }
362
363 fHandles.clear();
364 fDescriptor = nullptr;
365 fDssiDescriptor = nullptr;
366 }
367
368 if (fRdfDescriptor != nullptr)
369 {
370 delete fRdfDescriptor;
371 fRdfDescriptor = nullptr;
372 }
373
374 clearBuffers();
375 }
376
377 // -------------------------------------------------------------------
378 // Information (base)
379
getType() const380 PluginType getType() const noexcept override
381 {
382 return fDssiDescriptor != nullptr ? PLUGIN_DSSI : PLUGIN_LADSPA;
383 }
384
getCategory() const385 PluginCategory getCategory() const noexcept override
386 {
387 if (fRdfDescriptor != nullptr)
388 {
389 const LADSPA_RDF_PluginType category = fRdfDescriptor->Type;
390
391 // Specific Types
392 if (category & (LADSPA_RDF_PLUGIN_DELAY|LADSPA_RDF_PLUGIN_REVERB))
393 return PLUGIN_CATEGORY_DELAY;
394 if (category & (LADSPA_RDF_PLUGIN_PHASER|LADSPA_RDF_PLUGIN_FLANGER|LADSPA_RDF_PLUGIN_CHORUS))
395 return PLUGIN_CATEGORY_MODULATOR;
396 if (category & (LADSPA_RDF_PLUGIN_AMPLIFIER))
397 return PLUGIN_CATEGORY_DYNAMICS;
398 if (category & (LADSPA_RDF_PLUGIN_UTILITY|LADSPA_RDF_PLUGIN_SPECTRAL|LADSPA_RDF_PLUGIN_FREQUENCY_METER))
399 return PLUGIN_CATEGORY_UTILITY;
400
401 // Pre-set LADSPA Types
402 if (LADSPA_RDF_IS_PLUGIN_DYNAMICS(category))
403 return PLUGIN_CATEGORY_DYNAMICS;
404 if (LADSPA_RDF_IS_PLUGIN_AMPLITUDE(category))
405 return PLUGIN_CATEGORY_MODULATOR;
406 if (LADSPA_RDF_IS_PLUGIN_EQ(category))
407 return PLUGIN_CATEGORY_EQ;
408 if (LADSPA_RDF_IS_PLUGIN_FILTER(category))
409 return PLUGIN_CATEGORY_FILTER;
410 if (LADSPA_RDF_IS_PLUGIN_FREQUENCY(category))
411 return PLUGIN_CATEGORY_UTILITY;
412 if (LADSPA_RDF_IS_PLUGIN_SIMULATOR(category))
413 return PLUGIN_CATEGORY_OTHER;
414 if (LADSPA_RDF_IS_PLUGIN_TIME(category))
415 return PLUGIN_CATEGORY_DELAY;
416 if (LADSPA_RDF_IS_PLUGIN_GENERATOR(category))
417 return PLUGIN_CATEGORY_SYNTH;
418 }
419
420 if (fDssiDescriptor != nullptr && fDssiDescriptor->run_synth != nullptr)
421 if (pData->audioIn.count == 0 && pData->audioOut.count > 0)
422 return PLUGIN_CATEGORY_SYNTH;
423
424 return CarlaPlugin::getCategory();
425 }
426
getUniqueId() const427 int64_t getUniqueId() const noexcept override
428 {
429 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, 0);
430
431 return static_cast<int64_t>(fDescriptor->UniqueID);
432 }
433
getLatencyInFrames() const434 uint32_t getLatencyInFrames() const noexcept override
435 {
436 if (fLatencyIndex < 0 || fParamBuffers == nullptr)
437 return 0;
438
439 const float latency(fParamBuffers[fLatencyIndex]);
440 CARLA_SAFE_ASSERT_RETURN(latency >= 0.0f, 0);
441
442 return static_cast<uint32_t>(latency);
443 }
444
445 // -------------------------------------------------------------------
446 // Information (count)
447
getParameterScalePointCount(const uint32_t parameterId) const448 uint32_t getParameterScalePointCount(const uint32_t parameterId) const noexcept override
449 {
450 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0);
451
452 if (fRdfDescriptor == nullptr)
453 return 0;
454
455 const int32_t rindex(pData->param.data[parameterId].rindex);
456 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, 0);
457
458 if (rindex >= static_cast<int32_t>(fRdfDescriptor->PortCount))
459 return 0;
460
461 const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]);
462 return static_cast<uint32_t>(port.ScalePointCount);
463 }
464
465 // -------------------------------------------------------------------
466 // Information (current data)
467
getChunkData(void ** const dataPtr)468 std::size_t getChunkData(void** const dataPtr) noexcept override
469 {
470 CARLA_SAFE_ASSERT_RETURN(fUsesCustomData, 0);
471 CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0);
472 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr, 0);
473 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->get_custom_data != nullptr, 0);
474 CARLA_SAFE_ASSERT_RETURN(fHandles.count() > 0, 0);
475 CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0);
476
477 *dataPtr = nullptr;
478
479 int ret = 0;
480 ulong dataSize = 0;
481
482 try {
483 ret = fDssiDescriptor->get_custom_data(fHandles.getFirst(nullptr), dataPtr, &dataSize);
484 } CARLA_SAFE_EXCEPTION_RETURN("CarlaPluginLADSPADSSI::getChunkData", 0);
485
486 return (ret != 0) ? dataSize : 0;
487 }
488
489 // -------------------------------------------------------------------
490 // Information (per-plugin data)
491
getOptionsAvailable() const492 uint getOptionsAvailable() const noexcept override
493 {
494 uint options = 0x0;
495
496 // can't disable fixed buffers if using latency
497 if (fLatencyIndex == -1 && ! fNeedsFixedBuffers)
498 options |= PLUGIN_OPTION_FIXED_BUFFERS;
499
500 // can't disable forced stereo if enabled in the engine
501 if (pData->engine->getOptions().forceStereo)
502 pass();
503 // if inputs or outputs are just 1, then yes we can force stereo
504 else if (pData->audioIn.count == 1 || pData->audioOut.count == 1 || fForcedStereoIn || fForcedStereoOut)
505 options |= PLUGIN_OPTION_FORCE_STEREO;
506
507 if (fDssiDescriptor != nullptr)
508 {
509 if (fDssiDescriptor->get_program != nullptr && fDssiDescriptor->select_program != nullptr)
510 options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
511
512 if (fUsesCustomData)
513 options |= PLUGIN_OPTION_USE_CHUNKS;
514
515 if (fDssiDescriptor->run_synth != nullptr)
516 {
517 options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
518 options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
519 options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
520 options |= PLUGIN_OPTION_SEND_PITCHBEND;
521 options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
522 options |= PLUGIN_OPTION_SKIP_SENDING_NOTES;
523 }
524 }
525
526 return options;
527 }
528
getParameterValue(const uint32_t parameterId) const529 float getParameterValue(const uint32_t parameterId) const noexcept override
530 {
531 CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr, 0.0f);
532 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
533
534 // bad plugins might have set output values out of bounds
535 if (pData->param.data[parameterId].type == PARAMETER_OUTPUT)
536 return pData->param.ranges[parameterId].getFixedValue(fParamBuffers[parameterId]);
537
538 // not output, should be fine
539 return fParamBuffers[parameterId];
540 }
541
getParameterScalePointValue(const uint32_t parameterId,const uint32_t scalePointId) const542 float getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) const noexcept override
543 {
544 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0.0f);
545 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
546
547 const int32_t rindex(pData->param.data[parameterId].rindex);
548 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, 0.0f);
549 CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fRdfDescriptor->PortCount), 0.0f);
550
551 const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]);
552 CARLA_SAFE_ASSERT_RETURN(scalePointId < port.ScalePointCount, 0.0f);
553
554 const LADSPA_RDF_ScalePoint& scalePoint(port.ScalePoints[scalePointId]);
555 return pData->param.ranges[parameterId].getFixedValue(scalePoint.Value);
556 }
557
getLabel(char * const strBuf) const558 bool getLabel(char* const strBuf) const noexcept override
559 {
560 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false);
561 CARLA_SAFE_ASSERT_RETURN(fDescriptor->Label != nullptr, false);
562
563 std::strncpy(strBuf, fDescriptor->Label, STR_MAX);
564 return true;
565 }
566
getMaker(char * const strBuf) const567 bool getMaker(char* const strBuf) const noexcept override
568 {
569 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false);
570 CARLA_SAFE_ASSERT_RETURN(fDescriptor->Maker != nullptr, false);
571
572 if (fRdfDescriptor != nullptr && fRdfDescriptor->Creator != nullptr)
573 std::strncpy(strBuf, fRdfDescriptor->Creator, STR_MAX);
574 else
575 std::strncpy(strBuf, fDescriptor->Maker, STR_MAX);
576
577 return true;
578 }
579
getCopyright(char * const strBuf) const580 bool getCopyright(char* const strBuf) const noexcept override
581 {
582 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false);
583 CARLA_SAFE_ASSERT_RETURN(fDescriptor->Copyright != nullptr, false);
584
585 std::strncpy(strBuf, fDescriptor->Copyright, STR_MAX);
586 return true;
587 }
588
getRealName(char * const strBuf) const589 bool getRealName(char* const strBuf) const noexcept override
590 {
591 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false);
592 CARLA_SAFE_ASSERT_RETURN(fDescriptor->Name != nullptr, false);
593
594 if (fRdfDescriptor != nullptr && fRdfDescriptor->Title != nullptr)
595 std::strncpy(strBuf, fRdfDescriptor->Title, STR_MAX);
596 else
597 std::strncpy(strBuf, fDescriptor->Name, STR_MAX);
598
599 return true;
600 }
601
getParameterName(const uint32_t parameterId,char * const strBuf) const602 bool getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override
603 {
604 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false);
605 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
606
607 const int32_t rindex(pData->param.data[parameterId].rindex);
608 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
609 CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fDescriptor->PortCount), false);
610 CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames[rindex] != nullptr, false);
611
612 if (! getSeparatedParameterNameOrUnit(fDescriptor->PortNames[rindex], strBuf, true))
613 std::strncpy(strBuf, fDescriptor->PortNames[rindex], STR_MAX);
614
615 return true;
616 }
617
getParameterUnit(const uint32_t parameterId,char * const strBuf) const618 bool getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override
619 {
620 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
621
622 const int32_t rindex(pData->param.data[parameterId].rindex);
623 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
624
625 if (fRdfDescriptor != nullptr && rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
626 {
627 const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]);
628
629 if (LADSPA_RDF_PORT_HAS_UNIT(port.Hints))
630 {
631 switch (port.Unit)
632 {
633 case LADSPA_RDF_UNIT_DB:
634 std::strncpy(strBuf, "dB", STR_MAX);
635 return true;
636 case LADSPA_RDF_UNIT_COEF:
637 std::strncpy(strBuf, "(coef)", STR_MAX);
638 return true;
639 case LADSPA_RDF_UNIT_HZ:
640 std::strncpy(strBuf, "Hz", STR_MAX);
641 return true;
642 case LADSPA_RDF_UNIT_S:
643 std::strncpy(strBuf, "s", STR_MAX);
644 return true;
645 case LADSPA_RDF_UNIT_MS:
646 std::strncpy(strBuf, "ms", STR_MAX);
647 return true;
648 case LADSPA_RDF_UNIT_MIN:
649 std::strncpy(strBuf, "min", STR_MAX);
650 return true;
651 }
652 }
653 }
654
655 CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fDescriptor->PortCount), false);
656 CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames[rindex] != nullptr, false);
657
658 return getSeparatedParameterNameOrUnit(fDescriptor->PortNames[rindex], strBuf, false);
659 }
660
getParameterSymbol(const uint32_t parameterId,char * const strBuf) const661 bool getParameterSymbol(const uint32_t parameterId, char* const strBuf) const noexcept override
662 {
663 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
664
665 if (fRdfDescriptor == nullptr)
666 return false;
667
668 const int32_t rindex(pData->param.data[parameterId].rindex);
669 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
670
671 if (rindex >= static_cast<int32_t>(fRdfDescriptor->PortCount))
672 return false;
673
674 const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]);
675
676 if (! LADSPA_RDF_PORT_HAS_LABEL(port.Hints))
677 return false;
678
679 CARLA_SAFE_ASSERT_RETURN(port.Label != nullptr, false);
680
681 std::strncpy(strBuf, port.Label, STR_MAX);
682 return true;
683 }
684
getParameterScalePointLabel(const uint32_t parameterId,const uint32_t scalePointId,char * const strBuf) const685 bool getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) const noexcept override
686 {
687 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
688 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
689
690 const int32_t rindex(pData->param.data[parameterId].rindex);
691 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
692 CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fRdfDescriptor->PortCount), false);
693
694 const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]);
695 CARLA_SAFE_ASSERT_RETURN(scalePointId < port.ScalePointCount, false);
696
697 const LADSPA_RDF_ScalePoint& scalePoint(port.ScalePoints[scalePointId]);
698 CARLA_SAFE_ASSERT_RETURN(scalePoint.Label != nullptr, false);
699
700 std::strncpy(strBuf, scalePoint.Label, STR_MAX);
701 return true;
702 }
703
704 // -------------------------------------------------------------------
705 // Set data (state)
706
707 // nothing
708
709 // -------------------------------------------------------------------
710 // Set data (internal stuff)
711
setId(const uint newId)712 void setId(const uint newId) noexcept override
713 {
714 CarlaPlugin::setId(newId);
715
716 // UI osc-url uses Id, so we need to close it when it changes
717 // FIXME - must be RT safe
718 showCustomUI(false);
719 }
720
721 // -------------------------------------------------------------------
722 // Set data (plugin-specific stuff)
723
setParameterValue(const uint32_t parameterId,const float value,const bool sendGui,const bool sendOsc,const bool sendCallback)724 void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
725 {
726 CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr,);
727 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
728
729 const float fixedValue(pData->param.getFixedValue(parameterId, value));
730 fParamBuffers[parameterId] = fixedValue;
731
732 CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
733 }
734
setParameterValueRT(const uint32_t parameterId,const float value,const bool sendCallbackLater)735 void setParameterValueRT(const uint32_t parameterId, const float value, const bool sendCallbackLater) noexcept override
736 {
737 CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr,);
738 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
739
740 const float fixedValue(pData->param.getFixedValue(parameterId, value));
741 fParamBuffers[parameterId] = fixedValue;
742
743 CarlaPlugin::setParameterValueRT(parameterId, fixedValue, sendCallbackLater);
744 }
745
setCustomData(const char * const type,const char * const key,const char * const value,const bool sendGui)746 void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
747 {
748 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
749 CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',);
750 CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
751 CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
752 carla_debug("CarlaPluginLADSPADSSI::setCustomData(%s, %s, %s, %s)", type, key, value, bool2str(sendGui));
753
754 if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
755 return CarlaPlugin::setCustomData(type, key, value, sendGui);
756
757 if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) != 0)
758 return carla_stderr2("CarlaPluginLADSPADSSI::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string",
759 type, key, value, bool2str(sendGui));
760
761 if (fDssiDescriptor->configure != nullptr && fHandles.count() > 0)
762 {
763 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
764 {
765 LADSPA_Handle const handle(it.getValue(nullptr));
766 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
767
768 try {
769 fDssiDescriptor->configure(handle, key, value);
770 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI setCustomData");
771 }
772 }
773
774 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
775 if (sendGui && fOscData.target != nullptr)
776 osc_send_configure(fOscData, key, value);
777 #endif
778
779 if (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0)
780 {
781 const ScopedSingleProcessLocker spl(this, true);
782 reloadPrograms(false);
783 }
784
785 CarlaPlugin::setCustomData(type, key, value, sendGui);
786 }
787
setChunkData(const void * const data,const std::size_t dataSize)788 void setChunkData(const void* const data, const std::size_t dataSize) override
789 {
790 CARLA_SAFE_ASSERT_RETURN(fUsesCustomData,);
791 CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,);
792 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
793 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->set_custom_data != nullptr,);
794 CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
795 CARLA_SAFE_ASSERT_RETURN(dataSize > 0,);
796
797 if (fHandles.count() > 0)
798 {
799 const ScopedSingleProcessLocker spl(this, true);
800
801 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
802 {
803 LADSPA_Handle const handle(it.getValue(nullptr));
804 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
805
806 try {
807 fDssiDescriptor->set_custom_data(handle, const_cast<void*>(data), static_cast<ulong>(dataSize));
808 } CARLA_SAFE_EXCEPTION("CarlaPluginLADSPADSSI::setChunkData");
809 }
810 }
811
812 pData->updateParameterValues(this, true, true, false);
813 }
814
setMidiProgram(const int32_t index,const bool sendGui,const bool sendOsc,const bool sendCallback,const bool doingInit)815 void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override
816 {
817 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
818 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->select_program != nullptr,);
819 CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),);
820 CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback || doingInit,);
821
822 if (index >= 0 && fHandles.count() > 0)
823 {
824 const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback));
825
826 setMidiProgramInDSSI(static_cast<uint32_t>(index));
827 }
828
829 CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, doingInit);
830 }
831
setMidiProgramRT(const uint32_t uindex,const bool sendCallbackLater)832 void setMidiProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept override
833 {
834 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
835 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->select_program != nullptr,);
836 CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,);
837
838 setMidiProgramInDSSI(uindex);
839
840 CarlaPlugin::setMidiProgramRT(uindex, sendCallbackLater);
841 }
842
setMidiProgramInDSSI(const uint32_t uindex)843 void setMidiProgramInDSSI(const uint32_t uindex) noexcept
844 {
845 const uint32_t bank(pData->midiprog.data[uindex].bank);
846 const uint32_t program(pData->midiprog.data[uindex].program);
847
848 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
849 {
850 LADSPA_Handle const handle(it.getValue(nullptr));
851 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
852
853 try {
854 fDssiDescriptor->select_program(handle, bank, program);
855 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI setMidiProgram")
856 }
857 }
858
859 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
860 // -------------------------------------------------------------------
861 // Set ui stuff
862
setCustomUITitle(const char * title)863 void setCustomUITitle(const char* title) noexcept override
864 {
865 fThreadUI.setUITitle(title);
866 CarlaPlugin::setCustomUITitle(title);
867 }
868
showCustomUI(const bool yesNo)869 void showCustomUI(const bool yesNo) override
870 {
871 if (yesNo)
872 {
873 fOscData.clear();
874 fThreadUI.startThread();
875 }
876 else
877 {
878 #ifndef BUILD_BRIDGE
879 pData->transientTryCounter = 0;
880 #endif
881
882 if (fOscData.target != nullptr)
883 {
884 osc_send_hide(fOscData);
885 osc_send_quit(fOscData);
886 fOscData.clear();
887 }
888
889 fThreadUI.stopThread(static_cast<int>(pData->engine->getOptions().uiBridgesTimeout * 2));
890 }
891 }
892 #endif
893
894 // -------------------------------------------------------------------
895 // Plugin state
896
reload()897 void reload() override
898 {
899 CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
900 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
901 CARLA_SAFE_ASSERT_RETURN(fHandles.count() > 0,);
902 carla_debug("CarlaPluginLADSPADSSI::reload() - start");
903
904 const EngineProcessMode processMode(pData->engine->getProccessMode());
905
906 // Safely disable plugin for reload
907 const ScopedDisabler sd(this);
908
909 if (pData->active)
910 deactivate();
911
912 clearBuffers();
913
914 const float sampleRate(static_cast<float>(pData->engine->getSampleRate()));
915 const uint32_t portCount(getSafePortCount());
916
917 uint32_t aIns, aOuts, mIns, params;
918 aIns = aOuts = mIns = params = 0;
919
920 bool forcedStereoIn, forcedStereoOut;
921 forcedStereoIn = forcedStereoOut = false;
922
923 bool needsCtrlIn, needsCtrlOut;
924 needsCtrlIn = needsCtrlOut = false;
925
926 for (uint32_t i=0; i < portCount; ++i)
927 {
928 const LADSPA_PortDescriptor portType(fDescriptor->PortDescriptors[i]);
929
930 if (LADSPA_IS_PORT_AUDIO(portType))
931 {
932 if (LADSPA_IS_PORT_INPUT(portType))
933 aIns += 1;
934 else if (LADSPA_IS_PORT_OUTPUT(portType))
935 aOuts += 1;
936 }
937 else if (LADSPA_IS_PORT_CONTROL(portType))
938 params += 1;
939 }
940
941 if (pData->options & PLUGIN_OPTION_FORCE_STEREO)
942 {
943 if ((aIns == 1 || aOuts == 1) && fHandles.count() == 1 && addInstance())
944 {
945 if (aIns == 1)
946 {
947 aIns = 2;
948 forcedStereoIn = true;
949 }
950 if (aOuts == 1)
951 {
952 aOuts = 2;
953 forcedStereoOut = true;
954 }
955 }
956 }
957
958 if (fDssiDescriptor != nullptr && fDssiDescriptor->run_synth != nullptr)
959 {
960 mIns = 1;
961 needsCtrlIn = true;
962 }
963
964 if (aIns > 0)
965 {
966 pData->audioIn.createNew(aIns);
967 fAudioInBuffers = new float*[aIns];
968
969 for (uint32_t i=0; i < aIns; ++i)
970 fAudioInBuffers[i] = nullptr;
971 }
972
973 if (aOuts > 0)
974 {
975 pData->audioOut.createNew(aOuts);
976 fAudioOutBuffers = new float*[aOuts];
977 needsCtrlIn = true;
978
979 for (uint32_t i=0; i < aOuts; ++i)
980 fAudioOutBuffers[i] = nullptr;
981 }
982
983 if (params > 0)
984 {
985 pData->param.createNew(params, true);
986
987 fParamBuffers = new float[params];
988 carla_zeroFloats(fParamBuffers, params);
989 }
990
991 const uint portNameSize(pData->engine->getMaxPortNameSize());
992 CarlaString portName;
993
994 for (uint32_t i=0, iAudioIn=0, iAudioOut=0, iCtrl=0; i < portCount; ++i)
995 {
996 const LADSPA_PortDescriptor portType = fDescriptor->PortDescriptors[i];
997 const LADSPA_PortRangeHint portRangeHints = fDescriptor->PortRangeHints[i];
998 const bool hasPortRDF = (fRdfDescriptor != nullptr && i < fRdfDescriptor->PortCount);
999
1000 if (LADSPA_IS_PORT_AUDIO(portType))
1001 {
1002 portName.clear();
1003
1004 if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
1005 {
1006 portName = pData->name;
1007 portName += ":";
1008 }
1009
1010 if (fDescriptor->PortNames[i] != nullptr && fDescriptor->PortNames[i][0] != '\0')
1011 {
1012 portName += fDescriptor->PortNames[i];
1013 }
1014 else
1015 {
1016 if (LADSPA_IS_PORT_INPUT(portType))
1017 {
1018 if (aIns > 1)
1019 {
1020 portName += "audio-in_";
1021 portName += CarlaString(iAudioIn+1);
1022 }
1023 else
1024 portName += "audio-in";
1025 }
1026 else
1027 {
1028 if (aOuts > 1)
1029 {
1030 portName += "audio-out_";
1031 portName += CarlaString(iAudioOut+1);
1032 }
1033 else
1034 portName += "audio-out";
1035 }
1036 }
1037
1038 portName.truncate(portNameSize);
1039
1040 if (LADSPA_IS_PORT_INPUT(portType))
1041 {
1042 const uint32_t j = iAudioIn++;
1043 pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j);
1044 pData->audioIn.ports[j].rindex = i;
1045
1046 if (forcedStereoIn)
1047 {
1048 portName += "_2";
1049 pData->audioIn.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, 1);
1050 pData->audioIn.ports[1].rindex = i;
1051 }
1052 }
1053 else if (LADSPA_IS_PORT_OUTPUT(portType))
1054 {
1055 const uint32_t j = iAudioOut++;
1056 pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j);
1057 pData->audioOut.ports[j].rindex = i;
1058
1059 if (forcedStereoOut)
1060 {
1061 portName += "_2";
1062 pData->audioOut.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, 1);
1063 pData->audioOut.ports[1].rindex = i;
1064 }
1065 }
1066 else
1067 carla_stderr2("WARNING - Got a broken Port (Audio, but not input or output)");
1068 }
1069 else if (LADSPA_IS_PORT_CONTROL(portType))
1070 {
1071 const uint32_t j = iCtrl++;
1072 pData->param.data[j].index = static_cast<int32_t>(j);
1073 pData->param.data[j].rindex = static_cast<int32_t>(i);
1074
1075 const char* const paramName(fDescriptor->PortNames[i] != nullptr ? fDescriptor->PortNames[i] : "unknown");
1076
1077 float min, max, def, step, stepSmall, stepLarge;
1078
1079 // min value
1080 if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
1081 min = portRangeHints.LowerBound;
1082 else
1083 min = 0.0f;
1084
1085 // max value
1086 if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
1087 max = portRangeHints.UpperBound;
1088 else
1089 max = 1.0f;
1090
1091 if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
1092 {
1093 min *= sampleRate;
1094 max *= sampleRate;
1095 pData->param.data[j].hints |= PARAMETER_USES_SAMPLERATE;
1096 }
1097
1098 if (min >= max)
1099 {
1100 carla_stderr2("WARNING - Broken plugin parameter '%s': min >= max", paramName);
1101 max = min + 0.1f;
1102 }
1103
1104 // default value
1105 if (hasPortRDF && LADSPA_RDF_PORT_HAS_DEFAULT(fRdfDescriptor->Ports[i].Hints))
1106 def = fRdfDescriptor->Ports[i].Default;
1107 else
1108 def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
1109
1110 if (def < min)
1111 def = min;
1112 else if (def > max)
1113 def = max;
1114
1115 if (LADSPA_IS_HINT_TOGGLED(portRangeHints.HintDescriptor))
1116 {
1117 step = max - min;
1118 stepSmall = step;
1119 stepLarge = step;
1120 pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN;
1121 }
1122 else if (LADSPA_IS_HINT_INTEGER(portRangeHints.HintDescriptor))
1123 {
1124 step = 1.0f;
1125 stepSmall = 1.0f;
1126 stepLarge = 10.0f;
1127 pData->param.data[j].hints |= PARAMETER_IS_INTEGER;
1128 }
1129 else
1130 {
1131 const float range = max - min;
1132 step = range/100.0f;
1133 stepSmall = range/1000.0f;
1134 stepLarge = range/10.0f;
1135 }
1136
1137 if (LADSPA_IS_PORT_INPUT(portType))
1138 {
1139 pData->param.data[j].type = PARAMETER_INPUT;
1140 pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
1141 pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
1142 pData->param.data[j].hints |= PARAMETER_CAN_BE_CV_CONTROLLED;
1143 needsCtrlIn = true;
1144
1145 // MIDI CC value
1146 if (fDssiDescriptor != nullptr && fDssiDescriptor->get_midi_controller_for_port != nullptr)
1147 {
1148 const int ctrl = fDssiDescriptor->get_midi_controller_for_port(fHandles.getFirst(nullptr), i);
1149 if (DSSI_CONTROLLER_IS_SET(ctrl) && DSSI_IS_CC(ctrl))
1150 {
1151 const int16_t cc = DSSI_CC_NUMBER(ctrl);
1152 if (cc < MAX_MIDI_CONTROL && ! MIDI_IS_CONTROL_BANK_SELECT(cc))
1153 pData->param.data[j].mappedControlIndex = cc;
1154 }
1155 }
1156 }
1157 else if (LADSPA_IS_PORT_OUTPUT(portType))
1158 {
1159 pData->param.data[j].type = PARAMETER_OUTPUT;
1160
1161 if (std::strcmp(paramName, "latency") == 0 || std::strcmp(paramName, "_latency") == 0)
1162 {
1163 min = 0.0f;
1164 max = sampleRate;
1165 def = 0.0f;
1166 step = 1.0f;
1167 stepSmall = 1.0f;
1168 stepLarge = 1.0f;
1169 pData->param.special[j] = PARAMETER_SPECIAL_LATENCY;
1170 CARLA_SAFE_ASSERT_INT2(fLatencyIndex == static_cast<int32_t>(j), fLatencyIndex, j);
1171 }
1172 else
1173 {
1174 pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
1175 pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
1176 needsCtrlOut = true;
1177 }
1178 }
1179 else
1180 {
1181 carla_stderr2("WARNING - Got a broken Port (Control, but not input or output)");
1182 }
1183
1184 // extra parameter hints
1185 if (LADSPA_IS_HINT_LOGARITHMIC(portRangeHints.HintDescriptor))
1186 pData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC;
1187
1188 // check for scalepoints, require at least 2 to make it useful
1189 if (hasPortRDF && fRdfDescriptor->Ports[i].ScalePointCount >= 2)
1190 pData->param.data[j].hints |= PARAMETER_USES_SCALEPOINTS;
1191
1192 pData->param.ranges[j].min = min;
1193 pData->param.ranges[j].max = max;
1194 pData->param.ranges[j].def = def;
1195 pData->param.ranges[j].step = step;
1196 pData->param.ranges[j].stepSmall = stepSmall;
1197 pData->param.ranges[j].stepLarge = stepLarge;
1198
1199 // Start parameters in their default values
1200 fParamBuffers[j] = def;
1201
1202 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
1203 {
1204 LADSPA_Handle const handle(it.getValue(nullptr));
1205 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
1206
1207 try {
1208 fDescriptor->connect_port(handle, i, &fParamBuffers[j]);
1209 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (parameter)");
1210 }
1211 }
1212 else
1213 {
1214 // Not Audio or Control
1215 carla_stderr2("ERROR - Got a broken Port (neither Audio or Control)");
1216
1217 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
1218 {
1219 LADSPA_Handle const handle(it.getValue(nullptr));
1220 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
1221
1222 try {
1223 fDescriptor->connect_port(handle, i, nullptr);
1224 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (null)");
1225 }
1226 }
1227 }
1228
1229 if (needsCtrlIn)
1230 {
1231 portName.clear();
1232
1233 if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
1234 {
1235 portName = pData->name;
1236 portName += ":";
1237 }
1238
1239 portName += "events-in";
1240 portName.truncate(portNameSize);
1241
1242 pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0);
1243 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1244 pData->event.cvSourcePorts = pData->client->createCVSourcePorts();
1245 #endif
1246 }
1247
1248 if (needsCtrlOut)
1249 {
1250 portName.clear();
1251
1252 if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
1253 {
1254 portName = pData->name;
1255 portName += ":";
1256 }
1257
1258 portName += "events-out";
1259 portName.truncate(portNameSize);
1260
1261 pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0);
1262 }
1263
1264 if (forcedStereoIn || forcedStereoOut)
1265 pData->options |= PLUGIN_OPTION_FORCE_STEREO;
1266 else
1267 pData->options &= ~PLUGIN_OPTION_FORCE_STEREO;
1268
1269 // plugin hints
1270 pData->hints = 0x0;
1271
1272 if (LADSPA_IS_HARD_RT_CAPABLE(fDescriptor->Properties))
1273 pData->hints |= PLUGIN_IS_RTSAFE;
1274
1275 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
1276 if (fUiFilename != nullptr)
1277 pData->hints |= PLUGIN_HAS_CUSTOM_UI;
1278 #endif
1279
1280 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1281 if (aOuts > 0 && (aIns == aOuts || aIns == 1))
1282 pData->hints |= PLUGIN_CAN_DRYWET;
1283
1284 if (aOuts > 0)
1285 pData->hints |= PLUGIN_CAN_VOLUME;
1286
1287 if (aOuts >= 2 && aOuts % 2 == 0)
1288 pData->hints |= PLUGIN_CAN_BALANCE;
1289 #endif
1290
1291 // extra plugin hints
1292 pData->extraHints = 0x0;
1293
1294 if (mIns > 0)
1295 pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
1296
1297 // check initial latency
1298 findInitialLatencyValue(aIns, aOuts);
1299
1300 fForcedStereoIn = forcedStereoIn;
1301 fForcedStereoOut = forcedStereoOut;
1302
1303 bufferSizeChanged(pData->engine->getBufferSize());
1304 reloadPrograms(true);
1305
1306 if (pData->active)
1307 activate();
1308
1309 carla_debug("CarlaPluginLADSPADSSI::reload() - end");
1310 }
1311
findInitialLatencyValue(const uint32_t aIns,const uint32_t aOuts) const1312 void findInitialLatencyValue(const uint32_t aIns, const uint32_t aOuts) const
1313 {
1314 if (fLatencyIndex < 0 || fHandles.count() == 0)
1315 return;
1316
1317 // we need to pre-run the plugin so it can update its latency control-port
1318 const LADSPA_Handle handle(fHandles.getFirst(nullptr));
1319 CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
1320
1321 float tmpIn [(aIns > 0) ? aIns : 1][2];
1322 float tmpOut[(aOuts > 0) ? aOuts : 1][2];
1323
1324 for (uint32_t j=0; j < aIns; ++j)
1325 {
1326 tmpIn[j][0] = 0.0f;
1327 tmpIn[j][1] = 0.0f;
1328
1329 try {
1330 fDescriptor->connect_port(handle, pData->audioIn.ports[j].rindex, tmpIn[j]);
1331 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (latency input)");
1332 }
1333
1334 for (uint32_t j=0; j < aOuts; ++j)
1335 {
1336 tmpOut[j][0] = 0.0f;
1337 tmpOut[j][1] = 0.0f;
1338
1339 try {
1340 fDescriptor->connect_port(handle, pData->audioOut.ports[j].rindex, tmpOut[j]);
1341 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (latency output)");
1342 }
1343
1344 if (fDescriptor->activate != nullptr)
1345 {
1346 try {
1347 fDescriptor->activate(handle);
1348 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI latency activate");
1349 }
1350
1351 try {
1352 fDescriptor->run(handle, 2);
1353 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI latency run");
1354
1355 if (fDescriptor->deactivate != nullptr)
1356 {
1357 try {
1358 fDescriptor->deactivate(handle);
1359 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI latency deactivate");
1360 }
1361
1362 // done, let's get the value
1363 if (const uint32_t latency = getLatencyInFrames())
1364 {
1365 pData->client->setLatency(latency);
1366 #ifndef BUILD_BRIDGE
1367 pData->latency.recreateBuffers(std::max(aIns, aOuts), latency);
1368 #endif
1369 }
1370 }
1371
reloadPrograms(const bool doInit)1372 void reloadPrograms(const bool doInit) override
1373 {
1374 carla_debug("CarlaPluginLADSPADSSI::reloadPrograms(%s)", bool2str(doInit));
1375
1376 const LADSPA_Handle handle(fHandles.getFirst(nullptr));
1377 CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
1378
1379 const uint32_t oldCount = pData->midiprog.count;
1380 const int32_t current = pData->midiprog.current;
1381
1382 // Delete old programs
1383 pData->midiprog.clear();
1384
1385 // nothing to do for simple LADSPA plugins (do we want to bother with lrdf presets?)
1386 if (fDssiDescriptor == nullptr)
1387 return;
1388
1389 // Query new programs
1390 uint32_t newCount = 0;
1391 if (fDssiDescriptor->get_program != nullptr && fDssiDescriptor->select_program != nullptr)
1392 {
1393 for (; fDssiDescriptor->get_program(handle, newCount) != nullptr;)
1394 ++newCount;
1395 }
1396
1397 if (newCount > 0)
1398 {
1399 pData->midiprog.createNew(newCount);
1400
1401 // Update data
1402 for (uint32_t i=0; i < newCount; ++i)
1403 {
1404 const DSSI_Program_Descriptor* const pdesc(fDssiDescriptor->get_program(handle, i));
1405 CARLA_SAFE_ASSERT_CONTINUE(pdesc != nullptr);
1406 CARLA_SAFE_ASSERT(pdesc->Name != nullptr);
1407
1408 pData->midiprog.data[i].bank = static_cast<uint32_t>(pdesc->Bank);
1409 pData->midiprog.data[i].program = static_cast<uint32_t>(pdesc->Program);
1410 pData->midiprog.data[i].name = carla_strdup(pdesc->Name);
1411 }
1412 }
1413
1414 if (doInit)
1415 {
1416 if (newCount > 0)
1417 setMidiProgram(0, false, false, false, true);
1418 }
1419 else
1420 {
1421 // Check if current program is invalid
1422 bool programChanged = false;
1423
1424 if (newCount == oldCount+1)
1425 {
1426 // one midi program added, probably created by user
1427 pData->midiprog.current = static_cast<int32_t>(oldCount);
1428 programChanged = true;
1429 }
1430 else if (current < 0 && newCount > 0)
1431 {
1432 // programs exist now, but not before
1433 pData->midiprog.current = 0;
1434 programChanged = true;
1435 }
1436 else if (current >= 0 && newCount == 0)
1437 {
1438 // programs existed before, but not anymore
1439 pData->midiprog.current = -1;
1440 programChanged = true;
1441 }
1442 else if (current >= static_cast<int32_t>(newCount))
1443 {
1444 // current midi program > count
1445 pData->midiprog.current = 0;
1446 programChanged = true;
1447 }
1448 else
1449 {
1450 // no change
1451 pData->midiprog.current = current;
1452 }
1453
1454 if (programChanged)
1455 setMidiProgram(pData->midiprog.current, true, true, true, false);
1456
1457 pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0, 0.0f, nullptr);
1458 }
1459 }
1460
1461 // -------------------------------------------------------------------
1462 // Plugin processing
1463
activate()1464 void activate() noexcept override
1465 {
1466 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
1467
1468 if (fDescriptor->activate != nullptr)
1469 {
1470 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
1471 {
1472 LADSPA_Handle const handle(it.getValue(nullptr));
1473 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
1474
1475 try {
1476 fDescriptor->activate(handle);
1477 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI activate");
1478 }
1479 }
1480 }
1481
deactivate()1482 void deactivate() noexcept override
1483 {
1484 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
1485
1486 if (fDescriptor->deactivate != nullptr)
1487 {
1488 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
1489 {
1490 LADSPA_Handle const handle(it.getValue(nullptr));
1491 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
1492
1493 try {
1494 fDescriptor->deactivate(handle);
1495 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI deactivate");
1496 }
1497 }
1498 }
1499
process(const float * const * const audioIn,float ** const audioOut,const float * const * const cvIn,float **,const uint32_t frames)1500 void process(const float* const* const audioIn, float** const audioOut,
1501 const float* const* const cvIn, float**,
1502 const uint32_t frames) override
1503 {
1504 // --------------------------------------------------------------------------------------------------------
1505 // Check if active
1506
1507 if (! pData->active)
1508 {
1509 // disable any output sound
1510 for (uint32_t i=0; i < pData->audioOut.count; ++i)
1511 carla_zeroFloats(audioOut[i], frames);
1512 return;
1513 }
1514
1515 ulong midiEventCount = 0;
1516 carla_zeroStructs(fMidiEvents, kPluginMaxMidiEvents);
1517
1518 // --------------------------------------------------------------------------------------------------------
1519 // Check if needs reset
1520
1521 if (pData->needsReset)
1522 {
1523 if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
1524 {
1525 midiEventCount = MAX_MIDI_CHANNELS*2;
1526
1527 for (uchar i=0, k=MAX_MIDI_CHANNELS; i < MAX_MIDI_CHANNELS; ++i)
1528 {
1529 fMidiEvents[i].type = SND_SEQ_EVENT_CONTROLLER;
1530 fMidiEvents[i].data.control.channel = i;
1531 fMidiEvents[i].data.control.param = MIDI_CONTROL_ALL_NOTES_OFF;
1532
1533 fMidiEvents[k+i].type = SND_SEQ_EVENT_CONTROLLER;
1534 fMidiEvents[k+i].data.control.channel = i;
1535 fMidiEvents[k+i].data.control.param = MIDI_CONTROL_ALL_SOUND_OFF;
1536 }
1537 }
1538 else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS)
1539 {
1540 midiEventCount = MAX_MIDI_NOTE;
1541
1542 for (uchar i=0; i < MAX_MIDI_NOTE; ++i)
1543 {
1544 fMidiEvents[i].type = SND_SEQ_EVENT_NOTEOFF;
1545 fMidiEvents[i].data.note.channel = static_cast<uchar>(pData->ctrlChannel);
1546 fMidiEvents[i].data.note.note = i;
1547 }
1548 }
1549
1550 pData->needsReset = false;
1551 }
1552
1553 // --------------------------------------------------------------------------------------------------------
1554 // Event Input and Processing
1555
1556 if (pData->event.portIn != nullptr)
1557 {
1558 // ----------------------------------------------------------------------------------------------------
1559 // MIDI Input (External)
1560
1561 if (pData->extNotes.mutex.tryLock())
1562 {
1563 ExternalMidiNote note = { 0, 0, 0 };
1564
1565 for (; midiEventCount < kPluginMaxMidiEvents && ! pData->extNotes.data.isEmpty();)
1566 {
1567 note = pData->extNotes.data.getFirst(note, true);
1568 CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
1569
1570 snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]);
1571
1572 seqEvent.type = (note.velo > 0) ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF;
1573 seqEvent.data.note.channel = static_cast<uchar>(note.channel);
1574 seqEvent.data.note.note = note.note;
1575 seqEvent.data.note.velocity = note.velo;
1576 }
1577
1578 pData->extNotes.mutex.unlock();
1579
1580 } // End of MIDI Input (External)
1581
1582 // ----------------------------------------------------------------------------------------------------
1583 // Event Input (System)
1584
1585 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1586 bool allNotesOffSent = false;
1587 #endif
1588 const bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0;
1589
1590 uint32_t startTime = 0;
1591 uint32_t timeOffset = 0;
1592 uint32_t nextBankId;
1593
1594 if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
1595 nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
1596 else
1597 nextBankId = 0;
1598
1599 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1600 if (cvIn != nullptr && pData->event.cvSourcePorts != nullptr)
1601 pData->event.cvSourcePorts->initPortBuffers(cvIn, frames, isSampleAccurate, pData->event.portIn);
1602 #endif
1603
1604 for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i)
1605 {
1606 EngineEvent& event(pData->event.portIn->getEvent(i));
1607
1608 uint32_t eventTime = event.time;
1609 CARLA_SAFE_ASSERT_UINT2_CONTINUE(eventTime < frames, eventTime, frames);
1610
1611 if (eventTime < timeOffset)
1612 {
1613 carla_stderr2("Timing error, eventTime:%u < timeOffset:%u for '%s'",
1614 eventTime, timeOffset, pData->name);
1615 eventTime = timeOffset;
1616 }
1617
1618 if (isSampleAccurate && eventTime > timeOffset)
1619 {
1620 if (processSingle(audioIn, audioOut, eventTime - timeOffset, timeOffset, midiEventCount))
1621 {
1622 startTime = 0;
1623 timeOffset = eventTime;
1624 midiEventCount = 0;
1625
1626 if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
1627 nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
1628 else
1629 nextBankId = 0;
1630 }
1631 else
1632 startTime += timeOffset;
1633 }
1634
1635 switch (event.type)
1636 {
1637 case kEngineEventTypeNull:
1638 break;
1639
1640 case kEngineEventTypeControl: {
1641 EngineControlEvent& ctrlEvent(event.ctrl);
1642
1643 switch (ctrlEvent.type)
1644 {
1645 case kEngineControlEventTypeNull:
1646 break;
1647
1648 case kEngineControlEventTypeParameter: {
1649 float value;
1650
1651 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1652 // non-midi
1653 if (event.channel == kEngineEventNonMidiChannel)
1654 {
1655 const uint32_t k = ctrlEvent.param;
1656 CARLA_SAFE_ASSERT_CONTINUE(k < pData->param.count);
1657
1658 ctrlEvent.handled = true;
1659 value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.normalizedValue);
1660 setParameterValueRT(k, value, true);
1661 continue;
1662 }
1663
1664 // Control backend stuff
1665 if (event.channel == pData->ctrlChannel)
1666 {
1667 if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0)
1668 {
1669 ctrlEvent.handled = true;
1670 value = ctrlEvent.normalizedValue;
1671 setDryWetRT(value, true);
1672 }
1673 else if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0)
1674 {
1675 ctrlEvent.handled = true;
1676 value = ctrlEvent.normalizedValue*127.0f/100.0f;
1677 setVolumeRT(value, true);
1678 }
1679 else if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0)
1680 {
1681 float left, right;
1682 value = ctrlEvent.normalizedValue/0.5f - 1.0f;
1683
1684 if (value < 0.0f)
1685 {
1686 left = -1.0f;
1687 right = (value*2.0f)+1.0f;
1688 }
1689 else if (value > 0.0f)
1690 {
1691 left = (value*2.0f)-1.0f;
1692 right = 1.0f;
1693 }
1694 else
1695 {
1696 left = -1.0f;
1697 right = 1.0f;
1698 }
1699
1700 ctrlEvent.handled = true;
1701 setBalanceLeftRT(left, true);
1702 setBalanceRightRT(right, true);
1703 }
1704 }
1705 #endif
1706 // Control plugin parameters
1707 for (uint32_t k=0; k < pData->param.count; ++k)
1708 {
1709 if (pData->param.data[k].midiChannel != event.channel)
1710 continue;
1711 if (pData->param.data[k].mappedControlIndex != ctrlEvent.param)
1712 continue;
1713 if (pData->param.data[k].type != PARAMETER_INPUT)
1714 continue;
1715 if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0)
1716 continue;
1717
1718 ctrlEvent.handled = true;
1719 value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.normalizedValue);
1720 setParameterValueRT(k, value, true);
1721 }
1722
1723 if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_VALUE)
1724 {
1725 if (midiEventCount >= kPluginMaxMidiEvents)
1726 continue;
1727
1728 snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]);
1729
1730 seqEvent.time.tick = isSampleAccurate ? startTime : eventTime;
1731
1732 seqEvent.type = SND_SEQ_EVENT_CONTROLLER;
1733 seqEvent.data.control.channel = event.channel;
1734 seqEvent.data.control.param = ctrlEvent.param;
1735 seqEvent.data.control.value = int8_t(ctrlEvent.normalizedValue*127.0f);
1736 }
1737
1738 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1739 if (! ctrlEvent.handled)
1740 checkForMidiLearn(event);
1741 #endif
1742 break;
1743 } // case kEngineControlEventTypeParameter
1744
1745 case kEngineControlEventTypeMidiBank:
1746 if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
1747 nextBankId = ctrlEvent.param;
1748 break;
1749
1750 case kEngineControlEventTypeMidiProgram:
1751 if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
1752 {
1753 const uint32_t nextProgramId = ctrlEvent.param;
1754
1755 for (uint32_t k=0; k < pData->midiprog.count; ++k)
1756 {
1757 if (pData->midiprog.data[k].bank == nextBankId && pData->midiprog.data[k].program == nextProgramId)
1758 {
1759 setMidiProgramRT(k, true);
1760 break;
1761 }
1762 }
1763 }
1764 break;
1765
1766 case kEngineControlEventTypeAllSoundOff:
1767 if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
1768 {
1769 if (midiEventCount >= kPluginMaxMidiEvents)
1770 continue;
1771
1772 snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]);
1773
1774 seqEvent.time.tick = isSampleAccurate ? startTime : eventTime;
1775
1776 seqEvent.type = SND_SEQ_EVENT_CONTROLLER;
1777 seqEvent.data.control.channel = event.channel;
1778 seqEvent.data.control.param = MIDI_CONTROL_ALL_SOUND_OFF;
1779 }
1780 break;
1781
1782 case kEngineControlEventTypeAllNotesOff:
1783 if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
1784 {
1785 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1786 if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
1787 {
1788 allNotesOffSent = true;
1789 postponeRtAllNotesOff();
1790 }
1791 #endif
1792
1793 if (midiEventCount >= kPluginMaxMidiEvents)
1794 continue;
1795
1796 snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]);
1797
1798 seqEvent.time.tick = isSampleAccurate ? startTime : eventTime;
1799
1800 seqEvent.type = SND_SEQ_EVENT_CONTROLLER;
1801 seqEvent.data.control.channel = event.channel;
1802 seqEvent.data.control.param = MIDI_CONTROL_ALL_NOTES_OFF;
1803 }
1804 break;
1805 } // switch (ctrlEvent.type)
1806 break;
1807 } // case kEngineEventTypeControl
1808
1809 case kEngineEventTypeMidi: {
1810 if (midiEventCount >= kPluginMaxMidiEvents)
1811 continue;
1812
1813 const EngineMidiEvent& midiEvent(event.midi);
1814
1815 if (midiEvent.size > EngineMidiEvent::kDataSize)
1816 continue;
1817
1818 uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data));
1819
1820 // Fix bad note-off (per DSSI spec)
1821 if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0)
1822 status = MIDI_STATUS_NOTE_OFF;
1823
1824 snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]);
1825
1826 seqEvent.time.tick = isSampleAccurate ? startTime : eventTime;
1827
1828 switch (status)
1829 {
1830 case MIDI_STATUS_NOTE_OFF:
1831 if ((pData->options & PLUGIN_OPTION_SKIP_SENDING_NOTES) == 0x0)
1832 {
1833 const uint8_t note = midiEvent.data[1];
1834
1835 seqEvent.type = SND_SEQ_EVENT_NOTEOFF;
1836 seqEvent.data.note.channel = event.channel;
1837 seqEvent.data.note.note = note;
1838
1839 pData->postponeNoteOffRtEvent(true, event.channel, note);
1840 }
1841 break;
1842
1843 case MIDI_STATUS_NOTE_ON:
1844 if ((pData->options & PLUGIN_OPTION_SKIP_SENDING_NOTES) == 0x0)
1845 {
1846 const uint8_t note = midiEvent.data[1];
1847 const uint8_t velo = midiEvent.data[2];
1848
1849 seqEvent.type = SND_SEQ_EVENT_NOTEON;
1850 seqEvent.data.note.channel = event.channel;
1851 seqEvent.data.note.note = note;
1852 seqEvent.data.note.velocity = velo;
1853
1854 pData->postponeNoteOnRtEvent(true, event.channel, note, velo);
1855 }
1856 break;
1857
1858 case MIDI_STATUS_POLYPHONIC_AFTERTOUCH:
1859 if (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH)
1860 {
1861 const uint8_t note = midiEvent.data[1];
1862 const uint8_t pressure = midiEvent.data[2];
1863
1864 seqEvent.type = SND_SEQ_EVENT_KEYPRESS;
1865 seqEvent.data.note.channel = event.channel;
1866 seqEvent.data.note.note = note;
1867 seqEvent.data.note.velocity = pressure;
1868 }
1869 break;
1870
1871 case MIDI_STATUS_CONTROL_CHANGE:
1872 if (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES)
1873 {
1874 const uint8_t control = midiEvent.data[1];
1875 const uint8_t value = midiEvent.data[2];
1876
1877 seqEvent.type = SND_SEQ_EVENT_CONTROLLER;
1878 seqEvent.data.control.channel = event.channel;
1879 seqEvent.data.control.param = control;
1880 seqEvent.data.control.value = value;
1881 }
1882 break;
1883
1884 case MIDI_STATUS_CHANNEL_PRESSURE:
1885 if (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE)
1886 {
1887 const uint8_t pressure = midiEvent.data[1];
1888
1889 seqEvent.type = SND_SEQ_EVENT_CHANPRESS;
1890 seqEvent.data.control.channel = event.channel;
1891 seqEvent.data.control.value = pressure;
1892 }
1893 break;
1894
1895 case MIDI_STATUS_PITCH_WHEEL_CONTROL:
1896 if (pData->options & PLUGIN_OPTION_SEND_PITCHBEND)
1897 {
1898 const uint8_t lsb = midiEvent.data[1];
1899 const uint8_t msb = midiEvent.data[2];
1900
1901 seqEvent.type = SND_SEQ_EVENT_PITCHBEND;
1902 seqEvent.data.control.channel = event.channel;
1903 seqEvent.data.control.value = ((msb << 7) | lsb) - 8192;
1904 }
1905 break;
1906
1907 default:
1908 --midiEventCount;
1909 break;
1910 } // switch (status)
1911 } break;
1912 } // switch (event.type)
1913 }
1914
1915 pData->postRtEvents.trySplice();
1916
1917 if (frames > timeOffset)
1918 processSingle(audioIn, audioOut, frames - timeOffset, timeOffset, midiEventCount);
1919
1920 } // End of Event Input and Processing
1921
1922 // --------------------------------------------------------------------------------------------------------
1923 // Plugin processing (no events)
1924
1925 else
1926 {
1927 processSingle(audioIn, audioOut, frames, 0, midiEventCount);
1928
1929 } // End of Plugin processing (no events)
1930
1931 // --------------------------------------------------------------------------------------------------------
1932 // Control Output
1933
1934 if (pData->event.portOut != nullptr)
1935 {
1936 uint8_t channel;
1937 uint16_t param;
1938 float value;
1939
1940 for (uint32_t k=0; k < pData->param.count; ++k)
1941 {
1942 if (pData->param.data[k].type != PARAMETER_OUTPUT)
1943 continue;
1944
1945 pData->param.ranges[k].fixValue(fParamBuffers[k]);
1946
1947 if (pData->param.data[k].mappedControlIndex > 0)
1948 {
1949 channel = pData->param.data[k].midiChannel;
1950 param = static_cast<uint16_t>(pData->param.data[k].mappedControlIndex);
1951 value = pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]);
1952 pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter,
1953 param, -1, value);
1954 }
1955 }
1956 } // End of Control Output
1957
1958 #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH
1959 return;
1960
1961 // unused
1962 (void)cvIn;
1963 #endif
1964 }
1965
processSingle(const float * const * const audioIn,float ** const audioOut,const uint32_t frames,const uint32_t timeOffset,const ulong midiEventCount)1966 bool processSingle(const float* const* const audioIn, float** const audioOut, const uint32_t frames,
1967 const uint32_t timeOffset, const ulong midiEventCount)
1968 {
1969 CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
1970
1971 if (pData->audioIn.count > 0)
1972 {
1973 CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false);
1974 }
1975 if (pData->audioOut.count > 0)
1976 {
1977 CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false);
1978 }
1979
1980 // --------------------------------------------------------------------------------------------------------
1981 // Try lock, silence otherwise
1982
1983 #ifndef STOAT_TEST_BUILD
1984 if (pData->engine->isOffline())
1985 {
1986 pData->singleMutex.lock();
1987 }
1988 else
1989 #endif
1990 if (! pData->singleMutex.tryLock())
1991 {
1992 for (uint32_t i=0; i < pData->audioOut.count; ++i)
1993 {
1994 for (uint32_t k=0; k < frames; ++k)
1995 audioOut[i][k+timeOffset] = 0.0f;
1996 }
1997
1998 return false;
1999 }
2000
2001 // --------------------------------------------------------------------------------------------------------
2002 // Set audio buffers
2003
2004 const bool customMonoOut = pData->audioOut.count == 2 && fForcedStereoOut && ! fForcedStereoIn;
2005 const bool customStereoOut = pData->audioOut.count == 2 && fForcedStereoIn && ! fForcedStereoOut;
2006
2007 if (! customMonoOut)
2008 {
2009 for (uint32_t i=0; i < pData->audioOut.count; ++i)
2010 carla_zeroFloats(fAudioOutBuffers[i], frames);
2011 }
2012
2013 for (uint32_t i=0; i < pData->audioIn.count; ++i)
2014 carla_copyFloats(fAudioInBuffers[i], audioIn[i]+timeOffset, frames);
2015
2016 // --------------------------------------------------------------------------------------------------------
2017 // Run plugin
2018
2019 uint instn = 0;
2020 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next(), ++instn)
2021 {
2022 LADSPA_Handle const handle(it.getValue(nullptr));
2023 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
2024
2025 // ----------------------------------------------------------------------------------------------------
2026 // Mixdown for forced stereo
2027
2028 if (customMonoOut)
2029 carla_zeroFloats(fAudioOutBuffers[instn], frames);
2030
2031 // ----------------------------------------------------------------------------------------------------
2032 // Run it
2033
2034 if (fDssiDescriptor != nullptr && fDssiDescriptor->run_synth != nullptr)
2035 {
2036 try {
2037 fDssiDescriptor->run_synth(handle, frames, fMidiEvents, midiEventCount);
2038 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI run_synth");
2039 }
2040 else
2041 {
2042 try {
2043 fDescriptor->run(handle, frames);
2044 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI run");
2045 }
2046
2047 // ----------------------------------------------------------------------------------------------------
2048 // Mixdown for forced stereo
2049
2050 if (customMonoOut)
2051 carla_multiply(fAudioOutBuffers[instn], 0.5f, frames);
2052 else if (customStereoOut)
2053 carla_copyFloats(fExtraStereoBuffer[instn], fAudioOutBuffers[instn], frames);
2054 }
2055
2056 if (customStereoOut)
2057 {
2058 carla_copyFloats(fAudioOutBuffers[0], fExtraStereoBuffer[0], frames);
2059 carla_copyFloats(fAudioOutBuffers[1], fExtraStereoBuffer[1], frames);
2060 }
2061
2062 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2063 // --------------------------------------------------------------------------------------------------------
2064 // Post-processing (dry/wet, volume and balance)
2065
2066 {
2067 const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && carla_isNotEqual(pData->postProc.dryWet, 1.0f);
2068 const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f));
2069 const bool isMono = (pData->audioIn.count == 1);
2070
2071 bool isPair;
2072 float bufValue, oldBufLeft[doBalance ? frames : 1];
2073
2074 for (uint32_t i=0; i < pData->audioOut.count; ++i)
2075 {
2076 // Dry/Wet
2077 if (doDryWet)
2078 {
2079 const uint32_t c = isMono ? 0 : i;
2080
2081 for (uint32_t k=0; k < frames; ++k)
2082 {
2083 # ifndef BUILD_BRIDGE
2084 if (k < pData->latency.frames && pData->latency.buffers != nullptr)
2085 bufValue = pData->latency.buffers[c][k];
2086 else if (pData->latency.frames < frames)
2087 bufValue = fAudioInBuffers[c][k-pData->latency.frames];
2088 else
2089 # endif
2090 bufValue = fAudioInBuffers[c][k];
2091
2092 fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
2093 }
2094 }
2095
2096 // Balance
2097 if (doBalance)
2098 {
2099 isPair = (i % 2 == 0);
2100
2101 if (isPair)
2102 {
2103 CARLA_ASSERT(i+1 < pData->audioOut.count);
2104 carla_copyFloats(oldBufLeft, fAudioOutBuffers[i], frames);
2105 }
2106
2107 float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
2108 float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
2109
2110 for (uint32_t k=0; k < frames; ++k)
2111 {
2112 if (isPair)
2113 {
2114 // left
2115 fAudioOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
2116 fAudioOutBuffers[i][k] += fAudioOutBuffers[i+1][k] * (1.0f - balRangeR);
2117 }
2118 else
2119 {
2120 // right
2121 fAudioOutBuffers[i][k] = fAudioOutBuffers[i][k] * balRangeR;
2122 fAudioOutBuffers[i][k] += oldBufLeft[k] * balRangeL;
2123 }
2124 }
2125 }
2126
2127 // Volume (and buffer copy)
2128 {
2129 for (uint32_t k=0; k < frames; ++k)
2130 audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k] * pData->postProc.volume;
2131 }
2132 }
2133
2134 } // End of Post-processing
2135
2136 # ifndef BUILD_BRIDGE
2137 // --------------------------------------------------------------------------------------------------------
2138 // Save latency values for next callback
2139
2140 if (pData->latency.frames != 0 && pData->latency.buffers != nullptr)
2141 {
2142 CARLA_SAFE_ASSERT(timeOffset == 0);
2143 const uint32_t latframes = pData->latency.frames;
2144
2145 if (latframes <= frames)
2146 {
2147 for (uint32_t i=0; i < pData->audioIn.count; ++i)
2148 carla_copyFloats(pData->latency.buffers[i], audioIn[i]+(frames-latframes), latframes);
2149 }
2150 else
2151 {
2152 const uint32_t diff = latframes - frames;
2153
2154 for (uint32_t i=0, k; i<pData->audioIn.count; ++i)
2155 {
2156 // push back buffer by 'frames'
2157 for (k=0; k < diff; ++k)
2158 pData->latency.buffers[i][k] = pData->latency.buffers[i][k+frames];
2159
2160 // put current input at the end
2161 for (uint32_t j=0; k < latframes; ++j, ++k)
2162 pData->latency.buffers[i][k] = audioIn[i][j];
2163 }
2164 }
2165 }
2166 # endif
2167 #else // BUILD_BRIDGE_ALTERNATIVE_ARCH
2168 for (uint32_t i=0; i < pData->audioOut.count; ++i)
2169 {
2170 for (uint32_t k=0; k < frames; ++k)
2171 audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k];
2172 }
2173 #endif
2174
2175 // --------------------------------------------------------------------------------------------------------
2176
2177 pData->singleMutex.unlock();
2178 return true;
2179 }
2180
bufferSizeChanged(const uint32_t newBufferSize)2181 void bufferSizeChanged(const uint32_t newBufferSize) override
2182 {
2183 CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize);
2184 carla_debug("CarlaPluginLADSPADSSI::bufferSizeChanged(%i) - start", newBufferSize);
2185
2186 for (uint32_t i=0; i < pData->audioIn.count; ++i)
2187 {
2188 if (fAudioInBuffers[i] != nullptr)
2189 delete[] fAudioInBuffers[i];
2190
2191 fAudioInBuffers[i] = new float[newBufferSize];
2192 carla_zeroFloats(fAudioInBuffers[i], newBufferSize);
2193 }
2194
2195 for (uint32_t i=0; i < pData->audioOut.count; ++i)
2196 {
2197 if (fAudioOutBuffers[i] != nullptr)
2198 delete[] fAudioOutBuffers[i];
2199
2200 fAudioOutBuffers[i] = new float[newBufferSize];
2201 carla_zeroFloats(fAudioOutBuffers[i], newBufferSize);
2202 }
2203
2204 if (fExtraStereoBuffer[0] != nullptr)
2205 {
2206 delete[] fExtraStereoBuffer[0];
2207 fExtraStereoBuffer[0] = nullptr;
2208 }
2209
2210 if (fExtraStereoBuffer[1] != nullptr)
2211 {
2212 delete[] fExtraStereoBuffer[1];
2213 fExtraStereoBuffer[1] = nullptr;
2214 }
2215
2216 if (fForcedStereoIn && pData->audioOut.count == 2)
2217 {
2218 fExtraStereoBuffer[0] = new float[newBufferSize];
2219 fExtraStereoBuffer[1] = new float[newBufferSize];
2220 carla_zeroFloats(fExtraStereoBuffer[0], newBufferSize);
2221 carla_zeroFloats(fExtraStereoBuffer[1], newBufferSize);
2222 }
2223
2224 reconnectAudioPorts();
2225
2226 carla_debug("CarlaPluginLADSPADSSI::bufferSizeChanged(%i) - end", newBufferSize);
2227 }
2228
sampleRateChanged(const double newSampleRate)2229 void sampleRateChanged(const double newSampleRate) override
2230 {
2231 CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate);
2232 carla_debug("CarlaPluginLADSPADSSI::sampleRateChanged(%g) - start", newSampleRate);
2233
2234 // TODO - handle UI stuff
2235
2236 if (pData->active)
2237 deactivate();
2238
2239 const std::size_t instanceCount(fHandles.count());
2240
2241 if (fDescriptor->cleanup != nullptr)
2242 {
2243 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
2244 {
2245 LADSPA_Handle const handle(it.getValue(nullptr));
2246 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
2247
2248 try {
2249 fDescriptor->cleanup(handle);
2250 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI cleanup");
2251 }
2252 }
2253
2254 fHandles.clear();
2255
2256 for (std::size_t i=0; i<instanceCount; ++i)
2257 addInstance();
2258
2259 reconnectAudioPorts();
2260
2261 if (pData->active)
2262 activate();
2263
2264 carla_debug("CarlaPluginLADSPADSSI::sampleRateChanged(%g) - end", newSampleRate);
2265 }
2266
reconnectAudioPorts() const2267 void reconnectAudioPorts() const noexcept
2268 {
2269 if (fForcedStereoIn)
2270 {
2271 if (LADSPA_Handle const handle = fHandles.getFirst(nullptr))
2272 {
2273 try {
2274 fDescriptor->connect_port(handle, pData->audioIn.ports[0].rindex, fAudioInBuffers[0]);
2275 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo input, first)");
2276 }
2277
2278 if (LADSPA_Handle const handle = fHandles.getLast(nullptr))
2279 {
2280 try {
2281 fDescriptor->connect_port(handle, pData->audioIn.ports[1].rindex, fAudioInBuffers[1]);
2282 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo input, last)");
2283 }
2284 }
2285 else
2286 {
2287 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
2288 {
2289 LADSPA_Handle const handle(it.getValue(nullptr));
2290 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
2291
2292 for (uint32_t i=0; i < pData->audioIn.count; ++i)
2293 {
2294 try {
2295 fDescriptor->connect_port(handle, pData->audioIn.ports[i].rindex, fAudioInBuffers[i]);
2296 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (audio input)");
2297 }
2298 }
2299 }
2300
2301 if (fForcedStereoOut)
2302 {
2303 if (LADSPA_Handle const handle = fHandles.getFirst(nullptr))
2304 {
2305 try {
2306 fDescriptor->connect_port(handle, pData->audioOut.ports[0].rindex, fAudioOutBuffers[0]);
2307 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo output, first)");
2308 }
2309
2310 if (LADSPA_Handle const handle = fHandles.getLast(nullptr))
2311 {
2312 try {
2313 fDescriptor->connect_port(handle, pData->audioOut.ports[1].rindex, fAudioOutBuffers[1]);
2314 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo output, last)");
2315 }
2316 }
2317 else
2318 {
2319 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
2320 {
2321 LADSPA_Handle const handle(it.getValue(nullptr));
2322 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
2323
2324 for (uint32_t i=0; i < pData->audioOut.count; ++i)
2325 {
2326 try {
2327 fDescriptor->connect_port(handle, pData->audioOut.ports[i].rindex, fAudioOutBuffers[i]);
2328 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (audio output)");
2329 }
2330 }
2331 }
2332 }
2333
2334 // -------------------------------------------------------------------
2335 // Plugin buffers
2336
clearBuffers()2337 void clearBuffers() noexcept override
2338 {
2339 carla_debug("CarlaPluginLADSPADSSI::clearBuffers() - start");
2340
2341 if (fAudioInBuffers != nullptr)
2342 {
2343 for (uint32_t i=0; i < pData->audioIn.count; ++i)
2344 {
2345 if (fAudioInBuffers[i] != nullptr)
2346 {
2347 delete[] fAudioInBuffers[i];
2348 fAudioInBuffers[i] = nullptr;
2349 }
2350 }
2351
2352 delete[] fAudioInBuffers;
2353 fAudioInBuffers = nullptr;
2354 }
2355
2356 if (fAudioOutBuffers != nullptr)
2357 {
2358 for (uint32_t i=0; i < pData->audioOut.count; ++i)
2359 {
2360 if (fAudioOutBuffers[i] != nullptr)
2361 {
2362 delete[] fAudioOutBuffers[i];
2363 fAudioOutBuffers[i] = nullptr;
2364 }
2365 }
2366
2367 delete[] fAudioOutBuffers;
2368 fAudioOutBuffers = nullptr;
2369 }
2370
2371 if (fExtraStereoBuffer[0] != nullptr)
2372 {
2373 delete[] fExtraStereoBuffer[0];
2374 fExtraStereoBuffer[0] = nullptr;
2375 }
2376
2377 if (fExtraStereoBuffer[1] != nullptr)
2378 {
2379 delete[] fExtraStereoBuffer[1];
2380 fExtraStereoBuffer[1] = nullptr;
2381 }
2382
2383 if (fParamBuffers != nullptr)
2384 {
2385 delete[] fParamBuffers;
2386 fParamBuffers = nullptr;
2387 }
2388
2389 CarlaPlugin::clearBuffers();
2390
2391 carla_debug("CarlaPluginLADSPADSSI::clearBuffers() - end");
2392 }
2393
2394 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
2395 // -------------------------------------------------------------------
2396 // OSC stuff
2397
handleOscMessage(const char * const method,const int argc,const void * const argvx,const char * const types,const lo_message msg)2398 void handleOscMessage(const char* const method, const int argc, const void* const argvx, const char* const types, const lo_message msg) override
2399 {
2400 const lo_address source(lo_message_get_source(msg));
2401 CARLA_SAFE_ASSERT_RETURN(source != nullptr,);
2402
2403 // protocol for DSSI UIs *must* be UDP
2404 CARLA_SAFE_ASSERT_RETURN(lo_address_get_protocol(source) == LO_UDP,);
2405
2406 if (fOscData.source == nullptr)
2407 {
2408 // if no UI is registered yet only "configure" and "update" messages are valid
2409 CARLA_SAFE_ASSERT_RETURN(std::strcmp(method, "configure") == 0 || std::strcmp(method, "update") == 0,)
2410 }
2411 else
2412 {
2413 // make sure message source is the DSSI UI
2414 const char* const msghost = lo_address_get_hostname(source);
2415 const char* const msgport = lo_address_get_port(source);
2416
2417 const char* const ourhost = lo_address_get_hostname(fOscData.source);
2418 const char* const ourport = lo_address_get_port(fOscData.source);
2419
2420 CARLA_SAFE_ASSERT_RETURN(std::strcmp(msghost, ourhost) == 0,);
2421 CARLA_SAFE_ASSERT_RETURN(std::strcmp(msgport, ourport) == 0,);
2422 }
2423
2424 const lo_arg* const* const argv(static_cast<const lo_arg* const*>(argvx));
2425
2426 if (std::strcmp(method, "configure") == 0)
2427 return handleOscMessageConfigure(argc, argv, types);
2428 if (std::strcmp(method, "control") == 0)
2429 return handleOscMessageControl(argc, argv, types);
2430 if (std::strcmp(method, "program") == 0)
2431 return handleOscMessageProgram(argc, argv, types);
2432 if (std::strcmp(method, "midi") == 0)
2433 return handleOscMessageMIDI(argc, argv, types);
2434 if (std::strcmp(method, "update") == 0)
2435 return handleOscMessageUpdate(argc, argv, types, lo_message_get_source(msg));
2436 if (std::strcmp(method, "exiting") == 0)
2437 return handleOscMessageExiting();
2438
2439 carla_stdout("CarlaPluginLADSPADSSI::handleOscMessage() - unknown method '%s'", method);
2440 }
2441
handleOscMessageConfigure(const int argc,const lo_arg * const * const argv,const char * const types)2442 void handleOscMessageConfigure(const int argc, const lo_arg* const* const argv, const char* const types)
2443 {
2444 carla_debug("CarlaPluginLADSPADSSI::handleMsgConfigure()");
2445 CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(2, "ss");
2446
2447 const char* const key = (const char*)&argv[0]->s;
2448 const char* const value = (const char*)&argv[1]->s;
2449
2450 setCustomData(CUSTOM_DATA_TYPE_STRING, key, value, false);
2451 }
2452
handleOscMessageControl(const int argc,const lo_arg * const * const argv,const char * const types)2453 void handleOscMessageControl(const int argc, const lo_arg* const* const argv, const char* const types)
2454 {
2455 carla_debug("CarlaPluginLADSPADSSI::handleMsgControl()");
2456 CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(2, "if");
2457
2458 const int32_t rindex = argv[0]->i;
2459 const float value = argv[1]->f;
2460
2461 setParameterValueByRealIndex(rindex, value, false, true, true);
2462 }
2463
handleOscMessageProgram(const int argc,const lo_arg * const * const argv,const char * const types)2464 void handleOscMessageProgram(const int argc, const lo_arg* const* const argv, const char* const types)
2465 {
2466 carla_debug("CarlaPluginLADSPADSSI::handleMsgProgram()");
2467 CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(2, "ii");
2468
2469 const int32_t bank = argv[0]->i;
2470 const int32_t program = argv[1]->i;
2471
2472 CARLA_SAFE_ASSERT_RETURN(bank >= 0,);
2473 CARLA_SAFE_ASSERT_RETURN(program >= 0,);
2474
2475 setMidiProgramById(static_cast<uint32_t>(bank), static_cast<uint32_t>(program), false, true, true);
2476 }
2477
handleOscMessageMIDI(const int argc,const lo_arg * const * const argv,const char * const types)2478 void handleOscMessageMIDI(const int argc, const lo_arg* const* const argv, const char* const types)
2479 {
2480 carla_debug("CarlaPluginLADSPADSSI::handleMsgMidi()");
2481 CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(1, "m");
2482
2483 if (getMidiInCount() == 0)
2484 {
2485 carla_stderr("CarlaPluginLADSPADSSI::handleMsgMidi() - received midi when plugin has no midi inputs");
2486 return;
2487 }
2488
2489 const uint8_t* const data = argv[0]->m;
2490 uint8_t status = data[1];
2491 uint8_t channel = status & 0x0F;
2492
2493 // Fix bad note-off
2494 if (MIDI_IS_STATUS_NOTE_ON(status) && data[3] == 0)
2495 status = MIDI_STATUS_NOTE_OFF;
2496
2497 if (MIDI_IS_STATUS_NOTE_OFF(status))
2498 {
2499 const uint8_t note = data[2];
2500
2501 CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
2502
2503 sendMidiSingleNote(channel, note, 0, false, true, true);
2504 }
2505 else if (MIDI_IS_STATUS_NOTE_ON(status))
2506 {
2507 const uint8_t note = data[2];
2508 const uint8_t velo = data[3];
2509
2510 CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
2511 CARLA_SAFE_ASSERT_RETURN(velo < MAX_MIDI_VALUE,);
2512
2513 sendMidiSingleNote(channel, note, velo, false, true, true);
2514 }
2515 }
2516
handleOscMessageUpdate(const int argc,const lo_arg * const * const argv,const char * const types,const lo_address source)2517 void handleOscMessageUpdate(const int argc, const lo_arg* const* const argv, const char* const types, const lo_address source)
2518 {
2519 carla_debug("CarlaPluginLADSPADSSI::handleMsgUpdate()");
2520 CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(1, "s");
2521
2522 const char* const url = (const char*)&argv[0]->s;
2523
2524 // FIXME - remove debug prints later
2525 carla_stdout("CarlaPluginLADSPADSSI::updateOscData(%p, \"%s\")", source, url);
2526
2527 fOscData.clear();
2528
2529 const int proto = lo_address_get_protocol(source);
2530
2531 {
2532 const char* host = lo_address_get_hostname(source);
2533 const char* port = lo_address_get_port(source);
2534 fOscData.source = lo_address_new_with_proto(proto, host, port);
2535
2536 carla_stdout("CarlaPlugin::updateOscData() - source: host \"%s\", port \"%s\"", host, port);
2537 }
2538
2539 {
2540 char* host = lo_url_get_hostname(url);
2541 char* port = lo_url_get_port(url);
2542 fOscData.path = carla_strdup_free(lo_url_get_path(url));
2543 fOscData.target = lo_address_new_with_proto(proto, host, port);
2544 carla_stdout("CarlaPlugin::updateOscData() - target: host \"%s\", port \"%s\", path \"%s\"", host, port, fOscData.path);
2545
2546 std::free(host);
2547 std::free(port);
2548 }
2549
2550 osc_send_sample_rate(fOscData, static_cast<float>(pData->engine->getSampleRate()));
2551
2552 for (LinkedList<CustomData>::Itenerator it = pData->custom.begin2(); it.valid(); it.next())
2553 {
2554 const CustomData& customData(it.getValue(kCustomDataFallback));
2555 CARLA_SAFE_ASSERT_CONTINUE(customData.isValid());
2556
2557 if (std::strcmp(customData.type, CUSTOM_DATA_TYPE_STRING) == 0)
2558 osc_send_configure(fOscData, customData.key, customData.value);
2559 }
2560
2561 if (pData->prog.current >= 0)
2562 osc_send_program(fOscData, static_cast<uint32_t>(pData->prog.current));
2563
2564 if (pData->midiprog.current >= 0)
2565 {
2566 const MidiProgramData& curMidiProg(pData->midiprog.getCurrent());
2567 osc_send_program(fOscData, curMidiProg.bank, curMidiProg.program);
2568 }
2569
2570 for (uint32_t i=0; i < pData->param.count; ++i)
2571 osc_send_control(fOscData, pData->param.data[i].rindex, getParameterValue(i));
2572
2573 #ifndef BUILD_BRIDGE
2574 if (pData->engine->getOptions().frontendWinId != 0)
2575 pData->transientTryCounter = 1;
2576 #endif
2577
2578 carla_stdout("CarlaPluginLADSPADSSI::updateOscData() - done");
2579 }
2580
handleOscMessageExiting()2581 void handleOscMessageExiting()
2582 {
2583 carla_debug("CarlaPluginLADSPADSSI::handleMsgExiting()");
2584
2585 // hide UI
2586 showCustomUI(false);
2587
2588 // tell frontend
2589 pData->engine->callback(true, true,
2590 ENGINE_CALLBACK_UI_STATE_CHANGED,
2591 pData->id,
2592 0,
2593 0, 0, 0.0f, nullptr);
2594 }
2595
2596 // -------------------------------------------------------------------
2597 // Post-poned UI Stuff
2598
uiParameterChange(const uint32_t index,const float value)2599 void uiParameterChange(const uint32_t index, const float value) noexcept override
2600 {
2601 CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,);
2602
2603 if (fOscData.target == nullptr)
2604 return;
2605
2606 osc_send_control(fOscData, pData->param.data[index].rindex, value);
2607 }
2608
uiMidiProgramChange(const uint32_t index)2609 void uiMidiProgramChange(const uint32_t index) noexcept override
2610 {
2611 CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);
2612
2613 if (fOscData.target == nullptr)
2614 return;
2615
2616 osc_send_program(fOscData, pData->midiprog.data[index].bank, pData->midiprog.data[index].program);
2617 }
2618
uiNoteOn(const uint8_t channel,const uint8_t note,const uint8_t velo)2619 void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override
2620 {
2621 CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
2622 CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
2623 CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,);
2624
2625 if (fOscData.target == nullptr)
2626 return;
2627
2628 #if 0
2629 uint8_t midiData[4];
2630 midiData[0] = 0;
2631 midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT));
2632 midiData[2] = note;
2633 midiData[3] = velo;
2634
2635 osc_send_midi(fOscData, midiData);
2636 #endif
2637 }
2638
uiNoteOff(const uint8_t channel,const uint8_t note)2639 void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override
2640 {
2641 CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
2642 CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
2643
2644 if (fOscData.target == nullptr)
2645 return;
2646
2647 #if 0
2648 uint8_t midiData[4];
2649 midiData[0] = 0;
2650 midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT));
2651 midiData[2] = note;
2652 midiData[3] = 0;
2653
2654 osc_send_midi(fOscData, midiData);
2655 #endif
2656 }
2657 #endif // HAVE_LIBLO && !BUILD_BRIDGE
2658
2659 // -------------------------------------------------------------------
2660
getNativeDescriptor() const2661 const void* getNativeDescriptor() const noexcept override
2662 {
2663 return fDssiDescriptor != nullptr
2664 ? (const void*)fDssiDescriptor
2665 : (const void*)fDescriptor;
2666 }
2667
getExtraStuff() const2668 const void* getExtraStuff() const noexcept override
2669 {
2670 if (fDssiDescriptor != nullptr)
2671 {
2672 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
2673 return fUiFilename;
2674 #else
2675 return nullptr;
2676 #endif
2677 }
2678 return fRdfDescriptor;
2679 }
2680
2681 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
getUiBridgeProcessId() const2682 uintptr_t getUiBridgeProcessId() const noexcept override
2683 {
2684 return fThreadUI.getProcessId();
2685 }
2686 #endif
2687
2688 // -------------------------------------------------------------------
2689
initLADSPA(const CarlaPluginPtr plugin,const char * const filename,const char * name,const char * const label,const uint options,const LADSPA_RDF_Descriptor * const rdfDescriptor)2690 bool initLADSPA(const CarlaPluginPtr plugin,
2691 const char* const filename, const char* name, const char* const label, const uint options,
2692 const LADSPA_RDF_Descriptor* const rdfDescriptor)
2693 {
2694 CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
2695
2696 // ---------------------------------------------------------------
2697 // first checks
2698
2699 if (pData->client != nullptr)
2700 {
2701 pData->engine->setLastError("Plugin client is already registered");
2702 return false;
2703 }
2704
2705 if (filename == nullptr || filename[0] == '\0')
2706 {
2707 pData->engine->setLastError("null filename");
2708 return false;
2709 }
2710
2711 // ---------------------------------------------------------------
2712 // open DLL
2713
2714 if (! pData->libOpen(filename))
2715 {
2716 pData->engine->setLastError(pData->libError(filename));
2717 return false;
2718 }
2719
2720 // ---------------------------------------------------------------
2721 // get DLL main entry
2722
2723 const LADSPA_Descriptor_Function descFn = pData->libSymbol<LADSPA_Descriptor_Function>("ladspa_descriptor");
2724
2725 if (descFn == nullptr)
2726 {
2727 pData->engine->setLastError("Could not find the LASDPA Descriptor in the plugin library");
2728 return false;
2729 }
2730
2731 // ---------------------------------------------------------------
2732 // get descriptor that matches label
2733
2734 // if label is null, get first valid plugin
2735 const bool nullLabel = (label == nullptr || label[0] == '\0');
2736
2737 for (ulong d=0;; ++d)
2738 {
2739 try {
2740 fDescriptor = descFn(d);
2741 }
2742 catch(...) {
2743 carla_stderr2("Caught exception when trying to get LADSPA descriptor");
2744 fDescriptor = nullptr;
2745 break;
2746 }
2747
2748 if (fDescriptor == nullptr)
2749 break;
2750
2751 if (fDescriptor->Label == nullptr || fDescriptor->Label[0] == '\0')
2752 {
2753 carla_stderr2("WARNING - Got an invalid label, will not use this plugin");
2754 fDescriptor = nullptr;
2755 break;
2756 }
2757 if (fDescriptor->run == nullptr)
2758 {
2759 carla_stderr2("WARNING - Plugin has no run, cannot use it");
2760 fDescriptor = nullptr;
2761 break;
2762 }
2763
2764 if (nullLabel || std::strcmp(fDescriptor->Label, label) == 0)
2765 break;
2766 }
2767
2768 if (fDescriptor == nullptr)
2769 {
2770 pData->engine->setLastError("Could not find the requested plugin label in the plugin library");
2771 return false;
2772 }
2773
2774 return init2(plugin, filename, name, options, rdfDescriptor);
2775 }
2776
initDSSI(const CarlaPluginPtr plugin,const char * const filename,const char * name,const char * const label,const uint options)2777 bool initDSSI(const CarlaPluginPtr plugin,
2778 const char* const filename, const char* name, const char* const label, const uint options)
2779 {
2780 CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
2781
2782 // ---------------------------------------------------------------
2783 // first checks
2784
2785 if (pData->client != nullptr)
2786 {
2787 pData->engine->setLastError("Plugin client is already registered");
2788 return false;
2789 }
2790
2791 if (filename == nullptr || filename[0] == '\0')
2792 {
2793 pData->engine->setLastError("null filename");
2794 return false;
2795 }
2796
2797 // ---------------------------------------------------------------
2798 // open DLL
2799
2800 if (! pData->libOpen(filename))
2801 {
2802 pData->engine->setLastError(pData->libError(filename));
2803 return false;
2804 }
2805
2806 // ---------------------------------------------------------------
2807 // get DLL main entry
2808
2809 const DSSI_Descriptor_Function descFn = pData->libSymbol<DSSI_Descriptor_Function>("dssi_descriptor");
2810
2811 if (descFn == nullptr)
2812 {
2813 pData->engine->setLastError("Could not find the DSSI Descriptor in the plugin library");
2814 return false;
2815 }
2816
2817 // ---------------------------------------------------------------
2818 // get descriptor that matches label
2819
2820 // if label is null, get first valid plugin
2821 const bool nullLabel = (label == nullptr || label[0] == '\0');
2822
2823 for (ulong d=0;; ++d)
2824 {
2825 try {
2826 fDssiDescriptor = descFn(d);
2827 }
2828 catch(...) {
2829 carla_stderr2("Caught exception when trying to get DSSI descriptor");
2830 fDescriptor = nullptr;
2831 fDssiDescriptor = nullptr;
2832 break;
2833 }
2834
2835 if (fDssiDescriptor == nullptr)
2836 break;
2837
2838 fDescriptor = fDssiDescriptor->LADSPA_Plugin;
2839
2840 if (fDescriptor == nullptr)
2841 {
2842 carla_stderr2("WARNING - Missing LADSPA interface, will not use this plugin");
2843 fDssiDescriptor = nullptr;
2844 break;
2845 }
2846 if (fDescriptor->Label == nullptr || fDescriptor->Label[0] == '\0')
2847 {
2848 carla_stderr2("WARNING - Got an invalid label, will not use this plugin");
2849 fDescriptor = nullptr;
2850 fDssiDescriptor = nullptr;
2851 break;
2852 }
2853 if (fDescriptor->run == nullptr)
2854 {
2855 carla_stderr2("WARNING - Plugin has no run, cannot use it");
2856 fDescriptor = nullptr;
2857 fDssiDescriptor = nullptr;
2858 break;
2859 }
2860
2861 if (nullLabel || std::strcmp(fDescriptor->Label, label) == 0)
2862 break;
2863 }
2864
2865 if (fDescriptor == nullptr || fDssiDescriptor == nullptr)
2866 {
2867 pData->engine->setLastError("Could not find the requested plugin label in the plugin library");
2868 return false;
2869 }
2870
2871 // ---------------------------------------------------------------
2872 // check if uses global instance
2873
2874 if (fDssiDescriptor->run_synth == nullptr && fDssiDescriptor->run_multiple_synths != nullptr)
2875 {
2876 pData->engine->setLastError("This plugin requires run_multiple_synths which is not supported");
2877 return false;
2878 }
2879
2880 return init2(plugin, filename, name, options, nullptr);
2881 }
2882
init2(const CarlaPluginPtr plugin,const char * const filename,const char * name,const uint options,const LADSPA_RDF_Descriptor * const rdfDescriptor)2883 bool init2(const CarlaPluginPtr plugin,
2884 const char* const filename, const char* name, const uint options,
2885 const LADSPA_RDF_Descriptor* const rdfDescriptor)
2886 {
2887 // ---------------------------------------------------------------
2888 // check for fixed buffer size requirement
2889
2890 fNeedsFixedBuffers = CarlaString(filename).contains("dssi-vst", true);
2891
2892 if (fNeedsFixedBuffers && ! pData->engine->usesConstantBufferSize())
2893 {
2894 pData->engine->setLastError("Cannot use this plugin under the current engine.\n"
2895 "The plugin requires a fixed block size which is not possible right now.");
2896 return false;
2897 }
2898
2899 // ---------------------------------------------------------------
2900 // get info
2901
2902 if (is_ladspa_rdf_descriptor_valid(rdfDescriptor, fDescriptor))
2903 fRdfDescriptor = ladspa_rdf_dup(rdfDescriptor);
2904
2905 if (name == nullptr || name[0] == '\0')
2906 {
2907 /**/ if (fRdfDescriptor != nullptr && fRdfDescriptor->Title != nullptr && fRdfDescriptor->Title[0] != '\0')
2908 name = fRdfDescriptor->Title;
2909 else if (fDescriptor->Name != nullptr && fDescriptor->Name[0] != '\0')
2910 name = fDescriptor->Name;
2911 else
2912 name = fDescriptor->Label;
2913 }
2914
2915 pData->name = pData->engine->getUniquePluginName(name);
2916 pData->filename = carla_strdup(filename);
2917
2918 // ---------------------------------------------------------------
2919 // register client
2920
2921 pData->client = pData->engine->addClient(plugin);
2922
2923 if (pData->client == nullptr || ! pData->client->isOk())
2924 {
2925 pData->engine->setLastError("Failed to register plugin client");
2926 return false;
2927 }
2928
2929 // ---------------------------------------------------------------
2930 // initialize plugin
2931
2932 if (! addInstance())
2933 return false;
2934
2935 // ---------------------------------------------------------------
2936 // find latency port index
2937
2938 for (uint32_t i=0, iCtrl=0, count=getSafePortCount(); i<count; ++i)
2939 {
2940 const int portType(fDescriptor->PortDescriptors[i]);
2941
2942 if (! LADSPA_IS_PORT_CONTROL(portType))
2943 continue;
2944
2945 const uint32_t index(iCtrl++);
2946
2947 if (! LADSPA_IS_PORT_OUTPUT(portType))
2948 continue;
2949
2950 const char* const portName(fDescriptor->PortNames[i]);
2951 CARLA_SAFE_ASSERT_BREAK(portName != nullptr);
2952
2953 if (std::strcmp(portName, "latency") == 0 ||
2954 std::strcmp(portName, "_latency") == 0)
2955 {
2956 fLatencyIndex = static_cast<int32_t>(index);
2957 break;
2958 }
2959 }
2960
2961 // ---------------------------------------------------------------
2962 // check for custom data extension
2963
2964 if (fDssiDescriptor != nullptr && fDssiDescriptor->configure != nullptr)
2965 {
2966 if (char* const error = fDssiDescriptor->configure(fHandles.getFirst(nullptr), DSSI_CUSTOMDATA_EXTENSION_KEY, ""))
2967 {
2968 if (std::strcmp(error, "true") == 0 && fDssiDescriptor->get_custom_data != nullptr
2969 && fDssiDescriptor->set_custom_data != nullptr)
2970 fUsesCustomData = true;
2971
2972 std::free(error);
2973 }
2974 }
2975
2976 // ---------------------------------------------------------------
2977 // get engine options
2978
2979 const EngineOptions& opts(pData->engine->getOptions());
2980
2981 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
2982 // ---------------------------------------------------------------
2983 // check for gui
2984
2985 if (opts.oscEnabled && opts.oscPortUDP >= 0)
2986 {
2987 if (const char* const guiFilename = find_dssi_ui(filename, fDescriptor->Label))
2988 {
2989 fUiFilename = guiFilename;
2990
2991 CarlaString uiTitle;
2992
2993 if (pData->uiTitle.isNotEmpty())
2994 {
2995 uiTitle = pData->uiTitle;
2996 }
2997 else
2998 {
2999 uiTitle = pData->name;
3000 uiTitle += " (GUI)";
3001 }
3002
3003 fThreadUI.setData(guiFilename, fDescriptor->Label, uiTitle);
3004 }
3005 }
3006 #endif
3007
3008 // ---------------------------------------------------------------
3009 // set options
3010
3011 pData->options = 0x0;
3012
3013 /**/ if (fLatencyIndex >= 0 || fNeedsFixedBuffers)
3014 pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
3015 else if (options & PLUGIN_OPTION_FIXED_BUFFERS)
3016 pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
3017
3018 /**/ if (opts.forceStereo)
3019 pData->options |= PLUGIN_OPTION_FORCE_STEREO;
3020 else if (options & PLUGIN_OPTION_FORCE_STEREO)
3021 pData->options |= PLUGIN_OPTION_FORCE_STEREO;
3022
3023 if (fDssiDescriptor != nullptr)
3024 {
3025 if (fDssiDescriptor->get_program != nullptr && fDssiDescriptor->select_program != nullptr)
3026 if (isPluginOptionEnabled(options, PLUGIN_OPTION_MAP_PROGRAM_CHANGES))
3027 pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
3028
3029 if (fUsesCustomData)
3030 if (isPluginOptionEnabled(options, PLUGIN_OPTION_USE_CHUNKS))
3031 pData->options |= PLUGIN_OPTION_USE_CHUNKS;
3032
3033 if (fDssiDescriptor->run_synth != nullptr)
3034 {
3035 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES))
3036 pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
3037 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE))
3038 pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
3039 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH))
3040 pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
3041 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND))
3042 pData->options |= PLUGIN_OPTION_SEND_PITCHBEND;
3043 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF))
3044 pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
3045 if (isPluginOptionInverseEnabled(options, PLUGIN_OPTION_SKIP_SENDING_NOTES))
3046 pData->options |= PLUGIN_OPTION_SKIP_SENDING_NOTES;
3047 }
3048 }
3049
3050 return true;
3051 }
3052
3053 // -------------------------------------------------------------------
3054
3055 private:
3056 LinkedList<LADSPA_Handle> fHandles;
3057 const LADSPA_Descriptor* fDescriptor;
3058 const DSSI_Descriptor* fDssiDescriptor;
3059 const LADSPA_RDF_Descriptor* fRdfDescriptor;
3060
3061 float** fAudioInBuffers;
3062 float** fAudioOutBuffers;
3063 float* fExtraStereoBuffer[2]; // used only if forcedStereoIn and audioOut == 2
3064 float* fParamBuffers;
3065
3066 snd_seq_event_t fMidiEvents[kPluginMaxMidiEvents];
3067
3068 int32_t fLatencyIndex; // -1 if invalid
3069 bool fForcedStereoIn;
3070 bool fForcedStereoOut;
3071 bool fNeedsFixedBuffers;
3072 bool fUsesCustomData;
3073
3074 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
3075 CarlaOscData fOscData;
3076 CarlaThreadDSSIUI fThreadUI;
3077 const char* fUiFilename;
3078 #endif
3079
3080 // -------------------------------------------------------------------
3081
addInstance()3082 bool addInstance()
3083 {
3084 LADSPA_Handle handle;
3085
3086 try {
3087 handle = fDescriptor->instantiate(fDescriptor, static_cast<ulong>(pData->engine->getSampleRate()));
3088 } CARLA_SAFE_EXCEPTION_RETURN_ERR("LADSPA/DSSI instantiate", "Plugin failed to initialize");
3089
3090 for (uint32_t i=0, count=pData->param.count; i<count; ++i)
3091 {
3092 const int32_t rindex(pData->param.data[i].rindex);
3093 CARLA_SAFE_ASSERT_CONTINUE(rindex >= 0);
3094
3095 try {
3096 fDescriptor->connect_port(handle, static_cast<ulong>(rindex), &fParamBuffers[i]);
3097 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port");
3098 }
3099
3100 if (fHandles.append(handle))
3101 return true;
3102
3103 try {
3104 fDescriptor->cleanup(handle);
3105 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI cleanup");
3106
3107 pData->engine->setLastError("Out of memory");
3108 return false;
3109 }
3110
getSafePortCount() const3111 uint32_t getSafePortCount() const noexcept
3112 {
3113 if (fDescriptor->PortCount == 0)
3114 return 0;
3115
3116 CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortDescriptors != nullptr, 0);
3117 CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortRangeHints != nullptr, 0);
3118 CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames != nullptr, 0);
3119
3120 return static_cast<uint32_t>(fDescriptor->PortCount);
3121 }
3122
getSeparatedParameterNameOrUnit(const char * const paramName,char * const strBuf,const bool wantName) const3123 bool getSeparatedParameterNameOrUnit(const char* const paramName, char* const strBuf, const bool wantName) const noexcept
3124 {
3125 if (_getSeparatedParameterNameOrUnitImpl(paramName, strBuf, wantName, true))
3126 return true;
3127 if (_getSeparatedParameterNameOrUnitImpl(paramName, strBuf, wantName, false))
3128 return true;
3129 return false;
3130 }
3131
_getSeparatedParameterNameOrUnitImpl(const char * const paramName,char * const strBuf,const bool wantName,const bool useBracket)3132 static bool _getSeparatedParameterNameOrUnitImpl(const char* const paramName, char* const strBuf,
3133 const bool wantName, const bool useBracket) noexcept
3134 {
3135 const char* const sepBracketStart = std::strstr(paramName, useBracket ? " [" : " (");
3136
3137 if (sepBracketStart == nullptr)
3138 return false;
3139
3140 const char* const sepBracketEnd = std::strstr(sepBracketStart, useBracket ? "]" : ")");
3141
3142 if (sepBracketEnd == nullptr)
3143 return false;
3144
3145 const std::size_t unitSize = static_cast<std::size_t>(sepBracketEnd-sepBracketStart-2);
3146
3147 if (unitSize > 7) // very unlikely to have such big unit
3148 return false;
3149
3150 const std::size_t sepIndex = std::strlen(paramName)-unitSize-3;
3151
3152 // just in case
3153 if (sepIndex > STR_MAX-3)
3154 return false;
3155
3156 if (wantName)
3157 {
3158 std::strncpy(strBuf, paramName, sepIndex);
3159 strBuf[sepIndex] = '\0';
3160 }
3161 else
3162 {
3163 std::strncpy(strBuf, paramName+(sepIndex+2), unitSize);
3164 strBuf[unitSize] = '\0';
3165 }
3166
3167 return true;
3168 }
3169
3170 // -------------------------------------------------------------------
3171
3172 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginLADSPADSSI)
3173 };
3174
3175 // -------------------------------------------------------------------------------------------------------------------
3176
newLADSPA(const Initializer & init,const LADSPA_RDF_Descriptor * const rdfDescriptor)3177 CarlaPluginPtr CarlaPlugin::newLADSPA(const Initializer& init, const LADSPA_RDF_Descriptor* const rdfDescriptor)
3178 {
3179 carla_debug("CarlaPlugin::newLADSPA({%p, \"%s\", \"%s\", \"%s\", " P_INT64 ", %x}, %p)",
3180 init.engine, init.filename, init.name, init.label, init.uniqueId, init.options, rdfDescriptor);
3181
3182 std::shared_ptr<CarlaPluginLADSPADSSI> plugin(new CarlaPluginLADSPADSSI(init.engine, init.id));
3183
3184 if (! plugin->initLADSPA(plugin, init.filename, init.name, init.label, init.options, rdfDescriptor))
3185 return nullptr;
3186
3187 return plugin;
3188 }
3189
newDSSI(const Initializer & init)3190 CarlaPluginPtr CarlaPlugin::newDSSI(const Initializer& init)
3191 {
3192 carla_debug("CarlaPlugin::newDSSI({%p, \"%s\", \"%s\", \"%s\", " P_INT64 ", %x})",
3193 init.engine, init.filename, init.name, init.label, init.uniqueId, init.options);
3194
3195 std::shared_ptr<CarlaPluginLADSPADSSI> plugin(new CarlaPluginLADSPADSSI(init.engine, init.id));
3196
3197 if (! plugin->initDSSI(plugin, init.filename, init.name, init.label, init.options))
3198 return nullptr;
3199
3200 return plugin;
3201 }
3202
3203 // -------------------------------------------------------------------------------------------------------------------
3204
3205 CARLA_BACKEND_END_NAMESPACE
3206