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.

710 lines
22KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2014 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. #include "DistrhoPluginInternal.hpp"
  17. #ifdef DISTRHO_PLUGIN_TARGET_DSSI
  18. # include "dssi/dssi.h"
  19. #else
  20. # include "ladspa/ladspa.h"
  21. # if DISTRHO_PLUGIN_IS_SYNTH
  22. # error Cannot build synth plugin with LADSPA
  23. # endif
  24. # if DISTRHO_PLUGIN_WANT_STATE
  25. # warning LADSPA cannot handle states
  26. # endif
  27. #endif
  28. #if DISTRHO_PLUGIN_WANT_TIMEPOS
  29. # warning LADSPA/DSSI does not support TimePos
  30. #endif
  31. START_NAMESPACE_DISTRHO
  32. // -----------------------------------------------------------------------
  33. class PluginLadspaDssi
  34. {
  35. public:
  36. PluginLadspaDssi()
  37. : fPortControls(nullptr),
  38. fLastControlValues(nullptr)
  39. {
  40. #if DISTRHO_PLUGIN_NUM_INPUTS > 0
  41. for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
  42. fPortAudioIns[i] = nullptr;
  43. #else
  44. fPortAudioIns = nullptr;
  45. #endif
  46. #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
  47. for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
  48. fPortAudioOuts[i] = nullptr;
  49. #else
  50. fPortAudioOuts = nullptr;
  51. #endif
  52. if (const uint32_t count = fPlugin.getParameterCount())
  53. {
  54. fPortControls = new LADSPA_Data*[count];
  55. fLastControlValues = new LADSPA_Data[count];
  56. for (uint32_t i=0; i < count; ++i)
  57. {
  58. fPortControls[i] = nullptr;
  59. fLastControlValues[i] = fPlugin.getParameterValue(i);
  60. }
  61. }
  62. else
  63. {
  64. fPortControls = nullptr;
  65. fLastControlValues = nullptr;
  66. }
  67. #if DISTRHO_PLUGIN_WANT_LATENCY
  68. fPortLatency = nullptr;
  69. #endif
  70. }
  71. ~PluginLadspaDssi() noexcept
  72. {
  73. if (fPortControls != nullptr)
  74. {
  75. delete[] fPortControls;
  76. fPortControls = nullptr;
  77. }
  78. if (fLastControlValues != nullptr)
  79. {
  80. delete[] fLastControlValues;
  81. fLastControlValues = nullptr;
  82. }
  83. }
  84. // -------------------------------------------------------------------
  85. void ladspa_activate()
  86. {
  87. fPlugin.activate();
  88. }
  89. void ladspa_deactivate()
  90. {
  91. fPlugin.deactivate();
  92. }
  93. // -------------------------------------------------------------------
  94. void ladspa_connect_port(const ulong port, LADSPA_Data* const dataLocation) noexcept
  95. {
  96. ulong index = 0;
  97. #if DISTRHO_PLUGIN_NUM_INPUTS > 0
  98. for (ulong i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
  99. {
  100. if (port == index++)
  101. {
  102. fPortAudioIns[i] = dataLocation;
  103. return;
  104. }
  105. }
  106. #endif
  107. #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
  108. for (ulong i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
  109. {
  110. if (port == index++)
  111. {
  112. fPortAudioOuts[i] = dataLocation;
  113. return;
  114. }
  115. }
  116. #endif
  117. #if DISTRHO_PLUGIN_WANT_LATENCY
  118. if (port == index++)
  119. {
  120. fPortLatency = dataLocation;
  121. return;
  122. }
  123. #endif
  124. for (ulong i=0, count=fPlugin.getParameterCount(); i < count; ++i)
  125. {
  126. if (port == index++)
  127. {
  128. fPortControls[i] = dataLocation;
  129. return;
  130. }
  131. }
  132. }
  133. // -------------------------------------------------------------------
  134. #ifdef DISTRHO_PLUGIN_TARGET_DSSI
  135. void ladspa_run(const ulong sampleCount)
  136. {
  137. dssi_run_synth(sampleCount, nullptr, 0);
  138. }
  139. void dssi_run_synth(const ulong sampleCount, snd_seq_event_t* const events, const ulong eventCount)
  140. #else
  141. void ladspa_run(const ulong sampleCount)
  142. #endif
  143. {
  144. // pre-roll
  145. if (sampleCount == 0)
  146. return updateParameterOutputs();
  147. // Check for updated parameters
  148. float curValue;
  149. for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
  150. {
  151. if (fPortControls[i] == nullptr)
  152. continue;
  153. curValue = *fPortControls[i];
  154. if (fLastControlValues[i] != curValue && ! fPlugin.isParameterOutput(i))
  155. {
  156. fLastControlValues[i] = curValue;
  157. fPlugin.setParameterValue(i, curValue);
  158. }
  159. }
  160. #if DISTRHO_PLUGIN_IS_SYNTH
  161. // Get MIDI Events
  162. uint32_t midiEventCount = 0;
  163. MidiEvent midiEvents[eventCount];
  164. for (uint32_t i=0, j; i < eventCount; ++i)
  165. {
  166. const snd_seq_event_t& seqEvent(events[i]);
  167. // FIXME
  168. if (seqEvent.data.note.channel > 0xF || seqEvent.data.control.channel > 0xF)
  169. continue;
  170. switch (seqEvent.type)
  171. {
  172. case SND_SEQ_EVENT_NOTEOFF:
  173. j = midiEventCount++;
  174. midiEvents[j].frame = seqEvent.time.tick;
  175. midiEvents[j].size = 3;
  176. midiEvents[j].data[0] = 0x80 + seqEvent.data.note.channel;
  177. midiEvents[j].data[1] = seqEvent.data.note.note;
  178. midiEvents[j].data[2] = 0;
  179. midiEvents[j].data[3] = 0;
  180. break;
  181. case SND_SEQ_EVENT_NOTEON:
  182. j = midiEventCount++;
  183. midiEvents[j].frame = seqEvent.time.tick;
  184. midiEvents[j].size = 3;
  185. midiEvents[j].data[0] = 0x90 + seqEvent.data.note.channel;
  186. midiEvents[j].data[1] = seqEvent.data.note.note;
  187. midiEvents[j].data[2] = seqEvent.data.note.velocity;
  188. midiEvents[j].data[3] = 0;
  189. break;
  190. case SND_SEQ_EVENT_KEYPRESS:
  191. j = midiEventCount++;
  192. midiEvents[j].frame = seqEvent.time.tick;
  193. midiEvents[j].size = 3;
  194. midiEvents[j].data[0] = 0xA0 + seqEvent.data.note.channel;
  195. midiEvents[j].data[1] = seqEvent.data.note.note;
  196. midiEvents[j].data[2] = seqEvent.data.note.velocity;
  197. midiEvents[j].data[3] = 0;
  198. break;
  199. case SND_SEQ_EVENT_CONTROLLER:
  200. j = midiEventCount++;
  201. midiEvents[j].frame = seqEvent.time.tick;
  202. midiEvents[j].size = 3;
  203. midiEvents[j].data[0] = 0xB0 + seqEvent.data.control.channel;
  204. midiEvents[j].data[1] = seqEvent.data.control.param;
  205. midiEvents[j].data[2] = seqEvent.data.control.value;
  206. midiEvents[j].data[3] = 0;
  207. break;
  208. case SND_SEQ_EVENT_CHANPRESS:
  209. j = midiEventCount++;
  210. midiEvents[j].frame = seqEvent.time.tick;
  211. midiEvents[j].size = 2;
  212. midiEvents[j].data[0] = 0xD0 + seqEvent.data.control.channel;
  213. midiEvents[j].data[1] = seqEvent.data.control.value;
  214. midiEvents[j].data[2] = 0;
  215. midiEvents[j].data[3] = 0;
  216. break;
  217. #if 0 // TODO
  218. case SND_SEQ_EVENT_PITCHBEND:
  219. j = midiEventCount++;
  220. midiEvents[j].frame = seqEvent.time.tick;
  221. midiEvents[j].size = 3;
  222. midiEvents[j].data[0] = 0xE0 + seqEvent.data.control.channel;
  223. midiEvents[j].data[1] = 0;
  224. midiEvents[j].data[2] = 0;
  225. midiEvents[j].data[3] = 0;
  226. break;
  227. #endif
  228. }
  229. }
  230. fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, midiEvents, midiEventCount);
  231. #else
  232. fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount);
  233. #endif
  234. updateParameterOutputs();
  235. #if defined(DISTRHO_PLUGIN_TARGET_DSSI) && ! DISTRHO_PLUGIN_IS_SYNTH
  236. return; // unused
  237. (void)events; (void)eventCount;
  238. #endif
  239. }
  240. // -------------------------------------------------------------------
  241. #ifdef DISTRHO_PLUGIN_TARGET_DSSI
  242. # if DISTRHO_PLUGIN_WANT_STATE
  243. char* dssi_configure(const char* const key, const char* const value)
  244. {
  245. if (std::strncmp(key, DSSI_RESERVED_CONFIGURE_PREFIX, std::strlen(DSSI_RESERVED_CONFIGURE_PREFIX) == 0))
  246. return nullptr;
  247. if (std::strncmp(key, DSSI_GLOBAL_CONFIGURE_PREFIX, std::strlen(DSSI_GLOBAL_CONFIGURE_PREFIX) == 0))
  248. return nullptr;
  249. fPlugin.setState(key, value);
  250. return nullptr;
  251. }
  252. # endif
  253. # if DISTRHO_PLUGIN_WANT_PROGRAMS
  254. const DSSI_Program_Descriptor* dssi_get_program(const ulong index)
  255. {
  256. if (index >= fPlugin.getProgramCount())
  257. return nullptr;
  258. static DSSI_Program_Descriptor desc;
  259. desc.Bank = index / 128;
  260. desc.Program = index % 128;
  261. desc.Name = fPlugin.getProgramName(index);
  262. return &desc;
  263. }
  264. void dssi_select_program(const ulong bank, const ulong program)
  265. {
  266. const ulong realProgram(bank * 128 + program);
  267. DISTRHO_SAFE_ASSERT_RETURN(realProgram < fPlugin.getProgramCount(),);
  268. fPlugin.setProgram(realProgram);
  269. // Update control inputs
  270. for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
  271. {
  272. if (fPlugin.isParameterOutput(i))
  273. continue;
  274. fLastControlValues[i] = fPlugin.getParameterValue(i);
  275. if (fPortControls[i] != nullptr)
  276. *fPortControls[i] = fLastControlValues[i];
  277. }
  278. }
  279. # endif
  280. #endif
  281. // -------------------------------------------------------------------
  282. private:
  283. PluginExporter fPlugin;
  284. // LADSPA ports
  285. #if DISTRHO_PLUGIN_NUM_INPUTS > 0
  286. const LADSPA_Data* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS];
  287. #else
  288. const LADSPA_Data** fPortAudioIns;
  289. #endif
  290. #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
  291. LADSPA_Data* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS];
  292. #else
  293. LADSPA_Data** fPortAudioOuts;
  294. #endif
  295. LADSPA_Data** fPortControls;
  296. #if DISTRHO_PLUGIN_WANT_LATENCY
  297. LADSPA_Data* fPortLatency;
  298. #endif
  299. // Temporary data
  300. LADSPA_Data* fLastControlValues;
  301. // -------------------------------------------------------------------
  302. void updateParameterOutputs()
  303. {
  304. for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
  305. {
  306. if (! fPlugin.isParameterOutput(i))
  307. continue;
  308. fLastControlValues[i] = fPlugin.getParameterValue(i);
  309. if (fPortControls[i] != nullptr)
  310. *fPortControls[i] = fLastControlValues[i];
  311. }
  312. #if DISTRHO_PLUGIN_WANT_LATENCY
  313. if (fPortLatency != nullptr)
  314. *fPortLatency = fPlugin.getLatency();
  315. #endif
  316. }
  317. };
  318. // -----------------------------------------------------------------------
  319. static LADSPA_Handle ladspa_instantiate(const LADSPA_Descriptor*, ulong sampleRate)
  320. {
  321. if (d_lastBufferSize == 0)
  322. d_lastBufferSize = 2048;
  323. d_lastSampleRate = sampleRate;
  324. return new PluginLadspaDssi();
  325. }
  326. #define instancePtr ((PluginLadspaDssi*)instance)
  327. static void ladspa_connect_port(LADSPA_Handle instance, ulong port, LADSPA_Data* dataLocation)
  328. {
  329. instancePtr->ladspa_connect_port(port, dataLocation);
  330. }
  331. static void ladspa_activate(LADSPA_Handle instance)
  332. {
  333. instancePtr->ladspa_activate();
  334. }
  335. static void ladspa_run(LADSPA_Handle instance, ulong sampleCount)
  336. {
  337. instancePtr->ladspa_run(sampleCount);
  338. }
  339. static void ladspa_deactivate(LADSPA_Handle instance)
  340. {
  341. instancePtr->ladspa_deactivate();
  342. }
  343. static void ladspa_cleanup(LADSPA_Handle instance)
  344. {
  345. delete instancePtr;
  346. }
  347. #ifdef DISTRHO_PLUGIN_TARGET_DSSI
  348. # if DISTRHO_PLUGIN_WANT_STATE
  349. static char* dssi_configure(LADSPA_Handle instance, const char* key, const char* value)
  350. {
  351. return instancePtr->dssi_configure(key, value);
  352. }
  353. # endif
  354. # if DISTRHO_PLUGIN_WANT_PROGRAMS
  355. static const DSSI_Program_Descriptor* dssi_get_program(LADSPA_Handle instance, ulong index)
  356. {
  357. return instancePtr->dssi_get_program(index);
  358. }
  359. static void dssi_select_program(LADSPA_Handle instance, ulong bank, ulong program)
  360. {
  361. instancePtr->dssi_select_program(bank, program);
  362. }
  363. # endif
  364. # if DISTRHO_PLUGIN_IS_SYNTH
  365. static void dssi_run_synth(LADSPA_Handle instance, ulong sampleCount, snd_seq_event_t* events, ulong eventCount)
  366. {
  367. instancePtr->dssi_run_synth(sampleCount, events, eventCount);
  368. }
  369. # endif
  370. #endif
  371. #undef instancePtr
  372. // -----------------------------------------------------------------------
  373. static LADSPA_Descriptor sLadspaDescriptor = {
  374. /* UniqueID */ 0,
  375. /* Label */ nullptr,
  376. #if DISTRHO_PLUGIN_IS_RT_SAFE
  377. /* Properties */ LADSPA_PROPERTY_HARD_RT_CAPABLE,
  378. #else
  379. /* Properties */ 0x0,
  380. #endif
  381. /* Name */ nullptr,
  382. /* Maker */ nullptr,
  383. /* Copyright */ nullptr,
  384. /* PortCount */ 0,
  385. /* PortDescriptors */ nullptr,
  386. /* PortNames */ nullptr,
  387. /* PortRangeHints */ nullptr,
  388. /* ImplementationData */ nullptr,
  389. ladspa_instantiate,
  390. ladspa_connect_port,
  391. ladspa_activate,
  392. ladspa_run,
  393. /* run_adding */ nullptr,
  394. /* set_run_adding_gain */ nullptr,
  395. ladspa_deactivate,
  396. ladspa_cleanup
  397. };
  398. #ifdef DISTRHO_PLUGIN_TARGET_DSSI
  399. static DSSI_Descriptor sDssiDescriptor = {
  400. 1,
  401. &sLadspaDescriptor,
  402. # if DISTRHO_PLUGIN_WANT_STATE
  403. dssi_configure,
  404. # else
  405. /* configure */ nullptr,
  406. # endif
  407. # if DISTRHO_PLUGIN_WANT_PROGRAMS
  408. dssi_get_program,
  409. dssi_select_program,
  410. # else
  411. /* get_program */ nullptr,
  412. /* select_program */ nullptr,
  413. # endif
  414. /* get_midi_controller_for_port */ nullptr,
  415. # if DISTRHO_PLUGIN_IS_SYNTH
  416. dssi_run_synth,
  417. # else
  418. /* run_synth */ nullptr,
  419. # endif
  420. /* run_synth_adding */ nullptr,
  421. /* run_multiple_synths */ nullptr,
  422. /* run_multiple_synths_adding */ nullptr,
  423. nullptr, nullptr
  424. };
  425. #endif
  426. // -----------------------------------------------------------------------
  427. class DescriptorInitializer
  428. {
  429. public:
  430. DescriptorInitializer()
  431. {
  432. // Create dummy plugin to get data from
  433. d_lastBufferSize = 512;
  434. d_lastSampleRate = 44100.0;
  435. PluginExporter plugin;
  436. d_lastBufferSize = 0;
  437. d_lastSampleRate = 0.0;
  438. // Get port count, init
  439. ulong port = 0;
  440. ulong portCount = DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS + plugin.getParameterCount();
  441. #if DISTRHO_PLUGIN_WANT_LATENCY
  442. portCount += 1;
  443. #endif
  444. const char** const portNames = new const char*[portCount];
  445. LADSPA_PortDescriptor* portDescriptors = new LADSPA_PortDescriptor[portCount];
  446. LADSPA_PortRangeHint* portRangeHints = new LADSPA_PortRangeHint [portCount];
  447. // Set ports
  448. #if DISTRHO_PLUGIN_NUM_INPUTS > 0
  449. for (ulong i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++port)
  450. {
  451. char portName[24] = { '\0' };
  452. std::sprintf(portName, "Audio Input %lu", i+1);
  453. portNames[port] = strdup(portName);
  454. portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT;
  455. portRangeHints[port].HintDescriptor = 0x0;
  456. portRangeHints[port].LowerBound = 0.0f;
  457. portRangeHints[port].UpperBound = 1.0f;
  458. }
  459. #endif
  460. #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
  461. for (ulong i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++port)
  462. {
  463. char portName[24] = { '\0' };
  464. std::sprintf(portName, "Audio Output %lu", i+1);
  465. portNames[port] = strdup(portName);
  466. portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT;
  467. portRangeHints[port].HintDescriptor = 0x0;
  468. portRangeHints[port].LowerBound = 0.0f;
  469. portRangeHints[port].UpperBound = 1.0f;
  470. }
  471. #endif
  472. #if DISTRHO_PLUGIN_WANT_LATENCY
  473. // Set latency port
  474. portNames[port] = strdup("_latency");
  475. portDescriptors[port] = LADSPA_PORT_CONTROL | LADSPA_PORT_OUTPUT;
  476. portRangeHints[port].HintDescriptor = LADSPA_HINT_SAMPLE_RATE|LADSPA_HINT_INTEGER;
  477. portRangeHints[port].LowerBound = 0.0f;
  478. portRangeHints[port].UpperBound = 1.0f;
  479. ++port;
  480. #endif
  481. for (ulong i=0, count=plugin.getParameterCount(); i < count; ++i, ++port)
  482. {
  483. portNames[port] = strdup((const char*)plugin.getParameterName(i));
  484. portDescriptors[port] = LADSPA_PORT_CONTROL;
  485. if (plugin.isParameterOutput(i))
  486. portDescriptors[port] |= LADSPA_PORT_OUTPUT;
  487. else
  488. portDescriptors[port] |= LADSPA_PORT_INPUT;
  489. {
  490. const ParameterRanges& ranges(plugin.getParameterRanges(i));
  491. const float defValue(ranges.def);
  492. portRangeHints[port].HintDescriptor = LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE;
  493. portRangeHints[port].LowerBound = ranges.min;
  494. portRangeHints[port].UpperBound = ranges.max;
  495. if (defValue == 0.0f)
  496. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_0;
  497. else if (defValue == 1.0f)
  498. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_1;
  499. else if (defValue == 100.0f)
  500. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_100;
  501. else if (defValue == 440.0f)
  502. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_440;
  503. else if (ranges.min == defValue)
  504. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MINIMUM;
  505. else if (ranges.max == defValue)
  506. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM;
  507. else
  508. {
  509. const float middleValue = ranges.min/2.0f + ranges.max/2.0f;
  510. const float middleLow = (ranges.min/2.0f + middleValue/2.0f)/2.0f + middleValue/2.0f;
  511. const float middleHigh = (ranges.max/2.0f + middleValue/2.0f)/2.0f + middleValue/2.0f;
  512. if (defValue < middleLow)
  513. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_LOW;
  514. else if (defValue > middleHigh)
  515. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_HIGH;
  516. else
  517. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MIDDLE;
  518. }
  519. }
  520. {
  521. const uint32_t hints(plugin.getParameterHints(i));
  522. if (hints & kParameterIsBoolean)
  523. portRangeHints[port].HintDescriptor |= LADSPA_HINT_TOGGLED;
  524. if (hints & kParameterIsInteger)
  525. portRangeHints[port].HintDescriptor |= LADSPA_HINT_INTEGER;
  526. if (hints & kParameterIsLogarithmic)
  527. portRangeHints[port].HintDescriptor |= LADSPA_HINT_LOGARITHMIC;
  528. }
  529. }
  530. // Set data
  531. sLadspaDescriptor.UniqueID = plugin.getUniqueId();
  532. sLadspaDescriptor.Label = strdup(plugin.getLabel());
  533. sLadspaDescriptor.Name = strdup(plugin.getName());
  534. sLadspaDescriptor.Maker = strdup(plugin.getMaker());
  535. sLadspaDescriptor.Copyright = strdup(plugin.getLicense());
  536. sLadspaDescriptor.PortCount = portCount;
  537. sLadspaDescriptor.PortNames = portNames;
  538. sLadspaDescriptor.PortDescriptors = portDescriptors;
  539. sLadspaDescriptor.PortRangeHints = portRangeHints;
  540. }
  541. ~DescriptorInitializer()
  542. {
  543. if (sLadspaDescriptor.Label != nullptr)
  544. {
  545. std::free((void*)sLadspaDescriptor.Label);
  546. sLadspaDescriptor.Label = nullptr;
  547. }
  548. if (sLadspaDescriptor.Name != nullptr)
  549. {
  550. std::free((void*)sLadspaDescriptor.Name);
  551. sLadspaDescriptor.Name = nullptr;
  552. }
  553. if (sLadspaDescriptor.Maker != nullptr)
  554. {
  555. std::free((void*)sLadspaDescriptor.Maker);
  556. sLadspaDescriptor.Maker = nullptr;
  557. }
  558. if (sLadspaDescriptor.Copyright != nullptr)
  559. {
  560. std::free((void*)sLadspaDescriptor.Copyright);
  561. sLadspaDescriptor.Copyright = nullptr;
  562. }
  563. if (sLadspaDescriptor.PortDescriptors != nullptr)
  564. {
  565. delete[] sLadspaDescriptor.PortDescriptors;
  566. sLadspaDescriptor.PortDescriptors = nullptr;
  567. }
  568. if (sLadspaDescriptor.PortRangeHints != nullptr)
  569. {
  570. delete[] sLadspaDescriptor.PortRangeHints;
  571. sLadspaDescriptor.PortRangeHints = nullptr;
  572. }
  573. if (sLadspaDescriptor.PortNames != nullptr)
  574. {
  575. for (ulong i=0; i < sLadspaDescriptor.PortCount; ++i)
  576. {
  577. if (sLadspaDescriptor.PortNames[i] != nullptr)
  578. std::free((void*)sLadspaDescriptor.PortNames[i]);
  579. }
  580. delete[] sLadspaDescriptor.PortNames;
  581. sLadspaDescriptor.PortNames = nullptr;
  582. }
  583. }
  584. };
  585. static DescriptorInitializer sDescInit;
  586. // -----------------------------------------------------------------------
  587. END_NAMESPACE_DISTRHO
  588. DISTRHO_PLUGIN_EXPORT
  589. const LADSPA_Descriptor* ladspa_descriptor(ulong index)
  590. {
  591. USE_NAMESPACE_DISTRHO
  592. return (index == 0) ? &sLadspaDescriptor : nullptr;
  593. }
  594. #ifdef DISTRHO_PLUGIN_TARGET_DSSI
  595. DISTRHO_PLUGIN_EXPORT
  596. const DSSI_Descriptor* dssi_descriptor(ulong index)
  597. {
  598. USE_NAMESPACE_DISTRHO
  599. return (index == 0) ? &sDssiDescriptor : nullptr;
  600. }
  601. #endif
  602. // -----------------------------------------------------------------------