DistrhoPluginInternal.hpp (32620B)
1 /* 2 * DISTRHO Plugin Framework (DPF) 3 * Copyright (C) 2012-2024 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 /* 760 bool getParameterIndexForSymbol(const char* const symbol, uint32_t& index) 761 { 762 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, false); 763 764 for (uint32_t i=0; i < fData->parameterCount; ++i) 765 { 766 if (fData->parameters[i].symbol == symbol) 767 { 768 index = i; 769 return true; 770 } 771 } 772 773 return false; 774 } 775 */ 776 777 uint32_t getPortGroupCount() const noexcept 778 { 779 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); 780 781 return fData->portGroupCount; 782 } 783 784 const PortGroupWithId& getPortGroupById(const uint32_t groupId) const noexcept 785 { 786 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && fData->portGroupCount != 0, sFallbackPortGroup); 787 788 for (uint32_t i=0; i < fData->portGroupCount; ++i) 789 { 790 const PortGroupWithId& portGroup(fData->portGroups[i]); 791 792 if (portGroup.groupId == groupId) 793 return portGroup; 794 } 795 796 return sFallbackPortGroup; 797 } 798 799 const PortGroupWithId& getPortGroupByIndex(const uint32_t index) const noexcept 800 { 801 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->portGroupCount, sFallbackPortGroup); 802 803 return fData->portGroups[index]; 804 } 805 806 const String& getPortGroupSymbolForId(const uint32_t groupId) const noexcept 807 { 808 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackString); 809 810 return getPortGroupById(groupId).symbol; 811 } 812 813 #if DISTRHO_PLUGIN_WANT_PROGRAMS 814 uint32_t getProgramCount() const noexcept 815 { 816 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); 817 818 return fData->programCount; 819 } 820 821 const String& getProgramName(const uint32_t index) const noexcept 822 { 823 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->programCount, sFallbackString); 824 825 return fData->programNames[index]; 826 } 827 828 void loadProgram(const uint32_t index) 829 { 830 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); 831 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->programCount,); 832 833 fPlugin->loadProgram(index); 834 } 835 #endif 836 837 #if DISTRHO_PLUGIN_WANT_STATE 838 uint32_t getStateCount() const noexcept 839 { 840 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); 841 842 return fData->stateCount; 843 } 844 845 uint32_t getStateHints(const uint32_t index) const noexcept 846 { 847 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, 0x0); 848 849 return fData->states[index].hints; 850 } 851 852 const String& getStateKey(const uint32_t index) const noexcept 853 { 854 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString); 855 856 return fData->states[index].key; 857 } 858 859 const String& getStateDefaultValue(const uint32_t index) const noexcept 860 { 861 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString); 862 863 return fData->states[index].defaultValue; 864 } 865 866 const String& getStateLabel(const uint32_t index) const noexcept 867 { 868 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString); 869 870 return fData->states[index].label; 871 } 872 873 const String& getStateDescription(const uint32_t index) const noexcept 874 { 875 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString); 876 877 return fData->states[index].description; 878 } 879 880 #ifdef __MOD_DEVICES__ 881 const String& getStateFileTypes(const uint32_t index) const noexcept 882 { 883 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString); 884 885 return fData->states[index].fileTypes; 886 } 887 #endif 888 889 #if DISTRHO_PLUGIN_WANT_FULL_STATE 890 String getStateValue(const char* const key) const 891 { 892 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackString); 893 DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', sFallbackString); 894 895 return fPlugin->getState(key); 896 } 897 #endif 898 899 void setState(const char* const key, const char* const value) 900 { 901 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); 902 DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); 903 DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,); 904 905 fPlugin->setState(key, value); 906 } 907 908 bool wantStateKey(const char* const key) const noexcept 909 { 910 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, false); 911 DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', false); 912 913 for (uint32_t i=0; i < fData->stateCount; ++i) 914 { 915 if (fData->states[i].key == key) 916 return true; 917 } 918 919 return false; 920 } 921 #endif 922 923 #if DISTRHO_PLUGIN_WANT_TIMEPOS 924 void setTimePosition(const TimePosition& timePosition) noexcept 925 { 926 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); 927 928 std::memcpy(&fData->timePosition, &timePosition, sizeof(TimePosition)); 929 } 930 #endif 931 932 // ------------------------------------------------------------------- 933 934 bool isActive() const noexcept 935 { 936 return fIsActive; 937 } 938 939 void activate() 940 { 941 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); 942 DISTRHO_SAFE_ASSERT_RETURN(! fIsActive,); 943 944 fIsActive = true; 945 fPlugin->activate(); 946 } 947 948 void deactivate() 949 { 950 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); 951 DISTRHO_SAFE_ASSERT_RETURN(fIsActive,); 952 953 fIsActive = false; 954 fPlugin->deactivate(); 955 } 956 957 void deactivateIfNeeded() 958 { 959 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); 960 961 if (fIsActive) 962 { 963 fIsActive = false; 964 fPlugin->deactivate(); 965 } 966 } 967 968 #if DISTRHO_PLUGIN_WANT_MIDI_INPUT 969 void run(const float** const inputs, float** const outputs, const uint32_t frames, 970 const MidiEvent* const midiEvents, const uint32_t midiEventCount) 971 { 972 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); 973 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); 974 975 if (! fIsActive) 976 { 977 fIsActive = true; 978 fPlugin->activate(); 979 } 980 981 fData->isProcessing = true; 982 fPlugin->run(inputs, outputs, frames, midiEvents, midiEventCount); 983 fData->isProcessing = false; 984 } 985 #else 986 void run(const float** const inputs, float** const outputs, const uint32_t frames) 987 { 988 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); 989 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); 990 991 if (! fIsActive) 992 { 993 fIsActive = true; 994 fPlugin->activate(); 995 } 996 997 fData->isProcessing = true; 998 fPlugin->run(inputs, outputs, frames); 999 fData->isProcessing = false; 1000 } 1001 #endif 1002 1003 // ------------------------------------------------------------------- 1004 1005 #ifdef DISTRHO_PLUGIN_TARGET_AU 1006 void setAudioPortIO(const uint16_t numInputs, const uint16_t numOutputs) 1007 { 1008 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); 1009 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); 1010 1011 if (fIsActive) fPlugin->deactivate(); 1012 fPlugin->ioChanged(numInputs, numOutputs); 1013 if (fIsActive) fPlugin->activate(); 1014 } 1015 #endif 1016 1017 // ------------------------------------------------------------------- 1018 1019 uint32_t getBufferSize() const noexcept 1020 { 1021 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); 1022 return fData->bufferSize; 1023 } 1024 1025 double getSampleRate() const noexcept 1026 { 1027 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0.0); 1028 return fData->sampleRate; 1029 } 1030 1031 bool setBufferSize(const uint32_t bufferSize, const bool doCallback = false) 1032 { 1033 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, false); 1034 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, false); 1035 DISTRHO_SAFE_ASSERT(bufferSize >= 2); 1036 1037 if (fData->bufferSize == bufferSize) 1038 return false; 1039 1040 fData->bufferSize = bufferSize; 1041 1042 if (doCallback) 1043 { 1044 if (fIsActive) fPlugin->deactivate(); 1045 fPlugin->bufferSizeChanged(bufferSize); 1046 if (fIsActive) fPlugin->activate(); 1047 } 1048 1049 return true; 1050 } 1051 1052 void setSampleRate(const double sampleRate, const bool doCallback = false) 1053 { 1054 DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); 1055 DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); 1056 DISTRHO_SAFE_ASSERT(sampleRate > 0.0); 1057 1058 if (d_isEqual(fData->sampleRate, sampleRate)) 1059 return; 1060 1061 fData->sampleRate = sampleRate; 1062 1063 if (doCallback) 1064 { 1065 if (fIsActive) fPlugin->deactivate(); 1066 fPlugin->sampleRateChanged(sampleRate); 1067 if (fIsActive) fPlugin->activate(); 1068 } 1069 } 1070 1071 private: 1072 // ------------------------------------------------------------------- 1073 // Plugin and DistrhoPlugin data 1074 1075 Plugin* const fPlugin; 1076 Plugin::PrivateData* const fData; 1077 bool fIsActive; 1078 1079 // ------------------------------------------------------------------- 1080 // Static fallback data, see DistrhoPlugin.cpp 1081 1082 static const String sFallbackString; 1083 static /* */ AudioPortWithBusId sFallbackAudioPort; 1084 static const ParameterRanges sFallbackRanges; 1085 static const ParameterEnumerationValues sFallbackEnumValues; 1086 static const PortGroupWithId sFallbackPortGroup; 1087 1088 DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginExporter) 1089 }; 1090 1091 // ----------------------------------------------------------------------- 1092 1093 END_NAMESPACE_DISTRHO 1094 1095 #endif // DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED