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.

685 lines
21KB

  1. /*
  2. * DISTRHO Plugin Toolkit (DPT)
  3. * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser General Public License for more details.
  13. *
  14. * For a full copy of the license see the LGPL.txt file
  15. */
  16. #if defined(DISTRHO_PLUGIN_TARGET_LADSPA) || defined(DISTRHO_PLUGIN_TARGET_DSSI)
  17. #include "DistrhoPluginInternal.h"
  18. #ifdef DISTRHO_PLUGIN_TARGET_DSSI
  19. # include "dssi/dssi.h"
  20. #else
  21. # include "ladspa/ladspa.h"
  22. # if DISTRHO_PLUGIN_IS_SYNTH
  23. # error Cannot build synth plugin with LADSPA
  24. # endif
  25. # if DISTRHO_PLUGIN_WANT_STATE
  26. # warning LADSPA cannot handle states
  27. # endif
  28. #endif
  29. #include <vector>
  30. typedef LADSPA_Data* LADSPA_DataPtr;
  31. typedef std::vector<LADSPA_Data> LADSPA_DataVector;
  32. typedef std::vector<LADSPA_DataPtr> LADSPA_DataPtrVector;
  33. // -------------------------------------------------
  34. START_NAMESPACE_DISTRHO
  35. class PluginLadspaDssi
  36. {
  37. public:
  38. PluginLadspaDssi(const double sampleRate)
  39. : lastSampleRate(sampleRate),
  40. portAudioIns{nullptr},
  41. portAudioOuts{nullptr}
  42. {
  43. for (uint32_t i=0, count=plugin.parameterCount(); i < count; i++)
  44. {
  45. lastControlValues.push_back(plugin.parameterValue(i));
  46. portControls.push_back(nullptr);
  47. }
  48. #if DISTRHO_PLUGIN_WANT_LATENCY
  49. portLatency = nullptr;
  50. #endif
  51. #if defined(DISTRHO_PLUGIN_TARGET_DSSI) && DISTRHO_PLUGIN_HAS_UI
  52. portSampleRate = nullptr;
  53. #endif
  54. }
  55. ~PluginLadspaDssi()
  56. {
  57. lastControlValues.clear();
  58. portControls.clear();
  59. }
  60. // ---------------------------------------------
  61. void ladspa_connect_port(unsigned long port, LADSPA_DataPtr dataLocation)
  62. {
  63. unsigned long i, index = 0;
  64. for (i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; i++)
  65. {
  66. if (port == index++)
  67. {
  68. portAudioIns[i] = dataLocation;
  69. return;
  70. }
  71. }
  72. for (i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; i++)
  73. {
  74. if (port == index++)
  75. {
  76. portAudioOuts[i] = dataLocation;
  77. return;
  78. }
  79. }
  80. #if DISTRHO_PLUGIN_WANT_LATENCY
  81. if (port == index++)
  82. {
  83. portLatency = dataLocation;
  84. return;
  85. }
  86. #endif
  87. #if defined(DISTRHO_PLUGIN_TARGET_DSSI) && DISTRHO_PLUGIN_HAS_UI
  88. if (port == index++)
  89. {
  90. portSampleRate = dataLocation;
  91. return;
  92. }
  93. #endif
  94. for (i=0, count=plugin.parameterCount(); i < count; i++)
  95. {
  96. if (port == index++)
  97. {
  98. portControls[i] = dataLocation;
  99. return;
  100. }
  101. }
  102. }
  103. // ---------------------------------------------
  104. #ifdef DISTRHO_PLUGIN_TARGET_DSSI
  105. # if DISTRHO_PLUGIN_WANT_STATE
  106. char* dssi_configure(const char* key, const char* value)
  107. {
  108. if (strncmp(key, DSSI_RESERVED_CONFIGURE_PREFIX, strlen(DSSI_RESERVED_CONFIGURE_PREFIX) == 0))
  109. return nullptr;
  110. if (strncmp(key, DSSI_GLOBAL_CONFIGURE_PREFIX, strlen(DSSI_GLOBAL_CONFIGURE_PREFIX) == 0))
  111. return nullptr;
  112. plugin.setState(key, value);
  113. return nullptr;
  114. }
  115. # endif
  116. # if DISTRHO_PLUGIN_WANT_PROGRAMS
  117. const DSSI_Program_Descriptor* dssi_get_program(unsigned long index)
  118. {
  119. if (index >= plugin.programCount())
  120. return nullptr;
  121. static DSSI_Program_Descriptor desc;
  122. desc.Bank = index / 128;
  123. desc.Program = index % 128;
  124. desc.Name = plugin.programName(index);
  125. return &desc;
  126. }
  127. void dssi_select_program(unsigned long bank, unsigned long program)
  128. {
  129. const unsigned long realProgram = bank * 128 + program;
  130. if (realProgram >= plugin.programCount())
  131. return;
  132. plugin.setProgram(realProgram);
  133. // Update parameters
  134. for (uint32_t i=0, count=plugin.parameterCount(); i < count; i++)
  135. {
  136. if (! plugin.parameterIsOutput(i))
  137. {
  138. lastControlValues[i] = plugin.parameterValue(i);
  139. if (portControls[i])
  140. *portControls[i] = lastControlValues[i];
  141. }
  142. }
  143. }
  144. # endif
  145. #endif
  146. // ---------------------------------------------
  147. void ladspa_activate()
  148. {
  149. plugin.activate();
  150. }
  151. void ladspa_deactivate()
  152. {
  153. plugin.deactivate();
  154. }
  155. #ifdef DISTRHO_PLUGIN_TARGET_DSSI
  156. void ladspa_run(unsigned long bufferSize)
  157. {
  158. dssi_run_synth(bufferSize, nullptr, 0);
  159. }
  160. void dssi_run_synth(unsigned long bufferSize, snd_seq_event_t* events, unsigned long eventCount)
  161. #else
  162. void ladspa_run(unsigned long bufferSize)
  163. #endif
  164. {
  165. // Check for updated parameters
  166. float curValue;
  167. for (uint32_t i=0, count=plugin.parameterCount(); i < count; i++)
  168. {
  169. curValue = *portControls[i];
  170. if (lastControlValues[i] != curValue && ! plugin.parameterIsOutput(i))
  171. {
  172. lastControlValues[i] = curValue;
  173. plugin.setParameterValue(i, curValue);
  174. }
  175. }
  176. #ifdef DISTRHO_PLUGIN_TARGET_DSSI
  177. # if DISTRHO_PLUGIN_IS_SYNTH
  178. // Get MIDI Events
  179. uint32_t midiEventCount = 0;
  180. for (uint32_t i=0, j; i < eventCount && midiEventCount < MAX_MIDI_EVENTS; i++)
  181. {
  182. snd_seq_event_t* event = &events[i];
  183. if (event->type == SND_SEQ_EVENT_NOTEON)
  184. {
  185. j = midiEventCount++;
  186. midiEvents[j].frame = event->time.tick;
  187. midiEvents[j].buffer[0] = 0x90 + event->data.note.channel;
  188. midiEvents[j].buffer[1] = event->data.note.note;
  189. midiEvents[j].buffer[2] = event->data.note.velocity;
  190. }
  191. else if (event->type == SND_SEQ_EVENT_NOTEOFF)
  192. {
  193. j = midiEventCount++;
  194. midiEvents[j].frame = event->time.tick;
  195. midiEvents[j].buffer[0] = 0x80 + event->data.note.channel;
  196. midiEvents[j].buffer[1] = event->data.note.note;
  197. midiEvents[j].buffer[2] = 0;
  198. }
  199. else if (event->type == SND_SEQ_EVENT_KEYPRESS)
  200. {
  201. j = midiEventCount++;
  202. midiEvents[j].frame = event->time.tick;
  203. midiEvents[j].buffer[0] = 0xA0 + event->data.note.channel;
  204. midiEvents[j].buffer[1] = event->data.note.note;
  205. midiEvents[j].buffer[2] = event->data.note.velocity;
  206. }
  207. else if (event->type == SND_SEQ_EVENT_CONTROLLER)
  208. {
  209. j = midiEventCount++;
  210. midiEvents[j].frame = event->time.tick;
  211. midiEvents[j].buffer[0] = 0xB0 + event->data.control.channel;
  212. midiEvents[j].buffer[1] = event->data.control.param;
  213. midiEvents[j].buffer[2] = event->data.control.value;
  214. }
  215. else if (event->type == SND_SEQ_EVENT_CHANPRESS)
  216. {
  217. j = midiEventCount++;
  218. midiEvents[j].frame = event->time.tick;
  219. midiEvents[j].buffer[0] = 0xD0 + event->data.control.channel;
  220. midiEvents[j].buffer[1] = event->data.control.value;
  221. midiEvents[j].buffer[2] = 0;
  222. }
  223. else if (event->type == SND_SEQ_EVENT_PITCHBEND)
  224. {
  225. // TODO
  226. //j = midiEventCount++;
  227. //midiEvents[j].frame = event->time.tick;
  228. //midiEvents[j].buffer[0] = 0xE0 + event->data.control.channel;
  229. //midiEvents[j].buffer[1] = 0;
  230. //midiEvents[j].buffer[2] = 0;
  231. }
  232. }
  233. # else
  234. // unused
  235. (void)events;
  236. (void)eventCount;
  237. # endif
  238. #endif
  239. // Run plugin for this cycle
  240. #if DISTRHO_PLUGIN_IS_SYNTH
  241. plugin.run(portAudioIns, portAudioOuts, bufferSize, midiEventCount, midiEvents);
  242. #else
  243. plugin.run(portAudioIns, portAudioOuts, bufferSize, 0, nullptr);
  244. #endif
  245. updateParameterOutputs();
  246. }
  247. // ---------------------------------------------
  248. private:
  249. PluginInternal plugin;
  250. // Temporary data
  251. const double lastSampleRate;
  252. LADSPA_DataVector lastControlValues;
  253. #if DISTRHO_PLUGIN_IS_SYNTH
  254. MidiEvent midiEvents[MAX_MIDI_EVENTS];
  255. #endif
  256. // LADSPA ports
  257. LADSPA_DataPtr portAudioIns[DISTRHO_PLUGIN_NUM_INPUTS];
  258. LADSPA_DataPtr portAudioOuts[DISTRHO_PLUGIN_NUM_INPUTS];
  259. LADSPA_DataPtrVector portControls;
  260. #if DISTRHO_PLUGIN_WANT_LATENCY
  261. LADSPA_DataPtr portLatency;
  262. #endif
  263. #if defined(DISTRHO_PLUGIN_TARGET_DSSI) && DISTRHO_PLUGIN_HAS_UI
  264. LADSPA_DataPtr portSampleRate;
  265. #endif
  266. // ---------------------------------------------
  267. void updateParameterOutputs()
  268. {
  269. for (uint32_t i=0, count=plugin.parameterCount(); i < count; i++)
  270. {
  271. if (plugin.parameterIsOutput(i))
  272. {
  273. lastControlValues[i] = plugin.parameterValue(i);
  274. if (portControls[i])
  275. *portControls[i] = lastControlValues[i];
  276. }
  277. }
  278. #if DISTRHO_PLUGIN_WANT_LATENCY
  279. if (portLatency)
  280. *portLatency = plugin.latency();
  281. #endif
  282. #if defined(DISTRHO_PLUGIN_TARGET_DSSI) && DISTRHO_PLUGIN_HAS_UI
  283. if (portSampleRate)
  284. *portSampleRate = lastSampleRate;
  285. #endif
  286. }
  287. };
  288. // -------------------------------------------------
  289. static LADSPA_Handle ladspa_instantiate(const LADSPA_Descriptor*, unsigned long sampleRate)
  290. {
  291. if (d_lastBufferSize == 0)
  292. d_lastBufferSize = 2048;
  293. d_lastSampleRate = sampleRate;
  294. return new PluginLadspaDssi(sampleRate);
  295. }
  296. static void ladspa_connect_port(LADSPA_Handle instance, unsigned long port, LADSPA_Data* dataLocation)
  297. {
  298. PluginLadspaDssi* plugin = (PluginLadspaDssi*)instance;
  299. assert(plugin);
  300. plugin->ladspa_connect_port(port, dataLocation);
  301. }
  302. static void ladspa_activate(LADSPA_Handle instance)
  303. {
  304. PluginLadspaDssi* plugin = (PluginLadspaDssi*)instance;
  305. assert(plugin);
  306. plugin->ladspa_activate();
  307. }
  308. static void ladspa_run(LADSPA_Handle instance, unsigned long sampleCount)
  309. {
  310. PluginLadspaDssi* plugin = (PluginLadspaDssi*)instance;
  311. assert(plugin);
  312. plugin->ladspa_run(sampleCount);
  313. }
  314. static void ladspa_deactivate(LADSPA_Handle instance)
  315. {
  316. PluginLadspaDssi* plugin = (PluginLadspaDssi*)instance;
  317. assert(plugin);
  318. plugin->ladspa_deactivate();
  319. }
  320. static void ladspa_cleanup(LADSPA_Handle instance)
  321. {
  322. PluginLadspaDssi* plugin = (PluginLadspaDssi*)instance;
  323. assert(plugin);
  324. delete plugin;
  325. }
  326. #ifdef DISTRHO_PLUGIN_TARGET_DSSI
  327. # if DISTRHO_PLUGIN_WANT_STATE
  328. static char* dssi_configure(LADSPA_Handle instance, const char* key, const char* value)
  329. {
  330. PluginLadspaDssi* plugin = (PluginLadspaDssi*)instance;
  331. assert(plugin);
  332. return plugin->dssi_configure(key, value);
  333. }
  334. # endif
  335. # if DISTRHO_PLUGIN_WANT_PROGRAMS
  336. static const DSSI_Program_Descriptor* dssi_get_program(LADSPA_Handle instance, unsigned long index)
  337. {
  338. PluginLadspaDssi* plugin = (PluginLadspaDssi*)instance;
  339. assert(plugin);
  340. return plugin->dssi_get_program(index);
  341. }
  342. static void dssi_select_program(LADSPA_Handle instance, unsigned long bank, unsigned long program)
  343. {
  344. PluginLadspaDssi* plugin = (PluginLadspaDssi*)instance;
  345. assert(plugin);
  346. plugin->dssi_select_program(bank, program);
  347. }
  348. # endif
  349. # if DISTRHO_PLUGIN_IS_SYNTH
  350. static void dssi_run_synth(LADSPA_Handle instance, unsigned long sampleCount, snd_seq_event_t* events, unsigned long eventCount)
  351. {
  352. PluginLadspaDssi* plugin = (PluginLadspaDssi*)instance;
  353. assert(plugin);
  354. plugin->dssi_run_synth(sampleCount, events, eventCount);
  355. }
  356. # endif
  357. #endif
  358. // -------------------------------------------------
  359. static LADSPA_Descriptor ldescriptor = {
  360. /* UniqueID */ 0,
  361. /* Label */ nullptr,
  362. /* Properties */ LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE,
  363. /* Name */ nullptr,
  364. /* Maker */ nullptr,
  365. /* Copyright */ nullptr,
  366. /* PortCount */ 0,
  367. /* PortDescriptors */ nullptr,
  368. /* PortNames */ nullptr,
  369. /* PortRangeHints */ nullptr,
  370. /* ImplementationData */ nullptr,
  371. ladspa_instantiate,
  372. ladspa_connect_port,
  373. ladspa_activate,
  374. ladspa_run,
  375. /* run_adding */ nullptr,
  376. /* set_run_adding_gain */ nullptr,
  377. ladspa_deactivate,
  378. ladspa_cleanup
  379. };
  380. #ifdef DISTRHO_PLUGIN_TARGET_DSSI
  381. static DSSI_Descriptor descriptor = {
  382. 1,
  383. &ldescriptor,
  384. # if DISTRHO_PLUGIN_WANT_STATE
  385. dssi_configure,
  386. # else
  387. /* configure */ nullptr,
  388. # endif
  389. # if DISTRHO_PLUGIN_WANT_PROGRAMS
  390. dssi_get_program,
  391. dssi_select_program,
  392. # else
  393. /* get_program */ nullptr,
  394. /* select_program */ nullptr,
  395. # endif
  396. /* get_midi_controller_for_port */ nullptr,
  397. # if DISTRHO_PLUGIN_IS_SYNTH
  398. dssi_run_synth,
  399. # else
  400. /* run_synth */ nullptr,
  401. # endif
  402. /* run_synth_adding */ nullptr,
  403. /* run_multiple_synths */ nullptr,
  404. /* run_multiple_synths_adding */ nullptr,
  405. nullptr, nullptr
  406. };
  407. #endif
  408. // -------------------------------------------------
  409. class DescriptorInitializer
  410. {
  411. public:
  412. DescriptorInitializer()
  413. {
  414. // Create dummy plugin to get data from
  415. d_lastBufferSize = 512;
  416. d_lastSampleRate = 44100.0;
  417. PluginInternal plugin;
  418. d_lastBufferSize = 0;
  419. d_lastSampleRate = 0.0;
  420. // Get port count, init
  421. unsigned long i, port = 0;
  422. const unsigned long portCount = DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS + plugin.parameterCount();
  423. #if DISTRHO_PLUGIN_WANT_LATENCY
  424. portCount += 1;
  425. #endif
  426. #if defined(DISTRHO_PLUGIN_TARGET_DSSI) && DISTRHO_PLUGIN_HAS_UI
  427. portCount += 1; // sample-rate
  428. #endif
  429. const char** const portNames = new const char* [portCount];
  430. LADSPA_PortDescriptor* portDescriptors = new LADSPA_PortDescriptor [portCount];
  431. LADSPA_PortRangeHint* portRangeHints = new LADSPA_PortRangeHint [portCount];
  432. // Set ports
  433. for (i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; i++, port++)
  434. {
  435. char const portName[24] = { 0 };
  436. sprintf(portName, "Audio Input %lu", i+1);
  437. portNames[port] = strdup(portName);
  438. portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT;
  439. portRangeHints[port].HintDescriptor = 0;
  440. portRangeHints[port].LowerBound = 0.0f;
  441. portRangeHints[port].UpperBound = 1.0f;
  442. }
  443. for (i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; i++, port++)
  444. {
  445. char const portName[24] = { 0 };
  446. sprintf(portName, "Audio Output %lu", i+1);
  447. portNames[port] = strdup(portName);
  448. portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT;
  449. portRangeHints[port].HintDescriptor = 0;
  450. portRangeHints[port].LowerBound = 0.0f;
  451. portRangeHints[port].UpperBound = 1.0f;
  452. }
  453. #if DISTRHO_PLUGIN_WANT_LATENCY
  454. // Set latency port
  455. portNames[port] = strdup("_latency");
  456. portDescriptors[port] = LADSPA_PORT_CONTROL | LADSPA_PORT_OUTPUT;
  457. portRangeHints[port].HintDescriptor = LADSPA_HINT_SAMPLE_RATE;
  458. portRangeHints[port].LowerBound = 0.0f;
  459. portRangeHints[port].UpperBound = 1.0f;
  460. port++;
  461. #endif
  462. #if defined(DISTRHO_PLUGIN_TARGET_DSSI) && DISTRHO_PLUGIN_HAS_UI
  463. // Set sample-rate port
  464. portNames[port] = strdup("_sample-rate");
  465. portDescriptors[port] = LADSPA_PORT_CONTROL | LADSPA_PORT_OUTPUT;
  466. portRangeHints[port].HintDescriptor = LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE;
  467. portRangeHints[port].LowerBound = 0.0f;
  468. portRangeHints[port].UpperBound = 512000.0f;
  469. port++;
  470. #endif
  471. for (i=0; i < plugin.parameterCount(); i++, port++)
  472. {
  473. portNames[port] = strdup((const char*)plugin.parameterName(i));
  474. portDescriptors[port] = LADSPA_PORT_CONTROL;
  475. if (plugin.parameterIsOutput(i))
  476. portDescriptors[port] |= LADSPA_PORT_OUTPUT;
  477. else
  478. portDescriptors[port] |= LADSPA_PORT_INPUT;
  479. {
  480. const ParameterRanges& ranges = plugin.parameterRanges(i);
  481. const float defValue = ranges.def;
  482. portRangeHints[port].HintDescriptor = LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE;
  483. portRangeHints[port].LowerBound = ranges.min;
  484. portRangeHints[port].UpperBound = ranges.max;
  485. if (defValue == 0.0f)
  486. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_0;
  487. else if (defValue == 1.0f)
  488. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_1;
  489. else if (defValue == 100.0f)
  490. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_100;
  491. else if (defValue == 440.0f)
  492. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_440;
  493. else if (ranges.min == defValue)
  494. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MINIMUM;
  495. else if (ranges.max == defValue)
  496. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM;
  497. else
  498. {
  499. const float middleValue = ranges.min/2 + ranges.max/2;
  500. const float middleLow = (ranges.min/2 + middleValue/2)/2 + middleValue/2;
  501. const float middleHigh = (ranges.max/2 + middleValue/2)/2 + middleValue/2;
  502. if (defValue < middleLow)
  503. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_LOW;
  504. else if (defValue > middleHigh)
  505. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_HIGH;
  506. else
  507. portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MIDDLE;
  508. }
  509. }
  510. {
  511. const uint32_t hints = plugin.parameterHints(i);
  512. if (hints & PARAMETER_IS_BOOLEAN)
  513. portRangeHints[port].HintDescriptor |= LADSPA_HINT_TOGGLED;
  514. if (hints & PARAMETER_IS_INTEGER)
  515. portRangeHints[port].HintDescriptor |= LADSPA_HINT_INTEGER;
  516. if (hints & PARAMETER_IS_LOGARITHMIC)
  517. portRangeHints[port].HintDescriptor |= LADSPA_HINT_LOGARITHMIC;
  518. }
  519. }
  520. // Set data
  521. ldescriptor.UniqueID = plugin.uniqueId();
  522. ldescriptor.Label = strdup(plugin.label());
  523. ldescriptor.Name = strdup(plugin.name());
  524. ldescriptor.Maker = strdup(plugin.maker());
  525. ldescriptor.Copyright = strdup(plugin.license());
  526. ldescriptor.PortCount = portCount;
  527. ldescriptor.PortNames = portNames;
  528. ldescriptor.PortDescriptors = portDescriptors;
  529. ldescriptor.PortRangeHints = portRangeHints;
  530. }
  531. ~DescriptorInitializer()
  532. {
  533. if (ldescriptor.Label)
  534. free((void*)ldescriptor.Label);
  535. if (ldescriptor.Name)
  536. free((void*)ldescriptor.Name);
  537. if (ldescriptor.Maker)
  538. free((void*)ldescriptor.Maker);
  539. if (ldescriptor.Copyright)
  540. free((void*)ldescriptor.Copyright);
  541. if (ldescriptor.PortDescriptors)
  542. delete[] ldescriptor.PortDescriptors;
  543. if (ldescriptor.PortRangeHints)
  544. delete[] ldescriptor.PortRangeHints;
  545. if (ldescriptor.PortNames)
  546. {
  547. for (unsigned long i=0; i < ldescriptor.PortCount; i++)
  548. {
  549. if (ldescriptor.PortNames[i])
  550. free((void*)ldescriptor.PortNames[i]);
  551. }
  552. delete[] ldescriptor.PortNames;
  553. }
  554. }
  555. };
  556. static DescriptorInitializer init;
  557. END_NAMESPACE_DISTRHO
  558. // -------------------------------------------------
  559. DISTRHO_PLUGIN_EXPORT
  560. const LADSPA_Descriptor* ladspa_descriptor(unsigned long index)
  561. {
  562. USE_NAMESPACE_DISTRHO
  563. return (index == 0) ? &ldescriptor : nullptr;
  564. }
  565. #ifdef DISTRHO_PLUGIN_TARGET_DSSI
  566. DISTRHO_PLUGIN_EXPORT
  567. const DSSI_Descriptor* dssi_descriptor(unsigned long index)
  568. {
  569. USE_NAMESPACE_DISTRHO
  570. return (index == 0) ? &descriptor : nullptr;
  571. }
  572. #endif
  573. // -------------------------------------------------
  574. #endif // DISTRHO_PLUGIN_TARGET_LADSPA || DISTRHO_PLUGIN_TARGET_DSSI