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.

756 lines
23KB

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