Add initial bits for Qt6 support
[carla.git] / source / modules / distrho / src / DistrhoPluginInternal.hpp
blob94868aeeb093ba21d5cb4b24b2dc32c558ef0407
1 /*
2 * DISTRHO Plugin Framework (DPF)
3 * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com>
5 * Permission to use, copy, modify, and/or distribute this software for any purpose with
6 * or without fee is hereby granted, provided that the above copyright notice and this
7 * permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #ifndef DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED
18 #define DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED
20 #include "../DistrhoPlugin.hpp"
22 #ifdef DISTRHO_PLUGIN_TARGET_VST3
23 # include "DistrhoPluginVST.hpp"
24 #endif
26 #include <set>
28 START_NAMESPACE_DISTRHO
30 // -----------------------------------------------------------------------
31 // Maxmimum values
33 static const uint32_t kMaxMidiEvents = 512;
35 // -----------------------------------------------------------------------
36 // Static data, see DistrhoPlugin.cpp
38 extern uint32_t d_nextBufferSize;
39 extern double d_nextSampleRate;
40 extern const char* d_nextBundlePath;
41 extern bool d_nextPluginIsDummy;
42 extern bool d_nextCanRequestParameterValueChanges;
44 // -----------------------------------------------------------------------
45 // DSP callbacks
47 typedef bool (*writeMidiFunc) (void* ptr, const MidiEvent& midiEvent);
48 typedef bool (*requestParameterValueChangeFunc) (void* ptr, uint32_t index, float value);
49 typedef bool (*updateStateValueFunc) (void* ptr, const char* key, const char* value);
51 // -----------------------------------------------------------------------
52 // Helpers
54 struct AudioPortWithBusId : AudioPort {
55 uint32_t busId;
57 AudioPortWithBusId()
58 : AudioPort(),
59 busId(0) {}
62 struct PortGroupWithId : PortGroup {
63 uint32_t groupId;
65 PortGroupWithId()
66 : PortGroup(),
67 groupId(kPortGroupNone) {}
70 static void fillInPredefinedPortGroupData(const uint32_t groupId, PortGroup& portGroup)
72 switch (groupId)
74 case kPortGroupNone:
75 portGroup.name.clear();
76 portGroup.symbol.clear();
77 break;
78 case kPortGroupMono:
79 portGroup.name = "Mono";
80 portGroup.symbol = "dpf_mono";
81 break;
82 case kPortGroupStereo:
83 portGroup.name = "Stereo";
84 portGroup.symbol = "dpf_stereo";
85 break;
89 // -----------------------------------------------------------------------
90 // Plugin private data
92 struct Plugin::PrivateData {
93 const bool canRequestParameterValueChanges;
94 const bool isDummy;
95 bool isProcessing;
97 #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
98 AudioPortWithBusId* audioPorts;
99 #endif
101 uint32_t parameterCount;
102 uint32_t parameterOffset;
103 Parameter* parameters;
105 uint32_t portGroupCount;
106 PortGroupWithId* portGroups;
108 #if DISTRHO_PLUGIN_WANT_PROGRAMS
109 uint32_t programCount;
110 String* programNames;
111 #endif
113 #if DISTRHO_PLUGIN_WANT_STATE
114 uint32_t stateCount;
115 State* states;
116 #endif
118 #if DISTRHO_PLUGIN_WANT_LATENCY
119 uint32_t latency;
120 #endif
122 #if DISTRHO_PLUGIN_WANT_TIMEPOS
123 TimePosition timePosition;
124 #endif
126 // Callbacks
127 void* callbacksPtr;
128 writeMidiFunc writeMidiCallbackFunc;
129 requestParameterValueChangeFunc requestParameterValueChangeCallbackFunc;
130 updateStateValueFunc updateStateValueCallbackFunc;
132 uint32_t bufferSize;
133 double sampleRate;
134 char* bundlePath;
136 PrivateData() noexcept
137 : canRequestParameterValueChanges(d_nextCanRequestParameterValueChanges),
138 isDummy(d_nextPluginIsDummy),
139 isProcessing(false),
140 #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
141 audioPorts(nullptr),
142 #endif
143 parameterCount(0),
144 parameterOffset(0),
145 parameters(nullptr),
146 portGroupCount(0),
147 portGroups(nullptr),
148 #if DISTRHO_PLUGIN_WANT_PROGRAMS
149 programCount(0),
150 programNames(nullptr),
151 #endif
152 #if DISTRHO_PLUGIN_WANT_STATE
153 stateCount(0),
154 states(nullptr),
155 #endif
156 #if DISTRHO_PLUGIN_WANT_LATENCY
157 latency(0),
158 #endif
159 callbacksPtr(nullptr),
160 writeMidiCallbackFunc(nullptr),
161 requestParameterValueChangeCallbackFunc(nullptr),
162 updateStateValueCallbackFunc(nullptr),
163 bufferSize(d_nextBufferSize),
164 sampleRate(d_nextSampleRate),
165 bundlePath(d_nextBundlePath != nullptr ? strdup(d_nextBundlePath) : nullptr)
167 DISTRHO_SAFE_ASSERT(bufferSize != 0);
168 DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate));
170 #if defined(DISTRHO_PLUGIN_TARGET_DSSI) || defined(DISTRHO_PLUGIN_TARGET_LV2)
171 parameterOffset += DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS;
172 # if DISTRHO_PLUGIN_WANT_LATENCY
173 parameterOffset += 1;
174 # endif
175 #endif
177 #ifdef DISTRHO_PLUGIN_TARGET_LV2
178 # if (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_STATE || DISTRHO_PLUGIN_WANT_TIMEPOS)
179 parameterOffset += 1;
180 # endif
181 # if (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || DISTRHO_PLUGIN_WANT_STATE)
182 parameterOffset += 1;
183 # endif
184 #endif
186 #ifdef DISTRHO_PLUGIN_TARGET_VST3
187 parameterOffset += kVst3InternalParameterCount;
188 #endif
191 ~PrivateData() noexcept
193 #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
194 if (audioPorts != nullptr)
196 delete[] audioPorts;
197 audioPorts = nullptr;
199 #endif
201 if (parameters != nullptr)
203 delete[] parameters;
204 parameters = nullptr;
207 if (portGroups != nullptr)
209 delete[] portGroups;
210 portGroups = nullptr;
213 #if DISTRHO_PLUGIN_WANT_PROGRAMS
214 if (programNames != nullptr)
216 delete[] programNames;
217 programNames = nullptr;
219 #endif
221 #if DISTRHO_PLUGIN_WANT_STATE
222 if (states != nullptr)
224 delete[] states;
225 states = nullptr;
227 #endif
229 if (bundlePath != nullptr)
231 std::free(bundlePath);
232 bundlePath = nullptr;
236 #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
237 bool writeMidiCallback(const MidiEvent& midiEvent)
239 if (writeMidiCallbackFunc != nullptr)
240 return writeMidiCallbackFunc(callbacksPtr, midiEvent);
242 return false;
244 #endif
246 #if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST
247 bool requestParameterValueChangeCallback(const uint32_t index, const float value)
249 if (requestParameterValueChangeCallbackFunc != nullptr)
250 return requestParameterValueChangeCallbackFunc(callbacksPtr, index, value);
252 return false;
254 #endif
256 #if DISTRHO_PLUGIN_WANT_STATE
257 bool updateStateValueCallback(const char* const key, const char* const value)
259 d_stdout("updateStateValueCallback %p", updateStateValueCallbackFunc);
260 if (updateStateValueCallbackFunc != nullptr)
261 return updateStateValueCallbackFunc(callbacksPtr, key, value);
263 return false;
265 #endif
268 // -----------------------------------------------------------------------
269 // Plugin exporter class
271 class PluginExporter
273 public:
274 PluginExporter(void* const callbacksPtr,
275 const writeMidiFunc writeMidiCall,
276 const requestParameterValueChangeFunc requestParameterValueChangeCall,
277 const updateStateValueFunc updateStateValueCall)
278 : fPlugin(createPlugin()),
279 fData((fPlugin != nullptr) ? fPlugin->pData : nullptr),
280 fIsActive(false)
282 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
283 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
285 #if defined(DPF_RUNTIME_TESTING) && defined(__GNUC__) && !defined(__clang__)
286 /* Run-time testing build.
287 * Verify that virtual functions are overriden if parameters, programs or states are in use.
288 * This does not work on all compilers, but we use it purely as informational check anyway. */
289 if (fData->parameterCount != 0)
291 if ((void*)(fPlugin->*(&Plugin::initParameter)) == (void*)&Plugin::initParameter)
293 d_stderr2("DPF warning: Plugins with parameters must implement `initParameter`");
294 abort();
296 if ((void*)(fPlugin->*(&Plugin::getParameterValue)) == (void*)&Plugin::getParameterValue)
298 d_stderr2("DPF warning: Plugins with parameters must implement `getParameterValue`");
299 abort();
301 if ((void*)(fPlugin->*(&Plugin::setParameterValue)) == (void*)&Plugin::setParameterValue)
303 d_stderr2("DPF warning: Plugins with parameters must implement `setParameterValue`");
304 abort();
308 # if DISTRHO_PLUGIN_WANT_PROGRAMS
309 if (fData->programCount != 0)
311 if ((void*)(fPlugin->*(&Plugin::initProgramName)) == (void*)&Plugin::initProgramName)
313 d_stderr2("DPF warning: Plugins with programs must implement `initProgramName`");
314 abort();
316 if ((void*)(fPlugin->*(&Plugin::loadProgram)) == (void*)&Plugin::loadProgram)
318 d_stderr2("DPF warning: Plugins with programs must implement `loadProgram`");
319 abort();
322 # endif
324 # if DISTRHO_PLUGIN_WANT_STATE
325 if (fData->stateCount != 0)
327 if ((void*)(fPlugin->*(&Plugin::initState)) == (void*)&Plugin::initState)
329 d_stderr2("DPF warning: Plugins with state must implement `initState`");
330 abort();
333 if ((void*)(fPlugin->*(&Plugin::setState)) == (void*)&Plugin::setState)
335 d_stderr2("DPF warning: Plugins with state must implement `setState`");
336 abort();
339 # endif
341 # if DISTRHO_PLUGIN_WANT_FULL_STATE
342 if (fData->stateCount != 0)
344 if ((void*)(fPlugin->*(&Plugin::getState)) == (void*)&Plugin::getState)
346 d_stderr2("DPF warning: Plugins with full state must implement `getState`");
347 abort();
350 else
352 d_stderr2("DPF warning: Plugins with full state must have at least 1 state");
353 abort();
355 # endif
356 #endif
358 #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
360 uint32_t j=0;
361 # if DISTRHO_PLUGIN_NUM_INPUTS > 0
362 for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++j)
363 fPlugin->initAudioPort(true, i, fData->audioPorts[j]);
364 # endif
365 # if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
366 for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++j)
367 fPlugin->initAudioPort(false, i, fData->audioPorts[j]);
368 # endif
370 #endif // DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
372 for (uint32_t i=0, count=fData->parameterCount; i < count; ++i)
373 fPlugin->initParameter(i, fData->parameters[i]);
376 std::set<uint32_t> portGroupIndices;
378 #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
379 for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
380 portGroupIndices.insert(fData->audioPorts[i].groupId);
381 #endif
382 for (uint32_t i=0, count=fData->parameterCount; i < count; ++i)
383 portGroupIndices.insert(fData->parameters[i].groupId);
385 portGroupIndices.erase(kPortGroupNone);
387 if (const uint32_t portGroupSize = static_cast<uint32_t>(portGroupIndices.size()))
389 fData->portGroups = new PortGroupWithId[portGroupSize];
390 fData->portGroupCount = portGroupSize;
392 uint32_t index = 0;
393 for (std::set<uint32_t>::iterator it = portGroupIndices.begin(); it != portGroupIndices.end(); ++it, ++index)
395 PortGroupWithId& portGroup(fData->portGroups[index]);
396 portGroup.groupId = *it;
398 if (portGroup.groupId < portGroupSize)
399 fPlugin->initPortGroup(portGroup.groupId, portGroup);
400 else
401 fillInPredefinedPortGroupData(portGroup.groupId, portGroup);
406 #if DISTRHO_PLUGIN_WANT_PROGRAMS
407 for (uint32_t i=0, count=fData->programCount; i < count; ++i)
408 fPlugin->initProgramName(i, fData->programNames[i]);
409 #endif
411 #if DISTRHO_PLUGIN_WANT_STATE
412 for (uint32_t i=0, count=fData->stateCount; i < count; ++i)
413 fPlugin->initState(i, fData->states[i]);
414 #endif
416 fData->callbacksPtr = callbacksPtr;
417 fData->writeMidiCallbackFunc = writeMidiCall;
418 fData->requestParameterValueChangeCallbackFunc = requestParameterValueChangeCall;
419 fData->updateStateValueCallbackFunc = updateStateValueCall;
422 ~PluginExporter()
424 delete fPlugin;
427 // -------------------------------------------------------------------
429 const char* getName() const noexcept
431 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
433 return fPlugin->getName();
436 const char* getLabel() const noexcept
438 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
440 return fPlugin->getLabel();
443 const char* getDescription() const noexcept
445 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
447 return fPlugin->getDescription();
450 const char* getMaker() const noexcept
452 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
454 return fPlugin->getMaker();
457 const char* getHomePage() const noexcept
459 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
461 return fPlugin->getHomePage();
464 const char* getLicense() const noexcept
466 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
468 return fPlugin->getLicense();
471 uint32_t getVersion() const noexcept
473 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0);
475 return fPlugin->getVersion();
478 long getUniqueId() const noexcept
480 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0);
482 return fPlugin->getUniqueId();
485 void* getInstancePointer() const noexcept
487 return fPlugin;
490 // -------------------------------------------------------------------
492 #if DISTRHO_PLUGIN_WANT_LATENCY
493 uint32_t getLatency() const noexcept
495 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
497 return fData->latency;
499 #endif
501 #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
502 AudioPortWithBusId& getAudioPort(const bool input, const uint32_t index) const noexcept
504 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackAudioPort);
506 if (input)
508 # if DISTRHO_PLUGIN_NUM_INPUTS > 0
509 DISTRHO_SAFE_ASSERT_RETURN(index < DISTRHO_PLUGIN_NUM_INPUTS, sFallbackAudioPort);
510 # endif
512 else
514 # if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
515 DISTRHO_SAFE_ASSERT_RETURN(index < DISTRHO_PLUGIN_NUM_OUTPUTS, sFallbackAudioPort);
516 # endif
519 return fData->audioPorts[index + (input ? 0 : DISTRHO_PLUGIN_NUM_INPUTS)];
522 uint32_t getAudioPortHints(const bool input, const uint32_t index) const noexcept
524 return getAudioPort(input, index).hints;
527 uint32_t getAudioPortCountWithGroupId(const bool input, const uint32_t groupId) const noexcept
529 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
531 uint32_t numPorts = 0;
533 if (input)
535 #if DISTRHO_PLUGIN_NUM_INPUTS > 0
536 for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_INPUTS; ++i)
538 if (fData->audioPorts[i].groupId == groupId)
539 ++numPorts;
541 #endif
543 else
545 #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
546 for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
548 if (fData->audioPorts[i + DISTRHO_PLUGIN_NUM_INPUTS].groupId == groupId)
549 ++numPorts;
551 #endif
554 return numPorts;
556 #endif
558 uint32_t getParameterCount() const noexcept
560 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
562 return fData->parameterCount;
565 uint32_t getParameterOffset() const noexcept
567 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
569 return fData->parameterOffset;
572 uint32_t getParameterHints(const uint32_t index) const noexcept
574 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0x0);
576 return fData->parameters[index].hints;
579 ParameterDesignation getParameterDesignation(const uint32_t index) const noexcept
581 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, kParameterDesignationNull);
583 return fData->parameters[index].designation;
586 bool isParameterInput(const uint32_t index) const noexcept
588 return (getParameterHints(index) & kParameterIsOutput) == 0x0;
591 bool isParameterOutput(const uint32_t index) const noexcept
593 return (getParameterHints(index) & kParameterIsOutput) != 0x0;
596 bool isParameterTrigger(const uint32_t index) const noexcept
598 return (getParameterHints(index) & kParameterIsTrigger) == kParameterIsTrigger;
601 bool isParameterOutputOrTrigger(const uint32_t index) const noexcept
603 const uint32_t hints = getParameterHints(index);
605 if (hints & kParameterIsOutput)
606 return true;
607 if ((hints & kParameterIsTrigger) == kParameterIsTrigger)
608 return true;
610 return false;
613 const String& getParameterName(const uint32_t index) const noexcept
615 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);
617 return fData->parameters[index].name;
620 const String& getParameterShortName(const uint32_t index) const noexcept
622 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);
624 return fData->parameters[index].shortName;
627 const String& getParameterSymbol(const uint32_t index) const noexcept
629 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);
631 return fData->parameters[index].symbol;
634 const String& getParameterUnit(const uint32_t index) const noexcept
636 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);
638 return fData->parameters[index].unit;
641 const String& getParameterDescription(const uint32_t index) const noexcept
643 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);
645 return fData->parameters[index].description;
648 const ParameterEnumerationValues& getParameterEnumValues(const uint32_t index) const noexcept
650 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackEnumValues);
652 return fData->parameters[index].enumValues;
655 const ParameterRanges& getParameterRanges(const uint32_t index) const noexcept
657 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackRanges);
659 return fData->parameters[index].ranges;
662 uint8_t getParameterMidiCC(const uint32_t index) const noexcept
664 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0);
666 return fData->parameters[index].midiCC;
669 uint32_t getParameterGroupId(const uint32_t index) const noexcept
671 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, kPortGroupNone);
673 return fData->parameters[index].groupId;
676 float getParameterDefault(const uint32_t index) const
678 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0.0f);
679 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0.0f);
681 return fData->parameters[index].ranges.def;
684 float getParameterValue(const uint32_t index) const
686 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0.0f);
687 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0.0f);
689 return fPlugin->getParameterValue(index);
692 void setParameterValue(const uint32_t index, const float value)
694 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
695 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount,);
697 fPlugin->setParameterValue(index, value);
700 uint32_t getPortGroupCount() const noexcept
702 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
704 return fData->portGroupCount;
707 const PortGroupWithId& getPortGroupById(const uint32_t groupId) const noexcept
709 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && fData->portGroupCount != 0, sFallbackPortGroup);
711 for (uint32_t i=0; i < fData->portGroupCount; ++i)
713 const PortGroupWithId& portGroup(fData->portGroups[i]);
715 if (portGroup.groupId == groupId)
716 return portGroup;
719 return sFallbackPortGroup;
722 const PortGroupWithId& getPortGroupByIndex(const uint32_t index) const noexcept
724 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->portGroupCount, sFallbackPortGroup);
726 return fData->portGroups[index];
729 const String& getPortGroupSymbolForId(const uint32_t groupId) const noexcept
731 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackString);
733 return getPortGroupById(groupId).symbol;
736 #if DISTRHO_PLUGIN_WANT_PROGRAMS
737 uint32_t getProgramCount() const noexcept
739 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
741 return fData->programCount;
744 const String& getProgramName(const uint32_t index) const noexcept
746 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->programCount, sFallbackString);
748 return fData->programNames[index];
751 void loadProgram(const uint32_t index)
753 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
754 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->programCount,);
756 fPlugin->loadProgram(index);
758 #endif
760 #if DISTRHO_PLUGIN_WANT_STATE
761 uint32_t getStateCount() const noexcept
763 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
765 return fData->stateCount;
768 uint32_t getStateHints(const uint32_t index) const noexcept
770 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, 0x0);
772 return fData->states[index].hints;
775 const String& getStateKey(const uint32_t index) const noexcept
777 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString);
779 return fData->states[index].key;
782 const String& getStateDefaultValue(const uint32_t index) const noexcept
784 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString);
786 return fData->states[index].defaultValue;
789 const String& getStateLabel(const uint32_t index) const noexcept
791 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString);
793 return fData->states[index].label;
796 const String& getStateDescription(const uint32_t index) const noexcept
798 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString);
800 return fData->states[index].description;
803 # if DISTRHO_PLUGIN_WANT_FULL_STATE
804 String getStateValue(const char* const key) const
806 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackString);
807 DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', sFallbackString);
809 return fPlugin->getState(key);
811 # endif
813 void setState(const char* const key, const char* const value)
815 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
816 DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
817 DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,);
819 fPlugin->setState(key, value);
822 bool wantStateKey(const char* const key) const noexcept
824 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, false);
825 DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', false);
827 for (uint32_t i=0; i < fData->stateCount; ++i)
829 if (fData->states[i].key == key)
830 return true;
833 return false;
835 #endif
837 #if DISTRHO_PLUGIN_WANT_TIMEPOS
838 void setTimePosition(const TimePosition& timePosition) noexcept
840 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
842 std::memcpy(&fData->timePosition, &timePosition, sizeof(TimePosition));
844 #endif
846 // -------------------------------------------------------------------
848 bool isActive() const noexcept
850 return fIsActive;
853 void activate()
855 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
856 DISTRHO_SAFE_ASSERT_RETURN(! fIsActive,);
858 fIsActive = true;
859 fPlugin->activate();
862 void deactivate()
864 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
865 DISTRHO_SAFE_ASSERT_RETURN(fIsActive,);
867 fIsActive = false;
868 fPlugin->deactivate();
871 void deactivateIfNeeded()
873 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
875 if (fIsActive)
877 fIsActive = false;
878 fPlugin->deactivate();
882 #if DISTRHO_PLUGIN_WANT_MIDI_INPUT
883 void run(const float** const inputs, float** const outputs, const uint32_t frames,
884 const MidiEvent* const midiEvents, const uint32_t midiEventCount)
886 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
887 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
889 if (! fIsActive)
891 fIsActive = true;
892 fPlugin->activate();
895 fData->isProcessing = true;
896 fPlugin->run(inputs, outputs, frames, midiEvents, midiEventCount);
897 fData->isProcessing = false;
899 #else
900 void run(const float** const inputs, float** const outputs, const uint32_t frames)
902 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
903 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
905 if (! fIsActive)
907 fIsActive = true;
908 fPlugin->activate();
911 fData->isProcessing = true;
912 fPlugin->run(inputs, outputs, frames);
913 fData->isProcessing = false;
915 #endif
917 // -------------------------------------------------------------------
919 uint32_t getBufferSize() const noexcept
921 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
922 return fData->bufferSize;
925 double getSampleRate() const noexcept
927 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0.0);
928 return fData->sampleRate;
931 void setBufferSize(const uint32_t bufferSize, const bool doCallback = false)
933 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
934 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
935 DISTRHO_SAFE_ASSERT(bufferSize >= 2);
937 if (fData->bufferSize == bufferSize)
938 return;
940 fData->bufferSize = bufferSize;
942 if (doCallback)
944 if (fIsActive) fPlugin->deactivate();
945 fPlugin->bufferSizeChanged(bufferSize);
946 if (fIsActive) fPlugin->activate();
950 void setSampleRate(const double sampleRate, const bool doCallback = false)
952 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
953 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
954 DISTRHO_SAFE_ASSERT(sampleRate > 0.0);
956 if (d_isEqual(fData->sampleRate, sampleRate))
957 return;
959 fData->sampleRate = sampleRate;
961 if (doCallback)
963 if (fIsActive) fPlugin->deactivate();
964 fPlugin->sampleRateChanged(sampleRate);
965 if (fIsActive) fPlugin->activate();
969 private:
970 // -------------------------------------------------------------------
971 // Plugin and DistrhoPlugin data
973 Plugin* const fPlugin;
974 Plugin::PrivateData* const fData;
975 bool fIsActive;
977 // -------------------------------------------------------------------
978 // Static fallback data, see DistrhoPlugin.cpp
980 static const String sFallbackString;
981 static /* */ AudioPortWithBusId sFallbackAudioPort;
982 static const ParameterRanges sFallbackRanges;
983 static const ParameterEnumerationValues sFallbackEnumValues;
984 static const PortGroupWithId sFallbackPortGroup;
986 DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginExporter)
989 // -----------------------------------------------------------------------
991 END_NAMESPACE_DISTRHO
993 #endif // DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED