comparison DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginLADSPA+DSSI.cpp @ 3:84e66ea83026

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