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
;
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) \
42 carla_stderr("CarlaPluginLADSPADSSI::%s() - argument count mismatch: %i != %i", \
43 __FUNCTION__, argc, argcToCompare); \
48 /* check for nullness */ \
49 if (types == nullptr || typesToCompare == nullptr) \
51 carla_stderr("CarlaPluginLADSPADSSI::%s() - argument types are null", \
55 /* check argument types */ \
56 if (std::strcmp(types, typesToCompare) != 0) \
58 carla_stderr("CarlaPluginLADSPADSSI::%s() - argument types mismatch: '%s' != '%s'", \
59 __FUNCTION__, types, typesToCompare); \
64 CARLA_BACKEND_START_NAMESPACE
66 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
67 // -------------------------------------------------------------------
70 static const CustomData kCustomDataFallback
= { nullptr, nullptr, nullptr };
72 // -------------------------------------------------------------------
74 class CarlaThreadDSSIUI
: public CarlaThread
77 CarlaThreadDSSIUI(CarlaEngine
* const engine
, CarlaPlugin
* const plugin
, const CarlaOscData
& oscData
) noexcept
78 : CarlaThread("CarlaThreadDSSIUI"),
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());
102 void setUITitle(const char* const uiTitle
) noexcept
104 CARLA_SAFE_ASSERT_RETURN(uiTitle
!= nullptr && uiTitle
[0] != '\0',);
109 uintptr_t getProcessId() const noexcept
111 CARLA_SAFE_ASSERT_RETURN(fProcess
!= nullptr, 0);
113 return (uintptr_t)fProcess
->getPID();
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...");
130 kEngine
->callback(true, true,
131 ENGINE_CALLBACK_UI_STATE_CHANGED
,
134 0, 0, 0.0f
, nullptr);
138 String
name(kPlugin
->getName());
139 String
filename(kPlugin
->getFilename());
144 if (filename
.isEmpty())
147 StringArray arguments
;
150 arguments
.add(fBinary
.buffer());
153 arguments
.add(String(kEngine
->getOscServerPathUDP()) + String("/") + String(kPlugin
->getId()));
156 arguments
.add(filename
);
159 arguments
.add(fLabel
.buffer());
162 arguments
.add(fUiTitle
.buffer());
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';
179 CarlaString ldPreloadValue
;
183 std::snprintf(winIdStr
, STR_MAX
, P_UINTPTR
, winId
);
184 ldPreloadValue
= (CarlaString(kEngine
->getOptions().binaryDir
)
185 + "/libcarla_interposer-x11.so");
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
);
204 carla_stdout("failed!");
209 if (waitForOscGuiShow())
211 for (; fProcess
->isRunning() && ! shouldThreadExit();)
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");
226 carla_stdout("CarlaThreadDSSIUI::run() - UI auto-closed successfully");
229 else if (fProcess
->getExitCodeAndClearPID() != 0)
230 carla_stderr("CarlaThreadDSSIUI::run() - UI crashed while running");
232 carla_stdout("CarlaThreadDSSIUI::run() - UI closed cleanly");
237 carla_stdout("CarlaThreadDSSIUI::run() - GUI timeout");
241 kEngine
->callback(true, true,
242 ENGINE_CALLBACK_UI_STATE_CHANGED
,
245 0, 0, 0.0f
, nullptr);
247 carla_stdout("LADSPA/DSSI UI thread finished");
251 CarlaEngine
* const kEngine
;
252 CarlaPlugin
* const kPlugin
;
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
);
276 if (fProcess
!= nullptr && fProcess
->isRunning() && ! shouldThreadExit())
282 carla_stdout("CarlaThreadDSSIUI::waitForOscGuiShow() - Timeout while waiting for UI to respond"
283 "(waited %u msecs)", uiBridgesTimeout
);
287 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThreadDSSIUI
)
291 // -----------------------------------------------------
293 class CarlaPluginLADSPADSSI
: public CarlaPlugin
296 CarlaPluginLADSPADSSI(CarlaEngine
* const engine
, const uint id
) noexcept
297 : CarlaPlugin(engine
, id
),
299 fDescriptor(nullptr),
300 fDssiDescriptor(nullptr),
301 fRdfDescriptor(nullptr),
302 fAudioInBuffers(nullptr),
303 fAudioOutBuffers(nullptr),
304 fExtraStereoBuffer(),
305 fParamBuffers(nullptr),
307 fForcedStereoIn(false),
308 fForcedStereoOut(false),
309 fNeedsFixedBuffers(false),
310 fUsesCustomData(false)
311 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
313 fThreadUI(engine
, this, fOscData
),
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
328 if (fUiFilename
!= nullptr)
332 delete[] fUiFilename
;
333 fUiFilename
= nullptr;
337 pData
->singleMutex
.lock();
338 pData
->masterMutex
.lock();
340 if (pData
->client
!= nullptr && pData
->client
->isActive())
341 pData
->client
->deactivate(true);
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);
359 fDescriptor
->cleanup(handle
);
360 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI cleanup");
365 fDescriptor
= nullptr;
366 fDssiDescriptor
= nullptr;
369 if (fRdfDescriptor
!= nullptr)
371 delete fRdfDescriptor
;
372 fRdfDescriptor
= nullptr;
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
;
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)
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)
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
))
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);
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
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
)
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
;
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
;
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
);
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
);
576 std::strncpy(strBuf
, fDescriptor
->Maker
, STR_MAX
);
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
);
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
);
598 std::strncpy(strBuf
, fDescriptor
->Name
, STR_MAX
);
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
);
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
))
634 case LADSPA_RDF_UNIT_DB
:
635 std::strncpy(strBuf
, "dB", STR_MAX
);
637 case LADSPA_RDF_UNIT_COEF
:
638 std::strncpy(strBuf
, "(coef)", STR_MAX
);
640 case LADSPA_RDF_UNIT_HZ
:
641 std::strncpy(strBuf
, "Hz", STR_MAX
);
643 case LADSPA_RDF_UNIT_S
:
644 std::strncpy(strBuf
, "s", STR_MAX
);
646 case LADSPA_RDF_UNIT_MS
:
647 std::strncpy(strBuf
, "ms", STR_MAX
);
649 case LADSPA_RDF_UNIT_MIN
:
650 std::strncpy(strBuf
, "min", STR_MAX
);
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)
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
))
675 const LADSPA_RDF_Port
& port(fRdfDescriptor
->Ports
[rindex
]);
677 if (! LADSPA_RDF_PORT_HAS_LABEL(port
.Hints
))
680 CARLA_SAFE_ASSERT_RETURN(port
.Label
!= nullptr, false);
682 std::strncpy(strBuf
, port
.Label
, STR_MAX
);
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
);
705 // -------------------------------------------------------------------
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
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);
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
);
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);
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);
855 fDssiDescriptor
->select_program(handle
, bank
, program
);
856 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI setMidiProgram")
860 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
861 // -------------------------------------------------------------------
864 void setCustomUITitle(const char* title
) noexcept override
866 fThreadUI
.setUITitle(title
);
867 CarlaPlugin::setCustomUITitle(title
);
870 void showCustomUI(const bool yesNo
) override
875 fThreadUI
.startThread();
880 pData
->transientTryCounter
= 0;
883 if (fOscData
.target
!= nullptr)
885 osc_send_hide(fOscData
);
886 osc_send_quit(fOscData
);
890 fThreadUI
.stopThread(static_cast<int>(pData
->engine
->getOptions().uiBridgesTimeout
* 2));
895 // -------------------------------------------------------------------
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);
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
))
935 else if (LADSPA_IS_PORT_OUTPUT(portType
))
938 else if (LADSPA_IS_PORT_CONTROL(portType
))
942 if (pData
->options
& PLUGIN_OPTION_FORCE_STEREO
)
944 if ((aIns
== 1 || aOuts
== 1) && fHandles
.count() == 1 && addInstance())
949 forcedStereoIn
= true;
954 forcedStereoOut
= true;
959 if (fDssiDescriptor
!= nullptr && fDssiDescriptor
->run_synth
!= nullptr)
967 pData
->audioIn
.createNew(aIns
);
968 fAudioInBuffers
= new float*[aIns
];
970 for (uint32_t i
=0; i
< aIns
; ++i
)
971 fAudioInBuffers
[i
] = nullptr;
976 pData
->audioOut
.createNew(aOuts
);
977 fAudioOutBuffers
= new float*[aOuts
];
980 for (uint32_t i
=0; i
< aOuts
; ++i
)
981 fAudioOutBuffers
[i
] = nullptr;
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
))
1005 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
1007 portName
= pData
->name
;
1011 if (fDescriptor
->PortNames
[i
] != nullptr && fDescriptor
->PortNames
[i
][0] != '\0')
1013 portName
+= fDescriptor
->PortNames
[i
];
1017 if (LADSPA_IS_PORT_INPUT(portType
))
1021 portName
+= "audio-in_";
1022 portName
+= CarlaString(iAudioIn
+1);
1025 portName
+= "audio-in";
1031 portName
+= "audio-out_";
1032 portName
+= CarlaString(iAudioOut
+1);
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
;
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
)
1063 pData
->audioOut
.ports
[1].port
= (CarlaEngineAudioPort
*)pData
->client
->addPort(kEnginePortTypeAudio
, portName
, false, 1);
1064 pData
->audioOut
.ports
[1].rindex
= i
;
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
;
1081 if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints
.HintDescriptor
))
1082 min
= portRangeHints
.LowerBound
;
1087 if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints
.HintDescriptor
))
1088 max
= portRangeHints
.UpperBound
;
1092 if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints
.HintDescriptor
))
1096 pData
->param
.data
[j
].hints
|= PARAMETER_USES_SAMPLERATE
;
1101 carla_stderr2("WARNING - Broken plugin parameter '%s': min >= max", paramName
);
1106 if (hasPortRDF
&& LADSPA_RDF_PORT_HAS_DEFAULT(fRdfDescriptor
->Ports
[i
].Hints
))
1107 def
= fRdfDescriptor
->Ports
[i
].Default
;
1109 def
= get_default_ladspa_port_value(portRangeHints
.HintDescriptor
, min
, max
);
1116 if (LADSPA_IS_HINT_TOGGLED(portRangeHints
.HintDescriptor
))
1121 pData
->param
.data
[j
].hints
|= PARAMETER_IS_BOOLEAN
;
1123 else if (LADSPA_IS_HINT_INTEGER(portRangeHints
.HintDescriptor
))
1128 pData
->param
.data
[j
].hints
|= PARAMETER_IS_INTEGER
;
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
;
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)
1170 pData
->param
.special
[j
] = PARAMETER_SPECIAL_LATENCY
;
1171 CARLA_SAFE_ASSERT_INT2(fLatencyIndex
== static_cast<int32_t>(j
), fLatencyIndex
, j
);
1175 pData
->param
.data
[j
].hints
|= PARAMETER_IS_ENABLED
;
1176 pData
->param
.data
[j
].hints
|= PARAMETER_IS_AUTOMATABLE
;
1177 needsCtrlOut
= true;
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);
1209 fDescriptor
->connect_port(handle
, i
, &fParamBuffers
[j
]);
1210 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (parameter)");
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);
1224 fDescriptor
->connect_port(handle
, i
, nullptr);
1225 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (null)");
1234 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
1236 portName
= pData
->name
;
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();
1253 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
1255 portName
= pData
->name
;
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
;
1268 pData
->options
&= ~PLUGIN_OPTION_FORCE_STEREO
;
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
;
1281 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1282 if (aOuts
> 0 && (aIns
== aOuts
|| aIns
== 1))
1283 pData
->hints
|= PLUGIN_CAN_DRYWET
;
1286 pData
->hints
|= PLUGIN_CAN_VOLUME
;
1288 if (aOuts
>= 2 && aOuts
% 2 == 0)
1289 pData
->hints
|= PLUGIN_CAN_BALANCE
;
1292 // extra plugin hints
1293 pData
->extraHints
= 0x0;
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);
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)
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,);
1323 float tmpOut
[64][2];
1325 for (uint32_t j
=0; j
< aIns
; ++j
)
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
;
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)
1348 fDescriptor
->activate(handle
);
1349 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI latency activate");
1353 fDescriptor
->run(handle
, 2);
1354 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI latency run");
1356 if (fDescriptor
->deactivate
!= nullptr)
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
);
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)
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;)
1400 pData
->midiprog
.createNew(newCount
);
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
);
1418 setMidiProgram(0, false, false, false, true);
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;
1452 pData
->midiprog
.current
= current
;
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);
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);
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 // --------------------------------------------------------------------------------------------------------
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
);
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;
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
;
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
);
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
))
1625 timeOffset
= eventTime
;
1628 if (pData
->midiprog
.current
>= 0 && pData
->midiprog
.count
> 0)
1629 nextBankId
= pData
->midiprog
.data
[pData
->midiprog
.current
].bank
;
1634 startTime
+= timeOffset
;
1639 case kEngineEventTypeNull
:
1642 case kEngineEventTypeControl
: {
1643 EngineControlEvent
& ctrlEvent(event
.ctrl
);
1645 switch (ctrlEvent
.type
)
1647 case kEngineControlEventTypeNull
:
1650 case kEngineControlEventTypeParameter
: {
1653 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
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);
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)
1684 value
= ctrlEvent
.normalizedValue
/0.5f
- 1.0f
;
1689 right
= (value
*2.0f
)+1.0f
;
1691 else if (value
> 0.0f
)
1693 left
= (value
*2.0f
)-1.0f
;
1702 ctrlEvent
.handled
= true;
1703 setBalanceLeftRT(left
, true);
1704 setBalanceRightRT(right
, true);
1708 // Control plugin parameters
1709 for (uint32_t k
=0; k
< pData
->param
.count
; ++k
)
1711 if (pData
->param
.data
[k
].midiChannel
!= event
.channel
)
1713 if (pData
->param
.data
[k
].mappedControlIndex
!= ctrlEvent
.param
)
1715 if (pData
->param
.data
[k
].type
!= PARAMETER_INPUT
)
1717 if ((pData
->param
.data
[k
].hints
& PARAMETER_IS_AUTOMATABLE
) == 0)
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
)
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
);
1746 } // case kEngineControlEventTypeParameter
1748 case kEngineControlEventTypeMidiBank
:
1749 if (event
.channel
== pData
->ctrlChannel
&& (pData
->options
& PLUGIN_OPTION_MAP_PROGRAM_CHANGES
) != 0)
1750 nextBankId
= ctrlEvent
.param
;
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);
1769 case kEngineControlEventTypeAllSoundOff
:
1770 if (pData
->options
& PLUGIN_OPTION_SEND_ALL_SOUND_OFF
)
1772 if (midiEventCount
>= kPluginMaxMidiEvents
)
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
;
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();
1797 if (midiEventCount
>= kPluginMaxMidiEvents
)
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
;
1810 } // switch (ctrlEvent.type)
1812 } // case kEngineEventTypeControl
1814 case kEngineEventTypeMidi
: {
1815 if (midiEventCount
>= kPluginMaxMidiEvents
)
1818 const EngineMidiEvent
& midiEvent(event
.midi
);
1820 if (midiEvent
.size
> EngineMidiEvent::kDataSize
)
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
;
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
);
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
);
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
;
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
;
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
;
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;
1916 } // switch (status)
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)
1933 processSingle(audioIn
, audioOut
, frames
, 0, midiEventCount
);
1935 } // End of Plugin processing (no events)
1937 // --------------------------------------------------------------------------------------------------------
1940 if (pData
->event
.portOut
!= nullptr)
1946 for (uint32_t k
=0; k
< pData
->param
.count
; ++k
)
1948 if (pData
->param
.data
[k
].type
!= PARAMETER_OUTPUT
)
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
,
1962 } // End of Control Output
1964 #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH
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();
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
;
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 // --------------------------------------------------------------------------------------------------------
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
2035 carla_zeroFloats(fAudioOutBuffers
[instn
], frames
);
2037 // ----------------------------------------------------------------------------------------------------
2040 if (fDssiDescriptor
!= nullptr && fDssiDescriptor
->run_synth
!= nullptr)
2043 fDssiDescriptor
->run_synth(handle
, frames
, fMidiEvents
, midiEventCount
);
2044 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI run_synth");
2049 fDescriptor
->run(handle
, frames
);
2050 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI run");
2053 // ----------------------------------------------------------------------------------------------------
2054 // Mixdown for forced stereo
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);
2079 float* const oldBufLeft
= pData
->postProc
.extraBuffer
;
2081 for (uint32_t i
=0; i
< pData
->audioOut
.count
; ++i
)
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
];
2097 bufValue
= fAudioInBuffers
[c
][k
];
2099 fAudioOutBuffers
[i
][k
] = (fAudioOutBuffers
[i
][k
] * pData
->postProc
.dryWet
) + (bufValue
* (1.0f
- pData
->postProc
.dryWet
));
2106 isPair
= (i
% 2 == 0);
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
)
2122 fAudioOutBuffers
[i
][k
] = oldBufLeft
[k
] * (1.0f
- balRangeL
);
2123 fAudioOutBuffers
[i
][k
] += fAudioOutBuffers
[i
+1][k
] * (1.0f
- balRangeR
);
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
);
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
];
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
];
2182 // --------------------------------------------------------------------------------------------------------
2184 pData
->singleMutex
.unlock();
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
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);
2258 fDescriptor
->cleanup(handle
);
2259 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI cleanup");
2265 for (std::size_t i
=0; i
<instanceCount
; ++i
)
2268 reconnectAudioPorts();
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))
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))
2290 fDescriptor
->connect_port(handle
, pData
->audioIn
.ports
[1].rindex
, fAudioInBuffers
[1]);
2291 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo input, last)");
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
)
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))
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))
2322 fDescriptor
->connect_port(handle
, pData
->audioOut
.ports
[1].rindex
, fAudioOutBuffers
[1]);
2323 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo output, last)");
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
)
2336 fDescriptor
->connect_port(handle
, pData
->audioOut
.ports
[i
].rindex
, fAudioOutBuffers
[i
]);
2337 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (audio output)");
2343 // -------------------------------------------------------------------
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 // -------------------------------------------------------------------
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,)
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");
2498 const uint8_t* const data
= argv
[0]->m
;
2499 uint8_t status
= data
[1];
2500 uint8_t channel
= status
& 0x0F;
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
);
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
);
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;
2587 carla_stdout("CarlaPluginLADSPADSSI::updateOscData() - done");
2590 void handleOscMessageExiting()
2592 carla_debug("CarlaPluginLADSPADSSI::handleMsgExiting()");
2595 showCustomUI(false);
2598 pData
->engine
->callback(true, true,
2599 ENGINE_CALLBACK_UI_STATE_CHANGED
,
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)
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)
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)
2638 uint8_t midiData
[4];
2640 midiData
[1] = uint8_t(MIDI_STATUS_NOTE_ON
| (channel
& MIDI_CHANNEL_BIT
));
2644 osc_send_midi(fOscData
, midiData
);
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)
2657 uint8_t midiData
[4];
2659 midiData
[1] = uint8_t(MIDI_STATUS_NOTE_ON
| (channel
& MIDI_CHANNEL_BIT
));
2663 osc_send_midi(fOscData
, midiData
);
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
2687 return fRdfDescriptor
;
2690 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
2691 uintptr_t getUiBridgeProcessId() const noexcept override
2693 return fThreadUI
.getProcessId();
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 // ---------------------------------------------------------------
2708 if (pData
->client
!= nullptr)
2710 pData
->engine
->setLastError("Plugin client is already registered");
2714 if (filename
== nullptr || filename
[0] == '\0')
2716 pData
->engine
->setLastError("null filename");
2720 // ---------------------------------------------------------------
2723 if (! pData
->libOpen(filename
))
2725 pData
->engine
->setLastError(pData
->libError(filename
));
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");
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
)
2749 fDescriptor
= descFn(d
);
2752 carla_stderr2("Caught exception when trying to get LADSPA descriptor");
2753 fDescriptor
= nullptr;
2757 if (fDescriptor
== nullptr)
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;
2766 if (fDescriptor
->run
== nullptr)
2768 carla_stderr2("WARNING - Plugin has no run, cannot use it");
2769 fDescriptor
= nullptr;
2773 if (nullLabel
|| std::strcmp(fDescriptor
->Label
, label
) == 0)
2777 if (fDescriptor
== nullptr)
2779 pData
->engine
->setLastError("Could not find the requested plugin label in the plugin library");
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 // ---------------------------------------------------------------
2794 if (pData
->client
!= nullptr)
2796 pData
->engine
->setLastError("Plugin client is already registered");
2800 if (filename
== nullptr || filename
[0] == '\0')
2802 pData
->engine
->setLastError("null filename");
2806 // ---------------------------------------------------------------
2809 if (! pData
->libOpen(filename
))
2811 pData
->engine
->setLastError(pData
->libError(filename
));
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");
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
)
2835 fDssiDescriptor
= descFn(d
);
2838 carla_stderr2("Caught exception when trying to get DSSI descriptor");
2839 fDescriptor
= nullptr;
2840 fDssiDescriptor
= nullptr;
2844 if (fDssiDescriptor
== nullptr)
2847 fDescriptor
= fDssiDescriptor
->LADSPA_Plugin
;
2849 if (fDescriptor
== nullptr)
2851 carla_stderr2("WARNING - Missing LADSPA interface, will not use this plugin");
2852 fDssiDescriptor
= nullptr;
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;
2862 if (fDescriptor
->run
== nullptr)
2864 carla_stderr2("WARNING - Plugin has no run, cannot use it");
2865 fDescriptor
= nullptr;
2866 fDssiDescriptor
= nullptr;
2870 if (nullLabel
|| std::strcmp(fDescriptor
->Label
, label
) == 0)
2874 if (fDescriptor
== nullptr || fDssiDescriptor
== nullptr)
2876 pData
->engine
->setLastError("Could not find the requested plugin label in the plugin library");
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");
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.");
2908 // ---------------------------------------------------------------
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
;
2921 name
= fDescriptor
->Label
;
2924 pData
->name
= pData
->engine
->getUniquePluginName(name
);
2925 pData
->filename
= carla_strdup(filename
);
2927 // ---------------------------------------------------------------
2930 pData
->client
= pData
->engine
->addClient(plugin
);
2932 if (pData
->client
== nullptr || ! pData
->client
->isOk())
2934 pData
->engine
->setLastError("Failed to register plugin client");
2938 // ---------------------------------------------------------------
2939 // initialize plugin
2941 if (! addInstance())
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
))
2954 const uint32_t index(iCtrl
++);
2956 if (! LADSPA_IS_PORT_OUTPUT(portType
))
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
);
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;
2985 // ---------------------------------------------------------------
2986 // get engine options
2988 const EngineOptions
& opts(pData
->engine
->getOptions());
2990 #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
2991 // ---------------------------------------------------------------
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
;
3008 uiTitle
= pData
->name
;
3009 uiTitle
+= " (GUI)";
3012 fThreadUI
.setData(guiFilename
, fDescriptor
->Label
, uiTitle
);
3017 // ---------------------------------------------------------------
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
;
3062 // -------------------------------------------------------------------
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
;
3089 // -------------------------------------------------------------------
3093 LADSPA_Handle handle
;
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);
3105 fDescriptor
->connect_port(handle
, static_cast<ulong
>(rindex
), &fParamBuffers
[i
]);
3106 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port");
3109 if (fHandles
.append(handle
))
3113 fDescriptor
->cleanup(handle
);
3114 } CARLA_SAFE_EXCEPTION("LADSPA/DSSI cleanup");
3116 pData
->engine
->setLastError("Out of memory");
3120 uint32_t getSafePortCount() const noexcept
3122 if (fDescriptor
->PortCount
== 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))
3136 if (_getSeparatedParameterNameOrUnitImpl(paramName
, strBuf
, wantName
, 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)
3149 const char* const sepBracketEnd
= std::strstr(sepBracketStart
, useBracket
? "]" : ")");
3151 if (sepBracketEnd
== nullptr)
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
3159 const std::size_t sepIndex
= std::strlen(paramName
)-unitSize
-3;
3162 if (sepIndex
> STR_MAX
-3)
3167 std::strncpy(strBuf
, paramName
, sepIndex
);
3168 strBuf
[sepIndex
] = '\0';
3172 std::strncpy(strBuf
, paramName
+(sepIndex
+2), unitSize
);
3173 strBuf
[unitSize
] = '\0';
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
))
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
))
3212 // -------------------------------------------------------------------------------------------------------------------
3214 CARLA_BACKEND_END_NAMESPACE