1
// SPDX-FileCopyrightText: 2011-2024 Filipe Coelho <falktx@falktx.com>
2 // SPDX-License-Identifier: GPL-2.0-or-later
4 #include "CarlaPluginInternal.hpp"
5 #include "CarlaEngine.hpp"
7 #include "CarlaBackendUtils.hpp"
8 #include "CarlaBase64Utils.hpp"
9 #include "CarlaMathUtils.hpp"
10 #include "CarlaMIDI.h"
11 #include "CarlaPluginUI.hpp"
12 #include "CarlaScopeUtils.hpp"
13 #include "CarlaStringList.hpp"
17 #include "water/files/File.h"
18 #include "water/streams/MemoryOutputStream.h"
19 #include "water/xml/XmlDocument.h"
20 #include "water/xml/XmlElement.h"
22 using water::CharPointer_UTF8
;
24 using water::MemoryOutputStream
;
27 using water::XmlDocument
;
28 using water::XmlElement
;
30 CARLA_BACKEND_START_NAMESPACE
32 // -------------------------------------------------------------------------------------------------------------------
35 static const ParameterData kParameterDataNull
= { PARAMETER_UNKNOWN
, 0x0, PARAMETER_NULL
, -1, 0, CONTROL_INDEX_NONE
, 0.0f
, 1.0f
, 0x0 };
36 static const ParameterRanges kParameterRangesNull
= { 0.0f
, 0.0f
, 1.0f
, 0.01f
, 0.0001f
, 0.1f
};
37 static const MidiProgramData kMidiProgramDataNull
= { 0, 0, nullptr };
39 static const CustomData kCustomDataFallback
= { nullptr, nullptr, nullptr };
40 static /* */ CustomData kCustomDataFallbackNC
= { nullptr, nullptr, nullptr };
41 static const PluginPostRtEvent kPluginPostRtEventFallback
= { kPluginPostRtEventNull
, false, {} };
43 // -------------------------------------------------------------------------------------------------------------------
44 // ParamSymbol struct, needed for CarlaPlugin::loadStateSave()
50 ParamSymbol(const uint32_t i
, const char* const s
)
51 : index(static_cast<int32_t>(i
)),
52 symbol(carla_strdup(s
)) {}
54 ~ParamSymbol() noexcept
56 CARLA_SAFE_ASSERT_RETURN(symbol
!= nullptr,)
62 #ifdef CARLA_PROPER_CPP11_SUPPORT
63 ParamSymbol() = delete;
64 CARLA_DECLARE_NON_COPYABLE(ParamSymbol
)
68 // -------------------------------------------------------------------------------------------------------------------
69 // Constructor and destructor
71 CarlaPlugin::CarlaPlugin(CarlaEngine
* const engine
, const uint id
)
72 : pData(new ProtectedData(engine
, id
))
74 CARLA_SAFE_ASSERT_RETURN(engine
!= nullptr,);
75 CARLA_SAFE_ASSERT(id
< engine
->getMaxPluginNumber());
76 carla_debug("CarlaPlugin::CarlaPlugin(%p, %i)", engine
, id
);
78 switch (engine
->getProccessMode())
80 case ENGINE_PROCESS_MODE_SINGLE_CLIENT
:
81 case ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
:
82 CARLA_SAFE_ASSERT(id
< MAX_DEFAULT_PLUGINS
);
85 case ENGINE_PROCESS_MODE_CONTINUOUS_RACK
:
86 CARLA_SAFE_ASSERT(id
< MAX_RACK_PLUGINS
);
89 case ENGINE_PROCESS_MODE_PATCHBAY
:
90 CARLA_SAFE_ASSERT(id
< MAX_PATCHBAY_PLUGINS
);
93 case ENGINE_PROCESS_MODE_BRIDGE
:
94 CARLA_SAFE_ASSERT(id
== 0);
99 CarlaPlugin::~CarlaPlugin()
101 carla_debug("CarlaPlugin::~CarlaPlugin()");
106 // -------------------------------------------------------------------
107 // Information (base)
109 uint
CarlaPlugin::getId() const noexcept
114 uint
CarlaPlugin::getHints() const noexcept
119 uint
CarlaPlugin::getOptionsEnabled() const noexcept
121 return pData
->options
;
124 bool CarlaPlugin::isEnabled() const noexcept
126 return pData
->enabled
;
129 const char* CarlaPlugin::getName() const noexcept
134 const char* CarlaPlugin::getFilename() const noexcept
136 return pData
->filename
;
139 const char* CarlaPlugin::getIconName() const noexcept
141 return pData
->iconName
;
144 PluginCategory
CarlaPlugin::getCategory() const noexcept
146 return getPluginCategoryFromName(pData
->name
);
149 int64_t CarlaPlugin::getUniqueId() const noexcept
154 uint32_t CarlaPlugin::getLatencyInFrames() const noexcept
159 // -------------------------------------------------------------------
160 // Information (count)
162 uint32_t CarlaPlugin::getAudioInCount() const noexcept
164 return pData
->audioIn
.count
;
167 uint32_t CarlaPlugin::getAudioOutCount() const noexcept
169 return pData
->audioOut
.count
;
172 uint32_t CarlaPlugin::getCVInCount() const noexcept
174 return pData
->cvIn
.count
;
177 uint32_t CarlaPlugin::getCVOutCount() const noexcept
179 return pData
->cvOut
.count
;
182 uint32_t CarlaPlugin::getMidiInCount() const noexcept
184 return (pData
->extraHints
& PLUGIN_EXTRA_HINT_HAS_MIDI_IN
) ? 1 : 0;
187 uint32_t CarlaPlugin::getMidiOutCount() const noexcept
189 return (pData
->extraHints
& PLUGIN_EXTRA_HINT_HAS_MIDI_OUT
) ? 1 : 0;
192 uint32_t CarlaPlugin::getParameterCount() const noexcept
194 return pData
->param
.count
;
197 uint32_t CarlaPlugin::getParameterScalePointCount(const uint32_t parameterId
) const noexcept
199 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, 0);
203 uint32_t CarlaPlugin::getProgramCount() const noexcept
205 return pData
->prog
.count
;
208 uint32_t CarlaPlugin::getMidiProgramCount() const noexcept
210 return pData
->midiprog
.count
;
213 uint32_t CarlaPlugin::getCustomDataCount() const noexcept
215 return static_cast<uint32_t>(pData
->custom
.count());
218 // -------------------------------------------------------------------
219 // Information (current data)
221 int32_t CarlaPlugin::getCurrentProgram() const noexcept
223 return pData
->prog
.current
;
226 int32_t CarlaPlugin::getCurrentMidiProgram() const noexcept
228 return pData
->midiprog
.current
;
231 uint
CarlaPlugin::getAudioPortHints(bool, uint32_t) const noexcept
236 const ParameterData
& CarlaPlugin::getParameterData(const uint32_t parameterId
) const noexcept
238 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, kParameterDataNull
);
239 return pData
->param
.data
[parameterId
];
242 const ParameterRanges
& CarlaPlugin::getParameterRanges(const uint32_t parameterId
) const noexcept
244 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, kParameterRangesNull
);
245 return pData
->param
.ranges
[parameterId
];
248 bool CarlaPlugin::isParameterOutput(const uint32_t parameterId
) const noexcept
250 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, false);
251 return (pData
->param
.data
[parameterId
].type
== PARAMETER_OUTPUT
);
254 const MidiProgramData
& CarlaPlugin::getMidiProgramData(const uint32_t index
) const noexcept
256 CARLA_SAFE_ASSERT_RETURN(index
< pData
->midiprog
.count
, kMidiProgramDataNull
);
257 return pData
->midiprog
.data
[index
];
260 const CustomData
& CarlaPlugin::getCustomData(const uint32_t index
) const noexcept
262 return pData
->custom
.getAt(index
, kCustomDataFallback
);
265 std::size_t CarlaPlugin::getChunkData(void** const dataPtr
) noexcept
267 CARLA_SAFE_ASSERT_RETURN(dataPtr
!= nullptr, 0);
268 CARLA_SAFE_ASSERT(false); // this should never happen
272 // -------------------------------------------------------------------
273 // Information (per-plugin data)
275 uint
CarlaPlugin::getOptionsAvailable() const noexcept
277 CARLA_SAFE_ASSERT(false); // this should never happen
281 float CarlaPlugin::getParameterValue(const uint32_t parameterId
) const noexcept
283 CARLA_SAFE_ASSERT_RETURN(parameterId
< getParameterCount(), 0.0f
);
284 CARLA_SAFE_ASSERT(false); // this should never happen
288 float CarlaPlugin::getParameterScalePointValue(const uint32_t parameterId
, const uint32_t scalePointId
) const noexcept
290 CARLA_SAFE_ASSERT_RETURN(parameterId
< getParameterCount(), 0.0f
);
291 CARLA_SAFE_ASSERT_RETURN(scalePointId
< getParameterScalePointCount(parameterId
), 0.0f
);
292 CARLA_SAFE_ASSERT(false); // this should never happen
296 bool CarlaPlugin::getLabel(char* const strBuf
) const noexcept
302 bool CarlaPlugin::getMaker(char* const strBuf
) const noexcept
308 bool CarlaPlugin::getCopyright(char* const strBuf
) const noexcept
314 bool CarlaPlugin::getRealName(char* const strBuf
) const noexcept
320 bool CarlaPlugin::getParameterName(const uint32_t parameterId
, char* const strBuf
) const noexcept
322 CARLA_SAFE_ASSERT_RETURN(parameterId
< getParameterCount(), false);
323 CARLA_SAFE_ASSERT(false); // this should never happen
328 bool CarlaPlugin::getParameterSymbol(const uint32_t parameterId
, char* const strBuf
) const noexcept
330 CARLA_SAFE_ASSERT_RETURN(parameterId
< getParameterCount(), false);
335 bool CarlaPlugin::getParameterText(const uint32_t parameterId
, char* const strBuf
) noexcept
337 CARLA_SAFE_ASSERT_RETURN(parameterId
< getParameterCount(), false);
338 CARLA_SAFE_ASSERT(false); // this should never happen
343 bool CarlaPlugin::getParameterUnit(const uint32_t parameterId
, char* const strBuf
) const noexcept
345 CARLA_SAFE_ASSERT_RETURN(parameterId
< getParameterCount(), false);
350 bool CarlaPlugin::getParameterComment(const uint32_t parameterId
, char* const strBuf
) const noexcept
352 CARLA_SAFE_ASSERT_RETURN(parameterId
< getParameterCount(), false);
357 bool CarlaPlugin::getParameterGroupName(const uint32_t parameterId
, char* const strBuf
) const noexcept
359 CARLA_SAFE_ASSERT_RETURN(parameterId
< getParameterCount(), false);
364 bool CarlaPlugin::getParameterScalePointLabel(const uint32_t parameterId
, const uint32_t scalePointId
, char* const strBuf
) const noexcept
366 CARLA_SAFE_ASSERT_RETURN(parameterId
< getParameterCount(), false);
367 CARLA_SAFE_ASSERT_RETURN(scalePointId
< getParameterScalePointCount(parameterId
), false);
368 CARLA_SAFE_ASSERT(false); // this should never happen
373 float CarlaPlugin::getInternalParameterValue(const int32_t parameterId
) const noexcept
375 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
376 CARLA_SAFE_ASSERT_RETURN(parameterId
!= PARAMETER_NULL
&& parameterId
> PARAMETER_MAX
, 0.0f
);
380 case PARAMETER_ACTIVE
:
381 return pData
->active
;
382 case PARAMETER_CTRL_CHANNEL
:
383 return pData
->ctrlChannel
;
384 case PARAMETER_DRYWET
:
385 return pData
->postProc
.dryWet
;
386 case PARAMETER_VOLUME
:
387 return pData
->postProc
.volume
;
388 case PARAMETER_BALANCE_LEFT
:
389 return pData
->postProc
.balanceLeft
;
390 case PARAMETER_BALANCE_RIGHT
:
391 return pData
->postProc
.balanceRight
;
392 case PARAMETER_PANNING
:
393 return pData
->postProc
.panning
;
396 CARLA_SAFE_ASSERT_RETURN(parameterId
>= 0, 0.0f
);
398 return getParameterValue(static_cast<uint32_t>(parameterId
));
401 bool CarlaPlugin::getProgramName(const uint32_t index
, char* const strBuf
) const noexcept
403 CARLA_SAFE_ASSERT_RETURN(index
< pData
->prog
.count
, false);
404 CARLA_SAFE_ASSERT_RETURN(pData
->prog
.names
[index
] != nullptr, false);
405 std::strncpy(strBuf
, pData
->prog
.names
[index
], STR_MAX
);
409 bool CarlaPlugin::getMidiProgramName(const uint32_t index
, char* const strBuf
) const noexcept
411 CARLA_SAFE_ASSERT_RETURN(index
< pData
->midiprog
.count
, false);
412 CARLA_SAFE_ASSERT_RETURN(pData
->midiprog
.data
[index
].name
!= nullptr, false);
413 std::strncpy(strBuf
, pData
->midiprog
.data
[index
].name
, STR_MAX
);
417 void CarlaPlugin::getParameterCountInfo(uint32_t& ins
, uint32_t& outs
) const noexcept
422 for (uint32_t i
=0; i
< pData
->param
.count
; ++i
)
424 if (pData
->param
.data
[i
].type
== PARAMETER_INPUT
)
426 else if (pData
->param
.data
[i
].type
== PARAMETER_OUTPUT
)
431 // -------------------------------------------------------------------
434 void CarlaPlugin::prepareForSave(bool)
438 void CarlaPlugin::resetParameters() noexcept
440 for (uint i
=0; i
< pData
->param
.count
; ++i
)
442 const ParameterData
& paramData(pData
->param
.data
[i
]);
443 const ParameterRanges
& paramRanges(pData
->param
.ranges
[i
]);
445 if (paramData
.type
!= PARAMETER_INPUT
)
447 if ((paramData
.hints
& PARAMETER_IS_ENABLED
) == 0)
450 setParameterValue(i
, paramRanges
.def
, true, true, true);
454 void CarlaPlugin::randomizeParameters() noexcept
458 char strBuf
[STR_MAX
+1];
459 strBuf
[STR_MAX
] = '\0';
461 std::srand(static_cast<uint
>(std::time(nullptr)));
463 for (uint i
=0; i
< pData
->param
.count
; ++i
)
465 const ParameterData
& paramData(pData
->param
.data
[i
]);
467 if (paramData
.type
!= PARAMETER_INPUT
)
469 if ((paramData
.hints
& PARAMETER_IS_ENABLED
) == 0)
472 if (! getParameterName(i
, strBuf
))
475 if (std::strstr(strBuf
, "olume") != nullptr)
477 if (std::strstr(strBuf
, "Master") != nullptr)
480 const ParameterRanges
& paramRanges(pData
->param
.ranges
[i
]);
482 if (paramData
.hints
& PARAMETER_IS_BOOLEAN
)
484 random
= static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX
);
485 value
= random
> 0.5f
? paramRanges
.max
: paramRanges
.min
;
489 random
= static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX
);
490 value
= random
* (paramRanges
.max
- paramRanges
.min
) + paramRanges
.min
;
492 if (paramData
.hints
& PARAMETER_IS_INTEGER
)
493 value
= std::rint(value
);
496 setParameterValue(i
, value
, true, true, true);
500 const CarlaStateSave
& CarlaPlugin::getStateSave(const bool callPrepareForSave
)
502 pData
->stateSave
.clear();
504 if (callPrepareForSave
)
506 pData
->stateSave
.temporary
= true;
507 prepareForSave(true);
510 const PluginType pluginType
= getType();
512 char strBuf
[STR_MAX
+1];
513 carla_zeroChars(strBuf
, STR_MAX
+1);
515 // ---------------------------------------------------------------
518 if (! getLabel(strBuf
))
521 pData
->stateSave
.type
= carla_strdup(getPluginTypeAsString(pluginType
));
522 pData
->stateSave
.name
= carla_strdup(pData
->name
);
523 pData
->stateSave
.label
= carla_strdup(strBuf
);
524 pData
->stateSave
.uniqueId
= getUniqueId();
525 // #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
526 pData
->stateSave
.options
= pData
->options
;
529 if (pData
->filename
!= nullptr)
530 pData
->stateSave
.binary
= carla_strdup(pData
->filename
);
532 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
533 // ---------------------------------------------------------------
536 pData
->stateSave
.active
= pData
->active
;
537 pData
->stateSave
.dryWet
= pData
->postProc
.dryWet
;
538 pData
->stateSave
.volume
= pData
->postProc
.volume
;
539 pData
->stateSave
.balanceLeft
= pData
->postProc
.balanceLeft
;
540 pData
->stateSave
.balanceRight
= pData
->postProc
.balanceRight
;
541 pData
->stateSave
.panning
= pData
->postProc
.panning
;
542 pData
->stateSave
.ctrlChannel
= pData
->ctrlChannel
;
545 if (pData
->hints
& PLUGIN_IS_BRIDGE
)
546 waitForBridgeSaveSignal();
548 // ---------------------------------------------------------------
551 bool usingChunk
= false;
553 if (pData
->options
& PLUGIN_OPTION_USE_CHUNKS
)
555 void* data
= nullptr;
556 const std::size_t dataSize
= getChunkData(&data
);
558 if (data
!= nullptr && dataSize
> 0)
560 pData
->stateSave
.chunk
= CarlaString::asBase64(data
, dataSize
).dup();
562 if (pluginType
!= PLUGIN_INTERNAL
&& pluginType
!= PLUGIN_JSFX
)
567 // ---------------------------------------------------------------
570 if (pData
->prog
.current
>= 0 && pluginType
!= PLUGIN_LV2
)
572 pData
->stateSave
.currentProgramIndex
= pData
->prog
.current
;
573 pData
->stateSave
.currentProgramName
= carla_strdup(pData
->prog
.names
[pData
->prog
.current
]);
576 // ---------------------------------------------------------------
577 // Current MIDI Program
579 if (pData
->midiprog
.current
>= 0 && pluginType
!= PLUGIN_LV2
&& pluginType
!= PLUGIN_SF2
)
581 const MidiProgramData
& mpData(pData
->midiprog
.getCurrent());
583 pData
->stateSave
.currentMidiBank
= static_cast<int32_t>(mpData
.bank
);
584 pData
->stateSave
.currentMidiProgram
= static_cast<int32_t>(mpData
.program
);
587 // ---------------------------------------------------------------
590 const float sampleRate
= static_cast<float>(pData
->engine
->getSampleRate());
592 for (uint32_t i
=0; i
< pData
->param
.count
; ++i
)
594 const ParameterData
& paramData(pData
->param
.data
[i
]);
596 if ((paramData
.hints
& PARAMETER_IS_ENABLED
) == 0)
598 if (paramData
.hints
& PARAMETER_IS_NOT_SAVED
)
601 const bool dummy
= paramData
.type
!= PARAMETER_INPUT
|| usingChunk
;
603 if (dummy
&& paramData
.mappedControlIndex
<= CONTROL_INDEX_NONE
)
606 CarlaStateSave::Parameter
* const stateParameter(new CarlaStateSave::Parameter());
608 stateParameter
->dummy
= dummy
;
609 stateParameter
->index
= paramData
.index
;
610 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
611 if (paramData
.mappedControlIndex
!= CONTROL_INDEX_MIDI_LEARN
)
613 stateParameter
->mappedControlIndex
= paramData
.mappedControlIndex
;
614 stateParameter
->midiChannel
= paramData
.midiChannel
;
616 if (paramData
.hints
& PARAMETER_MAPPED_RANGES_SET
)
618 stateParameter
->mappedMinimum
= paramData
.mappedMinimum
;
619 stateParameter
->mappedMaximum
= paramData
.mappedMaximum
;
620 stateParameter
->mappedRangeValid
= true;
622 if (paramData
.hints
& PARAMETER_USES_SAMPLERATE
)
624 stateParameter
->mappedMinimum
/= sampleRate
;
625 stateParameter
->mappedMaximum
/= sampleRate
;
631 if (! getParameterName(i
, strBuf
))
633 stateParameter
->name
= carla_strdup(strBuf
);
635 if (! getParameterSymbol(i
, strBuf
))
637 stateParameter
->symbol
= carla_strdup(strBuf
);;
641 stateParameter
->value
= getParameterValue(i
);
643 if (paramData
.hints
& PARAMETER_USES_SAMPLERATE
)
644 stateParameter
->value
/= sampleRate
;
647 pData
->stateSave
.parameters
.append(stateParameter
);
650 // ---------------------------------------------------------------
653 for (LinkedList
<CustomData
>::Itenerator it
= pData
->custom
.begin2(); it
.valid(); it
.next())
655 const CustomData
& cData(it
.getValue(kCustomDataFallback
));
656 CARLA_SAFE_ASSERT_CONTINUE(cData
.isValid());
658 CarlaStateSave::CustomData
* stateCustomData(new CarlaStateSave::CustomData());
660 stateCustomData
->type
= carla_strdup(cData
.type
);
661 stateCustomData
->key
= carla_strdup(cData
.key
);
662 stateCustomData
->value
= carla_strdup(cData
.value
);
664 pData
->stateSave
.customData
.append(stateCustomData
);
667 return pData
->stateSave
;
670 void CarlaPlugin::loadStateSave(const CarlaStateSave
& stateSave
)
672 const bool usesMultiProgs
= pData
->hints
& PLUGIN_USES_MULTI_PROGS
;
673 const PluginType pluginType
= getType();
675 char strBuf
[STR_MAX
+1];
676 carla_zeroChars(strBuf
, STR_MAX
+1);
678 // ---------------------------------------------------------------
679 // Part 1 - PRE-set custom data (only those which reload programs)
681 for (CarlaStateSave::CustomDataItenerator it
= stateSave
.customData
.begin2(); it
.valid(); it
.next())
683 const CarlaStateSave::CustomData
* const stateCustomData(it
.getValue(nullptr));
684 CARLA_SAFE_ASSERT_CONTINUE(stateCustomData
!= nullptr);
685 CARLA_SAFE_ASSERT_CONTINUE(stateCustomData
->isValid());
687 const char* const key(stateCustomData
->key
);
689 /**/ if (pluginType
== PLUGIN_DSSI
&& (std::strcmp (key
, "reloadprograms") == 0 ||
690 std::strcmp (key
, "load" ) == 0 ||
691 std::strncmp(key
, "patches", 7) == 0 ))
693 else if (usesMultiProgs
&& std::strcmp(key
, "midiPrograms") == 0)
698 setCustomData(stateCustomData
->type
, key
, stateCustomData
->value
, true);
701 // ---------------------------------------------------------------
702 // Part 2 - set program
704 if (stateSave
.currentProgramIndex
>= 0 && stateSave
.currentProgramName
!= nullptr)
706 int32_t programId
= -1;
709 if (stateSave
.currentProgramIndex
< static_cast<int32_t>(pData
->prog
.count
))
711 programId
= stateSave
.currentProgramIndex
;
713 // index not valid, try to find by name
716 for (uint32_t i
=0; i
< pData
->prog
.count
; ++i
)
718 if (getProgramName(i
, strBuf
) && std::strcmp(stateSave
.currentProgramName
, strBuf
) == 0)
720 programId
= static_cast<int32_t>(i
);
726 // set program now, if valid
728 setProgram(programId
, true, true, true);
731 // ---------------------------------------------------------------
732 // Part 3 - set midi program
734 if (stateSave
.currentMidiBank
>= 0 && stateSave
.currentMidiProgram
>= 0 && ! usesMultiProgs
)
735 setMidiProgramById(static_cast<uint32_t>(stateSave
.currentMidiBank
), static_cast<uint32_t>(stateSave
.currentMidiProgram
), true, true, true);
737 // ---------------------------------------------------------------
738 // Part 4a - get plugin parameter symbols
740 LinkedList
<ParamSymbol
*> paramSymbols
;
742 if (pluginType
== PLUGIN_LADSPA
|| pluginType
== PLUGIN_LV2
|| pluginType
== PLUGIN_CLAP
)
744 for (uint32_t i
=0; i
< pData
->param
.count
; ++i
)
746 if (pData
->param
.data
[i
].hints
& PARAMETER_IS_NOT_SAVED
)
749 if (getParameterSymbol(i
, strBuf
))
751 ParamSymbol
* const paramSymbol(new ParamSymbol(i
, strBuf
));
752 paramSymbols
.append(paramSymbol
);
757 // ---------------------------------------------------------------
758 // Part 4b - set parameter values (carefully)
760 const float sampleRate
= static_cast<float>(pData
->engine
->getSampleRate());
762 for (CarlaStateSave::ParameterItenerator it
= stateSave
.parameters
.begin2(); it
.valid(); it
.next())
764 CarlaStateSave::Parameter
* const stateParameter(it
.getValue(nullptr));
765 CARLA_SAFE_ASSERT_CONTINUE(stateParameter
!= nullptr);
769 if (pluginType
== PLUGIN_LADSPA
)
771 // Try to set by symbol, otherwise use index
772 if (stateParameter
->symbol
!= nullptr && stateParameter
->symbol
[0] != '\0')
774 for (LinkedList
<ParamSymbol
*>::Itenerator it2
= paramSymbols
.begin2(); it2
.valid(); it2
.next())
776 ParamSymbol
* const paramSymbol(it2
.getValue(nullptr));
777 CARLA_SAFE_ASSERT_CONTINUE(paramSymbol
!= nullptr);
778 CARLA_SAFE_ASSERT_CONTINUE(paramSymbol
->symbol
!= nullptr);
780 if (std::strcmp(stateParameter
->symbol
, paramSymbol
->symbol
) == 0)
782 index
= paramSymbol
->index
;
787 index
= stateParameter
->index
;
791 index
= stateParameter
->index
;
794 else if (pluginType
== PLUGIN_LV2
|| pluginType
== PLUGIN_CLAP
)
797 if (stateParameter
->symbol
!= nullptr && stateParameter
->symbol
[0] != '\0')
799 for (LinkedList
<ParamSymbol
*>::Itenerator it2
= paramSymbols
.begin2(); it2
.valid(); it2
.next())
801 ParamSymbol
* const paramSymbol(it2
.getValue(nullptr));
802 CARLA_SAFE_ASSERT_CONTINUE(paramSymbol
!= nullptr);
803 CARLA_SAFE_ASSERT_CONTINUE(paramSymbol
->symbol
!= nullptr);
805 if (std::strcmp(stateParameter
->symbol
, paramSymbol
->symbol
) == 0)
807 index
= paramSymbol
->index
;
813 if (pluginType
== PLUGIN_LV2
)
814 carla_stderr("Failed to find LV2 parameter symbol '%s' for '%s'",
815 stateParameter
->symbol
, pData
->name
);
817 carla_stderr("Failed to find CLAP parameter id '%s' for '%s'",
818 stateParameter
->symbol
, pData
->name
);
823 if (pluginType
== PLUGIN_LV2
)
824 carla_stderr("LV2 Plugin parameter '%s' has no symbol", stateParameter
->name
);
826 carla_stderr("CLAP Plugin parameter '%s' has no id", stateParameter
->name
);
832 index
= stateParameter
->index
;
836 if (index
>= 0 && index
< static_cast<int32_t>(pData
->param
.count
))
838 //CARLA_SAFE_ASSERT(stateParameter->isInput == (pData
840 if (! stateParameter
->dummy
)
842 if (pData
->param
.data
[index
].hints
& PARAMETER_USES_SAMPLERATE
)
843 stateParameter
->value
*= sampleRate
;
845 setParameterValue(static_cast<uint32_t>(index
), stateParameter
->value
, true, true, true);
848 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
849 if (stateParameter
->mappedRangeValid
)
851 if (pData
->param
.data
[index
].hints
& PARAMETER_USES_SAMPLERATE
)
853 stateParameter
->mappedMinimum
*= sampleRate
;
854 stateParameter
->mappedMaximum
*= sampleRate
;
857 setParameterMappedRange(static_cast<uint32_t>(index
),
858 stateParameter
->mappedMinimum
,
859 stateParameter
->mappedMaximum
, true, true);
862 setParameterMappedControlIndex(static_cast<uint32_t>(index
),
863 stateParameter
->mappedControlIndex
, true, true, false);
864 setParameterMidiChannel(static_cast<uint32_t>(index
), stateParameter
->midiChannel
, true, true);
868 carla_stderr("Could not set parameter '%s' value for '%s'",
869 stateParameter
->name
, pData
->name
);
872 // ---------------------------------------------------------------
875 for (LinkedList
<ParamSymbol
*>::Itenerator it
= paramSymbols
.begin2(); it
.valid(); it
.next())
877 ParamSymbol
* const paramSymbol(it
.getValue(nullptr));
881 paramSymbols
.clear();
883 // ---------------------------------------------------------------
884 // Part 5 - set custom data
886 for (CarlaStateSave::CustomDataItenerator it
= stateSave
.customData
.begin2(); it
.valid(); it
.next())
888 const CarlaStateSave::CustomData
* const stateCustomData(it
.getValue(nullptr));
889 CARLA_SAFE_ASSERT_CONTINUE(stateCustomData
!= nullptr);
890 CARLA_SAFE_ASSERT_CONTINUE(stateCustomData
->isValid());
892 const char* const key(stateCustomData
->key
);
894 if (pluginType
== PLUGIN_DSSI
&& (std::strcmp (key
, "reloadprograms") == 0 ||
895 std::strcmp (key
, "load" ) == 0 ||
896 std::strncmp(key
, "patches", 7) == 0 ))
898 if (usesMultiProgs
&& std::strcmp(key
, "midiPrograms") == 0)
901 setCustomData(stateCustomData
->type
, key
, stateCustomData
->value
, true);
904 // ---------------------------------------------------------------
905 // Part 5x - set lv2 state
907 if (pluginType
== PLUGIN_LV2
)
909 for (LinkedList
<CustomData
>::Itenerator it
= pData
->custom
.begin2(); it
.valid(); it
.next())
911 const CustomData
& customData(it
.getValue(kCustomDataFallback
));
912 CARLA_SAFE_ASSERT_CONTINUE(customData
.isValid());
914 if (std::strcmp(customData
.type
, CUSTOM_DATA_TYPE_PROPERTY
) == 0)
917 restoreLV2State(stateSave
.temporary
);
922 // ---------------------------------------------------------------
923 // Part 6 - set chunk
925 if (stateSave
.chunk
!= nullptr && (pData
->options
& PLUGIN_OPTION_USE_CHUNKS
) != 0)
927 std::vector
<uint8_t> chunk(carla_getChunkFromBase64String(stateSave
.chunk
));
928 #ifdef CARLA_PROPER_CPP11_SUPPORT
929 setChunkData(chunk
.data(), chunk
.size());
931 setChunkData(&chunk
.front(), chunk
.size());
935 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
936 // ---------------------------------------------------------------
937 // Part 6 - set internal stuff
939 const uint availOptions
= getOptionsAvailable();
941 for (uint i
=0; i
<10; ++i
) // FIXME - get this value somehow...
943 const uint
option(1u << i
);
945 if (availOptions
& option
)
946 setOption(option
, (stateSave
.options
& option
) != 0, true);
949 setDryWet(stateSave
.dryWet
, true, true);
950 setVolume(stateSave
.volume
, true, true);
951 setBalanceLeft(stateSave
.balanceLeft
, true, true);
952 setBalanceRight(stateSave
.balanceRight
, true, true);
953 setPanning(stateSave
.panning
, true, true);
954 setCtrlChannel(stateSave
.ctrlChannel
, true, true);
955 setActive(stateSave
.active
, true, true);
957 if (! pData
->engine
->isLoadingProject())
958 pData
->engine
->callback(true, true, ENGINE_CALLBACK_UPDATE
, pData
->id
, 0, 0, 0, 0.0f
, nullptr);
962 bool CarlaPlugin::saveStateToFile(const char* const filename
)
964 CARLA_SAFE_ASSERT_RETURN(filename
!= nullptr && filename
[0] != '\0', false);
965 carla_debug("CarlaPlugin::saveStateToFile(\"%s\")", filename
);
967 MemoryOutputStream out
, streamState
;
968 getStateSave().dumpToMemoryStream(streamState
);
970 out
<< "<?xml version='1.0' encoding='UTF-8'?>\n";
971 out
<< "<!DOCTYPE CARLA-PRESET>\n";
972 out
<< "<CARLA-PRESET VERSION='2.0'>\n";
974 out
<< "</CARLA-PRESET>\n";
978 if (file
.replaceWithData(out
.getData(), out
.getDataSize()))
981 pData
->engine
->setLastError("Failed to write file");
985 bool CarlaPlugin::loadStateFromFile(const char* const filename
)
989 CARLA_SAFE_ASSERT_RETURN(filename
!= nullptr && filename
[0] != '\0', false);
990 carla_debug("CarlaPlugin::loadStateFromFile(\"%s\")", filename
);
993 CARLA_SAFE_ASSERT_RETURN(file
.existsAsFile(), false);
995 XmlDocument
xml(file
);
996 CarlaScopedPointer
<XmlElement
> xmlElement(xml
.getDocumentElement(true));
997 CARLA_SAFE_ASSERT_RETURN(xmlElement
!= nullptr, false);
998 CARLA_SAFE_ASSERT_RETURN(xmlElement
->getTagName().equalsIgnoreCase("carla-preset"), false);
1000 // completely load file
1001 xmlElement
= xml
.getDocumentElement(false);
1002 CARLA_SAFE_ASSERT_RETURN(xmlElement
!= nullptr, false);
1004 if (pData
->stateSave
.fillFromXmlElement(xmlElement
))
1006 loadStateSave(pData
->stateSave
);
1013 #ifndef CARLA_PLUGIN_ONLY_BRIDGE
1014 bool CarlaPlugin::exportAsLV2(const char* const lv2path
)
1016 CARLA_SAFE_ASSERT_RETURN(lv2path
!= nullptr && lv2path
[0] != '\0', false);
1017 carla_debug("CarlaPlugin::exportAsLV2(\"%s\")", lv2path
);
1019 CarlaString
bundlepath(lv2path
);
1021 if (! bundlepath
.endsWith(".lv2"))
1022 bundlepath
+= ".lv2";
1024 const File
bundlefolder(bundlepath
.buffer());
1026 if (bundlefolder
.existsAsFile())
1028 pData
->engine
->setLastError("Requested filename already exists as file, use a folder instead");
1032 if (! bundlefolder
.exists())
1034 const Result
res(bundlefolder
.createDirectory());
1038 pData
->engine
->setLastError(res
.getErrorMessage().c_str());
1043 CarlaString
symbol(pData
->name
);
1047 const CarlaString
pluginFilename(bundlepath
+ CARLA_OS_SEP_STR
+ symbol
+ ".xml");
1049 if (! saveStateToFile(pluginFilename
))
1054 MemoryOutputStream manifestStream
;
1056 manifestStream
<< "@prefix lv2: <http://lv2plug.in/ns/lv2core#> .\n";
1057 manifestStream
<< "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
1058 manifestStream
<< "@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .\n";
1059 manifestStream
<< "\n";
1060 manifestStream
<< "<" << symbol
.buffer() << ".ttl>\n";
1061 manifestStream
<< " a lv2:Plugin ;\n";
1062 manifestStream
<< " lv2:binary <" << symbol
.buffer() << CARLA_LIB_EXT
"> ;\n";
1063 manifestStream
<< " rdfs:seeAlso <" << symbol
.buffer() << ".ttl> .\n";
1064 manifestStream
<< "\n";
1065 manifestStream
<< "<ext-ui>\n";
1066 manifestStream
<< " a <http://kxstudio.sf.net/ns/lv2ext/external-ui#Widget> ;\n";
1067 manifestStream
<< " ui:binary <" << symbol
.buffer() << CARLA_LIB_EXT
"> ;\n";
1068 manifestStream
<< " lv2:extensionData <http://lv2plug.in/ns/extensions/ui#idleInterface> ,\n";
1069 manifestStream
<< " <http://lv2plug.in/ns/extensions/ui#showInterface> ;\n";
1070 manifestStream
<< " lv2:requiredFeature <http://lv2plug.in/ns/ext/instance-access> .\n";
1071 manifestStream
<< "\n";
1073 const CarlaString
manifestFilename(bundlepath
+ CARLA_OS_SEP_STR
"manifest.ttl");
1074 const File
manifestFile(manifestFilename
.buffer());
1076 if (! manifestFile
.replaceWithData(manifestStream
.getData(), manifestStream
.getDataSize()))
1078 pData
->engine
->setLastError("Failed to write manifest.ttl file");
1084 MemoryOutputStream mainStream
;
1086 mainStream
<< "@prefix atom: <http://lv2plug.in/ns/ext/atom#> .\n";
1087 mainStream
<< "@prefix doap: <http://usefulinc.com/ns/doap#> .\n";
1088 mainStream
<< "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n";
1089 mainStream
<< "@prefix lv2: <http://lv2plug.in/ns/lv2core#> .\n";
1090 mainStream
<< "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
1091 mainStream
<< "@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .\n";
1093 mainStream
<< "<>\n";
1094 mainStream
<< " a lv2:Plugin ;\n";
1096 mainStream
<< " lv2:requiredFeature <http://lv2plug.in/ns/ext/buf-size#boundedBlockLength> ,\n";
1097 mainStream
<< " <http://lv2plug.in/ns/ext/options#options> ,\n";
1098 mainStream
<< " <http://lv2plug.in/ns/ext/urid#map> ;\n";
1101 if (pData
->hints
& PLUGIN_HAS_CUSTOM_UI
)
1103 mainStream
<< " ui:ui <ext-ui> ;\n";
1107 const uint32_t midiIns
= getMidiInCount();
1108 const uint32_t midiOuts
= getMidiOutCount();
1114 mainStream
<< " lv2:port [\n";
1115 mainStream
<< " a lv2:InputPort, atom:AtomPort ;\n";
1116 mainStream
<< " lv2:index 0 ;\n";
1117 mainStream
<< " lv2:symbol \"clv2_events_in\" ;\n";
1118 mainStream
<< " lv2:name \"Events Input\" ;\n";
1119 mainStream
<< " atom:bufferType atom:Sequence ;\n";
1120 mainStream
<< " atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ,\n";
1121 mainStream
<< " <http://lv2plug.in/ns/ext/time#Position> ;\n";
1122 mainStream
<< " ] ;\n";
1125 for (uint32_t i
=1; i
<midiIns
; ++i
)
1127 const String
portIndexNum(portIndex
++);
1128 const String
portIndexLabel(portIndex
);
1130 mainStream
<< " lv2:port [\n";
1131 mainStream
<< " a lv2:InputPort, atom:AtomPort ;\n";
1132 mainStream
<< " lv2:index " << portIndexNum
<< " ;\n";
1133 mainStream
<< " lv2:symbol \"clv2_midi_in_" << portIndexLabel
<< "\" ;\n";
1134 mainStream
<< " lv2:name \"MIDI Input " << portIndexLabel
<< "\" ;\n";
1135 mainStream
<< " ] ;\n";
1140 mainStream
<< " lv2:port [\n";
1141 mainStream
<< " a lv2:InputPort, atom:AtomPort ;\n";
1142 mainStream
<< " lv2:index 0 ;\n";
1143 mainStream
<< " lv2:symbol \"clv2_time_info\" ;\n";
1144 mainStream
<< " lv2:name \"Time Info\" ;\n";
1145 mainStream
<< " atom:bufferType atom:Sequence ;\n";
1146 mainStream
<< " atom:supports <http://lv2plug.in/ns/ext/time#Position> ;\n";
1147 mainStream
<< " ] ;\n";
1151 for (uint32_t i
=0; i
<midiOuts
; ++i
)
1153 const String
portIndexNum(portIndex
++);
1154 const String
portIndexLabel(portIndex
);
1156 mainStream
<< " lv2:port [\n";
1157 mainStream
<< " a lv2:InputPort, atom:AtomPort ;\n";
1158 mainStream
<< " lv2:index " << portIndexNum
<< " ;\n";
1159 mainStream
<< " lv2:symbol \"clv2_midi_out_" << portIndexLabel
<< "\" ;\n";
1160 mainStream
<< " lv2:name \"MIDI Output " << portIndexLabel
<< "\" ;\n";
1161 mainStream
<< " atom:bufferType atom:Sequence ;\n";
1162 mainStream
<< " atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ;\n";
1163 mainStream
<< " ] ;\n";
1166 mainStream
<< " lv2:port [\n";
1167 mainStream
<< " a lv2:InputPort, lv2:ControlPort ;\n";
1168 mainStream
<< " lv2:index " << String(portIndex
++) << " ;\n";
1169 mainStream
<< " lv2:name \"freewheel\" ;\n";
1170 mainStream
<< " lv2:symbol \"clv2_freewheel\" ;\n";
1171 mainStream
<< " lv2:default 0 ;\n";
1172 mainStream
<< " lv2:minimum 0 ;\n";
1173 mainStream
<< " lv2:maximum 1 ;\n";
1174 mainStream
<< " lv2:designation lv2:freeWheeling ;\n";
1175 mainStream
<< " lv2:portProperty lv2:toggled , lv2:integer ;\n";
1176 mainStream
<< " lv2:portProperty <http://lv2plug.in/ns/ext/port-props#notOnGUI> ;\n";
1177 mainStream
<< " ] ;\n";
1179 for (uint32_t i
=0; i
<pData
->audioIn
.count
; ++i
)
1181 const String
portIndexNum(portIndex
++);
1182 const String
portIndexLabel(i
+1);
1184 mainStream
<< " lv2:port [\n";
1185 mainStream
<< " a lv2:InputPort, lv2:AudioPort ;\n";
1186 mainStream
<< " lv2:index " << portIndexNum
<< " ;\n";
1187 mainStream
<< " lv2:symbol \"clv2_audio_in_" << portIndexLabel
<< "\" ;\n";
1188 mainStream
<< " lv2:name \"Audio Input " << portIndexLabel
<< "\" ;\n";
1189 mainStream
<< " ] ;\n";
1192 for (uint32_t i
=0; i
<pData
->audioOut
.count
; ++i
)
1194 const String
portIndexNum(portIndex
++);
1195 const String
portIndexLabel(i
+1);
1197 mainStream
<< " lv2:port [\n";
1198 mainStream
<< " a lv2:OutputPort, lv2:AudioPort ;\n";
1199 mainStream
<< " lv2:index " << portIndexNum
<< " ;\n";
1200 mainStream
<< " lv2:symbol \"clv2_audio_out_" << portIndexLabel
<< "\" ;\n";
1201 mainStream
<< " lv2:name \"Audio Output " << portIndexLabel
<< "\" ;\n";
1202 mainStream
<< " ] ;\n";
1205 CarlaStringList uniqueSymbolNames
;
1207 char strBufName
[STR_MAX
+1];
1208 char strBufSymbol
[STR_MAX
+1];
1209 carla_zeroChars(strBufName
, STR_MAX
+1);
1210 carla_zeroChars(strBufSymbol
, STR_MAX
+1);
1212 for (uint32_t i
=0; i
<pData
->param
.count
; ++i
)
1214 const ParameterData
& paramData(pData
->param
.data
[i
]);
1215 const ParameterRanges
& paramRanges(pData
->param
.ranges
[i
]);
1217 const String
portIndexNum(portIndex
++);
1219 mainStream
<< " lv2:port [\n";
1221 if (paramData
.type
== PARAMETER_INPUT
)
1222 mainStream
<< " a lv2:InputPort, lv2:ControlPort ;\n";
1224 mainStream
<< " a lv2:OutputPort, lv2:ControlPort ;\n";
1226 if (paramData
.hints
& PARAMETER_IS_BOOLEAN
)
1227 mainStream
<< " lv2:portProperty lv2:toggled ;\n";
1229 if (paramData
.hints
& PARAMETER_IS_INTEGER
)
1230 mainStream
<< " lv2:portProperty lv2:integer ;\n";
1232 // TODO logarithmic, enabled (not on gui), automatable, samplerate, scalepoints
1234 if (! getParameterName(i
, strBufName
))
1235 strBufName
[0] = '\0';
1236 if (! getParameterSymbol(i
, strBufSymbol
))
1237 strBufSymbol
[0] = '\0';
1239 if (strBufSymbol
[0] == '\0')
1241 CarlaString
s(strBufName
);
1243 std::memcpy(strBufSymbol
, s
.buffer(), s
.length()+1);
1245 if (strBufSymbol
[0] >= '0' && strBufSymbol
[0] <= '9')
1247 const size_t len(std::strlen(strBufSymbol
));
1248 std::memmove(strBufSymbol
+1, strBufSymbol
, len
);
1249 strBufSymbol
[0] = '_';
1250 strBufSymbol
[len
+1] = '\0';
1254 if (uniqueSymbolNames
.contains(strBufSymbol
))
1255 std::snprintf(strBufSymbol
, STR_MAX
, "clv2_param_%d", i
+1);
1257 mainStream
<< " lv2:index " << portIndexNum
<< " ;\n";
1258 mainStream
<< " lv2:symbol \"" << strBufSymbol
<< "\" ;\n";
1259 mainStream
<< " lv2:name \"\"\"" << strBufName
<< "\"\"\" ;\n";
1260 mainStream
<< " lv2:default " << String(paramRanges
.def
) << " ;\n";
1261 mainStream
<< " lv2:minimum " << String(paramRanges
.min
) << " ;\n";
1262 mainStream
<< " lv2:maximum " << String(paramRanges
.max
) << " ;\n";
1264 // TODO midiCC, midiChannel
1266 mainStream
<< " ] ;\n";
1269 char strBuf
[STR_MAX
+1];
1270 carla_zeroChars(strBuf
, STR_MAX
+1);
1272 if (! getMaker(strBuf
))
1275 mainStream
<< " rdfs:comment \"Plugin generated using Carla LV2 export.\" ;\n";
1276 mainStream
<< " doap:name \"\"\"" << getName() << "\"\"\" ;\n";
1277 mainStream
<< " doap:maintainer [ foaf:name \"\"\"" << strBuf
<< "\"\"\" ] .\n";
1280 const CarlaString
mainFilename(bundlepath
+ CARLA_OS_SEP_STR
+ symbol
+ ".ttl");
1281 const File
mainFile(mainFilename
.buffer());
1283 if (! mainFile
.replaceWithData(mainStream
.getData(), mainStream
.getDataSize()))
1285 pData
->engine
->setLastError("Failed to write main plugin ttl file");
1290 const CarlaString
binaryFilename(bundlepath
+ CARLA_OS_SEP_STR
+ symbol
+ CARLA_LIB_EXT
);
1292 const File
binaryFileSource(File::getSpecialLocation(File::currentExecutableFile
).getSiblingFile("carla-bridge-lv2" CARLA_LIB_EXT
));
1293 const File
binaryFileTarget(binaryFilename
.buffer());
1295 const EngineOptions
& opts(pData
->engine
->getOptions());
1297 const CarlaString
binFolderTarget(bundlepath
+ CARLA_OS_SEP_STR
+ "bin");
1298 const CarlaString
resFolderTarget(bundlepath
+ CARLA_OS_SEP_STR
+ "res");
1300 if (! binaryFileSource
.copyFileTo(binaryFileTarget
))
1302 pData
->engine
->setLastError("Failed to copy plugin binary");
1307 File(opts
.resourceDir
).copyDirectoryTo(File(resFolderTarget
.buffer()));
1309 // Copying all the binaries is pointless, just go through the expected needed bits
1310 const File
binFolder1(opts
.binaryDir
);
1311 const File
binFolder2(binFolderTarget
.buffer());
1312 binFolder2
.createDirectory();
1314 static const char* files
[] = {
1315 "carla-bridge-native.exe",
1316 "carla-bridge-win32.exe",
1317 "carla-discovery-win32.exe",
1318 "carla-discovery-win64.exe",
1319 "libcarla_utils.dll"
1322 for (int i
=0; i
<5; ++i
)
1323 binFolder1
.getChildFile(files
[i
]).copyFileTo(binFolder2
.getChildFile(files
[i
]));;
1325 File(opts
.binaryDir
).createSymbolicLink(File(binFolderTarget
.buffer()), true);
1326 File(opts
.resourceDir
).createSymbolicLink(File(resFolderTarget
.buffer()), true);
1333 // -------------------------------------------------------------------
1334 // Set data (internal stuff)
1336 void CarlaPlugin::setId(const uint newId
) noexcept
1341 void CarlaPlugin::setName(const char* const newName
)
1343 CARLA_SAFE_ASSERT_RETURN(newName
!= nullptr && newName
[0] != '\0',);
1345 if (pData
->name
!= nullptr)
1346 delete[] pData
->name
;
1348 pData
->name
= carla_strdup(newName
);
1351 void CarlaPlugin::setOption(const uint option
, const bool yesNo
, const bool sendCallback
)
1353 CARLA_SAFE_ASSERT_UINT2_RETURN(getOptionsAvailable() & option
, getOptionsAvailable(), option
,);
1356 pData
->options
|= option
;
1358 pData
->options
&= ~option
;
1360 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1362 pData
->engine
->callback(true, true,
1363 ENGINE_CALLBACK_OPTION_CHANGED
,
1365 static_cast<int>(option
),
1370 return; (void)sendCallback
;
1374 void CarlaPlugin::setEnabled(const bool yesNo
) noexcept
1376 if (pData
->enabled
== yesNo
)
1379 pData
->masterMutex
.lock();
1380 pData
->enabled
= yesNo
;
1382 if (yesNo
&& ! pData
->client
->isActive())
1383 pData
->client
->activate();
1385 pData
->masterMutex
.unlock();
1388 void CarlaPlugin::setActive(const bool active
, const bool sendOsc
, const bool sendCallback
) noexcept
1390 if (pData
->engineBridged
) {
1391 CARLA_SAFE_ASSERT_RETURN(!sendOsc
&& !sendCallback
,);
1392 } else if (pData
->enginePlugin
) {
1395 CARLA_SAFE_ASSERT_RETURN(sendOsc
|| sendCallback
,); // never call this from RT
1398 if (pData
->active
== active
)
1402 const ScopedSingleProcessLocker
spl(this, true);
1410 pData
->active
= active
;
1412 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1413 const float value
= active
? 1.0f
: 0.0f
;
1415 pData
->engine
->callback(sendCallback
, sendOsc
,
1416 ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED
,
1425 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1426 void CarlaPlugin::setDryWet(const float value
, const bool sendOsc
, const bool sendCallback
) noexcept
1428 if (pData
->engineBridged
) {
1429 CARLA_SAFE_ASSERT_RETURN(!sendOsc
&& !sendCallback
,);
1431 CARLA_SAFE_ASSERT_RETURN(sendOsc
|| sendCallback
,); // never call this from RT
1433 CARLA_SAFE_ASSERT(value
>= 0.0f
&& value
<= 1.0f
);
1435 const float fixedValue(carla_fixedValue
<float>(0.0f
, 1.0f
, value
));
1437 if (carla_isEqual(pData
->postProc
.dryWet
, fixedValue
))
1440 pData
->postProc
.dryWet
= fixedValue
;
1442 pData
->engine
->callback(sendCallback
, sendOsc
,
1443 ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED
,
1451 void CarlaPlugin::setVolume(const float value
, const bool sendOsc
, const bool sendCallback
) noexcept
1453 if (pData
->engineBridged
) {
1454 CARLA_SAFE_ASSERT_RETURN(!sendOsc
&& !sendCallback
,);
1456 CARLA_SAFE_ASSERT_RETURN(sendOsc
|| sendCallback
,); // never call this from RT
1458 CARLA_SAFE_ASSERT(value
>= 0.0f
&& value
<= 1.27f
);
1460 const float fixedValue(carla_fixedValue
<float>(0.0f
, 1.27f
, value
));
1462 if (carla_isEqual(pData
->postProc
.volume
, fixedValue
))
1465 pData
->postProc
.volume
= fixedValue
;
1467 pData
->engine
->callback(sendCallback
, sendOsc
,
1468 ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED
,
1476 void CarlaPlugin::setBalanceLeft(const float value
, const bool sendOsc
, const bool sendCallback
) noexcept
1478 if (pData
->engineBridged
) {
1479 CARLA_SAFE_ASSERT_RETURN(!sendOsc
&& !sendCallback
,);
1481 CARLA_SAFE_ASSERT_RETURN(sendOsc
|| sendCallback
,); // never call this from RT
1483 CARLA_SAFE_ASSERT(value
>= -1.0f
&& value
<= 1.0f
);
1485 const float fixedValue(carla_fixedValue
<float>(-1.0f
, 1.0f
, value
));
1487 if (carla_isEqual(pData
->postProc
.balanceLeft
, fixedValue
))
1490 pData
->postProc
.balanceLeft
= fixedValue
;
1492 pData
->engine
->callback(sendCallback
, sendOsc
,
1493 ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED
,
1495 PARAMETER_BALANCE_LEFT
,
1501 void CarlaPlugin::setBalanceRight(const float value
, const bool sendOsc
, const bool sendCallback
) noexcept
1503 if (pData
->engineBridged
) {
1504 CARLA_SAFE_ASSERT_RETURN(!sendOsc
&& !sendCallback
,);
1506 CARLA_SAFE_ASSERT_RETURN(sendOsc
|| sendCallback
,); // never call this from RT
1508 CARLA_SAFE_ASSERT(value
>= -1.0f
&& value
<= 1.0f
);
1510 const float fixedValue(carla_fixedValue
<float>(-1.0f
, 1.0f
, value
));
1512 if (carla_isEqual(pData
->postProc
.balanceRight
, fixedValue
))
1515 pData
->postProc
.balanceRight
= fixedValue
;
1517 pData
->engine
->callback(sendCallback
, sendOsc
,
1518 ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED
,
1520 PARAMETER_BALANCE_RIGHT
,
1526 void CarlaPlugin::setPanning(const float value
, const bool sendOsc
, const bool sendCallback
) noexcept
1528 if (pData
->engineBridged
) {
1529 CARLA_SAFE_ASSERT_RETURN(!sendOsc
&& !sendCallback
,);
1531 CARLA_SAFE_ASSERT_RETURN(sendOsc
|| sendCallback
,); // never call this from RT
1533 CARLA_SAFE_ASSERT(value
>= -1.0f
&& value
<= 1.0f
);
1535 const float fixedValue(carla_fixedValue
<float>(-1.0f
, 1.0f
, value
));
1537 if (carla_isEqual(pData
->postProc
.panning
, fixedValue
))
1540 pData
->postProc
.panning
= fixedValue
;
1542 pData
->engine
->callback(sendCallback
, sendOsc
,
1543 ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED
,
1551 void CarlaPlugin::setDryWetRT(const float value
, const bool sendCallbackLater
) noexcept
1553 CARLA_SAFE_ASSERT(value
>= 0.0f
&& value
<= 1.0f
);
1555 const float fixedValue(carla_fixedValue
<float>(0.0f
, 1.0f
, value
));
1557 if (carla_isEqual(pData
->postProc
.dryWet
, fixedValue
))
1560 pData
->postProc
.dryWet
= fixedValue
;
1561 pData
->postponeParameterChangeRtEvent(sendCallbackLater
, PARAMETER_DRYWET
, fixedValue
);
1564 void CarlaPlugin::setVolumeRT(const float value
, const bool sendCallbackLater
) noexcept
1566 CARLA_SAFE_ASSERT(value
>= 0.0f
&& value
<= 1.27f
);
1568 const float fixedValue(carla_fixedValue
<float>(0.0f
, 1.27f
, value
));
1570 if (carla_isEqual(pData
->postProc
.volume
, fixedValue
))
1573 pData
->postProc
.volume
= fixedValue
;
1574 pData
->postponeParameterChangeRtEvent(sendCallbackLater
, PARAMETER_VOLUME
, fixedValue
);
1577 void CarlaPlugin::setBalanceLeftRT(const float value
, const bool sendCallbackLater
) noexcept
1579 CARLA_SAFE_ASSERT(value
>= -1.0f
&& value
<= 1.0f
);
1581 const float fixedValue(carla_fixedValue
<float>(-1.0f
, 1.0f
, value
));
1583 if (carla_isEqual(pData
->postProc
.balanceLeft
, fixedValue
))
1586 pData
->postProc
.balanceLeft
= fixedValue
;
1587 pData
->postponeParameterChangeRtEvent(sendCallbackLater
, PARAMETER_BALANCE_LEFT
, fixedValue
);
1590 void CarlaPlugin::setBalanceRightRT(const float value
, const bool sendCallbackLater
) noexcept
1592 CARLA_SAFE_ASSERT(value
>= -1.0f
&& value
<= 1.0f
);
1594 const float fixedValue(carla_fixedValue
<float>(-1.0f
, 1.0f
, value
));
1596 if (carla_isEqual(pData
->postProc
.balanceRight
, fixedValue
))
1599 pData
->postProc
.balanceRight
= fixedValue
;
1600 pData
->postponeParameterChangeRtEvent(sendCallbackLater
, PARAMETER_BALANCE_RIGHT
, fixedValue
);
1603 void CarlaPlugin::setPanningRT(const float value
, const bool sendCallbackLater
) noexcept
1605 CARLA_SAFE_ASSERT(value
>= -1.0f
&& value
<= 1.0f
);
1607 const float fixedValue(carla_fixedValue
<float>(-1.0f
, 1.0f
, value
));
1609 if (carla_isEqual(pData
->postProc
.panning
, fixedValue
))
1612 pData
->postProc
.panning
= fixedValue
;
1613 pData
->postponeParameterChangeRtEvent(sendCallbackLater
, PARAMETER_PANNING
, fixedValue
);
1615 #endif // ! BUILD_BRIDGE_ALTERNATIVE_ARCH
1617 void CarlaPlugin::setCtrlChannel(const int8_t channel
, const bool sendOsc
, const bool sendCallback
) noexcept
1619 if (pData
->engineBridged
) {
1620 CARLA_SAFE_ASSERT_RETURN(!sendOsc
&& !sendCallback
,);
1622 CARLA_SAFE_ASSERT_RETURN(sendOsc
|| sendCallback
,); // never call this from RT
1624 CARLA_SAFE_ASSERT_RETURN(channel
>= -1 && channel
< MAX_MIDI_CHANNELS
,);
1626 if (pData
->ctrlChannel
== channel
)
1629 pData
->ctrlChannel
= channel
;
1631 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1632 const float channelf
= static_cast<float>(channel
);
1634 pData
->engine
->callback(sendCallback
, sendOsc
,
1635 ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED
,
1637 PARAMETER_CTRL_CHANNEL
,
1643 // -------------------------------------------------------------------
1644 // Set data (plugin-specific stuff)
1646 void CarlaPlugin::setParameterValue(const uint32_t parameterId
, const float value
, const bool sendGui
, const bool sendOsc
, const bool sendCallback
) noexcept
1648 if (pData
->engineBridged
) {
1649 // NOTE: some LV2 plugins feedback messages to UI on purpose
1650 CARLA_SAFE_ASSERT_RETURN(getType() == PLUGIN_LV2
|| !sendGui
,);
1651 } else if (pData
->enginePlugin
) {
1654 CARLA_SAFE_ASSERT_RETURN(sendGui
|| sendOsc
|| sendCallback
,); // never call this from RT
1656 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
,);
1658 if (sendGui
&& (pData
->hints
& PLUGIN_HAS_CUSTOM_UI
) != 0)
1659 uiParameterChange(parameterId
, value
);
1661 pData
->engine
->callback(sendCallback
, sendOsc
,
1662 ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED
,
1664 static_cast<int>(parameterId
),
1670 void CarlaPlugin::setParameterValueRT(const uint32_t parameterId
, const float value
, uint32_t, const bool sendCallbackLater
) noexcept
1672 pData
->postponeParameterChangeRtEvent(sendCallbackLater
, static_cast<int32_t>(parameterId
), value
);
1675 void CarlaPlugin::setParameterValueByRealIndex(const int32_t rindex
, const float value
, const bool sendGui
, const bool sendOsc
, const bool sendCallback
) noexcept
1677 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1678 CARLA_SAFE_ASSERT_RETURN(rindex
> PARAMETER_MAX
&& rindex
!= PARAMETER_NULL
,);
1682 case PARAMETER_ACTIVE
:
1683 return setActive((value
> 0.0f
), sendOsc
, sendCallback
);
1684 case PARAMETER_CTRL_CHANNEL
:
1685 return setCtrlChannel(int8_t(value
), sendOsc
, sendCallback
);
1686 case PARAMETER_DRYWET
:
1687 return setDryWet(value
, sendOsc
, sendCallback
);
1688 case PARAMETER_VOLUME
:
1689 return setVolume(value
, sendOsc
, sendCallback
);
1690 case PARAMETER_BALANCE_LEFT
:
1691 return setBalanceLeft(value
, sendOsc
, sendCallback
);
1692 case PARAMETER_BALANCE_RIGHT
:
1693 return setBalanceRight(value
, sendOsc
, sendCallback
);
1694 case PARAMETER_PANNING
:
1695 return setPanning(value
, sendOsc
, sendCallback
);
1698 CARLA_SAFE_ASSERT_RETURN(rindex
>= 0,);
1700 for (uint32_t i
=0; i
< pData
->param
.count
; ++i
)
1702 if (pData
->param
.data
[i
].rindex
== rindex
)
1704 //if (carla_isNotEqual(getParameterValue(i), value))
1705 setParameterValue(i
, value
, sendGui
, sendOsc
, sendCallback
);
1711 void CarlaPlugin::setParameterMidiChannel(const uint32_t parameterId
, const uint8_t channel
, const bool sendOsc
, const bool sendCallback
) noexcept
1713 if (pData
->engineBridged
) {
1714 CARLA_SAFE_ASSERT_RETURN(!sendOsc
&& !sendCallback
,);
1716 CARLA_SAFE_ASSERT_RETURN(sendOsc
|| sendCallback
,); // never call this from RT
1718 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
,);
1719 CARLA_SAFE_ASSERT_RETURN(channel
< MAX_MIDI_CHANNELS
,);
1721 if (pData
->param
.data
[parameterId
].midiChannel
== channel
)
1724 pData
->param
.data
[parameterId
].midiChannel
= channel
;
1726 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1727 pData
->engine
->callback(sendCallback
, sendOsc
,
1728 ENGINE_CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED
,
1730 static_cast<int>(parameterId
),
1736 void CarlaPlugin::setParameterMappedControlIndex(const uint32_t parameterId
, const int16_t index
,
1737 const bool sendOsc
, const bool sendCallback
,
1738 const bool reconfigureNow
) noexcept
1740 if (pData
->engineBridged
) {
1741 CARLA_SAFE_ASSERT_RETURN(!sendOsc
&& !sendCallback
,);
1743 CARLA_SAFE_ASSERT_RETURN(sendOsc
|| sendCallback
,); // never call this from RT
1745 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
,);
1746 CARLA_SAFE_ASSERT_RETURN(index
>= CONTROL_INDEX_NONE
&& index
<= CONTROL_INDEX_MAX_ALLOWED
,);
1748 ParameterData
& paramData(pData
->param
.data
[parameterId
]);
1750 if (paramData
.mappedControlIndex
== index
)
1753 const ParameterRanges
& paramRanges(pData
->param
.ranges
[parameterId
]);
1755 if ((paramData
.hints
& PARAMETER_MAPPED_RANGES_SET
) == 0x0)
1756 setParameterMappedRange(parameterId
, paramRanges
.min
, paramRanges
.max
, true, true);
1758 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1759 char strBuf
[STR_MAX
+1];
1760 carla_zeroChars(strBuf
, STR_MAX
+1);
1761 if (! getParameterName(parameterId
, strBuf
))
1762 std::snprintf(strBuf
, STR_MAX
, "Param %u", parameterId
);
1764 const uint portNameSize
= pData
->engine
->getMaxPortNameSize();
1765 if (portNameSize
< STR_MAX
)
1766 strBuf
[portNameSize
] = '\0';
1768 // was learning something else before, stop that first
1769 if (pData
->midiLearnParameterIndex
>= 0 && pData
->midiLearnParameterIndex
!= static_cast<int32_t>(parameterId
))
1771 const int32_t oldParameterId
= pData
->midiLearnParameterIndex
;
1772 pData
->midiLearnParameterIndex
= -1;
1774 CARLA_SAFE_ASSERT_RETURN(oldParameterId
< static_cast<int32_t>(pData
->param
.count
),);
1776 pData
->param
.data
[oldParameterId
].mappedControlIndex
= CONTROL_INDEX_NONE
;
1777 pData
->engine
->callback(true, true,
1778 ENGINE_CALLBACK_PARAMETER_MAPPED_CONTROL_INDEX_CHANGED
,
1785 // mapping new parameter to CV
1786 if (index
== CONTROL_INDEX_CV
)
1788 CARLA_SAFE_ASSERT_RETURN(pData
->event
.cvSourcePorts
!= nullptr,);
1789 CARLA_SAFE_ASSERT_RETURN(paramData
.type
== PARAMETER_INPUT
,);
1790 CARLA_SAFE_ASSERT_RETURN(paramData
.hints
& PARAMETER_CAN_BE_CV_CONTROLLED
,);
1792 CarlaEngineCVPort
* const cvPort
=
1793 (CarlaEngineCVPort
*)pData
->client
->addPort(kEnginePortTypeCV
, strBuf
, true, parameterId
);
1794 cvPort
->setRange(paramData
.mappedMinimum
, paramData
.mappedMaximum
);
1795 pData
->event
.cvSourcePorts
->addCVSource(cvPort
, parameterId
, reconfigureNow
);
1797 // unmapping from CV
1798 else if (paramData
.mappedControlIndex
== CONTROL_INDEX_CV
)
1800 CARLA_SAFE_ASSERT_RETURN(pData
->event
.cvSourcePorts
!= nullptr,);
1802 CARLA_SAFE_ASSERT(pData
->client
->removePort(kEnginePortTypeCV
, strBuf
, true));
1803 CARLA_SAFE_ASSERT(pData
->event
.cvSourcePorts
->removeCVSource(parameterId
));
1805 // mapping to something new
1806 else if (paramData
.mappedControlIndex
== CONTROL_INDEX_NONE
)
1808 // when doing MIDI CC mapping, ensure ranges are within bounds
1809 if (paramData
.mappedMinimum
< paramRanges
.min
|| paramData
.mappedMaximum
> paramRanges
.max
)
1810 setParameterMappedRange(parameterId
,
1811 std::max(paramData
.mappedMinimum
, paramRanges
.min
),
1812 std::min(paramData
.mappedMaximum
, paramRanges
.max
),
1817 paramData
.mappedControlIndex
= index
;
1819 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1820 if (index
== CONTROL_INDEX_MIDI_LEARN
)
1821 pData
->midiLearnParameterIndex
= static_cast<int32_t>(parameterId
);
1823 pData
->midiLearnParameterIndex
= -1;
1825 pData
->engine
->callback(sendCallback
, sendOsc
,
1826 ENGINE_CALLBACK_PARAMETER_MAPPED_CONTROL_INDEX_CHANGED
,
1828 static_cast<int>(parameterId
),
1834 (void)reconfigureNow
;
1838 void CarlaPlugin::setParameterMappedRange(const uint32_t parameterId
, const float minimum
, const float maximum
,
1839 const bool sendOsc
, const bool sendCallback
) noexcept
1841 if (pData
->engineBridged
) {
1842 CARLA_SAFE_ASSERT_RETURN(!sendOsc
&& !sendCallback
,);
1844 CARLA_SAFE_ASSERT_RETURN(sendOsc
|| sendCallback
,); // never call this from RT
1846 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
,);
1848 ParameterData
& paramData(pData
->param
.data
[parameterId
]);
1850 if (carla_isEqual(paramData
.mappedMinimum
, minimum
) &&
1851 carla_isEqual(paramData
.mappedMaximum
, maximum
) &&
1852 (paramData
.hints
& PARAMETER_MAPPED_RANGES_SET
) != 0x0)
1855 if (paramData
.mappedControlIndex
!= CONTROL_INDEX_NONE
&& paramData
.mappedControlIndex
!= CONTROL_INDEX_CV
)
1857 const ParameterRanges
& paramRanges(pData
->param
.ranges
[parameterId
]);
1858 CARLA_SAFE_ASSERT_RETURN(minimum
>= paramRanges
.min
,);
1859 CARLA_SAFE_ASSERT_RETURN(maximum
<= paramRanges
.max
,);
1862 paramData
.hints
|= PARAMETER_MAPPED_RANGES_SET
;
1863 paramData
.mappedMinimum
= minimum
;
1864 paramData
.mappedMaximum
= maximum
;
1866 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1867 if (pData
->event
.cvSourcePorts
!= nullptr && paramData
.mappedControlIndex
== CONTROL_INDEX_CV
)
1868 pData
->event
.cvSourcePorts
->setCVSourceRange(parameterId
, minimum
, maximum
);
1870 char strBuf
[STR_MAX
+1];
1871 carla_zeroChars(strBuf
, STR_MAX
+1);
1872 std::snprintf(strBuf
, STR_MAX
, "%.12g:%.12g", static_cast<double>(minimum
), static_cast<double>(maximum
));
1874 pData
->engine
->callback(sendCallback
, sendOsc
,
1875 ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED
,
1877 static_cast<int>(parameterId
),
1883 void CarlaPlugin::setCustomData(const char* const type
, const char* const key
, const char* const value
, const bool)
1885 CARLA_SAFE_ASSERT_RETURN(type
!= nullptr && type
[0] != '\0',);
1886 CARLA_SAFE_ASSERT_RETURN(key
!= nullptr && key
[0] != '\0',);
1887 CARLA_SAFE_ASSERT_RETURN(value
!= nullptr,);
1890 if (std::strcmp(type
, CUSTOM_DATA_TYPE_STRING
) == 0)
1892 const PluginType ptype
= getType();
1894 if ((ptype
== PLUGIN_INTERNAL
&& std::strncmp(key
, "CarlaAlternateFile", 18) == 0) ||
1895 (ptype
== PLUGIN_DSSI
&& std::strcmp (key
, "guiVisible") == 0) ||
1896 (ptype
== PLUGIN_LV2
&& std::strncmp(key
, "OSC:", 4) == 0))
1900 // Check if we already have this key
1901 for (LinkedList
<CustomData
>::Itenerator it
= pData
->custom
.begin2(); it
.valid(); it
.next())
1903 CustomData
& customData(it
.getValue(kCustomDataFallbackNC
));
1904 CARLA_SAFE_ASSERT_CONTINUE(customData
.isValid());
1906 if (std::strcmp(customData
.key
, key
) == 0)
1908 if (customData
.value
!= nullptr)
1909 delete[] customData
.value
;
1911 customData
.value
= carla_strdup(value
);
1916 // Otherwise store it
1917 CustomData customData
;
1918 customData
.type
= carla_strdup(type
);
1919 customData
.key
= carla_strdup(key
);
1920 customData
.value
= carla_strdup(value
);
1921 pData
->custom
.append(customData
);
1924 void CarlaPlugin::setChunkData(const void* const data
, const std::size_t dataSize
)
1926 CARLA_SAFE_ASSERT_RETURN(data
!= nullptr,);
1927 CARLA_SAFE_ASSERT_RETURN(dataSize
> 0,);
1928 CARLA_SAFE_ASSERT(false); // this should never happen
1931 void CarlaPlugin::setProgram(const int32_t index
,
1932 const bool sendGui
, const bool sendOsc
, const bool sendCallback
, const bool) noexcept
1934 CARLA_SAFE_ASSERT_RETURN(index
>= -1 && index
< static_cast<int32_t>(pData
->prog
.count
),);
1936 pData
->prog
.current
= index
;
1938 pData
->engine
->callback(sendCallback
, sendOsc
,
1939 ENGINE_CALLBACK_PROGRAM_CHANGED
,
1942 0, 0, 0.0f
, nullptr);
1944 // Change default parameter values
1947 if (sendGui
&& (pData
->hints
& PLUGIN_HAS_CUSTOM_UI
) != 0)
1948 uiProgramChange(static_cast<uint32_t>(index
));
1957 pData
->updateParameterValues(this, sendCallback
, sendOsc
, true);
1963 void CarlaPlugin::setMidiProgram(const int32_t index
,
1964 const bool sendGui
, const bool sendOsc
, const bool sendCallback
, const bool) noexcept
1966 CARLA_SAFE_ASSERT_RETURN(index
>= -1 && index
< static_cast<int32_t>(pData
->midiprog
.count
),);
1968 pData
->midiprog
.current
= index
;
1970 pData
->engine
->callback(sendCallback
, sendOsc
,
1971 ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED
,
1974 0, 0, 0.0f
, nullptr);
1976 // Change default parameter values
1979 if (sendGui
&& (pData
->hints
& PLUGIN_HAS_CUSTOM_UI
) != 0)
1980 uiMidiProgramChange(static_cast<uint32_t>(index
));
1989 pData
->updateParameterValues(this, sendCallback
, sendOsc
, true);
1995 void CarlaPlugin::setMidiProgramById(const uint32_t bank
, const uint32_t program
, const bool sendGui
, const bool sendOsc
, const bool sendCallback
) noexcept
1997 for (uint32_t i
=0; i
< pData
->midiprog
.count
; ++i
)
1999 if (pData
->midiprog
.data
[i
].bank
== bank
&& pData
->midiprog
.data
[i
].program
== program
)
2000 return setMidiProgram(static_cast<int32_t>(i
), sendGui
, sendOsc
, sendCallback
);
2004 void CarlaPlugin::setProgramRT(const uint32_t uindex
, const bool sendCallbackLater
) noexcept
2006 CARLA_SAFE_ASSERT_RETURN(uindex
< pData
->prog
.count
,);
2008 const int32_t index
= static_cast<int32_t>(uindex
);
2009 pData
->prog
.current
= index
;
2011 // Change default parameter values
2019 pData
->updateDefaultParameterValues(this);
2023 pData
->postponeProgramChangeRtEvent(sendCallbackLater
, uindex
);
2026 void CarlaPlugin::setMidiProgramRT(const uint32_t uindex
, const bool sendCallbackLater
) noexcept
2028 CARLA_SAFE_ASSERT_RETURN(uindex
< pData
->midiprog
.count
,);
2030 const int32_t index
= static_cast<int32_t>(uindex
);
2031 pData
->midiprog
.current
= index
;
2033 // Change default parameter values
2041 pData
->updateDefaultParameterValues(this);
2045 pData
->postponeMidiProgramChangeRtEvent(sendCallbackLater
, uindex
);
2048 // -------------------------------------------------------------------
2051 void CarlaPlugin::reloadPrograms(const bool)
2055 // -------------------------------------------------------------------
2056 // Plugin processing
2058 void CarlaPlugin::activate() noexcept
2060 CARLA_SAFE_ASSERT(! pData
->active
);
2063 void CarlaPlugin::deactivate() noexcept
2065 CARLA_SAFE_ASSERT(pData
->active
);
2068 void CarlaPlugin::bufferSizeChanged(const uint32_t newBufferSize
)
2070 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2071 delete[] pData
->postProc
.extraBuffer
;
2072 pData
->postProc
.extraBuffer
= new float[newBufferSize
];
2075 (void)newBufferSize
;
2079 void CarlaPlugin::sampleRateChanged(const double)
2083 void CarlaPlugin::offlineModeChanged(const bool)
2087 // -------------------------------------------------------------------
2090 void CarlaPlugin::idle()
2092 if (! pData
->enabled
)
2095 const bool hasUI
= pData
->hints
& PLUGIN_HAS_CUSTOM_UI
;
2096 const bool needsUiMainThread
= pData
->hints
& PLUGIN_NEEDS_UI_MAIN_THREAD
;
2097 const uint32_t latency
= getLatencyInFrames();
2099 if (pData
->latency
.frames
!= latency
)
2101 carla_stdout("latency changed to %i samples", latency
);
2103 const ScopedSingleProcessLocker
sspl(this, true);
2105 pData
->client
->setLatency(latency
);
2106 #ifndef BUILD_BRIDGE
2107 pData
->latency
.recreateBuffers(pData
->latency
.channels
, latency
);
2109 pData
->latency
.frames
= latency
;
2113 ProtectedData::PostRtEvents::Access
rtEvents(pData
->postRtEvents
);
2115 if (rtEvents
.isEmpty())
2118 for (RtLinkedList
<PluginPostRtEvent
>::Itenerator it
= rtEvents
.getDataIterator(); it
.valid(); it
.next())
2120 const PluginPostRtEvent
& event(it
.getValue(kPluginPostRtEventFallback
));
2121 CARLA_SAFE_ASSERT_CONTINUE(event
.type
!= kPluginPostRtEventNull
);
2125 case kPluginPostRtEventNull
: {
2128 case kPluginPostRtEventParameterChange
: {
2130 if (event
.parameter
.index
>= 0 && hasUI
)
2132 if (needsUiMainThread
)
2133 pData
->postUiEvents
.append(event
);
2135 uiParameterChange(static_cast<uint32_t>(event
.parameter
.index
), event
.parameter
.value
);
2138 if (event
.sendCallback
)
2141 pData
->engine
->callback(true, true,
2142 ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED
,
2144 event
.parameter
.index
,
2146 event
.parameter
.value
,
2151 case kPluginPostRtEventProgramChange
: {
2155 if (needsUiMainThread
)
2156 pData
->postUiEvents
.append(event
);
2158 uiProgramChange(event
.program
.index
);
2161 // Update param values
2162 for (uint32_t j
=0; j
< pData
->param
.count
; ++j
)
2164 const float paramDefault(pData
->param
.ranges
[j
].def
);
2165 const float paramValue(getParameterValue(j
));
2167 pData
->engine
->callback(true, true,
2168 ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED
,
2170 static_cast<int>(j
),
2174 pData
->engine
->callback(true, true,
2175 ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED
,
2177 static_cast<int>(j
),
2183 if (event
.sendCallback
)
2186 pData
->engine
->callback(true, true,
2187 ENGINE_CALLBACK_PROGRAM_CHANGED
,
2189 static_cast<int>(event
.program
.index
),
2190 0, 0, 0.0f
, nullptr);
2194 case kPluginPostRtEventMidiProgramChange
: {
2198 if (needsUiMainThread
)
2199 pData
->postUiEvents
.append(event
);
2201 uiMidiProgramChange(event
.program
.index
);
2204 // Update param values
2205 for (uint32_t j
=0; j
< pData
->param
.count
; ++j
)
2207 const float paramDefault(pData
->param
.ranges
[j
].def
);
2208 const float paramValue(getParameterValue(j
));
2210 pData
->engine
->callback(true, true,
2211 ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED
,
2213 static_cast<int>(j
),
2217 pData
->engine
->callback(true, true,
2218 ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED
,
2220 static_cast<int>(j
),
2226 if (event
.sendCallback
)
2229 pData
->engine
->callback(true, true,
2230 ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED
,
2232 static_cast<int>(event
.program
.index
),
2233 0, 0, 0.0f
, nullptr);
2237 case kPluginPostRtEventNoteOn
: {
2238 CARLA_SAFE_ASSERT_BREAK(event
.note
.channel
< MAX_MIDI_CHANNELS
);
2239 CARLA_SAFE_ASSERT_BREAK(event
.note
.note
< MAX_MIDI_NOTE
);
2240 CARLA_SAFE_ASSERT_BREAK(event
.note
.velocity
< MAX_MIDI_VALUE
);
2245 if (needsUiMainThread
)
2246 pData
->postUiEvents
.append(event
);
2248 uiNoteOn(event
.note
.channel
, event
.note
.note
, event
.note
.velocity
);
2251 if (event
.sendCallback
)
2254 pData
->engine
->callback(true, true,
2255 ENGINE_CALLBACK_NOTE_ON
,
2257 static_cast<int>(event
.note
.channel
),
2258 static_cast<int>(event
.note
.note
),
2259 static_cast<int>(event
.note
.velocity
),
2264 case kPluginPostRtEventNoteOff
: {
2265 CARLA_SAFE_ASSERT_BREAK(event
.note
.channel
< MAX_MIDI_CHANNELS
);
2266 CARLA_SAFE_ASSERT_BREAK(event
.note
.note
< MAX_MIDI_NOTE
);
2271 if (needsUiMainThread
)
2272 pData
->postUiEvents
.append(event
);
2274 uiNoteOff(event
.note
.channel
, event
.note
.note
);
2277 if (event
.sendCallback
)
2280 pData
->engine
->callback(true, true,
2281 ENGINE_CALLBACK_NOTE_OFF
,
2283 static_cast<int>(event
.note
.channel
),
2284 static_cast<int>(event
.note
.note
),
2289 case kPluginPostRtEventMidiLearn
: {
2290 CARLA_SAFE_ASSERT_BREAK(event
.midiLearn
.cc
< MAX_MIDI_VALUE
);
2291 CARLA_SAFE_ASSERT_BREAK(event
.midiLearn
.channel
< MAX_MIDI_CHANNELS
);
2293 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2294 if (event
.sendCallback
)
2296 pData
->engine
->callback(true, true,
2297 ENGINE_CALLBACK_PARAMETER_MAPPED_CONTROL_INDEX_CHANGED
,
2299 static_cast<int>(event
.midiLearn
.parameter
),
2300 static_cast<int>(event
.midiLearn
.cc
),
2303 pData
->engine
->callback(true, true,
2304 ENGINE_CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED
,
2306 static_cast<int>(event
.midiLearn
.parameter
),
2307 static_cast<int>(event
.midiLearn
.channel
),
2316 bool CarlaPlugin::tryLock(const bool forcedOffline
) noexcept
2320 #ifndef STOAT_TEST_BUILD
2321 pData
->masterMutex
.lock();
2326 return pData
->masterMutex
.tryLock();
2329 void CarlaPlugin::unlock() noexcept
2331 pData
->masterMutex
.unlock();
2334 // -------------------------------------------------------------------
2337 void CarlaPlugin::initBuffers() const noexcept
2339 pData
->audioIn
.initBuffers();
2340 pData
->audioOut
.initBuffers();
2341 pData
->cvIn
.initBuffers();
2342 pData
->cvOut
.initBuffers();
2343 pData
->event
.initBuffers();
2346 void CarlaPlugin::clearBuffers() noexcept
2348 pData
->clearBuffers();
2351 // -------------------------------------------------------------------
2355 void CarlaPlugin::handleOscMessage(const char*, int, const void*, const char*, void*)
2360 // -------------------------------------------------------------------
2363 void CarlaPlugin::sendMidiSingleNote(const uint8_t channel
, const uint8_t note
, const uint8_t velo
, const bool sendGui
, const bool sendOsc
, const bool sendCallback
)
2365 CARLA_SAFE_ASSERT_RETURN(channel
< MAX_MIDI_CHANNELS
,);
2366 CARLA_SAFE_ASSERT_RETURN(note
< MAX_MIDI_NOTE
,);
2367 CARLA_SAFE_ASSERT_RETURN(velo
< MAX_MIDI_VALUE
,);
2369 if (! pData
->active
)
2372 ExternalMidiNote extNote
;
2373 extNote
.channel
= static_cast<int8_t>(channel
);
2374 extNote
.note
= note
;
2375 extNote
.velo
= velo
;
2377 pData
->extNotes
.appendNonRT(extNote
);
2379 if (sendGui
&& (pData
->hints
& PLUGIN_HAS_CUSTOM_UI
) != 0)
2382 uiNoteOn(channel
, note
, velo
);
2384 uiNoteOff(channel
, note
);
2387 pData
->engine
->callback(sendCallback
, sendOsc
,
2388 (velo
> 0) ? ENGINE_CALLBACK_NOTE_ON
: ENGINE_CALLBACK_NOTE_OFF
,
2396 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2397 void CarlaPlugin::postponeRtAllNotesOff()
2399 if (pData
->ctrlChannel
< 0 || pData
->ctrlChannel
>= MAX_MIDI_CHANNELS
)
2402 PluginPostRtEvent postEvent
= { kPluginPostRtEventNoteOff
, true, {} };
2403 postEvent
.note
.channel
= static_cast<uint8_t>(pData
->ctrlChannel
);
2405 for (uint8_t i
=0; i
< MAX_MIDI_NOTE
; ++i
)
2407 postEvent
.note
.note
= i
;
2408 pData
->postRtEvents
.appendRT(postEvent
);
2413 // -------------------------------------------------------------------
2416 void CarlaPlugin::setCustomUITitle(const char* const title
) noexcept
2418 pData
->uiTitle
= title
;
2421 void CarlaPlugin::showCustomUI(const bool yesNo
)
2424 CARLA_SAFE_ASSERT(false);
2428 void* CarlaPlugin::embedCustomUI(void*)
2433 void CarlaPlugin::uiIdle()
2435 if (pData
->hints
& PLUGIN_NEEDS_UI_MAIN_THREAD
)
2437 // Update parameter outputs
2438 for (uint32_t i
=0; i
< pData
->param
.count
; ++i
)
2440 if (pData
->param
.data
[i
].type
== PARAMETER_OUTPUT
)
2441 uiParameterChange(i
, getParameterValue(i
));
2444 const CarlaMutexLocker
sl(pData
->postUiEvents
.mutex
);
2446 for (LinkedList
<PluginPostRtEvent
>::Itenerator it
= pData
->postUiEvents
.data
.begin2(); it
.valid(); it
.next())
2448 const PluginPostRtEvent
& event(it
.getValue(kPluginPostRtEventFallback
));
2449 CARLA_SAFE_ASSERT_CONTINUE(event
.type
!= kPluginPostRtEventNull
);
2453 case kPluginPostRtEventNull
:
2454 case kPluginPostRtEventMidiLearn
:
2457 case kPluginPostRtEventParameterChange
:
2458 uiParameterChange(static_cast<uint32_t>(event
.parameter
.index
), event
.parameter
.value
);
2461 case kPluginPostRtEventProgramChange
:
2462 uiProgramChange(event
.program
.index
);
2465 case kPluginPostRtEventMidiProgramChange
:
2466 uiMidiProgramChange(event
.program
.index
);
2469 case kPluginPostRtEventNoteOn
:
2470 uiNoteOn(event
.note
.channel
, event
.note
.note
, event
.note
.velocity
);
2473 case kPluginPostRtEventNoteOff
:
2474 uiNoteOff(event
.note
.channel
, event
.note
.note
);
2479 pData
->postUiEvents
.data
.clear();
2482 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2483 if (pData
->transientTryCounter
== 0)
2485 if (++pData
->transientTryCounter
% 10 != 0)
2487 if (pData
->transientTryCounter
>= 200)
2490 carla_stdout("Trying to get window...");
2492 CarlaString uiTitle
;
2494 if (pData
->uiTitle
.isNotEmpty())
2496 uiTitle
= pData
->uiTitle
;
2500 uiTitle
= pData
->name
;
2501 uiTitle
+= " (GUI)";
2504 if (CarlaPluginUI::tryTransientWinIdMatch(getUiBridgeProcessId(), uiTitle
,
2505 pData
->engine
->getOptions().frontendWinId
, pData
->transientFirstTry
))
2507 pData
->transientTryCounter
= 0;
2508 pData
->transientFirstTry
= false;
2513 void CarlaPlugin::uiParameterChange(const uint32_t index
, const float value
) noexcept
2515 CARLA_SAFE_ASSERT_RETURN(index
< getParameterCount(),);
2522 void CarlaPlugin::uiProgramChange(const uint32_t index
) noexcept
2524 CARLA_SAFE_ASSERT_RETURN(index
< getProgramCount(),);
2527 void CarlaPlugin::uiMidiProgramChange(const uint32_t index
) noexcept
2529 CARLA_SAFE_ASSERT_RETURN(index
< getMidiProgramCount(),);
2532 void CarlaPlugin::uiNoteOn(const uint8_t channel
, const uint8_t note
, const uint8_t velo
) noexcept
2534 CARLA_SAFE_ASSERT_RETURN(channel
< MAX_MIDI_CHANNELS
,);
2535 CARLA_SAFE_ASSERT_RETURN(note
< MAX_MIDI_NOTE
,);
2536 CARLA_SAFE_ASSERT_RETURN(velo
> 0 && velo
< MAX_MIDI_VALUE
,);
2539 void CarlaPlugin::uiNoteOff(const uint8_t channel
, const uint8_t note
) noexcept
2541 CARLA_SAFE_ASSERT_RETURN(channel
< MAX_MIDI_CHANNELS
,);
2542 CARLA_SAFE_ASSERT_RETURN(note
< MAX_MIDI_NOTE
,);
2545 CarlaEngine
* CarlaPlugin::getEngine() const noexcept
2547 return pData
->engine
;
2550 CarlaEngineClient
* CarlaPlugin::getEngineClient() const noexcept
2552 return pData
->client
;
2555 CarlaEngineAudioPort
* CarlaPlugin::getAudioInPort(const uint32_t index
) const noexcept
2557 return pData
->audioIn
.ports
[index
].port
;
2560 CarlaEngineAudioPort
* CarlaPlugin::getAudioOutPort(const uint32_t index
) const noexcept
2562 return pData
->audioOut
.ports
[index
].port
;
2565 CarlaEngineCVPort
* CarlaPlugin::getCVInPort(const uint32_t index
) const noexcept
2567 return pData
->cvIn
.ports
[index
].port
;
2570 CarlaEngineCVPort
* CarlaPlugin::getCVOutPort(const uint32_t index
) const noexcept
2572 return pData
->cvOut
.ports
[index
].port
;
2575 CarlaEngineEventPort
* CarlaPlugin::getDefaultEventInPort() const noexcept
2577 return pData
->event
.portIn
;
2580 CarlaEngineEventPort
* CarlaPlugin::getDefaultEventOutPort() const noexcept
2582 return pData
->event
.portOut
;
2585 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2586 void CarlaPlugin::checkForMidiLearn(EngineEvent
& event
) noexcept
2588 if (pData
->midiLearnParameterIndex
< 0)
2590 if (event
.ctrl
.param
== MIDI_CONTROL_BANK_SELECT
|| event
.ctrl
.param
== MIDI_CONTROL_BANK_SELECT__LSB
)
2592 if (event
.ctrl
.param
>= MAX_MIDI_CONTROL
)
2595 const uint32_t parameterId
= static_cast<uint32_t>(pData
->midiLearnParameterIndex
);
2596 CARLA_SAFE_ASSERT_UINT2_RETURN(parameterId
< pData
->param
.count
, parameterId
, pData
->param
.count
,);
2598 ParameterData
& paramData(pData
->param
.data
[parameterId
]);
2599 CARLA_SAFE_ASSERT_INT_RETURN(paramData
.mappedControlIndex
== CONTROL_INDEX_MIDI_LEARN
,
2600 paramData
.mappedControlIndex
,);
2602 event
.ctrl
.handled
= true;
2603 paramData
.mappedControlIndex
= static_cast<int16_t>(event
.ctrl
.param
);
2604 paramData
.midiChannel
= event
.channel
;
2606 pData
->postponeMidiLearnRtEvent(true, parameterId
, static_cast<uint8_t>(event
.ctrl
.param
), event
.channel
);
2607 pData
->midiLearnParameterIndex
= -1;
2611 void* CarlaPlugin::getNativeHandle() const noexcept
2616 const void* CarlaPlugin::getNativeDescriptor() const noexcept
2621 uintptr_t CarlaPlugin::getUiBridgeProcessId() const noexcept
2626 // -------------------------------------------------------------------
2628 uint32_t CarlaPlugin::getPatchbayNodeId() const noexcept
2630 return pData
->nodeId
;
2633 void CarlaPlugin::setPatchbayNodeId(const uint32_t nodeId
) noexcept
2635 pData
->nodeId
= nodeId
;
2638 // -------------------------------------------------------------------
2640 void CarlaPlugin::cloneLV2Files(const CarlaPlugin
&)
2642 carla_stderr2("Warning: cloneLV2Files() called for non-implemented type");
2645 void CarlaPlugin::restoreLV2State(const bool temporary
) noexcept
2647 carla_stderr2("Warning: restoreLV2State(%s) called for non-implemented type", bool2str(temporary
));
2650 void CarlaPlugin::prepareForDeletion() noexcept
2652 carla_debug("CarlaPlugin::prepareForDeletion");
2654 const CarlaMutexLocker
cml(pData
->masterMutex
);
2656 pData
->client
->deactivate(true);
2659 void CarlaPlugin::waitForBridgeSaveSignal() noexcept
2663 // -------------------------------------------------------------------
2666 CarlaPlugin::ScopedDisabler::ScopedDisabler(CarlaPlugin
* const plugin
) noexcept
2670 CARLA_SAFE_ASSERT_RETURN(plugin
!= nullptr,);
2671 CARLA_SAFE_ASSERT_RETURN(plugin
->pData
!= nullptr,);
2672 CARLA_SAFE_ASSERT_RETURN(plugin
->pData
->client
!= nullptr,);
2673 carla_debug("CarlaPlugin::ScopedDisabler(%p)", plugin
);
2675 plugin
->pData
->masterMutex
.lock();
2677 if (plugin
->pData
->enabled
)
2680 plugin
->pData
->enabled
= false;
2682 if (plugin
->pData
->client
->isActive())
2683 plugin
->pData
->client
->deactivate(false);
2687 CarlaPlugin::ScopedDisabler::~ScopedDisabler() noexcept
2689 CARLA_SAFE_ASSERT_RETURN(fPlugin
!= nullptr,);
2690 CARLA_SAFE_ASSERT_RETURN(fPlugin
->pData
!= nullptr,);
2691 CARLA_SAFE_ASSERT_RETURN(fPlugin
->pData
->client
!= nullptr,);
2692 carla_debug("CarlaPlugin::~ScopedDisabler()");
2696 fPlugin
->pData
->enabled
= true;
2697 fPlugin
->pData
->client
->activate();
2700 fPlugin
->pData
->masterMutex
.unlock();
2703 // -------------------------------------------------------------------
2704 // Scoped Process Locker
2706 CarlaPlugin::ScopedSingleProcessLocker::ScopedSingleProcessLocker(CarlaPlugin
* const plugin
, const bool block
) noexcept
2710 CARLA_SAFE_ASSERT_RETURN(fPlugin
!= nullptr,);
2711 CARLA_SAFE_ASSERT_RETURN(fPlugin
->pData
!= nullptr,);
2712 carla_debug("CarlaPlugin::ScopedSingleProcessLocker(%p, %s)", plugin
, bool2str(block
));
2717 plugin
->pData
->singleMutex
.lock();
2720 CarlaPlugin::ScopedSingleProcessLocker::~ScopedSingleProcessLocker() noexcept
2722 CARLA_SAFE_ASSERT_RETURN(fPlugin
!= nullptr,);
2723 CARLA_SAFE_ASSERT_RETURN(fPlugin
->pData
!= nullptr,);
2724 carla_debug("CarlaPlugin::~ScopedSingleProcessLocker()");
2729 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2730 if (fPlugin
->pData
->singleMutex
.wasTryLockCalled())
2731 fPlugin
->pData
->needsReset
= true;
2734 fPlugin
->pData
->singleMutex
.unlock();
2737 // -------------------------------------------------------------------
2739 CARLA_BACKEND_END_NAMESPACE