Mercurial > hg > pub > prymula > com
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 |