DISTRHO Plugin Framework
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

666 lines
18KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2018 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. #ifndef DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED
  17. #define DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED
  18. #include "../DistrhoPlugin.hpp"
  19. START_NAMESPACE_DISTRHO
  20. // -----------------------------------------------------------------------
  21. // Maxmimum values
  22. static const uint32_t kMaxMidiEvents = 512;
  23. // -----------------------------------------------------------------------
  24. // Static data, see DistrhoPlugin.cpp
  25. extern uint32_t d_lastBufferSize;
  26. extern double d_lastSampleRate;
  27. // -----------------------------------------------------------------------
  28. // DSP callbacks
  29. typedef bool (*writeMidiFunc) (void* ptr, const MidiEvent& midiEvent);
  30. // -----------------------------------------------------------------------
  31. // Plugin private data
  32. struct Plugin::PrivateData {
  33. bool isProcessing;
  34. #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
  35. AudioPort* audioPorts;
  36. #endif
  37. uint32_t parameterCount;
  38. uint32_t parameterOffset;
  39. Parameter* parameters;
  40. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  41. uint32_t programCount;
  42. String* programNames;
  43. #endif
  44. #if DISTRHO_PLUGIN_WANT_STATE
  45. uint32_t stateCount;
  46. String* stateKeys;
  47. String* stateDefValues;
  48. #endif
  49. #if DISTRHO_PLUGIN_WANT_LATENCY
  50. uint32_t latency;
  51. #endif
  52. #if DISTRHO_PLUGIN_WANT_TIMEPOS
  53. TimePosition timePosition;
  54. #endif
  55. // Callbacks
  56. void* callbacksPtr;
  57. writeMidiFunc writeMidiCallbackFunc;
  58. uint32_t bufferSize;
  59. double sampleRate;
  60. PrivateData() noexcept
  61. : isProcessing(false),
  62. #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
  63. audioPorts(nullptr),
  64. #endif
  65. parameterCount(0),
  66. parameterOffset(0),
  67. parameters(nullptr),
  68. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  69. programCount(0),
  70. programNames(nullptr),
  71. #endif
  72. #if DISTRHO_PLUGIN_WANT_STATE
  73. stateCount(0),
  74. stateKeys(nullptr),
  75. stateDefValues(nullptr),
  76. #endif
  77. #if DISTRHO_PLUGIN_WANT_LATENCY
  78. latency(0),
  79. #endif
  80. callbacksPtr(nullptr),
  81. writeMidiCallbackFunc(nullptr),
  82. bufferSize(d_lastBufferSize),
  83. sampleRate(d_lastSampleRate)
  84. {
  85. DISTRHO_SAFE_ASSERT(bufferSize != 0);
  86. DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate));
  87. #if defined(DISTRHO_PLUGIN_TARGET_DSSI) || defined(DISTRHO_PLUGIN_TARGET_LV2)
  88. parameterOffset += DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS;
  89. # if DISTRHO_PLUGIN_WANT_LATENCY
  90. parameterOffset += 1;
  91. # endif
  92. #endif
  93. #ifdef DISTRHO_PLUGIN_TARGET_LV2
  94. # if (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_TIMEPOS || DISTRHO_PLUGIN_WANT_STATE)
  95. parameterOffset += 1;
  96. # if DISTRHO_PLUGIN_WANT_STATE
  97. parameterOffset += 1;
  98. # endif
  99. # endif
  100. #endif
  101. }
  102. ~PrivateData() noexcept
  103. {
  104. #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
  105. if (audioPorts != nullptr)
  106. {
  107. delete[] audioPorts;
  108. audioPorts = nullptr;
  109. }
  110. #endif
  111. if (parameters != nullptr)
  112. {
  113. delete[] parameters;
  114. parameters = nullptr;
  115. }
  116. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  117. if (programNames != nullptr)
  118. {
  119. delete[] programNames;
  120. programNames = nullptr;
  121. }
  122. #endif
  123. #if DISTRHO_PLUGIN_WANT_STATE
  124. if (stateKeys != nullptr)
  125. {
  126. delete[] stateKeys;
  127. stateKeys = nullptr;
  128. }
  129. if (stateDefValues != nullptr)
  130. {
  131. delete[] stateDefValues;
  132. stateDefValues = nullptr;
  133. }
  134. #endif
  135. }
  136. #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
  137. bool writeMidiCallback(const MidiEvent& midiEvent)
  138. {
  139. if (writeMidiCallbackFunc != nullptr)
  140. return writeMidiCallbackFunc(callbacksPtr, midiEvent);
  141. return false;
  142. }
  143. #endif
  144. };
  145. // -----------------------------------------------------------------------
  146. // Plugin exporter class
  147. class PluginExporter
  148. {
  149. public:
  150. PluginExporter(void* const callbacksPtr, const writeMidiFunc writeMidiCall)
  151. : fPlugin(createPlugin()),
  152. fData((fPlugin != nullptr) ? fPlugin->pData : nullptr),
  153. fIsActive(false)
  154. {
  155. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  156. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
  157. #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
  158. {
  159. uint32_t j=0;
  160. # if DISTRHO_PLUGIN_NUM_INPUTS > 0
  161. for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++j)
  162. fPlugin->initAudioPort(true, i, fData->audioPorts[j]);
  163. # endif
  164. # if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
  165. for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++j)
  166. fPlugin->initAudioPort(false, i, fData->audioPorts[j]);
  167. # endif
  168. }
  169. #endif
  170. for (uint32_t i=0, count=fData->parameterCount; i < count; ++i)
  171. fPlugin->initParameter(i, fData->parameters[i]);
  172. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  173. for (uint32_t i=0, count=fData->programCount; i < count; ++i)
  174. fPlugin->initProgramName(i, fData->programNames[i]);
  175. #endif
  176. #if DISTRHO_PLUGIN_WANT_STATE
  177. for (uint32_t i=0, count=fData->stateCount; i < count; ++i)
  178. fPlugin->initState(i, fData->stateKeys[i], fData->stateDefValues[i]);
  179. #endif
  180. fData->callbacksPtr = callbacksPtr;
  181. fData->writeMidiCallbackFunc = writeMidiCall;
  182. }
  183. ~PluginExporter()
  184. {
  185. delete fPlugin;
  186. }
  187. // -------------------------------------------------------------------
  188. const char* getName() const noexcept
  189. {
  190. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
  191. return fPlugin->getName();
  192. }
  193. const char* getLabel() const noexcept
  194. {
  195. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
  196. return fPlugin->getLabel();
  197. }
  198. const char* getDescription() const noexcept
  199. {
  200. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
  201. return fPlugin->getDescription();
  202. }
  203. const char* getMaker() const noexcept
  204. {
  205. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
  206. return fPlugin->getMaker();
  207. }
  208. const char* getHomePage() const noexcept
  209. {
  210. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
  211. return fPlugin->getHomePage();
  212. }
  213. const char* getLicense() const noexcept
  214. {
  215. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, "");
  216. return fPlugin->getLicense();
  217. }
  218. uint32_t getVersion() const noexcept
  219. {
  220. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0);
  221. return fPlugin->getVersion();
  222. }
  223. long getUniqueId() const noexcept
  224. {
  225. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0);
  226. return fPlugin->getUniqueId();
  227. }
  228. void* getInstancePointer() const noexcept
  229. {
  230. return fPlugin;
  231. }
  232. // -------------------------------------------------------------------
  233. #if DISTRHO_PLUGIN_WANT_LATENCY
  234. uint32_t getLatency() const noexcept
  235. {
  236. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
  237. return fData->latency;
  238. }
  239. #endif
  240. #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
  241. const AudioPort& getAudioPort(const bool input, const uint32_t index) const noexcept
  242. {
  243. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackAudioPort);
  244. if (input)
  245. {
  246. # if DISTRHO_PLUGIN_NUM_INPUTS > 0
  247. DISTRHO_SAFE_ASSERT_RETURN(index < DISTRHO_PLUGIN_NUM_INPUTS, sFallbackAudioPort);
  248. # endif
  249. }
  250. else
  251. {
  252. # if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
  253. DISTRHO_SAFE_ASSERT_RETURN(index < DISTRHO_PLUGIN_NUM_OUTPUTS, sFallbackAudioPort);
  254. # endif
  255. }
  256. return fData->audioPorts[index + (input ? 0 : DISTRHO_PLUGIN_NUM_INPUTS)];
  257. }
  258. #endif
  259. uint32_t getParameterCount() const noexcept
  260. {
  261. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
  262. return fData->parameterCount;
  263. }
  264. uint32_t getParameterOffset() const noexcept
  265. {
  266. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
  267. return fData->parameterOffset;
  268. }
  269. uint32_t getParameterHints(const uint32_t index) const noexcept
  270. {
  271. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0x0);
  272. return fData->parameters[index].hints;
  273. }
  274. ParameterDesignation getParameterDesignation(const uint32_t index) const noexcept
  275. {
  276. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, kParameterDesignationNull);
  277. return fData->parameters[index].designation;
  278. }
  279. bool isParameterInput(const uint32_t index) const noexcept
  280. {
  281. return (getParameterHints(index) & kParameterIsOutput) == 0x0;
  282. }
  283. bool isParameterOutput(const uint32_t index) const noexcept
  284. {
  285. return (getParameterHints(index) & kParameterIsOutput) != 0x0;
  286. }
  287. bool isParameterOutputOrTrigger(const uint32_t index) const noexcept
  288. {
  289. const uint32_t hints = getParameterHints(index);
  290. if (hints & kParameterIsOutput)
  291. return true;
  292. if ((hints & kParameterIsTrigger) == kParameterIsTrigger)
  293. return true;
  294. return false;
  295. }
  296. const String& getParameterName(const uint32_t index) const noexcept
  297. {
  298. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);
  299. return fData->parameters[index].name;
  300. }
  301. const String& getParameterSymbol(const uint32_t index) const noexcept
  302. {
  303. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);
  304. return fData->parameters[index].symbol;
  305. }
  306. const String& getParameterUnit(const uint32_t index) const noexcept
  307. {
  308. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString);
  309. return fData->parameters[index].unit;
  310. }
  311. const ParameterEnumerationValues& getParameterEnumValues(const uint32_t index) const noexcept
  312. {
  313. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackEnumValues);
  314. return fData->parameters[index].enumValues;
  315. }
  316. const ParameterRanges& getParameterRanges(const uint32_t index) const noexcept
  317. {
  318. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackRanges);
  319. return fData->parameters[index].ranges;
  320. }
  321. uint8_t getParameterMidiCC(const uint32_t index) const noexcept
  322. {
  323. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0);
  324. return fData->parameters[index].midiCC;
  325. }
  326. float getParameterValue(const uint32_t index) const
  327. {
  328. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0.0f);
  329. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0.0f);
  330. return fPlugin->getParameterValue(index);
  331. }
  332. void setParameterValue(const uint32_t index, const float value)
  333. {
  334. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  335. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount,);
  336. fPlugin->setParameterValue(index, value);
  337. }
  338. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  339. uint32_t getProgramCount() const noexcept
  340. {
  341. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
  342. return fData->programCount;
  343. }
  344. const String& getProgramName(const uint32_t index) const noexcept
  345. {
  346. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->programCount, sFallbackString);
  347. return fData->programNames[index];
  348. }
  349. void loadProgram(const uint32_t index)
  350. {
  351. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  352. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->programCount,);
  353. fPlugin->loadProgram(index);
  354. }
  355. #endif
  356. #if DISTRHO_PLUGIN_WANT_STATE
  357. uint32_t getStateCount() const noexcept
  358. {
  359. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
  360. return fData->stateCount;
  361. }
  362. const String& getStateKey(const uint32_t index) const noexcept
  363. {
  364. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString);
  365. return fData->stateKeys[index];
  366. }
  367. const String& getStateDefaultValue(const uint32_t index) const noexcept
  368. {
  369. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString);
  370. return fData->stateDefValues[index];
  371. }
  372. # if DISTRHO_PLUGIN_WANT_FULL_STATE
  373. String getState(const char* key) const
  374. {
  375. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackString);
  376. DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', sFallbackString);
  377. return fPlugin->getState(key);
  378. }
  379. # endif
  380. void setState(const char* const key, const char* const value)
  381. {
  382. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
  383. DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  384. DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,);
  385. fPlugin->setState(key, value);
  386. }
  387. bool wantStateKey(const char* const key) const noexcept
  388. {
  389. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, false);
  390. DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', false);
  391. for (uint32_t i=0; i < fData->stateCount; ++i)
  392. {
  393. if (fData->stateKeys[i] == key)
  394. return true;
  395. }
  396. return false;
  397. }
  398. #endif
  399. #if DISTRHO_PLUGIN_WANT_TIMEPOS
  400. void setTimePosition(const TimePosition& timePosition) noexcept
  401. {
  402. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
  403. std::memcpy(&fData->timePosition, &timePosition, sizeof(TimePosition));
  404. }
  405. #endif
  406. // -------------------------------------------------------------------
  407. bool isActive() const noexcept
  408. {
  409. return fIsActive;
  410. }
  411. void activate()
  412. {
  413. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  414. DISTRHO_SAFE_ASSERT_RETURN(! fIsActive,);
  415. fIsActive = true;
  416. fPlugin->activate();
  417. }
  418. void deactivate()
  419. {
  420. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  421. DISTRHO_SAFE_ASSERT_RETURN(fIsActive,);
  422. fIsActive = false;
  423. fPlugin->deactivate();
  424. }
  425. void deactivateIfNeeded()
  426. {
  427. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  428. if (fIsActive)
  429. {
  430. fIsActive = false;
  431. fPlugin->deactivate();
  432. }
  433. }
  434. #if DISTRHO_PLUGIN_WANT_MIDI_INPUT
  435. void run(const float** const inputs, float** const outputs, const uint32_t frames,
  436. const MidiEvent* const midiEvents, const uint32_t midiEventCount)
  437. {
  438. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
  439. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  440. if (! fIsActive)
  441. {
  442. fIsActive = true;
  443. fPlugin->activate();
  444. }
  445. fData->isProcessing = true;
  446. fPlugin->run(inputs, outputs, frames, midiEvents, midiEventCount);
  447. fData->isProcessing = false;
  448. }
  449. #else
  450. void run(const float** const inputs, float** const outputs, const uint32_t frames)
  451. {
  452. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
  453. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  454. if (! fIsActive)
  455. {
  456. fIsActive = true;
  457. fPlugin->activate();
  458. }
  459. fData->isProcessing = true;
  460. fPlugin->run(inputs, outputs, frames);
  461. fData->isProcessing = false;
  462. }
  463. #endif
  464. // -------------------------------------------------------------------
  465. uint32_t getBufferSize() const noexcept
  466. {
  467. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
  468. return fData->bufferSize;
  469. }
  470. double getSampleRate() const noexcept
  471. {
  472. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0.0);
  473. return fData->sampleRate;
  474. }
  475. void setBufferSize(const uint32_t bufferSize, const bool doCallback = false)
  476. {
  477. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
  478. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  479. DISTRHO_SAFE_ASSERT(bufferSize >= 2);
  480. if (fData->bufferSize == bufferSize)
  481. return;
  482. fData->bufferSize = bufferSize;
  483. if (doCallback)
  484. {
  485. if (fIsActive) fPlugin->deactivate();
  486. fPlugin->bufferSizeChanged(bufferSize);
  487. if (fIsActive) fPlugin->activate();
  488. }
  489. }
  490. void setSampleRate(const double sampleRate, const bool doCallback = false)
  491. {
  492. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
  493. DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  494. DISTRHO_SAFE_ASSERT(sampleRate > 0.0);
  495. if (d_isEqual(fData->sampleRate, sampleRate))
  496. return;
  497. fData->sampleRate = sampleRate;
  498. if (doCallback)
  499. {
  500. if (fIsActive) fPlugin->deactivate();
  501. fPlugin->sampleRateChanged(sampleRate);
  502. if (fIsActive) fPlugin->activate();
  503. }
  504. }
  505. private:
  506. // -------------------------------------------------------------------
  507. // Plugin and DistrhoPlugin data
  508. Plugin* const fPlugin;
  509. Plugin::PrivateData* const fData;
  510. bool fIsActive;
  511. // -------------------------------------------------------------------
  512. // Static fallback data, see DistrhoPlugin.cpp
  513. static const String sFallbackString;
  514. static const AudioPort sFallbackAudioPort;
  515. static const ParameterRanges sFallbackRanges;
  516. static const ParameterEnumerationValues sFallbackEnumValues;
  517. DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginExporter)
  518. DISTRHO_PREVENT_HEAP_ALLOCATION
  519. };
  520. // -----------------------------------------------------------------------
  521. END_NAMESPACE_DISTRHO
  522. #endif // DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED