comparison DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginInternal.hpp @ 3:84e66ea83026

DPF-Prymula-audioplugins-0.231015-2
author prymula <prymula76@outlook.com>
date Mon, 16 Oct 2023 21:53:34 +0200
parents
children
comparison
equal deleted inserted replaced
2:cf2cb71d31dd 3:84e66ea83026
1 /*
2 * DISTRHO Plugin Framework (DPF)
3 * Copyright (C) 2012-2023 Filipe Coelho <falktx@falktx.com>
4 *
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.
8 *
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.
15 */
16
17 #ifndef DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED
18 #define DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED
19
20 #include "../DistrhoPlugin.hpp"
21
22 #ifdef DISTRHO_PLUGIN_TARGET_VST3
23 # include "DistrhoPluginVST.hpp"
24 #endif
25
26 #include <set>
27
28 START_NAMESPACE_DISTRHO
29
30 // -----------------------------------------------------------------------
31 // Maxmimum values
32
33 static const uint32_t kMaxMidiEvents = 512;
34
35 // -----------------------------------------------------------------------
36 // Static data, see DistrhoPlugin.cpp
37
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_nextPluginIsSelfTest;
43 extern bool d_nextCanRequestParameterValueChanges;
44
45 // -----------------------------------------------------------------------
46 // DSP callbacks
47
48 typedef bool (*writeMidiFunc) (void* ptr, const MidiEvent& midiEvent);
49 typedef bool (*requestParameterValueChangeFunc) (void* ptr, uint32_t index, float value);
50 typedef bool (*updateStateValueFunc) (void* ptr, const char* key, const char* value);
51
52 // -----------------------------------------------------------------------
53 // Helpers
54
55 struct AudioPortWithBusId : AudioPort {
56 uint32_t busId;
57
58 AudioPortWithBusId()
59 : AudioPort(),
60 busId(0) {}
61 };
62
63 struct PortGroupWithId : PortGroup {
64 uint32_t groupId;
65
66 PortGroupWithId()
67 : PortGroup(),
68 groupId(kPortGroupNone) {}
69 };
70
71 static inline
72 void fillInPredefinedPortGroupData(const uint32_t groupId, PortGroup& portGroup)
73 {
74 switch (groupId)
75 {
76 case kPortGroupNone:
77 portGroup.name.clear();
78 portGroup.symbol.clear();
79 break;
80 case kPortGroupMono:
81 portGroup.name = "Mono";
82 portGroup.symbol = "dpf_mono";
83 break;
84 case kPortGroupStereo:
85 portGroup.name = "Stereo";
86 portGroup.symbol = "dpf_stereo";
87 break;
88 }
89 }
90
91 static inline
92 void d_strncpy(char* const dst, const char* const src, const size_t length)
93 {
94 DISTRHO_SAFE_ASSERT_RETURN(length > 0,);
95
96 if (const size_t len = std::min(std::strlen(src), length-1U))
97 {
98 std::memcpy(dst, src, len);
99 dst[len] = '\0';
100 }
101 else
102 {
103 dst[0] = '\0';
104 }
105 }
106
107 template<typename T>
108 static inline
109 void snprintf_t(char* const dst, const T value, const char* const format, const size_t size)
110 {
111 DISTRHO_SAFE_ASSERT_RETURN(size > 0,);
112 std::snprintf(dst, size-1, format, value);
113 dst[size-1] = '\0';
114 }
115
116 static inline
117 void snprintf_f32(char* const dst, const float value, const size_t size)
118 {
119 return snprintf_t<float>(dst, value, "%f", size);
120 }
121
122 static inline
123 void snprintf_f32(char* const dst, const double value, const size_t size)
124 {
125 return snprintf_t<double>(dst, value, "%f", size);
126 }
127
128 static inline
129 void snprintf_i32(char* const dst, const int32_t value, const size_t size)
130 {
131 return snprintf_t<int32_t>(dst, value, "%d", size);
132 }
133
134 static inline
135 void snprintf_u32(char* const dst, const uint32_t value, const size_t size)
136 {
137 return snprintf_t<uint32_t>(dst, value, "%u", size);
138 }
139
140 // -----------------------------------------------------------------------
141 // Plugin private data
142
143 struct Plugin::PrivateData {
144 const bool canRequestParameterValueChanges;
145 const bool isDummy;
146 const bool isSelfTest;
147 bool isProcessing;
148
149 #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
150 AudioPortWithBusId* audioPorts;
151 #endif
152
153 uint32_t parameterCount;
154 uint32_t parameterOffset;
155 Parameter* parameters;
156
157 uint32_t portGroupCount;
158 PortGroupWithId* portGroups;
159
160 #if DISTRHO_PLUGIN_WANT_PROGRAMS
161 uint32_t programCount;
162 String* programNames;
163 #endif
164
165 #if DISTRHO_PLUGIN_WANT_STATE
166 uint32_t stateCount;
167 State* states;
168 #endif
169
170 #if DISTRHO_PLUGIN_WANT_LATENCY
171 uint32_t latency;
172 #endif
173
174 #if DISTRHO_PLUGIN_WANT_TIMEPOS
175 TimePosition timePosition;
176 #endif
177
178 // Callbacks
179 void* callbacksPtr;
180 writeMidiFunc writeMidiCallbackFunc;
181 requestParameterValueChangeFunc requestParameterValueChangeCallbackFunc;
182 updateStateValueFunc updateStateValueCallbackFunc;
183
184 uint32_t bufferSize;
185 double sampleRate;
186 char* bundlePath;
187
188 PrivateData() noexcept
189 : canRequestParameterValueChanges(d_nextCanRequestParameterValueChanges),
190 isDummy(d_nextPluginIsDummy),
191 isSelfTest(d_nextPluginIsSelfTest),
192 isProcessing(false),
193 #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
194 audioPorts(nullptr),
195 #endif
196 parameterCount(0),
197 parameterOffset(0),
198 parameters(nullptr),
199 portGroupCount(0),
200 portGroups(nullptr),
201 #if DISTRHO_PLUGIN_WANT_PROGRAMS
202 programCount(0),
203 programNames(nullptr),
204 #endif
205 #if DISTRHO_PLUGIN_WANT_STATE
206 stateCount(0),
207 states(nullptr),
208 #endif
209 #if DISTRHO_PLUGIN_WANT_LATENCY
210 latency(0),
211 #endif
212 callbacksPtr(nullptr),
213 writeMidiCallbackFunc(nullptr),
214 requestParameterValueChangeCallbackFunc(nullptr),
215 updateStateValueCallbackFunc(nullptr),
216 bufferSize(d_nextBufferSize),
217 sampleRate(d_nextSampleRate),
218 bundlePath(d_nextBundlePath != nullptr ? strdup(d_nextBundlePath) : nullptr)
219 {
220 DISTRHO_SAFE_ASSERT(bufferSize != 0);
221 DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate));
222
223 #if defined(DISTRHO_PLUGIN_TARGET_DSSI) || defined(DISTRHO_PLUGIN_TARGET_LV2)
224 parameterOffset += DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS;
225 # if DISTRHO_PLUGIN_WANT_LATENCY
226 parameterOffset += 1;
227 # endif
228 #endif
229
230 #ifdef DISTRHO_PLUGIN_TARGET_LV2
231 # if (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_STATE || DISTRHO_PLUGIN_WANT_TIMEPOS)
232 parameterOffset += 1;
233 # endif
234 # if (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || DISTRHO_PLUGIN_WANT_STATE)
235 parameterOffset += 1;
236 # endif
237 #endif
238
239 #ifdef DISTRHO_PLUGIN_TARGET_VST3
240 parameterOffset += kVst3InternalParameterCount;
241 #endif
242 }
243
244 ~PrivateData() noexcept
245 {
246 #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
247 if (audioPorts != nullptr)
248 {
249 delete[] audioPorts;
250 audioPorts = nullptr;
251 }
252 #endif
253
254 if (parameters != nullptr)
255 {
256 delete[] parameters;
257 parameters = nullptr;
258 }
259
260 if (portGroups != nullptr)
261 {
262 delete[] portGroups;
263 portGroups = nullptr;
264 }
265
266 #if DISTRHO_PLUGIN_WANT_PROGRAMS
267 if (programNames != nullptr)
268 {
269 delete[] programNames;
270 programNames = nullptr;
271 }
272 #endif
273
274 #if DISTRHO_PLUGIN_WANT_STATE
275 if (states != nullptr)
276 {
277 delete[] states;
278 states = nullptr;
279 }
280 #endif
281
282 if (bundlePath != nullptr)
283 {
284 std::free(bundlePath);
285 bundlePath = nullptr;
286 }
287 }
288
289 #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
290 bool writeMidiCallback(const MidiEvent& midiEvent)
291 {
292 if (writeMidiCallbackFunc != nullptr)
293 return writeMidiCallbackFunc(callbacksPtr, midiEvent);
294
295 return false;
296 }
297 #endif
298
299 #if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST
300 bool requestParameterValueChangeCallback(const uint32_t index, const float value)
301 {
302 if (requestParameterValueChangeCallbackFunc != nullptr)
303 return requestParameterValueChangeCallbackFunc(callbacksPtr, index, value);
304
305 return false;
306 }
307 #endif
308
309 #if DISTRHO_PLUGIN_WANT_STATE
310 bool updateStateValueCallback(const char* const key, const char* const value)
311 {
312 d_stdout("updateStateValueCallback %p", updateStateValueCallbackFunc);
313 if (updateStateValueCallbackFunc != nullptr)
314 return updateStateValueCallbackFunc(callbacksPtr, key, value);
315
316 return false;
317 }
318 #endif
319 };
320
321 // -----------------------------------------------------------------------
322 // Plugin exporter class
323
324 class PluginExporter
325 {
326 public:
327 PluginExporter(void* const callbacksPtr,
328 const writeMidiFunc writeMidiCall,
329 const requestParameterValueChangeFunc requestParameterValueChangeCall,
330 const updateStateValueFunc updateStateValueCall)
331 : fPlugin(createPlugin()),
332 fData((fPlugin != nullptr) ? fPlugin->pData : nullptr),
333 fIsActive(false)
334 {
335 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
336 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
337
338 #if defined(DPF_RUNTIME_TESTING) && defined(__GNUC__) && !defined(__clang__)
339 /* Run-time testing build.
340 * Verify that virtual functions are overriden if parameters, programs or states are in use.
341 * This does not work on all compilers, but we use it purely as informational check anyway. */
342 if (fData->parameterCount != 0)
343 {
344 if ((void*)(fPlugin->*(&Plugin::initParameter)) == (void*)&Plugin::initParameter)
345 {
346 d_stderr2("DPF warning: Plugins with parameters must implement `initParameter`");
347 abort();
348 }
349 if ((void*)(fPlugin->*(&Plugin::getParameterValue)) == (void*)&Plugin::getParameterValue)
350 {
351 d_stderr2("DPF warning: Plugins with parameters must implement `getParameterValue`");
352 abort();
353 }
354 if ((void*)(fPlugin->*(&Plugin::setParameterValue)) == (void*)&Plugin::setParameterValue)
355 {
356 d_stderr2("DPF warning: Plugins with parameters must implement `setParameterValue`");
357 abort();
358 }
359 }
360
361 # if DISTRHO_PLUGIN_WANT_PROGRAMS
362 if (fData->programCount != 0)
363 {
364 if ((void*)(fPlugin->*(&Plugin::initProgramName)) == (void*)&Plugin::initProgramName)
365 {
366 d_stderr2("DPF warning: Plugins with programs must implement `initProgramName`");
367 abort();
368 }
369 if ((void*)(fPlugin->*(&Plugin::loadProgram)) == (void*)&Plugin::loadProgram)
370 {
371 d_stderr2("DPF warning: Plugins with programs must implement `loadProgram`");
372 abort();
373 }
374 }
375 # endif
376
377 # if DISTRHO_PLUGIN_WANT_STATE
378 if (fData->stateCount != 0)
379 {
380 if ((void*)(fPlugin->*(static_cast<void(Plugin::*)(uint32_t,State&)>(&Plugin::initState))) ==
381 (void*)static_cast<void(Plugin::*)(uint32_t,State&)>(&Plugin::initState))
382 {
383 d_stderr2("DPF warning: Plugins with state must implement `initState`");
384 abort();
385 }
386
387 if ((void*)(fPlugin->*(&Plugin::setState)) == (void*)&Plugin::setState)
388 {
389 d_stderr2("DPF warning: Plugins with state must implement `setState`");
390 abort();
391 }
392 }
393 # endif
394
395 # if DISTRHO_PLUGIN_WANT_FULL_STATE
396 if (fData->stateCount != 0)
397 {
398 if ((void*)(fPlugin->*(&Plugin::getState)) == (void*)&Plugin::getState)
399 {
400 d_stderr2("DPF warning: Plugins with full state must implement `getState`");
401 abort();
402 }
403 }
404 else
405 {
406 d_stderr2("DPF warning: Plugins with full state must have at least 1 state");
407 abort();
408 }
409 # endif
410 #endif
411
412 #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
413 {
414 uint32_t j=0;
415 # if DISTRHO_PLUGIN_NUM_INPUTS > 0
416 for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++j)
417 fPlugin->initAudioPort(true, i, fData->audioPorts[j]);
418 # endif
419 # if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
420 for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++j)
421 fPlugin->initAudioPort(false, i, fData->audioPorts[j]);
422 # endif
423 }
424 #endif // DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
425
426 for (uint32_t i=0, count=fData->parameterCount; i < count; ++i)
427 fPlugin->initParameter(i, fData->parameters[i]);
428
429 {
430 std::set<uint32_t> portGroupIndices;
431
432 #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
433 for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
434 portGroupIndices.insert(fData->audioPorts[i].groupId);
435 #endif
436 for (uint32_t i=0, count=fData->parameterCount; i < count; ++i)
437 portGroupIndices.insert(fData->parameters[i].groupId);
438
439 portGroupIndices.erase(kPortGroupNone);
440
441 if (const uint32_t portGroupSize = static_cast<uint32_t>(portGroupIndices.size()))
442 {
443 fData->portGroups = new PortGroupWithId[portGroupSize];
444 fData->portGroupCount = portGroupSize;
445
446 uint32_t index = 0;
447 for (std::set<uint32_t>::iterator it = portGroupIndices.begin(); it != portGroupIndices.end(); ++it, ++index)
448 {
449 PortGroupWithId& portGroup(fData->portGroups[index]);
450 portGroup.groupId = *it;
451
452 if (portGroup.groupId < portGroupSize)
453 fPlugin->initPortGroup(portGroup.groupId, portGroup);
454 else
455 fillInPredefinedPortGroupData(portGroup.groupId, portGroup);
456 }
457 }
458 }
459
460 #if DISTRHO_PLUGIN_WANT_PROGRAMS
461 for (uint32_t i=0, count=fData->programCount; i < count; ++i)
462 fPlugin->initProgramName(i, fData->programNames[i]);
463 #endif
464
465 #if DISTRHO_PLUGIN_WANT_STATE
466 for (uint32_t i=0, count=fData->stateCount; i < count; ++i)
467 fPlugin->initState(i, fData->states[i]);
468 #endif
469
470 fData->callbacksPtr = callbacksPtr;
471 fData->writeMidiCallbackFunc = writeMidiCall;
472 fData->requestParameterValueChangeCallbackFunc = requestParameterValueChangeCall;
473 fData->updateStateValueCallbackFunc = updateStateValueCall;
474 }
475
476 ~PluginExporter()
477 {
478 delete fPlugin;
479 }
480
481 // -------------------------------------------------------------------
482
483 const char* getName() const noexcept
484 {
485 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
486
487 return fPlugin->getName();
488 }
489
490 const char* getLabel() const noexcept
491 {
492 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
493
494 return fPlugin->getLabel();
495 }
496
497 const char* getDescription() const noexcept
498 {
499 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
500
501 return fPlugin->getDescription();
502 }
503
504 const char* getMaker() const noexcept
505 {
506 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
507
508 return fPlugin->getMaker();
509 }
510
511 const char* getHomePage() const noexcept
512 {
513 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
514
515 return fPlugin->getHomePage();
516 }
517
518 const char* getLicense() const noexcept
519 {
520 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
521
522 return fPlugin->getLicense();
523 }
524
525 uint32_t getVersion() const noexcept
526 {
527 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0);
528
529 return fPlugin->getVersion();
530 }
531
532 long getUniqueId() const noexcept
533 {
534 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0);
535
536 return fPlugin->getUniqueId();
537 }
538
539 void* getInstancePointer() const noexcept
540 {
541 return fPlugin;
542 }
543
544 // -------------------------------------------------------------------
545
546 #if DISTRHO_PLUGIN_WANT_LATENCY
547 uint32_t getLatency() const noexcept
548 {
549 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
550
551 return fData->latency;
552 }
553 #endif
554
555 #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
556 AudioPortWithBusId& getAudioPort(const bool input, const uint32_t index) const noexcept
557 {
558 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackAudioPort);
559
560 if (input)
561 {
562 # if DISTRHO_PLUGIN_NUM_INPUTS > 0
563 DISTRHO_SAFE_ASSERT_RETURN(index < DISTRHO_PLUGIN_NUM_INPUTS, sFallbackAudioPort);
564 # endif
565 }
566 else
567 {
568 # if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
569 DISTRHO_SAFE_ASSERT_RETURN(index < DISTRHO_PLUGIN_NUM_OUTPUTS, sFallbackAudioPort);
570 # endif
571 }
572
573 return fData->audioPorts[index + (input ? 0 : DISTRHO_PLUGIN_NUM_INPUTS)];
574 }
575
576 uint32_t getAudioPortHints(const bool input, const uint32_t index) const noexcept
577 {
578 return getAudioPort(input, index).hints;
579 }
580
581 uint32_t getAudioPortCountWithGroupId(const bool input, const uint32_t groupId) const noexcept
582 {
583 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
584
585 uint32_t numPorts = 0;
586
587 if (input)
588 {
589 #if DISTRHO_PLUGIN_NUM_INPUTS > 0
590 for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_INPUTS; ++i)
591 {
592 if (fData->audioPorts[i].groupId == groupId)
593 ++numPorts;
594 }
595 #endif
596 }
597 else
598 {
599 #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
600 for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
601 {
602 if (fData->audioPorts[i + DISTRHO_PLUGIN_NUM_INPUTS].groupId == groupId)
603 ++numPorts;
604 }
605 #endif
606 }
607
608 return numPorts;
609 }
610 #endif
611
612 uint32_t getParameterCount() const noexcept
613 {
614 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
615
616 return fData->parameterCount;
617 }
618
619 uint32_t getParameterOffset() const noexcept
620 {
621 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
622
623 return fData->parameterOffset;
624 }
625
626 uint32_t getParameterHints(const uint32_t index) const noexcept
627 {
628 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0x0);
629
630 return fData->parameters[index].hints;
631 }
632
633 ParameterDesignation getParameterDesignation(const uint32_t index) const noexcept
634 {
635 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, kParameterDesignationNull);
636
637 return fData->parameters[index].designation;
638 }
639
640 bool isParameterInput(const uint32_t index) const noexcept
641 {
642 return (getParameterHints(index) & kParameterIsOutput) == 0x0;
643 }
644
645 bool isParameterOutput(const uint32_t index) const noexcept
646 {
647 return (getParameterHints(index) & kParameterIsOutput) != 0x0;
648 }
649
650 bool isParameterInteger(const uint32_t index) const noexcept
651 {
652 return (getParameterHints(index) & kParameterIsInteger) != 0x0;
653 }
654
655 bool isParameterTrigger(const uint32_t index) const noexcept
656 {
657 return (getParameterHints(index) & kParameterIsTrigger) == kParameterIsTrigger;
658 }
659
660 bool isParameterOutputOrTrigger(const uint32_t index) const noexcept
661 {
662 const uint32_t hints = getParameterHints(index);
663
664 if (hints & kParameterIsOutput)
665 return true;
666 if ((hints & kParameterIsTrigger) == kParameterIsTrigger)
667 return true;
668
669 return false;
670 }
671
672 const String& getParameterName(const uint32_t index) const noexcept
673 {
674 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);
675
676 return fData->parameters[index].name;
677 }
678
679 const String& getParameterShortName(const uint32_t index) const noexcept
680 {
681 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);
682
683 return fData->parameters[index].shortName;
684 }
685
686 const String& getParameterSymbol(const uint32_t index) const noexcept
687 {
688 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);
689
690 return fData->parameters[index].symbol;
691 }
692
693 const String& getParameterUnit(const uint32_t index) const noexcept
694 {
695 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);
696
697 return fData->parameters[index].unit;
698 }
699
700 const String& getParameterDescription(const uint32_t index) const noexcept
701 {
702 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);
703
704 return fData->parameters[index].description;
705 }
706
707 const ParameterEnumerationValues& getParameterEnumValues(const uint32_t index) const noexcept
708 {
709 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackEnumValues);
710
711 return fData->parameters[index].enumValues;
712 }
713
714 const ParameterRanges& getParameterRanges(const uint32_t index) const noexcept
715 {
716 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackRanges);
717
718 return fData->parameters[index].ranges;
719 }
720
721 uint8_t getParameterMidiCC(const uint32_t index) const noexcept
722 {
723 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0);
724
725 return fData->parameters[index].midiCC;
726 }
727
728 uint32_t getParameterGroupId(const uint32_t index) const noexcept
729 {
730 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, kPortGroupNone);
731
732 return fData->parameters[index].groupId;
733 }
734
735 float getParameterDefault(const uint32_t index) const
736 {
737 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0.0f);
738 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0.0f);
739
740 return fData->parameters[index].ranges.def;
741 }
742
743 float getParameterValue(const uint32_t index) const
744 {
745 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0.0f);
746 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0.0f);
747
748 return fPlugin->getParameterValue(index);
749 }
750
751 void setParameterValue(const uint32_t index, const float value)
752 {
753 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
754 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount,);
755
756 fPlugin->setParameterValue(index, value);
757 }
758
759 uint32_t getPortGroupCount() const noexcept
760 {
761 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
762
763 return fData->portGroupCount;
764 }
765
766 const PortGroupWithId& getPortGroupById(const uint32_t groupId) const noexcept
767 {
768 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && fData->portGroupCount != 0, sFallbackPortGroup);
769
770 for (uint32_t i=0; i < fData->portGroupCount; ++i)
771 {
772 const PortGroupWithId& portGroup(fData->portGroups[i]);
773
774 if (portGroup.groupId == groupId)
775 return portGroup;
776 }
777
778 return sFallbackPortGroup;
779 }
780
781 const PortGroupWithId& getPortGroupByIndex(const uint32_t index) const noexcept
782 {
783 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->portGroupCount, sFallbackPortGroup);
784
785 return fData->portGroups[index];
786 }
787
788 const String& getPortGroupSymbolForId(const uint32_t groupId) const noexcept
789 {
790 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackString);
791
792 return getPortGroupById(groupId).symbol;
793 }
794
795 #if DISTRHO_PLUGIN_WANT_PROGRAMS
796 uint32_t getProgramCount() const noexcept
797 {
798 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
799
800 return fData->programCount;
801 }
802
803 const String& getProgramName(const uint32_t index) const noexcept
804 {
805 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->programCount, sFallbackString);
806
807 return fData->programNames[index];
808 }
809
810 void loadProgram(const uint32_t index)
811 {
812 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
813 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->programCount,);
814
815 fPlugin->loadProgram(index);
816 }
817 #endif
818
819 #if DISTRHO_PLUGIN_WANT_STATE
820 uint32_t getStateCount() const noexcept
821 {
822 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
823
824 return fData->stateCount;
825 }
826
827 uint32_t getStateHints(const uint32_t index) const noexcept
828 {
829 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, 0x0);
830
831 return fData->states[index].hints;
832 }
833
834 const String& getStateKey(const uint32_t index) const noexcept
835 {
836 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString);
837
838 return fData->states[index].key;
839 }
840
841 const String& getStateDefaultValue(const uint32_t index) const noexcept
842 {
843 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString);
844
845 return fData->states[index].defaultValue;
846 }
847
848 const String& getStateLabel(const uint32_t index) const noexcept
849 {
850 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString);
851
852 return fData->states[index].label;
853 }
854
855 const String& getStateDescription(const uint32_t index) const noexcept
856 {
857 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString);
858
859 return fData->states[index].description;
860 }
861
862 #ifdef __MOD_DEVICES__
863 const String& getStateFileTypes(const uint32_t index) const noexcept
864 {
865 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString);
866
867 return fData->states[index].fileTypes;
868 }
869 #endif
870
871 # if DISTRHO_PLUGIN_WANT_FULL_STATE
872 String getStateValue(const char* const key) const
873 {
874 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackString);
875 DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', sFallbackString);
876
877 return fPlugin->getState(key);
878 }
879 # endif
880
881 void setState(const char* const key, const char* const value)
882 {
883 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
884 DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
885 DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,);
886
887 fPlugin->setState(key, value);
888 }
889
890 bool wantStateKey(const char* const key) const noexcept
891 {
892 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, false);
893 DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', false);
894
895 for (uint32_t i=0; i < fData->stateCount; ++i)
896 {
897 if (fData->states[i].key == key)
898 return true;
899 }
900
901 return false;
902 }
903 #endif
904
905 #if DISTRHO_PLUGIN_WANT_TIMEPOS
906 void setTimePosition(const TimePosition& timePosition) noexcept
907 {
908 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
909
910 std::memcpy(&fData->timePosition, &timePosition, sizeof(TimePosition));
911 }
912 #endif
913
914 // -------------------------------------------------------------------
915
916 bool isActive() const noexcept
917 {
918 return fIsActive;
919 }
920
921 void activate()
922 {
923 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
924 DISTRHO_SAFE_ASSERT_RETURN(! fIsActive,);
925
926 fIsActive = true;
927 fPlugin->activate();
928 }
929
930 void deactivate()
931 {
932 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
933 DISTRHO_SAFE_ASSERT_RETURN(fIsActive,);
934
935 fIsActive = false;
936 fPlugin->deactivate();
937 }
938
939 void deactivateIfNeeded()
940 {
941 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
942
943 if (fIsActive)
944 {
945 fIsActive = false;
946 fPlugin->deactivate();
947 }
948 }
949
950 #if DISTRHO_PLUGIN_WANT_MIDI_INPUT
951 void run(const float** const inputs, float** const outputs, const uint32_t frames,
952 const MidiEvent* const midiEvents, const uint32_t midiEventCount)
953 {
954 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
955 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
956
957 if (! fIsActive)
958 {
959 fIsActive = true;
960 fPlugin->activate();
961 }
962
963 fData->isProcessing = true;
964 fPlugin->run(inputs, outputs, frames, midiEvents, midiEventCount);
965 fData->isProcessing = false;
966 }
967 #else
968 void run(const float** const inputs, float** const outputs, const uint32_t frames)
969 {
970 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
971 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
972
973 if (! fIsActive)
974 {
975 fIsActive = true;
976 fPlugin->activate();
977 }
978
979 fData->isProcessing = true;
980 fPlugin->run(inputs, outputs, frames);
981 fData->isProcessing = false;
982 }
983 #endif
984
985 // -------------------------------------------------------------------
986
987 uint32_t getBufferSize() const noexcept
988 {
989 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
990 return fData->bufferSize;
991 }
992
993 double getSampleRate() const noexcept
994 {
995 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0.0);
996 return fData->sampleRate;
997 }
998
999 void setBufferSize(const uint32_t bufferSize, const bool doCallback = false)
1000 {
1001 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
1002 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
1003 DISTRHO_SAFE_ASSERT(bufferSize >= 2);
1004
1005 if (fData->bufferSize == bufferSize)
1006 return;
1007
1008 fData->bufferSize = bufferSize;
1009
1010 if (doCallback)
1011 {
1012 if (fIsActive) fPlugin->deactivate();
1013 fPlugin->bufferSizeChanged(bufferSize);
1014 if (fIsActive) fPlugin->activate();
1015 }
1016 }
1017
1018 void setSampleRate(const double sampleRate, const bool doCallback = false)
1019 {
1020 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
1021 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
1022 DISTRHO_SAFE_ASSERT(sampleRate > 0.0);
1023
1024 if (d_isEqual(fData->sampleRate, sampleRate))
1025 return;
1026
1027 fData->sampleRate = sampleRate;
1028
1029 if (doCallback)
1030 {
1031 if (fIsActive) fPlugin->deactivate();
1032 fPlugin->sampleRateChanged(sampleRate);
1033 if (fIsActive) fPlugin->activate();
1034 }
1035 }
1036
1037 private:
1038 // -------------------------------------------------------------------
1039 // Plugin and DistrhoPlugin data
1040
1041 Plugin* const fPlugin;
1042 Plugin::PrivateData* const fData;
1043 bool fIsActive;
1044
1045 // -------------------------------------------------------------------
1046 // Static fallback data, see DistrhoPlugin.cpp
1047
1048 static const String sFallbackString;
1049 static /* */ AudioPortWithBusId sFallbackAudioPort;
1050 static const ParameterRanges sFallbackRanges;
1051 static const ParameterEnumerationValues sFallbackEnumValues;
1052 static const PortGroupWithId sFallbackPortGroup;
1053
1054 DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginExporter)
1055 };
1056
1057 // -----------------------------------------------------------------------
1058
1059 END_NAMESPACE_DISTRHO
1060
1061 #endif // DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED