Implement LV2 ControlInputPort change request feature
[carla.git] / source / backend / plugin / CarlaPluginLADSPADSSI.cpp
blobfa2ad19352c56d542567fa952bcfa19e32380557
1 /*
2 * Carla Plugin, LADSPA/DSSI implementation
3 * Copyright (C) 2011-2023 Filipe Coelho <falktx@falktx.com>
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.
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.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #include "CarlaPluginInternal.hpp"
19 #include "CarlaEngineUtils.hpp"
21 #include "CarlaBackendUtils.hpp"
22 #include "CarlaLadspaUtils.hpp"
23 #include "CarlaDssiUtils.hpp"
24 #include "CarlaMathUtils.hpp"
26 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) && !defined(CARLA_OS_WASM)
27 # define CARLA_ENABLE_DSSI_PLUGIN_GUI
28 # include "CarlaOscUtils.hpp"
29 # include "CarlaScopeUtils.hpp"
30 # include "CarlaThread.hpp"
31 # include "water/threads/ChildProcess.h"
32 using water::ChildProcess;
33 #endif
35 using water::String;
36 using water::StringArray;
38 #define CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \
39 /* check argument count */ \
40 if (argc != argcToCompare) \
41 { \
42 carla_stderr("CarlaPluginLADSPADSSI::%s() - argument count mismatch: %i != %i", \
43 __FUNCTION__, argc, argcToCompare); \
44 return; \
45 } \
46 if (argc > 0) \
47 { \
48 /* check for nullness */ \
49 if (types == nullptr || typesToCompare == nullptr) \
50 { \
51 carla_stderr("CarlaPluginLADSPADSSI::%s() - argument types are null", \
52 __FUNCTION__); \
53 return; \
54 } \
55 /* check argument types */ \
56 if (std::strcmp(types, typesToCompare) != 0) \
57 { \
58 carla_stderr("CarlaPluginLADSPADSSI::%s() - argument types mismatch: '%s' != '%s'", \
59 __FUNCTION__, types, typesToCompare); \
60 return; \
61 } \
64 CARLA_BACKEND_START_NAMESPACE
66 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
67 // -------------------------------------------------------------------
68 // Fallback data
70 static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr };
72 // -------------------------------------------------------------------
74 class CarlaThreadDSSIUI : public CarlaThread
76 public:
77 CarlaThreadDSSIUI(CarlaEngine* const engine, CarlaPlugin* const plugin, const CarlaOscData& oscData) noexcept
78 : CarlaThread("CarlaThreadDSSIUI"),
79 kEngine(engine),
80 kPlugin(plugin),
81 fBinary(),
82 fLabel(),
83 fUiTitle(),
84 fOscData(oscData),
85 fProcess() {}
87 void setData(const char* const binary, const char* const label, const char* const uiTitle) noexcept
89 CARLA_SAFE_ASSERT_RETURN(binary != nullptr && binary[0] != '\0',);
90 CARLA_SAFE_ASSERT_RETURN(label != nullptr,);
91 CARLA_SAFE_ASSERT_RETURN(uiTitle != nullptr && uiTitle[0] != '\0',);
92 CARLA_SAFE_ASSERT(! isThreadRunning());
94 fBinary = binary;
95 fLabel = label;
96 fUiTitle = uiTitle;
98 if (fLabel.isEmpty())
99 fLabel = "\"\"";
102 void setUITitle(const char* const uiTitle) noexcept
104 CARLA_SAFE_ASSERT_RETURN(uiTitle != nullptr && uiTitle[0] != '\0',);
106 fUiTitle = uiTitle;
109 uintptr_t getProcessId() const noexcept
111 CARLA_SAFE_ASSERT_RETURN(fProcess != nullptr, 0);
113 return (uintptr_t)fProcess->getPID();
116 void run()
118 carla_stdout("LADSPA/DSSI UI thread started");
120 if (fProcess == nullptr)
122 fProcess = new ChildProcess();
124 else if (fProcess->isRunning())
126 carla_stderr("CarlaThreadDSSI::run() - already running, giving up...");
128 fProcess->kill();
129 fProcess = nullptr;
130 kEngine->callback(true, true,
131 ENGINE_CALLBACK_UI_STATE_CHANGED,
132 kPlugin->getId(),
134 0, 0, 0.0f, nullptr);
135 return;
138 String name(kPlugin->getName());
139 String filename(kPlugin->getFilename());
141 if (name.isEmpty())
142 name = "(none)";
144 if (filename.isEmpty())
145 filename = "\"\"";
147 StringArray arguments;
149 // binary
150 arguments.add(fBinary.buffer());
152 // osc-url
153 arguments.add(String(kEngine->getOscServerPathUDP()) + String("/") + String(kPlugin->getId()));
155 // filename
156 arguments.add(filename);
158 // label
159 arguments.add(fLabel.buffer());
161 // ui-title
162 arguments.add(fUiTitle.buffer());
164 bool started;
167 #ifdef CARLA_OS_LINUX
169 * If the frontend uses winId parent, set LD_PRELOAD to auto-map the DSSI UI.
170 * If not, unset LD_PRELOAD.
172 const uintptr_t winId(kEngine->getOptions().frontendWinId);
174 // for CARLA_ENGINE_OPTION_FRONTEND_WIN_ID
175 char winIdStr[STR_MAX+1];
176 winIdStr[STR_MAX] = '\0';
178 // for LD_PRELOAD
179 CarlaString ldPreloadValue;
181 if (winId != 0)
183 std::snprintf(winIdStr, STR_MAX, P_UINTPTR, winId);
184 ldPreloadValue = (CarlaString(kEngine->getOptions().binaryDir)
185 + "/libcarla_interposer-x11.so");
187 else
189 winIdStr[0] = '\0';
192 const ScopedEngineEnvironmentLocker _seel(kEngine);
193 const CarlaScopedEnvVar _sev1("CARLA_ENGINE_OPTION_FRONTEND_WIN_ID", winIdStr[0] != '\0' ? winIdStr : nullptr);
194 const CarlaScopedEnvVar _sev2("LD_PRELOAD", ldPreloadValue.isNotEmpty() ? ldPreloadValue.buffer() : nullptr);
195 #endif // CARLA_OS_LINUX
197 // start the DSSI UI application
198 carla_stdout("starting DSSI UI...");
199 started = fProcess->start(arguments);
202 if (! started)
204 carla_stdout("failed!");
205 fProcess = nullptr;
206 return;
209 if (waitForOscGuiShow())
211 for (; fProcess->isRunning() && ! shouldThreadExit();)
212 carla_sleep(1);
214 // we only get here if UI was closed or thread asked to exit
215 if (fProcess->isRunning() && shouldThreadExit())
217 fProcess->waitForProcessToFinish(static_cast<int>(kEngine->getOptions().uiBridgesTimeout));
219 if (fProcess->isRunning())
221 carla_stdout("CarlaThreadDSSIUI::run() - UI refused to close, force kill now");
222 fProcess->kill();
224 else
226 carla_stdout("CarlaThreadDSSIUI::run() - UI auto-closed successfully");
229 else if (fProcess->getExitCodeAndClearPID() != 0)
230 carla_stderr("CarlaThreadDSSIUI::run() - UI crashed while running");
231 else
232 carla_stdout("CarlaThreadDSSIUI::run() - UI closed cleanly");
234 else
236 fProcess->kill();
237 carla_stdout("CarlaThreadDSSIUI::run() - GUI timeout");
240 fProcess = nullptr;
241 kEngine->callback(true, true,
242 ENGINE_CALLBACK_UI_STATE_CHANGED,
243 kPlugin->getId(),
245 0, 0, 0.0f, nullptr);
247 carla_stdout("LADSPA/DSSI UI thread finished");
250 private:
251 CarlaEngine* const kEngine;
252 CarlaPlugin* const kPlugin;
254 CarlaString fBinary;
255 CarlaString fLabel;
256 CarlaString fUiTitle;
258 const CarlaOscData& fOscData;
259 CarlaScopedPointer<ChildProcess> fProcess;
261 bool waitForOscGuiShow()
263 carla_stdout("CarlaThreadDSSIUI::waitForOscGuiShow()");
264 const uint uiBridgesTimeout = kEngine->getOptions().uiBridgesTimeout;
266 // wait for UI 'update' call
267 for (uint i=0; i < uiBridgesTimeout/100; ++i)
269 if (fOscData.target != nullptr)
271 carla_stdout("CarlaThreadDSSIUI::waitForOscGuiShow() - got response, asking UI to show itself now");
272 osc_send_show(fOscData);
273 return true;
276 if (fProcess != nullptr && fProcess->isRunning() && ! shouldThreadExit())
277 carla_msleep(100);
278 else
279 return false;
282 carla_stdout("CarlaThreadDSSIUI::waitForOscGuiShow() - Timeout while waiting for UI to respond"
283 "(waited %u msecs)", uiBridgesTimeout);
284 return false;
287 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThreadDSSIUI)
289 #endif
291 // -----------------------------------------------------
293 class CarlaPluginLADSPADSSI : public CarlaPlugin
295 public:
296 CarlaPluginLADSPADSSI(CarlaEngine* const engine, const uint id) noexcept
297 : CarlaPlugin(engine, id),
298 fHandles(),
299 fDescriptor(nullptr),
300 fDssiDescriptor(nullptr),
301 fRdfDescriptor(nullptr),
302 fAudioInBuffers(nullptr),
303 fAudioOutBuffers(nullptr),
304 fExtraStereoBuffer(),
305 fParamBuffers(nullptr),
306 fLatencyIndex(-1),
307 fForcedStereoIn(false),
308 fForcedStereoOut(false),
309 fNeedsFixedBuffers(false),
310 fUsesCustomData(false)
311 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
312 , fOscData(),
313 fThreadUI(engine, this, fOscData),
314 fUiFilename(nullptr)
315 #endif
317 carla_debug("CarlaPluginLADSPADSSI::CarlaPluginLADSPADSSI(%p, %i)", engine, id);
319 carla_zeroPointers(fExtraStereoBuffer, 2);
322 ~CarlaPluginLADSPADSSI() noexcept override
324 carla_debug("CarlaPluginLADSPADSSI::~CarlaPluginLADSPADSSI()");
326 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
327 // close UI
328 if (fUiFilename != nullptr)
330 showCustomUI(false);
332 delete[] fUiFilename;
333 fUiFilename = nullptr;
335 #endif
337 pData->singleMutex.lock();
338 pData->masterMutex.lock();
340 if (pData->client != nullptr && pData->client->isActive())
341 pData->client->deactivate(true);
343 if (pData->active)
345 deactivate();
346 pData->active = false;
349 if (fDescriptor != nullptr)
351 if (fDescriptor->cleanup != nullptr)
353 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
355 LADSPA_Handle const handle(it.getValue(nullptr));
356 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
358 try {
359 fDescriptor->cleanup(handle);
360 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI cleanup");
364 fHandles.clear();
365 fDescriptor = nullptr;
366 fDssiDescriptor = nullptr;
369 if (fRdfDescriptor != nullptr)
371 delete fRdfDescriptor;
372 fRdfDescriptor = nullptr;
375 clearBuffers();
378 // -------------------------------------------------------------------
379 // Information (base)
381 PluginType getType() const noexcept override
383 return fDssiDescriptor != nullptr ? PLUGIN_DSSI : PLUGIN_LADSPA;
386 PluginCategory getCategory() const noexcept override
388 if (fRdfDescriptor != nullptr)
390 const LADSPA_RDF_PluginType category = fRdfDescriptor->Type;
392 // Specific Types
393 if (category & (LADSPA_RDF_PLUGIN_DELAY|LADSPA_RDF_PLUGIN_REVERB))
394 return PLUGIN_CATEGORY_DELAY;
395 if (category & (LADSPA_RDF_PLUGIN_PHASER|LADSPA_RDF_PLUGIN_FLANGER|LADSPA_RDF_PLUGIN_CHORUS))
396 return PLUGIN_CATEGORY_MODULATOR;
397 if (category & (LADSPA_RDF_PLUGIN_AMPLIFIER))
398 return PLUGIN_CATEGORY_DYNAMICS;
399 if (category & (LADSPA_RDF_PLUGIN_UTILITY|LADSPA_RDF_PLUGIN_SPECTRAL|LADSPA_RDF_PLUGIN_FREQUENCY_METER))
400 return PLUGIN_CATEGORY_UTILITY;
402 // Pre-set LADSPA Types
403 if (LADSPA_RDF_IS_PLUGIN_DYNAMICS(category))
404 return PLUGIN_CATEGORY_DYNAMICS;
405 if (LADSPA_RDF_IS_PLUGIN_AMPLITUDE(category))
406 return PLUGIN_CATEGORY_MODULATOR;
407 if (LADSPA_RDF_IS_PLUGIN_EQ(category))
408 return PLUGIN_CATEGORY_EQ;
409 if (LADSPA_RDF_IS_PLUGIN_FILTER(category))
410 return PLUGIN_CATEGORY_FILTER;
411 if (LADSPA_RDF_IS_PLUGIN_FREQUENCY(category))
412 return PLUGIN_CATEGORY_UTILITY;
413 if (LADSPA_RDF_IS_PLUGIN_SIMULATOR(category))
414 return PLUGIN_CATEGORY_OTHER;
415 if (LADSPA_RDF_IS_PLUGIN_TIME(category))
416 return PLUGIN_CATEGORY_DELAY;
417 if (LADSPA_RDF_IS_PLUGIN_GENERATOR(category))
418 return PLUGIN_CATEGORY_SYNTH;
421 if (fDssiDescriptor != nullptr && fDssiDescriptor->run_synth != nullptr)
422 if (pData->audioIn.count == 0 && pData->audioOut.count > 0)
423 return PLUGIN_CATEGORY_SYNTH;
425 return CarlaPlugin::getCategory();
428 int64_t getUniqueId() const noexcept override
430 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, 0);
432 return static_cast<int64_t>(fDescriptor->UniqueID);
435 uint32_t getLatencyInFrames() const noexcept override
437 if (fLatencyIndex < 0 || fParamBuffers == nullptr)
438 return 0;
440 const float latency(fParamBuffers[fLatencyIndex]);
441 CARLA_SAFE_ASSERT_RETURN(latency >= 0.0f, 0);
443 return static_cast<uint32_t>(latency);
446 // -------------------------------------------------------------------
447 // Information (count)
449 uint32_t getParameterScalePointCount(const uint32_t parameterId) const noexcept override
451 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0);
453 if (fRdfDescriptor == nullptr)
454 return 0;
456 const int32_t rindex(pData->param.data[parameterId].rindex);
457 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, 0);
459 if (rindex >= static_cast<int32_t>(fRdfDescriptor->PortCount))
460 return 0;
462 const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]);
463 return static_cast<uint32_t>(port.ScalePointCount);
466 // -------------------------------------------------------------------
467 // Information (current data)
469 std::size_t getChunkData(void** const dataPtr) noexcept override
471 CARLA_SAFE_ASSERT_RETURN(fUsesCustomData, 0);
472 CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0);
473 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr, 0);
474 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->get_custom_data != nullptr, 0);
475 CARLA_SAFE_ASSERT_RETURN(fHandles.count() > 0, 0);
476 CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0);
478 *dataPtr = nullptr;
480 int ret = 0;
481 ulong dataSize = 0;
483 try {
484 ret = fDssiDescriptor->get_custom_data(fHandles.getFirst(nullptr), dataPtr, &dataSize);
485 } CARLA_SAFE_EXCEPTION_RETURN("CarlaPluginLADSPADSSI::getChunkData", 0);
487 return (ret != 0) ? dataSize : 0;
490 // -------------------------------------------------------------------
491 // Information (per-plugin data)
493 uint getOptionsAvailable() const noexcept override
495 uint options = 0x0;
497 // can't disable fixed buffers if using latency
498 if (fLatencyIndex == -1 && ! fNeedsFixedBuffers)
499 options |= PLUGIN_OPTION_FIXED_BUFFERS;
501 // can't disable forced stereo if enabled in the engine
502 if (pData->engine->getOptions().forceStereo)
503 pass();
504 // if inputs or outputs are just 1, then yes we can force stereo
505 else if (pData->audioIn.count == 1 || pData->audioOut.count == 1 || fForcedStereoIn || fForcedStereoOut)
506 options |= PLUGIN_OPTION_FORCE_STEREO;
508 if (fDssiDescriptor != nullptr)
510 if (fDssiDescriptor->get_program != nullptr && fDssiDescriptor->select_program != nullptr)
511 options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
513 if (fUsesCustomData)
514 options |= PLUGIN_OPTION_USE_CHUNKS;
516 if (fDssiDescriptor->run_synth != nullptr)
518 options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
519 options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
520 options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
521 options |= PLUGIN_OPTION_SEND_PITCHBEND;
522 options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
523 options |= PLUGIN_OPTION_SKIP_SENDING_NOTES;
527 return options;
530 float getParameterValue(const uint32_t parameterId) const noexcept override
532 CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr, 0.0f);
533 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
535 // bad plugins might have set output values out of bounds
536 if (pData->param.data[parameterId].type == PARAMETER_OUTPUT)
537 return pData->param.ranges[parameterId].getFixedValue(fParamBuffers[parameterId]);
539 // not output, should be fine
540 return fParamBuffers[parameterId];
543 float getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) const noexcept override
545 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0.0f);
546 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
548 const int32_t rindex(pData->param.data[parameterId].rindex);
549 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, 0.0f);
550 CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fRdfDescriptor->PortCount), 0.0f);
552 const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]);
553 CARLA_SAFE_ASSERT_RETURN(scalePointId < port.ScalePointCount, 0.0f);
555 const LADSPA_RDF_ScalePoint& scalePoint(port.ScalePoints[scalePointId]);
556 return pData->param.ranges[parameterId].getFixedValue(scalePoint.Value);
559 bool getLabel(char* const strBuf) const noexcept override
561 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false);
562 CARLA_SAFE_ASSERT_RETURN(fDescriptor->Label != nullptr, false);
564 std::strncpy(strBuf, fDescriptor->Label, STR_MAX);
565 return true;
568 bool getMaker(char* const strBuf) const noexcept override
570 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false);
571 CARLA_SAFE_ASSERT_RETURN(fDescriptor->Maker != nullptr, false);
573 if (fRdfDescriptor != nullptr && fRdfDescriptor->Creator != nullptr)
574 std::strncpy(strBuf, fRdfDescriptor->Creator, STR_MAX);
575 else
576 std::strncpy(strBuf, fDescriptor->Maker, STR_MAX);
578 return true;
581 bool getCopyright(char* const strBuf) const noexcept override
583 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false);
584 CARLA_SAFE_ASSERT_RETURN(fDescriptor->Copyright != nullptr, false);
586 std::strncpy(strBuf, fDescriptor->Copyright, STR_MAX);
587 return true;
590 bool getRealName(char* const strBuf) const noexcept override
592 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false);
593 CARLA_SAFE_ASSERT_RETURN(fDescriptor->Name != nullptr, false);
595 if (fRdfDescriptor != nullptr && fRdfDescriptor->Title != nullptr)
596 std::strncpy(strBuf, fRdfDescriptor->Title, STR_MAX);
597 else
598 std::strncpy(strBuf, fDescriptor->Name, STR_MAX);
600 return true;
603 bool getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override
605 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false);
606 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
608 const int32_t rindex(pData->param.data[parameterId].rindex);
609 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
610 CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fDescriptor->PortCount), false);
611 CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames[rindex] != nullptr, false);
613 if (! getSeparatedParameterNameOrUnit(fDescriptor->PortNames[rindex], strBuf, true))
614 std::strncpy(strBuf, fDescriptor->PortNames[rindex], STR_MAX);
616 return true;
619 bool getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override
621 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
623 const int32_t rindex(pData->param.data[parameterId].rindex);
624 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
626 if (fRdfDescriptor != nullptr && rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
628 const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]);
630 if (LADSPA_RDF_PORT_HAS_UNIT(port.Hints))
632 switch (port.Unit)
634 case LADSPA_RDF_UNIT_DB:
635 std::strncpy(strBuf, "dB", STR_MAX);
636 return true;
637 case LADSPA_RDF_UNIT_COEF:
638 std::strncpy(strBuf, "(coef)", STR_MAX);
639 return true;
640 case LADSPA_RDF_UNIT_HZ:
641 std::strncpy(strBuf, "Hz", STR_MAX);
642 return true;
643 case LADSPA_RDF_UNIT_S:
644 std::strncpy(strBuf, "s", STR_MAX);
645 return true;
646 case LADSPA_RDF_UNIT_MS:
647 std::strncpy(strBuf, "ms", STR_MAX);
648 return true;
649 case LADSPA_RDF_UNIT_MIN:
650 std::strncpy(strBuf, "min", STR_MAX);
651 return true;
656 CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fDescriptor->PortCount), false);
657 CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames[rindex] != nullptr, false);
659 return getSeparatedParameterNameOrUnit(fDescriptor->PortNames[rindex], strBuf, false);
662 bool getParameterSymbol(const uint32_t parameterId, char* const strBuf) const noexcept override
664 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
666 if (fRdfDescriptor == nullptr)
667 return false;
669 const int32_t rindex(pData->param.data[parameterId].rindex);
670 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
672 if (rindex >= static_cast<int32_t>(fRdfDescriptor->PortCount))
673 return false;
675 const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]);
677 if (! LADSPA_RDF_PORT_HAS_LABEL(port.Hints))
678 return false;
680 CARLA_SAFE_ASSERT_RETURN(port.Label != nullptr, false);
682 std::strncpy(strBuf, port.Label, STR_MAX);
683 return true;
686 bool getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) const noexcept override
688 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
689 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
691 const int32_t rindex(pData->param.data[parameterId].rindex);
692 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
693 CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fRdfDescriptor->PortCount), false);
695 const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]);
696 CARLA_SAFE_ASSERT_RETURN(scalePointId < port.ScalePointCount, false);
698 const LADSPA_RDF_ScalePoint& scalePoint(port.ScalePoints[scalePointId]);
699 CARLA_SAFE_ASSERT_RETURN(scalePoint.Label != nullptr, false);
701 std::strncpy(strBuf, scalePoint.Label, STR_MAX);
702 return true;
705 // -------------------------------------------------------------------
706 // Set data (state)
708 // nothing
710 // -------------------------------------------------------------------
711 // Set data (internal stuff)
713 void setId(const uint newId) noexcept override
715 CarlaPlugin::setId(newId);
717 // UI osc-url uses Id, so we need to close it when it changes
718 // FIXME - must be RT safe
719 showCustomUI(false);
722 // -------------------------------------------------------------------
723 // Set data (plugin-specific stuff)
725 void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
727 CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr,);
728 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
730 const float fixedValue(pData->param.getFixedValue(parameterId, value));
731 fParamBuffers[parameterId] = fixedValue;
733 CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
736 void setParameterValueRT(const uint32_t parameterId, const float value, const uint32_t frameOffset, const bool sendCallbackLater) noexcept override
738 CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr,);
739 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
741 const float fixedValue(pData->param.getFixedValue(parameterId, value));
742 fParamBuffers[parameterId] = fixedValue;
744 CarlaPlugin::setParameterValueRT(parameterId, fixedValue, frameOffset, sendCallbackLater);
747 void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
749 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
750 CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',);
751 CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
752 CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
753 carla_debug("CarlaPluginLADSPADSSI::setCustomData(%s, %s, %s, %s)", type, key, value, bool2str(sendGui));
755 if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
756 return CarlaPlugin::setCustomData(type, key, value, sendGui);
758 if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) != 0)
759 return carla_stderr2("CarlaPluginLADSPADSSI::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string",
760 type, key, value, bool2str(sendGui));
762 if (fDssiDescriptor->configure != nullptr && fHandles.count() > 0)
764 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
766 LADSPA_Handle const handle(it.getValue(nullptr));
767 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
769 try {
770 fDssiDescriptor->configure(handle, key, value);
771 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI setCustomData");
775 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
776 if (sendGui && fOscData.target != nullptr)
777 osc_send_configure(fOscData, key, value);
778 #endif
780 if (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0)
782 const ScopedSingleProcessLocker spl(this, true);
783 reloadPrograms(false);
786 CarlaPlugin::setCustomData(type, key, value, sendGui);
789 void setChunkData(const void* const data, const std::size_t dataSize) override
791 CARLA_SAFE_ASSERT_RETURN(fUsesCustomData,);
792 CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,);
793 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
794 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->set_custom_data != nullptr,);
795 CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
796 CARLA_SAFE_ASSERT_RETURN(dataSize > 0,);
798 if (fHandles.count() > 0)
800 const ScopedSingleProcessLocker spl(this, true);
802 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
804 LADSPA_Handle const handle(it.getValue(nullptr));
805 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
807 try {
808 fDssiDescriptor->set_custom_data(handle, const_cast<void*>(data), static_cast<ulong>(dataSize));
809 } CARLA_SAFE_EXCEPTION("CarlaPluginLADSPADSSI::setChunkData");
813 pData->updateParameterValues(this, true, true, false);
816 void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override
818 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
819 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->select_program != nullptr,);
820 CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),);
821 CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback || doingInit,);
823 if (index >= 0 && fHandles.count() > 0)
825 const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback));
827 setMidiProgramInDSSI(static_cast<uint32_t>(index));
830 CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, doingInit);
833 void setMidiProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept override
835 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
836 CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->select_program != nullptr,);
837 CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,);
839 setMidiProgramInDSSI(uindex);
841 CarlaPlugin::setMidiProgramRT(uindex, sendCallbackLater);
844 void setMidiProgramInDSSI(const uint32_t uindex) noexcept
846 const uint32_t bank(pData->midiprog.data[uindex].bank);
847 const uint32_t program(pData->midiprog.data[uindex].program);
849 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
851 LADSPA_Handle const handle(it.getValue(nullptr));
852 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
854 try {
855 fDssiDescriptor->select_program(handle, bank, program);
856 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI setMidiProgram")
860 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
861 // -------------------------------------------------------------------
862 // Set ui stuff
864 void setCustomUITitle(const char* title) noexcept override
866 fThreadUI.setUITitle(title);
867 CarlaPlugin::setCustomUITitle(title);
870 void showCustomUI(const bool yesNo) override
872 if (yesNo)
874 fOscData.clear();
875 fThreadUI.startThread();
877 else
879 #ifndef BUILD_BRIDGE
880 pData->transientTryCounter = 0;
881 #endif
883 if (fOscData.target != nullptr)
885 osc_send_hide(fOscData);
886 osc_send_quit(fOscData);
887 fOscData.clear();
890 fThreadUI.stopThread(static_cast<int>(pData->engine->getOptions().uiBridgesTimeout * 2));
893 #endif
895 // -------------------------------------------------------------------
896 // Plugin state
898 void reload() override
900 CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
901 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
902 CARLA_SAFE_ASSERT_RETURN(fHandles.count() > 0,);
903 carla_debug("CarlaPluginLADSPADSSI::reload() - start");
905 const EngineProcessMode processMode(pData->engine->getProccessMode());
907 // Safely disable plugin for reload
908 const ScopedDisabler sd(this);
910 if (pData->active)
911 deactivate();
913 clearBuffers();
915 const float sampleRate(static_cast<float>(pData->engine->getSampleRate()));
916 const uint32_t portCount(getSafePortCount());
918 uint32_t aIns, aOuts, mIns, params;
919 aIns = aOuts = mIns = params = 0;
921 bool forcedStereoIn, forcedStereoOut;
922 forcedStereoIn = forcedStereoOut = false;
924 bool needsCtrlIn, needsCtrlOut;
925 needsCtrlIn = needsCtrlOut = false;
927 for (uint32_t i=0; i < portCount; ++i)
929 const LADSPA_PortDescriptor portType(fDescriptor->PortDescriptors[i]);
931 if (LADSPA_IS_PORT_AUDIO(portType))
933 if (LADSPA_IS_PORT_INPUT(portType))
934 aIns += 1;
935 else if (LADSPA_IS_PORT_OUTPUT(portType))
936 aOuts += 1;
938 else if (LADSPA_IS_PORT_CONTROL(portType))
939 params += 1;
942 if (pData->options & PLUGIN_OPTION_FORCE_STEREO)
944 if ((aIns == 1 || aOuts == 1) && fHandles.count() == 1 && addInstance())
946 if (aIns == 1)
948 aIns = 2;
949 forcedStereoIn = true;
951 if (aOuts == 1)
953 aOuts = 2;
954 forcedStereoOut = true;
959 if (fDssiDescriptor != nullptr && fDssiDescriptor->run_synth != nullptr)
961 mIns = 1;
962 needsCtrlIn = true;
965 if (aIns > 0)
967 pData->audioIn.createNew(aIns);
968 fAudioInBuffers = new float*[aIns];
970 for (uint32_t i=0; i < aIns; ++i)
971 fAudioInBuffers[i] = nullptr;
974 if (aOuts > 0)
976 pData->audioOut.createNew(aOuts);
977 fAudioOutBuffers = new float*[aOuts];
978 needsCtrlIn = true;
980 for (uint32_t i=0; i < aOuts; ++i)
981 fAudioOutBuffers[i] = nullptr;
984 if (params > 0)
986 pData->param.createNew(params, true);
988 fParamBuffers = new float[params];
989 carla_zeroFloats(fParamBuffers, params);
992 const uint portNameSize(pData->engine->getMaxPortNameSize());
993 CarlaString portName;
995 for (uint32_t i=0, iAudioIn=0, iAudioOut=0, iCtrl=0; i < portCount; ++i)
997 const LADSPA_PortDescriptor portType = fDescriptor->PortDescriptors[i];
998 const LADSPA_PortRangeHint portRangeHints = fDescriptor->PortRangeHints[i];
999 const bool hasPortRDF = (fRdfDescriptor != nullptr && i < fRdfDescriptor->PortCount);
1001 if (LADSPA_IS_PORT_AUDIO(portType))
1003 portName.clear();
1005 if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
1007 portName = pData->name;
1008 portName += ":";
1011 if (fDescriptor->PortNames[i] != nullptr && fDescriptor->PortNames[i][0] != '\0')
1013 portName += fDescriptor->PortNames[i];
1015 else
1017 if (LADSPA_IS_PORT_INPUT(portType))
1019 if (aIns > 1)
1021 portName += "audio-in_";
1022 portName += CarlaString(iAudioIn+1);
1024 else
1025 portName += "audio-in";
1027 else
1029 if (aOuts > 1)
1031 portName += "audio-out_";
1032 portName += CarlaString(iAudioOut+1);
1034 else
1035 portName += "audio-out";
1039 portName.truncate(portNameSize);
1041 if (LADSPA_IS_PORT_INPUT(portType))
1043 const uint32_t j = iAudioIn++;
1044 pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j);
1045 pData->audioIn.ports[j].rindex = i;
1047 if (forcedStereoIn)
1049 portName += "_2";
1050 pData->audioIn.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, 1);
1051 pData->audioIn.ports[1].rindex = i;
1054 else if (LADSPA_IS_PORT_OUTPUT(portType))
1056 const uint32_t j = iAudioOut++;
1057 pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j);
1058 pData->audioOut.ports[j].rindex = i;
1060 if (forcedStereoOut)
1062 portName += "_2";
1063 pData->audioOut.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, 1);
1064 pData->audioOut.ports[1].rindex = i;
1067 else
1068 carla_stderr2("WARNING - Got a broken Port (Audio, but not input or output)");
1070 else if (LADSPA_IS_PORT_CONTROL(portType))
1072 const uint32_t j = iCtrl++;
1073 pData->param.data[j].index = static_cast<int32_t>(j);
1074 pData->param.data[j].rindex = static_cast<int32_t>(i);
1076 const char* const paramName(fDescriptor->PortNames[i] != nullptr ? fDescriptor->PortNames[i] : "unknown");
1078 float min, max, def, step, stepSmall, stepLarge;
1080 // min value
1081 if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
1082 min = portRangeHints.LowerBound;
1083 else
1084 min = 0.0f;
1086 // max value
1087 if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
1088 max = portRangeHints.UpperBound;
1089 else
1090 max = 1.0f;
1092 if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
1094 min *= sampleRate;
1095 max *= sampleRate;
1096 pData->param.data[j].hints |= PARAMETER_USES_SAMPLERATE;
1099 if (min >= max)
1101 carla_stderr2("WARNING - Broken plugin parameter '%s': min >= max", paramName);
1102 max = min + 0.1f;
1105 // default value
1106 if (hasPortRDF && LADSPA_RDF_PORT_HAS_DEFAULT(fRdfDescriptor->Ports[i].Hints))
1107 def = fRdfDescriptor->Ports[i].Default;
1108 else
1109 def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
1111 if (def < min)
1112 def = min;
1113 else if (def > max)
1114 def = max;
1116 if (LADSPA_IS_HINT_TOGGLED(portRangeHints.HintDescriptor))
1118 step = max - min;
1119 stepSmall = step;
1120 stepLarge = step;
1121 pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN;
1123 else if (LADSPA_IS_HINT_INTEGER(portRangeHints.HintDescriptor))
1125 step = 1.0f;
1126 stepSmall = 1.0f;
1127 stepLarge = 10.0f;
1128 pData->param.data[j].hints |= PARAMETER_IS_INTEGER;
1130 else
1132 const float range = max - min;
1133 step = range/100.0f;
1134 stepSmall = range/1000.0f;
1135 stepLarge = range/10.0f;
1138 if (LADSPA_IS_PORT_INPUT(portType))
1140 pData->param.data[j].type = PARAMETER_INPUT;
1141 pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
1142 pData->param.data[j].hints |= PARAMETER_IS_AUTOMATABLE;
1143 pData->param.data[j].hints |= PARAMETER_CAN_BE_CV_CONTROLLED;
1144 needsCtrlIn = true;
1146 // MIDI CC value
1147 if (fDssiDescriptor != nullptr && fDssiDescriptor->get_midi_controller_for_port != nullptr)
1149 const int ctrl = fDssiDescriptor->get_midi_controller_for_port(fHandles.getFirst(nullptr), i);
1150 if (DSSI_CONTROLLER_IS_SET(ctrl) && DSSI_IS_CC(ctrl))
1152 const int16_t cc = DSSI_CC_NUMBER(ctrl);
1153 if (cc < MAX_MIDI_CONTROL && ! MIDI_IS_CONTROL_BANK_SELECT(cc))
1154 pData->param.data[j].mappedControlIndex = cc;
1158 else if (LADSPA_IS_PORT_OUTPUT(portType))
1160 pData->param.data[j].type = PARAMETER_OUTPUT;
1162 if (std::strcmp(paramName, "latency") == 0 || std::strcmp(paramName, "_latency") == 0)
1164 min = 0.0f;
1165 max = sampleRate;
1166 def = 0.0f;
1167 step = 1.0f;
1168 stepSmall = 1.0f;
1169 stepLarge = 1.0f;
1170 pData->param.special[j] = PARAMETER_SPECIAL_LATENCY;
1171 CARLA_SAFE_ASSERT_INT2(fLatencyIndex == static_cast<int32_t>(j), fLatencyIndex, j);
1173 else
1175 pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
1176 pData->param.data[j].hints |= PARAMETER_IS_AUTOMATABLE;
1177 needsCtrlOut = true;
1180 else
1182 carla_stderr2("WARNING - Got a broken Port (Control, but not input or output)");
1185 // extra parameter hints
1186 if (LADSPA_IS_HINT_LOGARITHMIC(portRangeHints.HintDescriptor))
1187 pData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC;
1189 // check for scalepoints, require at least 2 to make it useful
1190 if (hasPortRDF && fRdfDescriptor->Ports[i].ScalePointCount >= 2)
1191 pData->param.data[j].hints |= PARAMETER_USES_SCALEPOINTS;
1193 pData->param.ranges[j].min = min;
1194 pData->param.ranges[j].max = max;
1195 pData->param.ranges[j].def = def;
1196 pData->param.ranges[j].step = step;
1197 pData->param.ranges[j].stepSmall = stepSmall;
1198 pData->param.ranges[j].stepLarge = stepLarge;
1200 // Start parameters in their default values
1201 fParamBuffers[j] = def;
1203 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
1205 LADSPA_Handle const handle(it.getValue(nullptr));
1206 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
1208 try {
1209 fDescriptor->connect_port(handle, i, &fParamBuffers[j]);
1210 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (parameter)");
1213 else
1215 // Not Audio or Control
1216 carla_stderr2("ERROR - Got a broken Port (neither Audio or Control)");
1218 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
1220 LADSPA_Handle const handle(it.getValue(nullptr));
1221 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
1223 try {
1224 fDescriptor->connect_port(handle, i, nullptr);
1225 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (null)");
1230 if (needsCtrlIn)
1232 portName.clear();
1234 if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
1236 portName = pData->name;
1237 portName += ":";
1240 portName += "events-in";
1241 portName.truncate(portNameSize);
1243 pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0);
1244 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1245 pData->event.cvSourcePorts = pData->client->createCVSourcePorts();
1246 #endif
1249 if (needsCtrlOut)
1251 portName.clear();
1253 if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
1255 portName = pData->name;
1256 portName += ":";
1259 portName += "events-out";
1260 portName.truncate(portNameSize);
1262 pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0);
1265 if (forcedStereoIn || forcedStereoOut)
1266 pData->options |= PLUGIN_OPTION_FORCE_STEREO;
1267 else
1268 pData->options &= ~PLUGIN_OPTION_FORCE_STEREO;
1270 // plugin hints
1271 pData->hints = 0x0;
1273 if (LADSPA_IS_HARD_RT_CAPABLE(fDescriptor->Properties))
1274 pData->hints |= PLUGIN_IS_RTSAFE;
1276 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
1277 if (fUiFilename != nullptr)
1278 pData->hints |= PLUGIN_HAS_CUSTOM_UI;
1279 #endif
1281 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1282 if (aOuts > 0 && (aIns == aOuts || aIns == 1))
1283 pData->hints |= PLUGIN_CAN_DRYWET;
1285 if (aOuts > 0)
1286 pData->hints |= PLUGIN_CAN_VOLUME;
1288 if (aOuts >= 2 && aOuts % 2 == 0)
1289 pData->hints |= PLUGIN_CAN_BALANCE;
1290 #endif
1292 // extra plugin hints
1293 pData->extraHints = 0x0;
1295 if (mIns > 0)
1296 pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
1298 // check initial latency
1299 findInitialLatencyValue(aIns, aOuts);
1301 fForcedStereoIn = forcedStereoIn;
1302 fForcedStereoOut = forcedStereoOut;
1304 bufferSizeChanged(pData->engine->getBufferSize());
1305 reloadPrograms(true);
1307 if (pData->active)
1308 activate();
1310 carla_debug("CarlaPluginLADSPADSSI::reload() - end");
1313 void findInitialLatencyValue(const uint32_t aIns, const uint32_t aOuts) const
1315 if (fLatencyIndex < 0 || fHandles.count() == 0)
1316 return;
1318 // we need to pre-run the plugin so it can update its latency control-port
1319 const LADSPA_Handle handle(fHandles.getFirst(nullptr));
1320 CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
1322 float tmpIn[64][2];
1323 float tmpOut[64][2];
1325 for (uint32_t j=0; j < aIns; ++j)
1327 tmpIn[j][0] = 0.0f;
1328 tmpIn[j][1] = 0.0f;
1330 try {
1331 fDescriptor->connect_port(handle, pData->audioIn.ports[j].rindex, tmpIn[j]);
1332 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (latency input)");
1335 for (uint32_t j=0; j < aOuts; ++j)
1337 tmpOut[j][0] = 0.0f;
1338 tmpOut[j][1] = 0.0f;
1340 try {
1341 fDescriptor->connect_port(handle, pData->audioOut.ports[j].rindex, tmpOut[j]);
1342 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (latency output)");
1345 if (fDescriptor->activate != nullptr)
1347 try {
1348 fDescriptor->activate(handle);
1349 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI latency activate");
1352 try {
1353 fDescriptor->run(handle, 2);
1354 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI latency run");
1356 if (fDescriptor->deactivate != nullptr)
1358 try {
1359 fDescriptor->deactivate(handle);
1360 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI latency deactivate");
1363 // done, let's get the value
1364 if (const uint32_t latency = getLatencyInFrames())
1366 pData->client->setLatency(latency);
1367 #ifndef BUILD_BRIDGE
1368 pData->latency.recreateBuffers(std::max(aIns, aOuts), latency);
1369 #endif
1373 void reloadPrograms(const bool doInit) override
1375 carla_debug("CarlaPluginLADSPADSSI::reloadPrograms(%s)", bool2str(doInit));
1377 const LADSPA_Handle handle(fHandles.getFirst(nullptr));
1378 CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
1380 const uint32_t oldCount = pData->midiprog.count;
1381 const int32_t current = pData->midiprog.current;
1383 // Delete old programs
1384 pData->midiprog.clear();
1386 // nothing to do for simple LADSPA plugins (do we want to bother with lrdf presets?)
1387 if (fDssiDescriptor == nullptr)
1388 return;
1390 // Query new programs
1391 uint32_t newCount = 0;
1392 if (fDssiDescriptor->get_program != nullptr && fDssiDescriptor->select_program != nullptr)
1394 for (; fDssiDescriptor->get_program(handle, newCount) != nullptr;)
1395 ++newCount;
1398 if (newCount > 0)
1400 pData->midiprog.createNew(newCount);
1402 // Update data
1403 for (uint32_t i=0; i < newCount; ++i)
1405 const DSSI_Program_Descriptor* const pdesc(fDssiDescriptor->get_program(handle, i));
1406 CARLA_SAFE_ASSERT_CONTINUE(pdesc != nullptr);
1407 CARLA_SAFE_ASSERT(pdesc->Name != nullptr);
1409 pData->midiprog.data[i].bank = static_cast<uint32_t>(pdesc->Bank);
1410 pData->midiprog.data[i].program = static_cast<uint32_t>(pdesc->Program);
1411 pData->midiprog.data[i].name = carla_strdup(pdesc->Name);
1415 if (doInit)
1417 if (newCount > 0)
1418 setMidiProgram(0, false, false, false, true);
1420 else
1422 // Check if current program is invalid
1423 bool programChanged = false;
1425 if (newCount == oldCount+1)
1427 // one midi program added, probably created by user
1428 pData->midiprog.current = static_cast<int32_t>(oldCount);
1429 programChanged = true;
1431 else if (current < 0 && newCount > 0)
1433 // programs exist now, but not before
1434 pData->midiprog.current = 0;
1435 programChanged = true;
1437 else if (current >= 0 && newCount == 0)
1439 // programs existed before, but not anymore
1440 pData->midiprog.current = -1;
1441 programChanged = true;
1443 else if (current >= static_cast<int32_t>(newCount))
1445 // current midi program > count
1446 pData->midiprog.current = 0;
1447 programChanged = true;
1449 else
1451 // no change
1452 pData->midiprog.current = current;
1455 if (programChanged)
1456 setMidiProgram(pData->midiprog.current, true, true, true, false);
1458 pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0, 0.0f, nullptr);
1462 // -------------------------------------------------------------------
1463 // Plugin processing
1465 void activate() noexcept override
1467 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
1469 if (fDescriptor->activate != nullptr)
1471 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
1473 LADSPA_Handle const handle(it.getValue(nullptr));
1474 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
1476 try {
1477 fDescriptor->activate(handle);
1478 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI activate");
1483 void deactivate() noexcept override
1485 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
1487 if (fDescriptor->deactivate != nullptr)
1489 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
1491 LADSPA_Handle const handle(it.getValue(nullptr));
1492 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
1494 try {
1495 fDescriptor->deactivate(handle);
1496 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI deactivate");
1501 void process(const float* const* const audioIn, float** const audioOut,
1502 const float* const* const cvIn, float**,
1503 const uint32_t frames) override
1505 // --------------------------------------------------------------------------------------------------------
1506 // Check if active
1508 if (! pData->active)
1510 // disable any output sound
1511 for (uint32_t i=0; i < pData->audioOut.count; ++i)
1512 carla_zeroFloats(audioOut[i], frames);
1513 return;
1516 ulong midiEventCount = 0;
1517 carla_zeroStructs(fMidiEvents, kPluginMaxMidiEvents);
1519 // --------------------------------------------------------------------------------------------------------
1520 // Check if needs reset
1522 if (pData->needsReset)
1524 if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
1526 midiEventCount = MAX_MIDI_CHANNELS*2;
1528 for (uchar i=0, k=MAX_MIDI_CHANNELS; i < MAX_MIDI_CHANNELS; ++i)
1530 fMidiEvents[i].type = SND_SEQ_EVENT_CONTROLLER;
1531 fMidiEvents[i].data.control.channel = i;
1532 fMidiEvents[i].data.control.param = MIDI_CONTROL_ALL_NOTES_OFF;
1534 fMidiEvents[k+i].type = SND_SEQ_EVENT_CONTROLLER;
1535 fMidiEvents[k+i].data.control.channel = i;
1536 fMidiEvents[k+i].data.control.param = MIDI_CONTROL_ALL_SOUND_OFF;
1539 else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS)
1541 midiEventCount = MAX_MIDI_NOTE;
1543 for (uchar i=0; i < MAX_MIDI_NOTE; ++i)
1545 fMidiEvents[i].type = SND_SEQ_EVENT_NOTEOFF;
1546 fMidiEvents[i].data.note.channel = static_cast<uchar>(pData->ctrlChannel);
1547 fMidiEvents[i].data.note.note = i;
1551 pData->needsReset = false;
1554 // --------------------------------------------------------------------------------------------------------
1555 // Event Input and Processing
1557 if (pData->event.portIn != nullptr)
1559 // ----------------------------------------------------------------------------------------------------
1560 // MIDI Input (External)
1562 if (pData->extNotes.mutex.tryLock())
1564 ExternalMidiNote note = { 0, 0, 0 };
1566 for (; midiEventCount < kPluginMaxMidiEvents && ! pData->extNotes.data.isEmpty();)
1568 note = pData->extNotes.data.getFirst(note, true);
1569 CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
1571 snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]);
1572 carla_zeroStruct(seqEvent);
1574 seqEvent.type = (note.velo > 0) ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF;
1575 seqEvent.data.note.channel = static_cast<uchar>(note.channel);
1576 seqEvent.data.note.note = note.note;
1577 seqEvent.data.note.velocity = note.velo;
1580 pData->extNotes.mutex.unlock();
1582 } // End of MIDI Input (External)
1584 // ----------------------------------------------------------------------------------------------------
1585 // Event Input (System)
1587 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1588 bool allNotesOffSent = false;
1589 #endif
1590 const bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0;
1592 uint32_t startTime = 0;
1593 uint32_t timeOffset = 0;
1594 uint32_t nextBankId;
1596 if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
1597 nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
1598 else
1599 nextBankId = 0;
1601 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1602 if (cvIn != nullptr && pData->event.cvSourcePorts != nullptr)
1603 pData->event.cvSourcePorts->initPortBuffers(cvIn, frames, isSampleAccurate, pData->event.portIn);
1604 #endif
1606 for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i)
1608 EngineEvent& event(pData->event.portIn->getEvent(i));
1610 uint32_t eventTime = event.time;
1611 CARLA_SAFE_ASSERT_UINT2_CONTINUE(eventTime < frames, eventTime, frames);
1613 if (eventTime < timeOffset)
1615 carla_stderr2("Timing error, eventTime:%u < timeOffset:%u for '%s'",
1616 eventTime, timeOffset, pData->name);
1617 eventTime = timeOffset;
1620 if (isSampleAccurate && eventTime > timeOffset)
1622 if (processSingle(audioIn, audioOut, eventTime - timeOffset, timeOffset, midiEventCount))
1624 startTime = 0;
1625 timeOffset = eventTime;
1626 midiEventCount = 0;
1628 if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
1629 nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
1630 else
1631 nextBankId = 0;
1633 else
1634 startTime += timeOffset;
1637 switch (event.type)
1639 case kEngineEventTypeNull:
1640 break;
1642 case kEngineEventTypeControl: {
1643 EngineControlEvent& ctrlEvent(event.ctrl);
1645 switch (ctrlEvent.type)
1647 case kEngineControlEventTypeNull:
1648 break;
1650 case kEngineControlEventTypeParameter: {
1651 float value;
1653 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1654 // non-midi
1655 if (event.channel == kEngineEventNonMidiChannel)
1657 const uint32_t k = ctrlEvent.param;
1658 CARLA_SAFE_ASSERT_CONTINUE(k < pData->param.count);
1660 ctrlEvent.handled = true;
1661 value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.normalizedValue);
1662 setParameterValueRT(k, value, event.time, true);
1663 continue;
1666 // Control backend stuff
1667 if (event.channel == pData->ctrlChannel)
1669 if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0)
1671 ctrlEvent.handled = true;
1672 value = ctrlEvent.normalizedValue;
1673 setDryWetRT(value, true);
1675 else if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0)
1677 ctrlEvent.handled = true;
1678 value = ctrlEvent.normalizedValue*127.0f/100.0f;
1679 setVolumeRT(value, true);
1681 else if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0)
1683 float left, right;
1684 value = ctrlEvent.normalizedValue/0.5f - 1.0f;
1686 if (value < 0.0f)
1688 left = -1.0f;
1689 right = (value*2.0f)+1.0f;
1691 else if (value > 0.0f)
1693 left = (value*2.0f)-1.0f;
1694 right = 1.0f;
1696 else
1698 left = -1.0f;
1699 right = 1.0f;
1702 ctrlEvent.handled = true;
1703 setBalanceLeftRT(left, true);
1704 setBalanceRightRT(right, true);
1707 #endif
1708 // Control plugin parameters
1709 for (uint32_t k=0; k < pData->param.count; ++k)
1711 if (pData->param.data[k].midiChannel != event.channel)
1712 continue;
1713 if (pData->param.data[k].mappedControlIndex != ctrlEvent.param)
1714 continue;
1715 if (pData->param.data[k].type != PARAMETER_INPUT)
1716 continue;
1717 if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMATABLE) == 0)
1718 continue;
1720 ctrlEvent.handled = true;
1721 value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.normalizedValue);
1722 setParameterValueRT(k, value, event.time, true);
1725 if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_VALUE)
1727 if (midiEventCount >= kPluginMaxMidiEvents)
1728 continue;
1730 snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]);
1731 carla_zeroStruct(seqEvent);
1733 seqEvent.time.tick = isSampleAccurate ? startTime : eventTime;
1735 seqEvent.type = SND_SEQ_EVENT_CONTROLLER;
1736 seqEvent.data.control.channel = event.channel;
1737 seqEvent.data.control.param = ctrlEvent.param;
1738 seqEvent.data.control.value = int8_t(ctrlEvent.normalizedValue*127.0f + 0.5f);
1741 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1742 if (! ctrlEvent.handled)
1743 checkForMidiLearn(event);
1744 #endif
1745 break;
1746 } // case kEngineControlEventTypeParameter
1748 case kEngineControlEventTypeMidiBank:
1749 if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
1750 nextBankId = ctrlEvent.param;
1751 break;
1753 case kEngineControlEventTypeMidiProgram:
1754 if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
1756 const uint32_t nextProgramId = ctrlEvent.param;
1758 for (uint32_t k=0; k < pData->midiprog.count; ++k)
1760 if (pData->midiprog.data[k].bank == nextBankId && pData->midiprog.data[k].program == nextProgramId)
1762 setMidiProgramRT(k, true);
1763 break;
1767 break;
1769 case kEngineControlEventTypeAllSoundOff:
1770 if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
1772 if (midiEventCount >= kPluginMaxMidiEvents)
1773 continue;
1775 snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]);
1776 carla_zeroStruct(seqEvent);
1778 seqEvent.time.tick = isSampleAccurate ? startTime : eventTime;
1780 seqEvent.type = SND_SEQ_EVENT_CONTROLLER;
1781 seqEvent.data.control.channel = event.channel;
1782 seqEvent.data.control.param = MIDI_CONTROL_ALL_SOUND_OFF;
1784 break;
1786 case kEngineControlEventTypeAllNotesOff:
1787 if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
1789 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1790 if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
1792 allNotesOffSent = true;
1793 postponeRtAllNotesOff();
1795 #endif
1797 if (midiEventCount >= kPluginMaxMidiEvents)
1798 continue;
1800 snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]);
1801 carla_zeroStruct(seqEvent);
1803 seqEvent.time.tick = isSampleAccurate ? startTime : eventTime;
1805 seqEvent.type = SND_SEQ_EVENT_CONTROLLER;
1806 seqEvent.data.control.channel = event.channel;
1807 seqEvent.data.control.param = MIDI_CONTROL_ALL_NOTES_OFF;
1809 break;
1810 } // switch (ctrlEvent.type)
1811 break;
1812 } // case kEngineEventTypeControl
1814 case kEngineEventTypeMidi: {
1815 if (midiEventCount >= kPluginMaxMidiEvents)
1816 continue;
1818 const EngineMidiEvent& midiEvent(event.midi);
1820 if (midiEvent.size > EngineMidiEvent::kDataSize)
1821 continue;
1823 uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data));
1825 // Fix bad note-off (per DSSI spec)
1826 if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0)
1827 status = MIDI_STATUS_NOTE_OFF;
1829 snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]);
1830 carla_zeroStruct(seqEvent);
1832 seqEvent.time.tick = isSampleAccurate ? startTime : eventTime;
1834 switch (status)
1836 case MIDI_STATUS_NOTE_OFF:
1837 if ((pData->options & PLUGIN_OPTION_SKIP_SENDING_NOTES) == 0x0)
1839 const uint8_t note = midiEvent.data[1];
1841 seqEvent.type = SND_SEQ_EVENT_NOTEOFF;
1842 seqEvent.data.note.channel = event.channel;
1843 seqEvent.data.note.note = note;
1845 pData->postponeNoteOffRtEvent(true, event.channel, note);
1847 break;
1849 case MIDI_STATUS_NOTE_ON:
1850 if ((pData->options & PLUGIN_OPTION_SKIP_SENDING_NOTES) == 0x0)
1852 const uint8_t note = midiEvent.data[1];
1853 const uint8_t velo = midiEvent.data[2];
1855 seqEvent.type = SND_SEQ_EVENT_NOTEON;
1856 seqEvent.data.note.channel = event.channel;
1857 seqEvent.data.note.note = note;
1858 seqEvent.data.note.velocity = velo;
1860 pData->postponeNoteOnRtEvent(true, event.channel, note, velo);
1862 break;
1864 case MIDI_STATUS_POLYPHONIC_AFTERTOUCH:
1865 if (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH)
1867 const uint8_t note = midiEvent.data[1];
1868 const uint8_t pressure = midiEvent.data[2];
1870 seqEvent.type = SND_SEQ_EVENT_KEYPRESS;
1871 seqEvent.data.note.channel = event.channel;
1872 seqEvent.data.note.note = note;
1873 seqEvent.data.note.velocity = pressure;
1875 break;
1877 case MIDI_STATUS_CONTROL_CHANGE:
1878 if (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES)
1880 const uint8_t control = midiEvent.data[1];
1881 const uint8_t value = midiEvent.data[2];
1883 seqEvent.type = SND_SEQ_EVENT_CONTROLLER;
1884 seqEvent.data.control.channel = event.channel;
1885 seqEvent.data.control.param = control;
1886 seqEvent.data.control.value = value;
1888 break;
1890 case MIDI_STATUS_CHANNEL_PRESSURE:
1891 if (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE)
1893 const uint8_t pressure = midiEvent.data[1];
1895 seqEvent.type = SND_SEQ_EVENT_CHANPRESS;
1896 seqEvent.data.control.channel = event.channel;
1897 seqEvent.data.control.value = pressure;
1899 break;
1901 case MIDI_STATUS_PITCH_WHEEL_CONTROL:
1902 if (pData->options & PLUGIN_OPTION_SEND_PITCHBEND)
1904 const uint8_t lsb = midiEvent.data[1];
1905 const uint8_t msb = midiEvent.data[2];
1907 seqEvent.type = SND_SEQ_EVENT_PITCHBEND;
1908 seqEvent.data.control.channel = event.channel;
1909 seqEvent.data.control.value = ((msb << 7) | lsb) - 8192;
1911 break;
1913 default:
1914 --midiEventCount;
1915 break;
1916 } // switch (status)
1917 } break;
1918 } // switch (event.type)
1921 pData->postRtEvents.trySplice();
1923 if (frames > timeOffset)
1924 processSingle(audioIn, audioOut, frames - timeOffset, timeOffset, midiEventCount);
1926 } // End of Event Input and Processing
1928 // --------------------------------------------------------------------------------------------------------
1929 // Plugin processing (no events)
1931 else
1933 processSingle(audioIn, audioOut, frames, 0, midiEventCount);
1935 } // End of Plugin processing (no events)
1937 // --------------------------------------------------------------------------------------------------------
1938 // Control Output
1940 if (pData->event.portOut != nullptr)
1942 uint8_t channel;
1943 uint16_t param;
1944 float value;
1946 for (uint32_t k=0; k < pData->param.count; ++k)
1948 if (pData->param.data[k].type != PARAMETER_OUTPUT)
1949 continue;
1951 pData->param.ranges[k].fixValue(fParamBuffers[k]);
1953 if (pData->param.data[k].mappedControlIndex > 0)
1955 channel = pData->param.data[k].midiChannel;
1956 param = static_cast<uint16_t>(pData->param.data[k].mappedControlIndex);
1957 value = pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]);
1958 pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter,
1959 param, -1, value);
1962 } // End of Control Output
1964 #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH
1965 return;
1967 // unused
1968 (void)cvIn;
1969 #endif
1972 bool processSingle(const float* const* const audioIn, float** const audioOut, const uint32_t frames,
1973 const uint32_t timeOffset, const ulong midiEventCount)
1975 CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
1977 if (pData->audioIn.count > 0)
1979 CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false);
1981 if (pData->audioOut.count > 0)
1983 CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false);
1986 // --------------------------------------------------------------------------------------------------------
1987 // Try lock, silence otherwise
1989 #ifndef STOAT_TEST_BUILD
1990 if (pData->engine->isOffline())
1992 pData->singleMutex.lock();
1994 else
1995 #endif
1996 if (! pData->singleMutex.tryLock())
1998 for (uint32_t i=0; i < pData->audioOut.count; ++i)
2000 for (uint32_t k=0; k < frames; ++k)
2001 audioOut[i][k+timeOffset] = 0.0f;
2004 return false;
2007 // --------------------------------------------------------------------------------------------------------
2008 // Set audio buffers
2010 const bool customMonoOut = pData->audioOut.count == 2 && fForcedStereoOut && ! fForcedStereoIn;
2011 const bool customStereoOut = pData->audioOut.count == 2 && fForcedStereoIn && ! fForcedStereoOut;
2013 if (! customMonoOut)
2015 for (uint32_t i=0; i < pData->audioOut.count; ++i)
2016 carla_zeroFloats(fAudioOutBuffers[i], frames);
2019 for (uint32_t i=0; i < pData->audioIn.count; ++i)
2020 carla_copyFloats(fAudioInBuffers[i], audioIn[i]+timeOffset, frames);
2022 // --------------------------------------------------------------------------------------------------------
2023 // Run plugin
2025 uint instn = 0;
2026 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next(), ++instn)
2028 LADSPA_Handle const handle(it.getValue(nullptr));
2029 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
2031 // ----------------------------------------------------------------------------------------------------
2032 // Mixdown for forced stereo
2034 if (customMonoOut)
2035 carla_zeroFloats(fAudioOutBuffers[instn], frames);
2037 // ----------------------------------------------------------------------------------------------------
2038 // Run it
2040 if (fDssiDescriptor != nullptr && fDssiDescriptor->run_synth != nullptr)
2042 try {
2043 fDssiDescriptor->run_synth(handle, frames, fMidiEvents, midiEventCount);
2044 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI run_synth");
2046 else
2048 try {
2049 fDescriptor->run(handle, frames);
2050 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI run");
2053 // ----------------------------------------------------------------------------------------------------
2054 // Mixdown for forced stereo
2056 if (customMonoOut)
2057 carla_multiply(fAudioOutBuffers[instn], 0.5f, frames);
2058 else if (customStereoOut)
2059 carla_copyFloats(fExtraStereoBuffer[instn], fAudioOutBuffers[instn], frames);
2062 if (customStereoOut)
2064 carla_copyFloats(fAudioOutBuffers[0], fExtraStereoBuffer[0], frames);
2065 carla_copyFloats(fAudioOutBuffers[1], fExtraStereoBuffer[1], frames);
2068 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2069 // --------------------------------------------------------------------------------------------------------
2070 // Post-processing (dry/wet, volume and balance)
2073 const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && carla_isNotEqual(pData->postProc.dryWet, 1.0f);
2074 const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f));
2075 const bool isMono = (pData->audioIn.count == 1);
2077 bool isPair;
2078 float bufValue;
2079 float* const oldBufLeft = pData->postProc.extraBuffer;
2081 for (uint32_t i=0; i < pData->audioOut.count; ++i)
2083 // Dry/Wet
2084 if (doDryWet)
2086 const uint32_t c = isMono ? 0 : i;
2088 for (uint32_t k=0; k < frames; ++k)
2090 # ifndef BUILD_BRIDGE
2091 if (k < pData->latency.frames && pData->latency.buffers != nullptr)
2092 bufValue = pData->latency.buffers[c][k];
2093 else if (pData->latency.frames < frames)
2094 bufValue = fAudioInBuffers[c][k-pData->latency.frames];
2095 else
2096 # endif
2097 bufValue = fAudioInBuffers[c][k];
2099 fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
2103 // Balance
2104 if (doBalance)
2106 isPair = (i % 2 == 0);
2108 if (isPair)
2110 CARLA_ASSERT(i+1 < pData->audioOut.count);
2111 carla_copyFloats(oldBufLeft, fAudioOutBuffers[i], frames);
2114 float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
2115 float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
2117 for (uint32_t k=0; k < frames; ++k)
2119 if (isPair)
2121 // left
2122 fAudioOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
2123 fAudioOutBuffers[i][k] += fAudioOutBuffers[i+1][k] * (1.0f - balRangeR);
2125 else
2127 // right
2128 fAudioOutBuffers[i][k] = fAudioOutBuffers[i][k] * balRangeR;
2129 fAudioOutBuffers[i][k] += oldBufLeft[k] * balRangeL;
2134 // Volume (and buffer copy)
2136 for (uint32_t k=0; k < frames; ++k)
2137 audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k] * pData->postProc.volume;
2141 } // End of Post-processing
2143 # ifndef BUILD_BRIDGE
2144 // --------------------------------------------------------------------------------------------------------
2145 // Save latency values for next callback
2147 if (pData->latency.frames != 0 && pData->latency.buffers != nullptr)
2149 CARLA_SAFE_ASSERT(timeOffset == 0);
2150 const uint32_t latframes = pData->latency.frames;
2152 if (latframes <= frames)
2154 for (uint32_t i=0; i < pData->audioIn.count; ++i)
2155 carla_copyFloats(pData->latency.buffers[i], audioIn[i]+(frames-latframes), latframes);
2157 else
2159 const uint32_t diff = latframes - frames;
2161 for (uint32_t i=0, k; i<pData->audioIn.count; ++i)
2163 // push back buffer by 'frames'
2164 for (k=0; k < diff; ++k)
2165 pData->latency.buffers[i][k] = pData->latency.buffers[i][k+frames];
2167 // put current input at the end
2168 for (uint32_t j=0; k < latframes; ++j, ++k)
2169 pData->latency.buffers[i][k] = audioIn[i][j];
2173 # endif
2174 #else // BUILD_BRIDGE_ALTERNATIVE_ARCH
2175 for (uint32_t i=0; i < pData->audioOut.count; ++i)
2177 for (uint32_t k=0; k < frames; ++k)
2178 audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k];
2180 #endif
2182 // --------------------------------------------------------------------------------------------------------
2184 pData->singleMutex.unlock();
2185 return true;
2188 void bufferSizeChanged(const uint32_t newBufferSize) override
2190 CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize);
2191 carla_debug("CarlaPluginLADSPADSSI::bufferSizeChanged(%i) - start", newBufferSize);
2193 for (uint32_t i=0; i < pData->audioIn.count; ++i)
2195 if (fAudioInBuffers[i] != nullptr)
2196 delete[] fAudioInBuffers[i];
2198 fAudioInBuffers[i] = new float[newBufferSize];
2199 carla_zeroFloats(fAudioInBuffers[i], newBufferSize);
2202 for (uint32_t i=0; i < pData->audioOut.count; ++i)
2204 if (fAudioOutBuffers[i] != nullptr)
2205 delete[] fAudioOutBuffers[i];
2207 fAudioOutBuffers[i] = new float[newBufferSize];
2208 carla_zeroFloats(fAudioOutBuffers[i], newBufferSize);
2211 if (fExtraStereoBuffer[0] != nullptr)
2213 delete[] fExtraStereoBuffer[0];
2214 fExtraStereoBuffer[0] = nullptr;
2217 if (fExtraStereoBuffer[1] != nullptr)
2219 delete[] fExtraStereoBuffer[1];
2220 fExtraStereoBuffer[1] = nullptr;
2223 if (fForcedStereoIn && pData->audioOut.count == 2)
2225 fExtraStereoBuffer[0] = new float[newBufferSize];
2226 fExtraStereoBuffer[1] = new float[newBufferSize];
2227 carla_zeroFloats(fExtraStereoBuffer[0], newBufferSize);
2228 carla_zeroFloats(fExtraStereoBuffer[1], newBufferSize);
2231 reconnectAudioPorts();
2233 carla_debug("CarlaPluginLADSPADSSI::bufferSizeChanged(%i) - end", newBufferSize);
2235 CarlaPlugin::bufferSizeChanged(newBufferSize);
2238 void sampleRateChanged(const double newSampleRate) override
2240 CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate);
2241 carla_debug("CarlaPluginLADSPADSSI::sampleRateChanged(%g) - start", newSampleRate);
2243 // TODO - handle UI stuff
2245 if (pData->active)
2246 deactivate();
2248 const std::size_t instanceCount(fHandles.count());
2250 if (fDescriptor->cleanup != nullptr)
2252 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
2254 LADSPA_Handle const handle(it.getValue(nullptr));
2255 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
2257 try {
2258 fDescriptor->cleanup(handle);
2259 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI cleanup");
2263 fHandles.clear();
2265 for (std::size_t i=0; i<instanceCount; ++i)
2266 addInstance();
2268 reconnectAudioPorts();
2270 if (pData->active)
2271 activate();
2273 carla_debug("CarlaPluginLADSPADSSI::sampleRateChanged(%g) - end", newSampleRate);
2276 void reconnectAudioPorts() const noexcept
2278 if (fForcedStereoIn)
2280 if (LADSPA_Handle const handle = fHandles.getFirst(nullptr))
2282 try {
2283 fDescriptor->connect_port(handle, pData->audioIn.ports[0].rindex, fAudioInBuffers[0]);
2284 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo input, first)");
2287 if (LADSPA_Handle const handle = fHandles.getLast(nullptr))
2289 try {
2290 fDescriptor->connect_port(handle, pData->audioIn.ports[1].rindex, fAudioInBuffers[1]);
2291 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo input, last)");
2294 else
2296 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
2298 LADSPA_Handle const handle(it.getValue(nullptr));
2299 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
2301 for (uint32_t i=0; i < pData->audioIn.count; ++i)
2303 try {
2304 fDescriptor->connect_port(handle, pData->audioIn.ports[i].rindex, fAudioInBuffers[i]);
2305 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (audio input)");
2310 if (fForcedStereoOut)
2312 if (LADSPA_Handle const handle = fHandles.getFirst(nullptr))
2314 try {
2315 fDescriptor->connect_port(handle, pData->audioOut.ports[0].rindex, fAudioOutBuffers[0]);
2316 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo output, first)");
2319 if (LADSPA_Handle const handle = fHandles.getLast(nullptr))
2321 try {
2322 fDescriptor->connect_port(handle, pData->audioOut.ports[1].rindex, fAudioOutBuffers[1]);
2323 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo output, last)");
2326 else
2328 for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
2330 LADSPA_Handle const handle(it.getValue(nullptr));
2331 CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
2333 for (uint32_t i=0; i < pData->audioOut.count; ++i)
2335 try {
2336 fDescriptor->connect_port(handle, pData->audioOut.ports[i].rindex, fAudioOutBuffers[i]);
2337 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (audio output)");
2343 // -------------------------------------------------------------------
2344 // Plugin buffers
2346 void clearBuffers() noexcept override
2348 carla_debug("CarlaPluginLADSPADSSI::clearBuffers() - start");
2350 if (fAudioInBuffers != nullptr)
2352 for (uint32_t i=0; i < pData->audioIn.count; ++i)
2354 if (fAudioInBuffers[i] != nullptr)
2356 delete[] fAudioInBuffers[i];
2357 fAudioInBuffers[i] = nullptr;
2361 delete[] fAudioInBuffers;
2362 fAudioInBuffers = nullptr;
2365 if (fAudioOutBuffers != nullptr)
2367 for (uint32_t i=0; i < pData->audioOut.count; ++i)
2369 if (fAudioOutBuffers[i] != nullptr)
2371 delete[] fAudioOutBuffers[i];
2372 fAudioOutBuffers[i] = nullptr;
2376 delete[] fAudioOutBuffers;
2377 fAudioOutBuffers = nullptr;
2380 if (fExtraStereoBuffer[0] != nullptr)
2382 delete[] fExtraStereoBuffer[0];
2383 fExtraStereoBuffer[0] = nullptr;
2386 if (fExtraStereoBuffer[1] != nullptr)
2388 delete[] fExtraStereoBuffer[1];
2389 fExtraStereoBuffer[1] = nullptr;
2392 if (fParamBuffers != nullptr)
2394 delete[] fParamBuffers;
2395 fParamBuffers = nullptr;
2398 CarlaPlugin::clearBuffers();
2400 carla_debug("CarlaPluginLADSPADSSI::clearBuffers() - end");
2403 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
2404 // -------------------------------------------------------------------
2405 // OSC stuff
2407 void handleOscMessage(const char* const method, const int argc, const void* const argvx, const char* const types, const lo_message msg) override
2409 const lo_address source(lo_message_get_source(msg));
2410 CARLA_SAFE_ASSERT_RETURN(source != nullptr,);
2412 // protocol for DSSI UIs *must* be UDP
2413 CARLA_SAFE_ASSERT_RETURN(lo_address_get_protocol(source) == LO_UDP,);
2415 if (fOscData.source == nullptr)
2417 // if no UI is registered yet only "configure" and "update" messages are valid
2418 CARLA_SAFE_ASSERT_RETURN(std::strcmp(method, "configure") == 0 || std::strcmp(method, "update") == 0,)
2420 else
2422 // make sure message source is the DSSI UI
2423 const char* const msghost = lo_address_get_hostname(source);
2424 const char* const msgport = lo_address_get_port(source);
2426 const char* const ourhost = lo_address_get_hostname(fOscData.source);
2427 const char* const ourport = lo_address_get_port(fOscData.source);
2429 CARLA_SAFE_ASSERT_RETURN(std::strcmp(msghost, ourhost) == 0,);
2430 CARLA_SAFE_ASSERT_RETURN(std::strcmp(msgport, ourport) == 0,);
2433 const lo_arg* const* const argv(static_cast<const lo_arg* const*>(argvx));
2435 if (std::strcmp(method, "configure") == 0)
2436 return handleOscMessageConfigure(argc, argv, types);
2437 if (std::strcmp(method, "control") == 0)
2438 return handleOscMessageControl(argc, argv, types);
2439 if (std::strcmp(method, "program") == 0)
2440 return handleOscMessageProgram(argc, argv, types);
2441 if (std::strcmp(method, "midi") == 0)
2442 return handleOscMessageMIDI(argc, argv, types);
2443 if (std::strcmp(method, "update") == 0)
2444 return handleOscMessageUpdate(argc, argv, types, lo_message_get_source(msg));
2445 if (std::strcmp(method, "exiting") == 0)
2446 return handleOscMessageExiting();
2448 carla_stdout("CarlaPluginLADSPADSSI::handleOscMessage() - unknown method '%s'", method);
2451 void handleOscMessageConfigure(const int argc, const lo_arg* const* const argv, const char* const types)
2453 carla_debug("CarlaPluginLADSPADSSI::handleMsgConfigure()");
2454 CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(2, "ss");
2456 const char* const key = (const char*)&argv[0]->s;
2457 const char* const value = (const char*)&argv[1]->s;
2459 setCustomData(CUSTOM_DATA_TYPE_STRING, key, value, false);
2462 void handleOscMessageControl(const int argc, const lo_arg* const* const argv, const char* const types)
2464 carla_debug("CarlaPluginLADSPADSSI::handleMsgControl()");
2465 CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(2, "if");
2467 const int32_t rindex = argv[0]->i;
2468 const float value = argv[1]->f;
2470 setParameterValueByRealIndex(rindex, value, false, true, true);
2473 void handleOscMessageProgram(const int argc, const lo_arg* const* const argv, const char* const types)
2475 carla_debug("CarlaPluginLADSPADSSI::handleMsgProgram()");
2476 CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(2, "ii");
2478 const int32_t bank = argv[0]->i;
2479 const int32_t program = argv[1]->i;
2481 CARLA_SAFE_ASSERT_RETURN(bank >= 0,);
2482 CARLA_SAFE_ASSERT_RETURN(program >= 0,);
2484 setMidiProgramById(static_cast<uint32_t>(bank), static_cast<uint32_t>(program), false, true, true);
2487 void handleOscMessageMIDI(const int argc, const lo_arg* const* const argv, const char* const types)
2489 carla_debug("CarlaPluginLADSPADSSI::handleMsgMidi()");
2490 CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(1, "m");
2492 if (getMidiInCount() == 0)
2494 carla_stderr("CarlaPluginLADSPADSSI::handleMsgMidi() - received midi when plugin has no midi inputs");
2495 return;
2498 const uint8_t* const data = argv[0]->m;
2499 uint8_t status = data[1];
2500 uint8_t channel = status & 0x0F;
2502 // Fix bad note-off
2503 if (MIDI_IS_STATUS_NOTE_ON(status) && data[3] == 0)
2504 status = MIDI_STATUS_NOTE_OFF;
2506 if (MIDI_IS_STATUS_NOTE_OFF(status))
2508 const uint8_t note = data[2];
2510 CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
2512 sendMidiSingleNote(channel, note, 0, false, true, true);
2514 else if (MIDI_IS_STATUS_NOTE_ON(status))
2516 const uint8_t note = data[2];
2517 const uint8_t velo = data[3];
2519 CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
2520 CARLA_SAFE_ASSERT_RETURN(velo < MAX_MIDI_VALUE,);
2522 sendMidiSingleNote(channel, note, velo, false, true, true);
2526 void handleOscMessageUpdate(const int argc, const lo_arg* const* const argv, const char* const types, const lo_address source)
2528 carla_debug("CarlaPluginLADSPADSSI::handleMsgUpdate()");
2529 CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(1, "s");
2531 const char* const url = (const char*)&argv[0]->s;
2533 // FIXME - remove debug prints later
2534 carla_stdout("CarlaPluginLADSPADSSI::updateOscData(%p, \"%s\")", source, url);
2536 fOscData.clear();
2538 const int proto = lo_address_get_protocol(source);
2541 const char* host = lo_address_get_hostname(source);
2542 const char* port = lo_address_get_port(source);
2543 fOscData.source = lo_address_new_with_proto(proto, host, port);
2545 carla_stdout("CarlaPlugin::updateOscData() - source: host \"%s\", port \"%s\"", host, port);
2549 char* host = lo_url_get_hostname(url);
2550 char* port = lo_url_get_port(url);
2551 fOscData.path = carla_strdup_free(lo_url_get_path(url));
2552 fOscData.target = lo_address_new_with_proto(proto, host, port);
2553 carla_stdout("CarlaPlugin::updateOscData() - target: host \"%s\", port \"%s\", path \"%s\"", host, port, fOscData.path);
2555 std::free(host);
2556 std::free(port);
2559 osc_send_sample_rate(fOscData, static_cast<float>(pData->engine->getSampleRate()));
2561 for (LinkedList<CustomData>::Itenerator it = pData->custom.begin2(); it.valid(); it.next())
2563 const CustomData& customData(it.getValue(kCustomDataFallback));
2564 CARLA_SAFE_ASSERT_CONTINUE(customData.isValid());
2566 if (std::strcmp(customData.type, CUSTOM_DATA_TYPE_STRING) == 0)
2567 osc_send_configure(fOscData, customData.key, customData.value);
2570 if (pData->prog.current >= 0)
2571 osc_send_program(fOscData, static_cast<uint32_t>(pData->prog.current));
2573 if (pData->midiprog.current >= 0)
2575 const MidiProgramData& curMidiProg(pData->midiprog.getCurrent());
2576 osc_send_program(fOscData, curMidiProg.bank, curMidiProg.program);
2579 for (uint32_t i=0; i < pData->param.count; ++i)
2580 osc_send_control(fOscData, pData->param.data[i].rindex, getParameterValue(i));
2582 #ifndef BUILD_BRIDGE
2583 if (pData->engine->getOptions().frontendWinId != 0)
2584 pData->transientTryCounter = 1;
2585 #endif
2587 carla_stdout("CarlaPluginLADSPADSSI::updateOscData() - done");
2590 void handleOscMessageExiting()
2592 carla_debug("CarlaPluginLADSPADSSI::handleMsgExiting()");
2594 // hide UI
2595 showCustomUI(false);
2597 // tell frontend
2598 pData->engine->callback(true, true,
2599 ENGINE_CALLBACK_UI_STATE_CHANGED,
2600 pData->id,
2602 0, 0, 0.0f, nullptr);
2605 // -------------------------------------------------------------------
2606 // Post-poned UI Stuff
2608 void uiParameterChange(const uint32_t index, const float value) noexcept override
2610 CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,);
2612 if (fOscData.target == nullptr)
2613 return;
2615 osc_send_control(fOscData, pData->param.data[index].rindex, value);
2618 void uiMidiProgramChange(const uint32_t index) noexcept override
2620 CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);
2622 if (fOscData.target == nullptr)
2623 return;
2625 osc_send_program(fOscData, pData->midiprog.data[index].bank, pData->midiprog.data[index].program);
2628 void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override
2630 CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
2631 CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
2632 CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,);
2634 if (fOscData.target == nullptr)
2635 return;
2637 #if 0
2638 uint8_t midiData[4];
2639 midiData[0] = 0;
2640 midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT));
2641 midiData[2] = note;
2642 midiData[3] = velo;
2644 osc_send_midi(fOscData, midiData);
2645 #endif
2648 void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override
2650 CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
2651 CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
2653 if (fOscData.target == nullptr)
2654 return;
2656 #if 0
2657 uint8_t midiData[4];
2658 midiData[0] = 0;
2659 midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT));
2660 midiData[2] = note;
2661 midiData[3] = 0;
2663 osc_send_midi(fOscData, midiData);
2664 #endif
2666 #endif // CARLA_ENABLE_DSSI_PLUGIN_GUI
2668 // -------------------------------------------------------------------
2670 const void* getNativeDescriptor() const noexcept override
2672 return fDssiDescriptor != nullptr
2673 ? (const void*)fDssiDescriptor
2674 : (const void*)fDescriptor;
2677 const void* getExtraStuff() const noexcept override
2679 if (fDssiDescriptor != nullptr)
2681 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
2682 return fUiFilename;
2683 #else
2684 return nullptr;
2685 #endif
2687 return fRdfDescriptor;
2690 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
2691 uintptr_t getUiBridgeProcessId() const noexcept override
2693 return fThreadUI.getProcessId();
2695 #endif
2697 // -------------------------------------------------------------------
2699 bool initLADSPA(const CarlaPluginPtr plugin,
2700 const char* const filename, const char* name, const char* const label, const uint options,
2701 const LADSPA_RDF_Descriptor* const rdfDescriptor)
2703 CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
2705 // ---------------------------------------------------------------
2706 // first checks
2708 if (pData->client != nullptr)
2710 pData->engine->setLastError("Plugin client is already registered");
2711 return false;
2714 if (filename == nullptr || filename[0] == '\0')
2716 pData->engine->setLastError("null filename");
2717 return false;
2720 // ---------------------------------------------------------------
2721 // open DLL
2723 if (! pData->libOpen(filename))
2725 pData->engine->setLastError(pData->libError(filename));
2726 return false;
2729 // ---------------------------------------------------------------
2730 // get DLL main entry
2732 const LADSPA_Descriptor_Function descFn = pData->libSymbol<LADSPA_Descriptor_Function>("ladspa_descriptor");
2734 if (descFn == nullptr)
2736 pData->engine->setLastError("Could not find the LASDPA Descriptor in the plugin library");
2737 return false;
2740 // ---------------------------------------------------------------
2741 // get descriptor that matches label
2743 // if label is null, get first valid plugin
2744 const bool nullLabel = (label == nullptr || label[0] == '\0');
2746 for (ulong d=0;; ++d)
2748 try {
2749 fDescriptor = descFn(d);
2751 catch(...) {
2752 carla_stderr2("Caught exception when trying to get LADSPA descriptor");
2753 fDescriptor = nullptr;
2754 break;
2757 if (fDescriptor == nullptr)
2758 break;
2760 if (fDescriptor->Label == nullptr || fDescriptor->Label[0] == '\0')
2762 carla_stderr2("WARNING - Got an invalid label, will not use this plugin");
2763 fDescriptor = nullptr;
2764 break;
2766 if (fDescriptor->run == nullptr)
2768 carla_stderr2("WARNING - Plugin has no run, cannot use it");
2769 fDescriptor = nullptr;
2770 break;
2773 if (nullLabel || std::strcmp(fDescriptor->Label, label) == 0)
2774 break;
2777 if (fDescriptor == nullptr)
2779 pData->engine->setLastError("Could not find the requested plugin label in the plugin library");
2780 return false;
2783 return init2(plugin, filename, name, options, rdfDescriptor);
2786 bool initDSSI(const CarlaPluginPtr plugin,
2787 const char* const filename, const char* name, const char* const label, const uint options)
2789 CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
2791 // ---------------------------------------------------------------
2792 // first checks
2794 if (pData->client != nullptr)
2796 pData->engine->setLastError("Plugin client is already registered");
2797 return false;
2800 if (filename == nullptr || filename[0] == '\0')
2802 pData->engine->setLastError("null filename");
2803 return false;
2806 // ---------------------------------------------------------------
2807 // open DLL
2809 if (! pData->libOpen(filename))
2811 pData->engine->setLastError(pData->libError(filename));
2812 return false;
2815 // ---------------------------------------------------------------
2816 // get DLL main entry
2818 const DSSI_Descriptor_Function descFn = pData->libSymbol<DSSI_Descriptor_Function>("dssi_descriptor");
2820 if (descFn == nullptr)
2822 pData->engine->setLastError("Could not find the DSSI Descriptor in the plugin library");
2823 return false;
2826 // ---------------------------------------------------------------
2827 // get descriptor that matches label
2829 // if label is null, get first valid plugin
2830 const bool nullLabel = (label == nullptr || label[0] == '\0');
2832 for (ulong d=0;; ++d)
2834 try {
2835 fDssiDescriptor = descFn(d);
2837 catch(...) {
2838 carla_stderr2("Caught exception when trying to get DSSI descriptor");
2839 fDescriptor = nullptr;
2840 fDssiDescriptor = nullptr;
2841 break;
2844 if (fDssiDescriptor == nullptr)
2845 break;
2847 fDescriptor = fDssiDescriptor->LADSPA_Plugin;
2849 if (fDescriptor == nullptr)
2851 carla_stderr2("WARNING - Missing LADSPA interface, will not use this plugin");
2852 fDssiDescriptor = nullptr;
2853 break;
2855 if (fDescriptor->Label == nullptr || fDescriptor->Label[0] == '\0')
2857 carla_stderr2("WARNING - Got an invalid label, will not use this plugin");
2858 fDescriptor = nullptr;
2859 fDssiDescriptor = nullptr;
2860 break;
2862 if (fDescriptor->run == nullptr)
2864 carla_stderr2("WARNING - Plugin has no run, cannot use it");
2865 fDescriptor = nullptr;
2866 fDssiDescriptor = nullptr;
2867 break;
2870 if (nullLabel || std::strcmp(fDescriptor->Label, label) == 0)
2871 break;
2874 if (fDescriptor == nullptr || fDssiDescriptor == nullptr)
2876 pData->engine->setLastError("Could not find the requested plugin label in the plugin library");
2877 return false;
2880 // ---------------------------------------------------------------
2881 // check if uses global instance
2883 if (fDssiDescriptor->run_synth == nullptr && fDssiDescriptor->run_multiple_synths != nullptr)
2885 pData->engine->setLastError("This plugin requires run_multiple_synths which is not supported");
2886 return false;
2889 return init2(plugin, filename, name, options, nullptr);
2892 bool init2(const CarlaPluginPtr plugin,
2893 const char* const filename, const char* name, const uint options,
2894 const LADSPA_RDF_Descriptor* const rdfDescriptor)
2896 // ---------------------------------------------------------------
2897 // check for fixed buffer size requirement
2899 fNeedsFixedBuffers = CarlaString(filename).contains("dssi-vst", true);
2901 if (fNeedsFixedBuffers && ! pData->engine->usesConstantBufferSize())
2903 pData->engine->setLastError("Cannot use this plugin under the current engine.\n"
2904 "The plugin requires a fixed block size which is not possible right now.");
2905 return false;
2908 // ---------------------------------------------------------------
2909 // get info
2911 if (is_ladspa_rdf_descriptor_valid(rdfDescriptor, fDescriptor))
2912 fRdfDescriptor = ladspa_rdf_dup(rdfDescriptor);
2914 if (name == nullptr || name[0] == '\0')
2916 /**/ if (fRdfDescriptor != nullptr && fRdfDescriptor->Title != nullptr && fRdfDescriptor->Title[0] != '\0')
2917 name = fRdfDescriptor->Title;
2918 else if (fDescriptor->Name != nullptr && fDescriptor->Name[0] != '\0')
2919 name = fDescriptor->Name;
2920 else
2921 name = fDescriptor->Label;
2924 pData->name = pData->engine->getUniquePluginName(name);
2925 pData->filename = carla_strdup(filename);
2927 // ---------------------------------------------------------------
2928 // register client
2930 pData->client = pData->engine->addClient(plugin);
2932 if (pData->client == nullptr || ! pData->client->isOk())
2934 pData->engine->setLastError("Failed to register plugin client");
2935 return false;
2938 // ---------------------------------------------------------------
2939 // initialize plugin
2941 if (! addInstance())
2942 return false;
2944 // ---------------------------------------------------------------
2945 // find latency port index
2947 for (uint32_t i=0, iCtrl=0, count=getSafePortCount(); i<count; ++i)
2949 const int portType(fDescriptor->PortDescriptors[i]);
2951 if (! LADSPA_IS_PORT_CONTROL(portType))
2952 continue;
2954 const uint32_t index(iCtrl++);
2956 if (! LADSPA_IS_PORT_OUTPUT(portType))
2957 continue;
2959 const char* const portName(fDescriptor->PortNames[i]);
2960 CARLA_SAFE_ASSERT_BREAK(portName != nullptr);
2962 if (std::strcmp(portName, "latency") == 0 ||
2963 std::strcmp(portName, "_latency") == 0)
2965 fLatencyIndex = static_cast<int32_t>(index);
2966 break;
2970 // ---------------------------------------------------------------
2971 // check for custom data extension
2973 if (fDssiDescriptor != nullptr && fDssiDescriptor->configure != nullptr)
2975 if (char* const error = fDssiDescriptor->configure(fHandles.getFirst(nullptr), DSSI_CUSTOMDATA_EXTENSION_KEY, ""))
2977 if (std::strcmp(error, "true") == 0 && fDssiDescriptor->get_custom_data != nullptr
2978 && fDssiDescriptor->set_custom_data != nullptr)
2979 fUsesCustomData = true;
2981 std::free(error);
2985 // ---------------------------------------------------------------
2986 // get engine options
2988 const EngineOptions& opts(pData->engine->getOptions());
2990 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
2991 // ---------------------------------------------------------------
2992 // check for gui
2994 if (opts.oscEnabled && opts.oscPortUDP >= 0)
2996 if (const char* const guiFilename = find_dssi_ui(filename, fDescriptor->Label))
2998 fUiFilename = guiFilename;
3000 CarlaString uiTitle;
3002 if (pData->uiTitle.isNotEmpty())
3004 uiTitle = pData->uiTitle;
3006 else
3008 uiTitle = pData->name;
3009 uiTitle += " (GUI)";
3012 fThreadUI.setData(guiFilename, fDescriptor->Label, uiTitle);
3015 #endif
3017 // ---------------------------------------------------------------
3018 // set options
3020 pData->options = 0x0;
3022 /**/ if (fLatencyIndex >= 0 || fNeedsFixedBuffers)
3023 pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
3024 else if (options & PLUGIN_OPTION_FIXED_BUFFERS)
3025 pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
3027 /**/ if (opts.forceStereo)
3028 pData->options |= PLUGIN_OPTION_FORCE_STEREO;
3029 else if (options & PLUGIN_OPTION_FORCE_STEREO)
3030 pData->options |= PLUGIN_OPTION_FORCE_STEREO;
3032 if (fDssiDescriptor != nullptr)
3034 if (fDssiDescriptor->get_program != nullptr && fDssiDescriptor->select_program != nullptr)
3035 if (isPluginOptionEnabled(options, PLUGIN_OPTION_MAP_PROGRAM_CHANGES))
3036 pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
3038 if (fUsesCustomData)
3039 if (isPluginOptionEnabled(options, PLUGIN_OPTION_USE_CHUNKS))
3040 pData->options |= PLUGIN_OPTION_USE_CHUNKS;
3042 if (fDssiDescriptor->run_synth != nullptr)
3044 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES))
3045 pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
3046 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE))
3047 pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
3048 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH))
3049 pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
3050 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND))
3051 pData->options |= PLUGIN_OPTION_SEND_PITCHBEND;
3052 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF))
3053 pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
3054 if (isPluginOptionInverseEnabled(options, PLUGIN_OPTION_SKIP_SENDING_NOTES))
3055 pData->options |= PLUGIN_OPTION_SKIP_SENDING_NOTES;
3059 return true;
3062 // -------------------------------------------------------------------
3064 private:
3065 LinkedList<LADSPA_Handle> fHandles;
3066 const LADSPA_Descriptor* fDescriptor;
3067 const DSSI_Descriptor* fDssiDescriptor;
3068 const LADSPA_RDF_Descriptor* fRdfDescriptor;
3070 float** fAudioInBuffers;
3071 float** fAudioOutBuffers;
3072 float* fExtraStereoBuffer[2]; // used only if forcedStereoIn and audioOut == 2
3073 float* fParamBuffers;
3075 snd_seq_event_t fMidiEvents[kPluginMaxMidiEvents];
3077 int32_t fLatencyIndex; // -1 if invalid
3078 bool fForcedStereoIn;
3079 bool fForcedStereoOut;
3080 bool fNeedsFixedBuffers;
3081 bool fUsesCustomData;
3083 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
3084 CarlaOscData fOscData;
3085 CarlaThreadDSSIUI fThreadUI;
3086 const char* fUiFilename;
3087 #endif
3089 // -------------------------------------------------------------------
3091 bool addInstance()
3093 LADSPA_Handle handle;
3095 try {
3096 handle = fDescriptor->instantiate(fDescriptor, static_cast<ulong>(pData->engine->getSampleRate()));
3097 } CARLA_SAFE_EXCEPTION_RETURN_ERR("LADSPA/DSSI instantiate", "Plugin failed to initialize");
3099 for (uint32_t i=0, count=pData->param.count; i<count; ++i)
3101 const int32_t rindex(pData->param.data[i].rindex);
3102 CARLA_SAFE_ASSERT_CONTINUE(rindex >= 0);
3104 try {
3105 fDescriptor->connect_port(handle, static_cast<ulong>(rindex), &fParamBuffers[i]);
3106 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port");
3109 if (fHandles.append(handle))
3110 return true;
3112 try {
3113 fDescriptor->cleanup(handle);
3114 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI cleanup");
3116 pData->engine->setLastError("Out of memory");
3117 return false;
3120 uint32_t getSafePortCount() const noexcept
3122 if (fDescriptor->PortCount == 0)
3123 return 0;
3125 CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortDescriptors != nullptr, 0);
3126 CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortRangeHints != nullptr, 0);
3127 CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames != nullptr, 0);
3129 return static_cast<uint32_t>(fDescriptor->PortCount);
3132 bool getSeparatedParameterNameOrUnit(const char* const paramName, char* const strBuf, const bool wantName) const noexcept
3134 if (_getSeparatedParameterNameOrUnitImpl(paramName, strBuf, wantName, true))
3135 return true;
3136 if (_getSeparatedParameterNameOrUnitImpl(paramName, strBuf, wantName, false))
3137 return true;
3138 return false;
3141 static bool _getSeparatedParameterNameOrUnitImpl(const char* const paramName, char* const strBuf,
3142 const bool wantName, const bool useBracket) noexcept
3144 const char* const sepBracketStart = std::strstr(paramName, useBracket ? " [" : " (");
3146 if (sepBracketStart == nullptr)
3147 return false;
3149 const char* const sepBracketEnd = std::strstr(sepBracketStart, useBracket ? "]" : ")");
3151 if (sepBracketEnd == nullptr)
3152 return false;
3154 const std::size_t unitSize = static_cast<std::size_t>(sepBracketEnd-sepBracketStart-2);
3156 if (unitSize > 7) // very unlikely to have such big unit
3157 return false;
3159 const std::size_t sepIndex = std::strlen(paramName)-unitSize-3;
3161 // just in case
3162 if (sepIndex > STR_MAX-3)
3163 return false;
3165 if (wantName)
3167 std::strncpy(strBuf, paramName, sepIndex);
3168 strBuf[sepIndex] = '\0';
3170 else
3172 std::strncpy(strBuf, paramName+(sepIndex+2), unitSize);
3173 strBuf[unitSize] = '\0';
3176 return true;
3179 // -------------------------------------------------------------------
3181 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginLADSPADSSI)
3184 // -------------------------------------------------------------------------------------------------------------------
3186 CarlaPluginPtr CarlaPlugin::newLADSPA(const Initializer& init, const LADSPA_RDF_Descriptor* const rdfDescriptor)
3188 carla_debug("CarlaPlugin::newLADSPA({%p, \"%s\", \"%s\", \"%s\", " P_INT64 ", %x}, %p)",
3189 init.engine, init.filename, init.name, init.label, init.uniqueId, init.options, rdfDescriptor);
3191 std::shared_ptr<CarlaPluginLADSPADSSI> plugin(new CarlaPluginLADSPADSSI(init.engine, init.id));
3193 if (! plugin->initLADSPA(plugin, init.filename, init.name, init.label, init.options, rdfDescriptor))
3194 return nullptr;
3196 return plugin;
3199 CarlaPluginPtr CarlaPlugin::newDSSI(const Initializer& init)
3201 carla_debug("CarlaPlugin::newDSSI({%p, \"%s\", \"%s\", \"%s\", " P_INT64 ", %x})",
3202 init.engine, init.filename, init.name, init.label, init.uniqueId, init.options);
3204 std::shared_ptr<CarlaPluginLADSPADSSI> plugin(new CarlaPluginLADSPADSSI(init.engine, init.id));
3206 if (! plugin->initDSSI(plugin, init.filename, init.name, init.label, init.options))
3207 return nullptr;
3209 return plugin;
3212 // -------------------------------------------------------------------------------------------------------------------
3214 CARLA_BACKEND_END_NAMESPACE