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.

585 lines
16KB

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