Audio plugin host https://kx.studio/carla
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.

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