1 /*
2  * DISTRHO Plugin Framework (DPF)
3  * Copyright (C) 2012-2020 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 #include "lv2/atom.h"
20 #include "lv2/atom-util.h"
21 #include "lv2/buf-size.h"
22 #include "lv2/data-access.h"
23 #include "lv2/instance-access.h"
24 #include "lv2/midi.h"
25 #include "lv2/options.h"
26 #include "lv2/parameters.h"
27 #include "lv2/patch.h"
28 #include "lv2/state.h"
29 #include "lv2/time.h"
30 #include "lv2/urid.h"
31 #include "lv2/worker.h"
32 #include "lv2/lv2_kxstudio_properties.h"
33 #include "lv2/lv2_programs.h"
34 
35 #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
36 # include "libmodla.h"
37 #endif
38 
39 #ifdef noexcept
40 # undef noexcept
41 #endif
42 
43 #include <map>
44 
45 #ifndef DISTRHO_PLUGIN_URI
46 # error DISTRHO_PLUGIN_URI undefined!
47 #endif
48 
49 #ifndef DISTRHO_PLUGIN_LV2_STATE_PREFIX
50 # define DISTRHO_PLUGIN_LV2_STATE_PREFIX "urn:distrho:"
51 #endif
52 
53 #define DISTRHO_LV2_USE_EVENTS_IN  (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
54 #define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
55 
56 START_NAMESPACE_DISTRHO
57 
58 typedef std::map<const String, String> StringToStringMap;
59 typedef std::map<const LV2_URID, String> UridToStringMap;
60 
61 #if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
62 static const writeMidiFunc writeMidiCallback = nullptr;
63 #endif
64 
65 // -----------------------------------------------------------------------
66 
67 class PluginLv2
68 {
69 public:
70     PluginLv2(const double sampleRate,
71               const LV2_URID_Map* const uridMap,
72               const LV2_Worker_Schedule* const worker,
73               const bool usingNominal)
74         : fPlugin(this, writeMidiCallback),
75           fUsingNominal(usingNominal),
76 #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
77           fRunCount(0),
78 #endif
79           fPortControls(nullptr),
80           fLastControlValues(nullptr),
81           fSampleRate(sampleRate),
82           fURIDs(uridMap),
83           fUridMap(uridMap),
84           fWorker(worker)
85     {
86 #if DISTRHO_PLUGIN_NUM_INPUTS > 0
87         for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
88             fPortAudioIns[i] = nullptr;
89 #else
90         fPortAudioIns = nullptr;
91 #endif
92 
93 #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
94         for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
95             fPortAudioOuts[i] = nullptr;
96 #else
97         fPortAudioOuts = nullptr;
98 #endif
99 
100         if (const uint32_t count = fPlugin.getParameterCount())
101         {
102             fPortControls      = new float*[count];
103             fLastControlValues = new float[count];
104 
105             for (uint32_t i=0; i < count; ++i)
106             {
107                 fPortControls[i] = nullptr;
108                 fLastControlValues[i] = fPlugin.getParameterValue(i);
109             }
110         }
111         else
112         {
113             fPortControls      = nullptr;
114             fLastControlValues = nullptr;
115         }
116 
117 #if DISTRHO_LV2_USE_EVENTS_IN
118         fPortEventsIn = nullptr;
119 #endif
120 #if DISTRHO_PLUGIN_WANT_LATENCY
121         fPortLatency = nullptr;
122 #endif
123 
124 #if DISTRHO_PLUGIN_WANT_STATE
125         if (const uint32_t count = fPlugin.getStateCount())
126         {
127             fNeededUiSends = new bool[count];
128 
129             for (uint32_t i=0; i < count; ++i)
130             {
131                 fNeededUiSends[i] = false;
132 
133                 const String& dkey(fPlugin.getStateKey(i));
134                 fStateMap[dkey] = fPlugin.getStateDefaultValue(i);
135 
136 # if DISTRHO_PLUGIN_WANT_STATEFILES
137                 if (fPlugin.isStateFile(i))
138                 {
139                     const String dpf_lv2_key(DISTRHO_PLUGIN_URI "#" + dkey);
140                     const LV2_URID urid = uridMap->map(uridMap->handle, dpf_lv2_key.buffer());
141                     fUridStateFileMap[urid] = dkey;
142                 }
143 # endif
144             }
145         }
146         else
147         {
148             fNeededUiSends = nullptr;
149         }
150 #else
151         // unused
152         (void)fWorker;
153 #endif
154     }
155 
156     ~PluginLv2()
157     {
158         if (fPortControls != nullptr)
159         {
160             delete[] fPortControls;
161             fPortControls = nullptr;
162         }
163 
164         if (fLastControlValues)
165         {
166             delete[] fLastControlValues;
167             fLastControlValues = nullptr;
168         }
169 
170 #if DISTRHO_PLUGIN_WANT_STATE
171         if (fNeededUiSends != nullptr)
172         {
173             delete[] fNeededUiSends;
174             fNeededUiSends = nullptr;
175         }
176 
177         fStateMap.clear();
178 #endif
179     }
180 
181     // -------------------------------------------------------------------
182 
183     bool getPortControlValue(uint32_t index, float& value) const
184     {
185         if (const float* control = fPortControls[index])
186         {
187             switch (fPlugin.getParameterDesignation(index))
188             {
189             default:
190                 value = *control;
191                 break;
192             case kParameterDesignationBypass:
193                 value = 1.0f - *control;
194                 break;
195             }
196 
197             return true;
198         }
199 
200         return false;
201     }
202 
203     void setPortControlValue(uint32_t index, float value)
204     {
205         if (float* control = fPortControls[index])
206         {
207             switch (fPlugin.getParameterDesignation(index))
208             {
209             default:
210                 *control = value;
211                 break;
212             case kParameterDesignationBypass:
213                 *control = 1.0f - value;
214                 break;
215             }
216         }
217     }
218 
219     // -------------------------------------------------------------------
220 
221     void lv2_activate()
222     {
223 #if DISTRHO_PLUGIN_WANT_TIMEPOS
224         fTimePosition.clear();
225 
226         // hosts may not send all values, resulting on some invalid data
227         fTimePosition.bbt.bar   = 1;
228         fTimePosition.bbt.beat  = 1;
229         fTimePosition.bbt.tick  = 0;
230         fTimePosition.bbt.barStartTick = 0;
231         fTimePosition.bbt.beatsPerBar  = 4;
232         fTimePosition.bbt.beatType     = 4;
233         fTimePosition.bbt.ticksPerBeat = 960.0;
234         fTimePosition.bbt.beatsPerMinute = 120.0;
235 #endif
236         fPlugin.activate();
237     }
238 
239     void lv2_deactivate()
240     {
241         fPlugin.deactivate();
242     }
243 
244     // -------------------------------------------------------------------
245 
246     void lv2_connect_port(const uint32_t port, void* const dataLocation)
247     {
248         uint32_t index = 0;
249 
250 #if DISTRHO_PLUGIN_NUM_INPUTS > 0
251         for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
252         {
253             if (port == index++)
254             {
255                 fPortAudioIns[i] = (const float*)dataLocation;
256                 return;
257             }
258         }
259 #endif
260 
261 #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
262         for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
263         {
264             if (port == index++)
265             {
266                 fPortAudioOuts[i] = (float*)dataLocation;
267                 return;
268             }
269         }
270 #endif
271 
272 #if DISTRHO_LV2_USE_EVENTS_IN
273         if (port == index++)
274         {
275             fPortEventsIn = (LV2_Atom_Sequence*)dataLocation;
276             return;
277         }
278 #endif
279 
280 #if DISTRHO_LV2_USE_EVENTS_OUT
281         if (port == index++)
282         {
283             fEventsOutData.port = (LV2_Atom_Sequence*)dataLocation;
284             return;
285         }
286 #endif
287 
288 #if DISTRHO_PLUGIN_WANT_LATENCY
289         if (port == index++)
290         {
291             fPortLatency = (float*)dataLocation;
292             return;
293         }
294 #endif
295 
296         for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
297         {
298             if (port == index++)
299             {
300                 fPortControls[i] = (float*)dataLocation;
301                 return;
302             }
303         }
304     }
305 
306     // -------------------------------------------------------------------
307 
308     void lv2_run(const uint32_t sampleCount)
309     {
310         // cache midi input and time position first
311 #if DISTRHO_PLUGIN_WANT_MIDI_INPUT
312         uint32_t midiEventCount = 0;
313 #endif
314 
315 #if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS
316         LV2_ATOM_SEQUENCE_FOREACH(fPortEventsIn, event)
317         {
318             if (event == nullptr)
319                 break;
320 
321 # if DISTRHO_PLUGIN_WANT_MIDI_INPUT
322             if (event->body.type == fURIDs.midiEvent)
323             {
324                 if (midiEventCount >= kMaxMidiEvents)
325                     continue;
326 
327                 const uint8_t* const data((const uint8_t*)(event + 1));
328 
329                 MidiEvent& midiEvent(fMidiEvents[midiEventCount++]);
330 
331                 midiEvent.frame = event->time.frames;
332                 midiEvent.size  = event->body.size;
333 
334                 if (midiEvent.size > MidiEvent::kDataSize)
335                 {
336                     midiEvent.dataExt = data;
337                     std::memset(midiEvent.data, 0, MidiEvent::kDataSize);
338                 }
339                 else
340                 {
341                     midiEvent.dataExt = nullptr;
342                     std::memcpy(midiEvent.data, data, midiEvent.size);
343                 }
344 
345                 continue;
346             }
347 # endif
348 # if DISTRHO_PLUGIN_WANT_TIMEPOS
349             if (event->body.type == fURIDs.atomBlank || event->body.type == fURIDs.atomObject)
350             {
351                 const LV2_Atom_Object* const obj((const LV2_Atom_Object*)&event->body);
352 
353                 if (obj->body.otype != fURIDs.timePosition)
354                     continue;
355 
356                 LV2_Atom* bar     = nullptr;
357                 LV2_Atom* barBeat = nullptr;
358                 LV2_Atom* beatUnit = nullptr;
359                 LV2_Atom* beatsPerBar = nullptr;
360                 LV2_Atom* beatsPerMinute = nullptr;
361                 LV2_Atom* frame = nullptr;
362                 LV2_Atom* speed = nullptr;
363                 LV2_Atom* ticksPerBeat = nullptr;
364 
365                 lv2_atom_object_get(obj,
366                                     fURIDs.timeBar, &bar,
367                                     fURIDs.timeBarBeat, &barBeat,
368                                     fURIDs.timeBeatUnit, &beatUnit,
369                                     fURIDs.timeBeatsPerBar, &beatsPerBar,
370                                     fURIDs.timeBeatsPerMinute, &beatsPerMinute,
371                                     fURIDs.timeFrame, &frame,
372                                     fURIDs.timeSpeed, &speed,
373                                     fURIDs.timeTicksPerBeat, &ticksPerBeat,
374                                     0);
375 
376                 // need to handle this first as other values depend on it
377                 if (ticksPerBeat != nullptr)
378                 {
379                     /**/ if (ticksPerBeat->type == fURIDs.atomDouble)
380                         fLastPositionData.ticksPerBeat = ((LV2_Atom_Double*)ticksPerBeat)->body;
381                     else if (ticksPerBeat->type == fURIDs.atomFloat)
382                         fLastPositionData.ticksPerBeat = ((LV2_Atom_Float*)ticksPerBeat)->body;
383                     else if (ticksPerBeat->type == fURIDs.atomInt)
384                         fLastPositionData.ticksPerBeat = ((LV2_Atom_Int*)ticksPerBeat)->body;
385                     else if (ticksPerBeat->type == fURIDs.atomLong)
386                         fLastPositionData.ticksPerBeat = ((LV2_Atom_Long*)ticksPerBeat)->body;
387                     else
388                         d_stderr("Unknown lv2 ticksPerBeat value type");
389 
390                     if (fLastPositionData.ticksPerBeat > 0.0)
391                         fTimePosition.bbt.ticksPerBeat = fLastPositionData.ticksPerBeat;
392                 }
393 
394                 // same
395                 if (speed != nullptr)
396                 {
397                     /**/ if (speed->type == fURIDs.atomDouble)
398                         fLastPositionData.speed = ((LV2_Atom_Double*)speed)->body;
399                     else if (speed->type == fURIDs.atomFloat)
400                         fLastPositionData.speed = ((LV2_Atom_Float*)speed)->body;
401                     else if (speed->type == fURIDs.atomInt)
402                         fLastPositionData.speed = ((LV2_Atom_Int*)speed)->body;
403                     else if (speed->type == fURIDs.atomLong)
404                         fLastPositionData.speed = ((LV2_Atom_Long*)speed)->body;
405                     else
406                         d_stderr("Unknown lv2 speed value type");
407 
408                     fTimePosition.playing = d_isNotZero(fLastPositionData.speed);
409                 }
410 
411                 if (bar != nullptr)
412                 {
413                     /**/ if (bar->type == fURIDs.atomDouble)
414                         fLastPositionData.bar = ((LV2_Atom_Double*)bar)->body;
415                     else if (bar->type == fURIDs.atomFloat)
416                         fLastPositionData.bar = ((LV2_Atom_Float*)bar)->body;
417                     else if (bar->type == fURIDs.atomInt)
418                         fLastPositionData.bar = ((LV2_Atom_Int*)bar)->body;
419                     else if (bar->type == fURIDs.atomLong)
420                         fLastPositionData.bar = ((LV2_Atom_Long*)bar)->body;
421                     else
422                         d_stderr("Unknown lv2 bar value type");
423 
424                     if (fLastPositionData.bar >= 0)
425                         fTimePosition.bbt.bar = fLastPositionData.bar + 1;
426                 }
427 
428                 if (barBeat != nullptr)
429                 {
430                     /**/ if (barBeat->type == fURIDs.atomDouble)
431                         fLastPositionData.barBeat = ((LV2_Atom_Double*)barBeat)->body;
432                     else if (barBeat->type == fURIDs.atomFloat)
433                         fLastPositionData.barBeat = ((LV2_Atom_Float*)barBeat)->body;
434                     else if (barBeat->type == fURIDs.atomInt)
435                         fLastPositionData.barBeat = ((LV2_Atom_Int*)barBeat)->body;
436                     else if (barBeat->type == fURIDs.atomLong)
437                         fLastPositionData.barBeat = ((LV2_Atom_Long*)barBeat)->body;
438                     else
439                         d_stderr("Unknown lv2 barBeat value type");
440 
441                     if (fLastPositionData.barBeat >= 0.0f)
442                     {
443                         const double rest = std::fmod(fLastPositionData.barBeat, 1.0f);
444                         fTimePosition.bbt.beat = std::round(fLastPositionData.barBeat-rest+1.0);
445                         fTimePosition.bbt.tick = rest*fTimePosition.bbt.ticksPerBeat+0.5;
446                     }
447                 }
448 
449                 if (beatUnit != nullptr)
450                 {
451                     /**/ if (beatUnit->type == fURIDs.atomDouble)
452                         fLastPositionData.beatUnit = ((LV2_Atom_Double*)beatUnit)->body;
453                     else if (beatUnit->type == fURIDs.atomFloat)
454                         fLastPositionData.beatUnit = ((LV2_Atom_Float*)beatUnit)->body;
455                     else if (beatUnit->type == fURIDs.atomInt)
456                         fLastPositionData.beatUnit = ((LV2_Atom_Int*)beatUnit)->body;
457                     else if (beatUnit->type == fURIDs.atomLong)
458                         fLastPositionData.beatUnit = ((LV2_Atom_Long*)beatUnit)->body;
459                     else
460                         d_stderr("Unknown lv2 beatUnit value type");
461 
462                     if (fLastPositionData.beatUnit > 0)
463                         fTimePosition.bbt.beatType = fLastPositionData.beatUnit;
464                 }
465 
466                 if (beatsPerBar != nullptr)
467                 {
468                     /**/ if (beatsPerBar->type == fURIDs.atomDouble)
469                         fLastPositionData.beatsPerBar = ((LV2_Atom_Double*)beatsPerBar)->body;
470                     else if (beatsPerBar->type == fURIDs.atomFloat)
471                         fLastPositionData.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body;
472                     else if (beatsPerBar->type == fURIDs.atomInt)
473                         fLastPositionData.beatsPerBar = ((LV2_Atom_Int*)beatsPerBar)->body;
474                     else if (beatsPerBar->type == fURIDs.atomLong)
475                         fLastPositionData.beatsPerBar = ((LV2_Atom_Long*)beatsPerBar)->body;
476                     else
477                         d_stderr("Unknown lv2 beatsPerBar value type");
478 
479                     if (fLastPositionData.beatsPerBar > 0.0f)
480                         fTimePosition.bbt.beatsPerBar = fLastPositionData.beatsPerBar;
481                 }
482 
483                 if (beatsPerMinute != nullptr)
484                 {
485                     /**/ if (beatsPerMinute->type == fURIDs.atomDouble)
486                         fLastPositionData.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body;
487                     else if (beatsPerMinute->type == fURIDs.atomFloat)
488                         fLastPositionData.beatsPerMinute = ((LV2_Atom_Float*)beatsPerMinute)->body;
489                     else if (beatsPerMinute->type == fURIDs.atomInt)
490                         fLastPositionData.beatsPerMinute = ((LV2_Atom_Int*)beatsPerMinute)->body;
491                     else if (beatsPerMinute->type == fURIDs.atomLong)
492                         fLastPositionData.beatsPerMinute = ((LV2_Atom_Long*)beatsPerMinute)->body;
493                     else
494                         d_stderr("Unknown lv2 beatsPerMinute value type");
495 
496                     if (fLastPositionData.beatsPerMinute > 0.0f)
497                     {
498                         fTimePosition.bbt.beatsPerMinute = fLastPositionData.beatsPerMinute;
499 
500                         if (d_isNotZero(fLastPositionData.speed))
501                             fTimePosition.bbt.beatsPerMinute *= std::abs(fLastPositionData.speed);
502                     }
503                 }
504 
505                 if (frame != nullptr)
506                 {
507                     /**/ if (frame->type == fURIDs.atomDouble)
508                         fLastPositionData.frame = ((LV2_Atom_Double*)frame)->body;
509                     else if (frame->type == fURIDs.atomFloat)
510                         fLastPositionData.frame = ((LV2_Atom_Float*)frame)->body;
511                     else if (frame->type == fURIDs.atomInt)
512                         fLastPositionData.frame = ((LV2_Atom_Int*)frame)->body;
513                     else if (frame->type == fURIDs.atomLong)
514                         fLastPositionData.frame = ((LV2_Atom_Long*)frame)->body;
515                     else
516                         d_stderr("Unknown lv2 frame value type");
517 
518                     if (fLastPositionData.frame >= 0)
519                         fTimePosition.frame = fLastPositionData.frame;
520                 }
521 
522                 fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*
523                                                  fTimePosition.bbt.beatsPerBar*
524                                                  (fTimePosition.bbt.bar-1);
525 
526                 fTimePosition.bbt.valid = (fLastPositionData.beatsPerMinute > 0.0 &&
527                                            fLastPositionData.beatUnit > 0 &&
528                                            fLastPositionData.beatsPerBar > 0.0f);
529 
530                 fPlugin.setTimePosition(fTimePosition);
531 
532                 continue;
533             }
534 # endif
535         }
536 #endif
537 
538         // check for messages from UI or files
539 #if DISTRHO_PLUGIN_WANT_STATE && (DISTRHO_PLUGIN_HAS_UI || DISTRHO_PLUGIN_WANT_STATEFILES)
540         LV2_ATOM_SEQUENCE_FOREACH(fPortEventsIn, event)
541         {
542             if (event == nullptr)
543                 break;
544 
545             if (event->body.type == fURIDs.dpfKeyValue)
546             {
547                 const void* const data = (const void*)(event + 1);
548 
549                 // check if this is our special message
550                 if (std::strcmp((const char*)data, "__dpf_ui_data__") == 0)
551                 {
552                     for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i)
553                         fNeededUiSends[i] = true;
554                 }
555                 // no, send to DSP as usual
556                 else if (fWorker != nullptr)
557                 {
558                     fWorker->schedule_work(fWorker->handle, sizeof(LV2_Atom)+event->body.size, &event->body);
559                 }
560             }
561 # if DISTRHO_PLUGIN_WANT_STATEFILES
562             else if (event->body.type == fURIDs.atomObject && fWorker != nullptr)
563             {
564                 const LV2_Atom_Object* const object = (const LV2_Atom_Object*)&event->body;
565 
566                 const LV2_Atom* property = nullptr;
567                 const LV2_Atom* value    = nullptr;
568                 lv2_atom_object_get(object, fURIDs.patchProperty, &property, fURIDs.patchValue, &value, nullptr);
569 
570                 if (property != nullptr && property->type == fURIDs.atomURID &&
571                     value != nullptr && value->type == fURIDs.atomPath)
572                 {
573                     fWorker->schedule_work(fWorker->handle, sizeof(LV2_Atom)+event->body.size, &event->body);
574                 }
575             }
576 # endif
577         }
578 #endif
579 
580         // Check for updated parameters
581         float curValue;
582 
583         for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
584         {
585             if (!getPortControlValue(i, curValue))
586                 continue;
587 
588             if (fPlugin.isParameterInput(i) && d_isNotEqual(fLastControlValues[i], curValue))
589             {
590                 fLastControlValues[i] = curValue;
591 
592                 fPlugin.setParameterValue(i, curValue);
593             }
594         }
595 
596         // Run plugin
597         if (sampleCount != 0)
598         {
599 #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
600             fRunCount = mod_license_run_begin(fRunCount, sampleCount);
601 #endif
602 
603 #if DISTRHO_PLUGIN_WANT_MIDI_INPUT
604             fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, fMidiEvents, midiEventCount);
605 #else
606             fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount);
607 #endif
608 
609 #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
610             for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
611                 mod_license_run_silence(fRunCount, fPortAudioOuts[i], sampleCount, i);
612 #endif
613 
614 #if DISTRHO_PLUGIN_WANT_TIMEPOS
615             // update timePos for next callback
616             if (d_isNotZero(fLastPositionData.speed))
617             {
618                 if (fLastPositionData.speed > 0.0)
619                 {
620                     // playing forwards
621                     fLastPositionData.frame += sampleCount;
622                 }
623                 else
624                 {
625                     // playing backwards
626                     fLastPositionData.frame -= sampleCount;
627 
628                     if (fLastPositionData.frame < 0)
629                         fLastPositionData.frame = 0;
630                 }
631 
632                 fTimePosition.frame = fLastPositionData.frame;
633 
634                 if (fTimePosition.bbt.valid)
635                 {
636                     const double beatsPerMinute = fLastPositionData.beatsPerMinute * fLastPositionData.speed;
637                     const double framesPerBeat  = 60.0 * fSampleRate / beatsPerMinute;
638                     const double addedBarBeats  = double(sampleCount) / framesPerBeat;
639 
640                     if (fLastPositionData.barBeat >= 0.0f)
641                     {
642                         fLastPositionData.barBeat = std::fmod(fLastPositionData.barBeat+addedBarBeats,
643                                                               (double)fLastPositionData.beatsPerBar);
644 
645                         const double rest = std::fmod(fLastPositionData.barBeat, 1.0f);
646                         fTimePosition.bbt.beat = std::round(fLastPositionData.barBeat-rest+1.0);
647                         fTimePosition.bbt.tick = rest*fTimePosition.bbt.ticksPerBeat+0.5;
648 
649                         if (fLastPositionData.bar >= 0)
650                         {
651                             fLastPositionData.bar += std::floor((fLastPositionData.barBeat+addedBarBeats)/
652                                                              fLastPositionData.beatsPerBar);
653 
654                             if (fLastPositionData.bar < 0)
655                                 fLastPositionData.bar = 0;
656 
657                             fTimePosition.bbt.bar = fLastPositionData.bar + 1;
658 
659                             fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*
660                                                              fTimePosition.bbt.beatsPerBar*
661                                                             (fTimePosition.bbt.bar-1);
662                         }
663                     }
664 
665                     fTimePosition.bbt.beatsPerMinute = std::abs(beatsPerMinute);
666                 }
667 
668                 fPlugin.setTimePosition(fTimePosition);
669             }
670 #endif
671         }
672 
673         updateParameterOutputsAndTriggers();
674 
675 #if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI
676         fEventsOutData.initIfNeeded(fURIDs.atomSequence);
677 
678         LV2_Atom_Event* aev;
679         const uint32_t capacity = fEventsOutData.capacity;
680 
681         for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i)
682         {
683             if (! fNeededUiSends[i])
684                 continue;
685 
686             const String& curKey(fPlugin.getStateKey(i));
687 
688             for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit)
689             {
690                 const String& key(cit->first);
691 
692                 if (curKey != key)
693                     continue;
694 
695                 const String& value(cit->second);
696 
697                 // set msg size (key + value + separator + 2x null terminator)
698                 const size_t msgSize = key.length()+value.length()+3;
699 
700                 if (sizeof(LV2_Atom_Event) + msgSize > capacity - fEventsOutData.offset)
701                 {
702                     d_stdout("Sending key '%s' to UI failed, out of space", key.buffer());
703                     break;
704                 }
705 
706                 // put data
707                 aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fEventsOutData.port) + fEventsOutData.offset);
708                 aev->time.frames = 0;
709                 aev->body.type   = fURIDs.dpfKeyValue;
710                 aev->body.size   = msgSize;
711 
712                 uint8_t* const msgBuf = LV2_ATOM_BODY(&aev->body);
713                 std::memset(msgBuf, 0, msgSize);
714 
715                 // write key and value in atom buffer
716                 std::memcpy(msgBuf, key.buffer(), key.length()+1);
717                 std::memcpy(msgBuf+(key.length()+1), value.buffer(), value.length()+1);
718 
719                 fEventsOutData.growBy(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + msgSize));
720 
721                 fNeededUiSends[i] = false;
722                 break;
723             }
724         }
725 #endif
726 
727 #if DISTRHO_LV2_USE_EVENTS_OUT
728         fEventsOutData.endRun();
729 #endif
730     }
731 
732     // -------------------------------------------------------------------
733 
734     uint32_t lv2_get_options(LV2_Options_Option* const /*options*/)
735     {
736         // currently unused
737         return LV2_OPTIONS_ERR_UNKNOWN;
738     }
739 
740     uint32_t lv2_set_options(const LV2_Options_Option* const options)
741     {
742         for (int i=0; options[i].key != 0; ++i)
743         {
744             if (options[i].key == fUridMap->map(fUridMap->handle, LV2_BUF_SIZE__nominalBlockLength))
745             {
746                 if (options[i].type == fURIDs.atomInt)
747                 {
748                     const int32_t bufferSize(*(const int32_t*)options[i].value);
749                     fPlugin.setBufferSize(bufferSize);
750                 }
751                 else
752                 {
753                     d_stderr("Host changed nominalBlockLength but with wrong value type");
754                 }
755             }
756             else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_BUF_SIZE__maxBlockLength) && ! fUsingNominal)
757             {
758                 if (options[i].type == fURIDs.atomInt)
759                 {
760                     const int32_t bufferSize(*(const int32_t*)options[i].value);
761                     fPlugin.setBufferSize(bufferSize);
762                 }
763                 else
764                 {
765                     d_stderr("Host changed maxBlockLength but with wrong value type");
766                 }
767             }
768             else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_PARAMETERS__sampleRate))
769             {
770                 if (options[i].type == fURIDs.atomFloat)
771                 {
772                     const float sampleRate(*(const float*)options[i].value);
773                     fSampleRate = sampleRate;
774                     fPlugin.setSampleRate(sampleRate);
775                 }
776                 else
777                 {
778                     d_stderr("Host changed sampleRate but with wrong value type");
779                 }
780             }
781         }
782 
783         return LV2_OPTIONS_SUCCESS;
784     }
785 
786     // -------------------------------------------------------------------
787 
788 #if DISTRHO_PLUGIN_WANT_PROGRAMS
789     const LV2_Program_Descriptor* lv2_get_program(const uint32_t index)
790     {
791         if (index >= fPlugin.getProgramCount())
792             return nullptr;
793 
794         static LV2_Program_Descriptor desc;
795 
796         desc.bank    = index / 128;
797         desc.program = index % 128;
798         desc.name    = fPlugin.getProgramName(index);
799 
800         return &desc;
801     }
802 
803     void lv2_select_program(const uint32_t bank, const uint32_t program)
804     {
805         const uint32_t realProgram(bank * 128 + program);
806 
807         if (realProgram >= fPlugin.getProgramCount())
808             return;
809 
810         fPlugin.loadProgram(realProgram);
811 
812         // Update control inputs
813         for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
814         {
815             if (fPlugin.isParameterOutput(i))
816                 continue;
817 
818             fLastControlValues[i] = fPlugin.getParameterValue(i);
819 
820             setPortControlValue(i, fLastControlValues[i]);
821         }
822 
823 # if DISTRHO_PLUGIN_WANT_FULL_STATE
824         // Update state
825         for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit)
826         {
827             const String& key = cit->first;
828             fStateMap[key] = fPlugin.getState(key);
829         }
830 # endif
831     }
832 #endif
833 
834     // -------------------------------------------------------------------
835 
836 #if DISTRHO_PLUGIN_WANT_STATE
837     LV2_State_Status lv2_save(const LV2_State_Store_Function store, const LV2_State_Handle handle)
838     {
839 # if DISTRHO_PLUGIN_WANT_FULL_STATE
840         // Update current state
841         for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit)
842         {
843             const String& key = cit->first;
844             fStateMap[key] = fPlugin.getState(key);
845         }
846 # endif
847 
848         String dpf_lv2_key;
849         LV2_URID urid;
850 
851         for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i)
852         {
853             const String& curKey(fPlugin.getStateKey(i));
854 
855             for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit)
856             {
857                 const String& key(cit->first);
858 
859                 if (curKey != key)
860                     continue;
861 
862                 const String& value(cit->second);
863 
864 # if DISTRHO_PLUGIN_WANT_STATEFILES
865                 if (fPlugin.isStateFile(i))
866                 {
867                     dpf_lv2_key = DISTRHO_PLUGIN_URI "#";
868                     urid = fURIDs.atomPath;
869                 }
870                 else
871 # endif
872                 {
873                     dpf_lv2_key = DISTRHO_PLUGIN_LV2_STATE_PREFIX;
874                     urid = fURIDs.atomString;
875                 }
876 
877                 dpf_lv2_key += key;
878 
879                 // some hosts need +1 for the null terminator, even though the type is string
880                 store(handle,
881                       fUridMap->map(fUridMap->handle, dpf_lv2_key.buffer()),
882                       value.buffer(),
883                       value.length()+1,
884                       urid,
885                       LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE);
886             }
887         }
888 
889         return LV2_STATE_SUCCESS;
890     }
891 
892     LV2_State_Status lv2_restore(const LV2_State_Retrieve_Function retrieve, const LV2_State_Handle handle)
893     {
894         size_t   size;
895         uint32_t type, flags;
896 
897         String dpf_lv2_key;
898         LV2_URID urid;
899 
900         for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i)
901         {
902             const String& key(fPlugin.getStateKey(i));
903 
904 # if DISTRHO_PLUGIN_WANT_STATEFILES
905             if (fPlugin.isStateFile(i))
906             {
907                 dpf_lv2_key = DISTRHO_PLUGIN_URI "#";
908                 urid = fURIDs.atomPath;
909             }
910             else
911 # endif
912             {
913                 dpf_lv2_key = DISTRHO_PLUGIN_LV2_STATE_PREFIX;
914                 urid = fURIDs.atomString;
915             }
916 
917             dpf_lv2_key += key;
918 
919             size  = 0;
920             type  = 0;
921             flags = LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE;
922             const void* data = retrieve(handle,
923                                         fUridMap->map(fUridMap->handle, dpf_lv2_key.buffer()),
924                                         &size, &type, &flags);
925 
926             if (data == nullptr || size == 0)
927                 continue;
928 
929             DISTRHO_SAFE_ASSERT_CONTINUE(type == urid);
930 
931             const char* const value  = (const char*)data;
932             const std::size_t length = std::strlen(value);
933             DISTRHO_SAFE_ASSERT_CONTINUE(length == size || length+1 == size);
934 
935             setState(key, value);
936 
937 #if DISTRHO_LV2_USE_EVENTS_OUT
938             // signal msg needed for UI
939             fNeededUiSends[i] = true;
940 #endif
941         }
942 
943         return LV2_STATE_SUCCESS;
944     }
945 
946     // -------------------------------------------------------------------
947 
948     LV2_Worker_Status lv2_work(const void* const data)
949     {
950         const LV2_Atom* const eventBody = (const LV2_Atom*)data;
951 
952         if (eventBody->type == fURIDs.dpfKeyValue)
953         {
954             const char* const key   = (const char*)(eventBody + 1);
955             const char* const value = key + (std::strlen(key) + 1U);
956 
957             setState(key, value);
958             return LV2_WORKER_SUCCESS;
959         }
960 
961 # if DISTRHO_PLUGIN_WANT_STATEFILES
962         if (eventBody->type == fURIDs.atomObject)
963         {
964             const LV2_Atom_Object* const object = (const LV2_Atom_Object*)eventBody;
965 
966             const LV2_Atom* property = nullptr;
967             const LV2_Atom* value    = nullptr;
968             lv2_atom_object_get(object, fURIDs.patchProperty, &property, fURIDs.patchValue, &value, nullptr);
969             DISTRHO_SAFE_ASSERT_RETURN(property != nullptr, LV2_WORKER_ERR_UNKNOWN);
970             DISTRHO_SAFE_ASSERT_RETURN(property->type == fURIDs.atomURID, LV2_WORKER_ERR_UNKNOWN);
971             DISTRHO_SAFE_ASSERT_RETURN(value != nullptr, LV2_WORKER_ERR_UNKNOWN);
972             DISTRHO_SAFE_ASSERT_RETURN(value->type == fURIDs.atomPath, LV2_WORKER_ERR_UNKNOWN);
973 
974             const LV2_URID urid        = ((const LV2_Atom_URID*)property)->body;
975             const char* const filename = (const char*)(value + 1);
976 
977             String key;
978 
979             try {
980                 key = fUridStateFileMap[urid];
981             } DISTRHO_SAFE_EXCEPTION_RETURN("lv2_work fUridStateFileMap[urid]", LV2_WORKER_ERR_UNKNOWN);
982 
983             setState(key, filename);
984 
985             for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i)
986             {
987                 if (fPlugin.getStateKey(i) == key)
988                 {
989                     fNeededUiSends[i] = true;
990                     break;
991                 }
992             }
993 
994             return LV2_WORKER_SUCCESS;
995         }
996 # endif
997 
998         return LV2_WORKER_ERR_UNKNOWN;
999     }
1000 
1001     LV2_Worker_Status lv2_work_response(uint32_t, const void*)
1002     {
1003         return LV2_WORKER_SUCCESS;
1004     }
1005 #endif
1006 
1007     // -------------------------------------------------------------------
1008 
1009 #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
1010     void* lv2_get_instance_pointer()
1011     {
1012         return fPlugin.getInstancePointer();
1013     }
1014 #endif
1015 
1016     // -------------------------------------------------------------------
1017 
1018 private:
1019     PluginExporter fPlugin;
1020     const bool fUsingNominal; // if false use maxBlockLength
1021 
1022 #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
1023     uint32_t fRunCount;
1024 #endif
1025 
1026     // LV2 ports
1027 #if DISTRHO_PLUGIN_NUM_INPUTS > 0
1028     const float*  fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS];
1029 #else
1030     const float** fPortAudioIns;
1031 #endif
1032 #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
1033     float*  fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS];
1034 #else
1035     float** fPortAudioOuts;
1036 #endif
1037     float** fPortControls;
1038 #if DISTRHO_LV2_USE_EVENTS_IN
1039     LV2_Atom_Sequence* fPortEventsIn;
1040 #endif
1041 #if DISTRHO_PLUGIN_WANT_LATENCY
1042     float* fPortLatency;
1043 #endif
1044 
1045     // Temporary data
1046     float* fLastControlValues;
1047     double fSampleRate;
1048 #if DISTRHO_PLUGIN_WANT_MIDI_INPUT
1049     MidiEvent fMidiEvents[kMaxMidiEvents];
1050 #endif
1051 #if DISTRHO_PLUGIN_WANT_TIMEPOS
1052     TimePosition fTimePosition;
1053 
1054     struct Lv2PositionData {
1055         int64_t  bar;
1056         float    barBeat;
1057         uint32_t beatUnit;
1058         float    beatsPerBar;
1059         float    beatsPerMinute;
1060         int64_t  frame;
1061         double   speed;
1062         double   ticksPerBeat;
1063 
1064         Lv2PositionData()
1065             : bar(-1),
1066               barBeat(-1.0f),
1067               beatUnit(0),
1068               beatsPerBar(0.0f),
1069               beatsPerMinute(0.0f),
1070               frame(-1),
1071               speed(0.0),
1072               ticksPerBeat(-1.0) {}
1073 
1074     } fLastPositionData;
1075 #endif
1076 
1077 #if DISTRHO_LV2_USE_EVENTS_OUT
1078     struct Lv2EventsOutData {
1079         uint32_t capacity, offset;
1080         LV2_Atom_Sequence* port;
1081 
1082         Lv2EventsOutData()
1083             : capacity(0),
1084               offset(0),
1085               port(nullptr) {}
1086 
1087         void initIfNeeded(const LV2_URID uridAtomSequence)
1088         {
1089             if (capacity != 0)
1090                 return;
1091 
1092             capacity = port->atom.size;
1093 
1094             port->atom.size = sizeof(LV2_Atom_Sequence_Body);
1095             port->atom.type = uridAtomSequence;
1096             port->body.unit = 0;
1097             port->body.pad  = 0;
1098         }
1099 
1100         void growBy(const uint32_t size)
1101         {
1102             offset += size;
1103             port->atom.size += size;
1104         }
1105 
1106         void endRun()
1107         {
1108             capacity = 0;
1109             offset = 0;
1110         }
1111 
1112     } fEventsOutData;
1113 #endif
1114 
1115     // LV2 URIDs
1116     struct URIDs {
1117         const LV2_URID_Map* _uridMap;
1118         LV2_URID atomBlank;
1119         LV2_URID atomObject;
1120         LV2_URID atomDouble;
1121         LV2_URID atomFloat;
1122         LV2_URID atomInt;
1123         LV2_URID atomLong;
1124         LV2_URID atomPath;
1125         LV2_URID atomSequence;
1126         LV2_URID atomString;
1127         LV2_URID atomURID;
1128         LV2_URID dpfKeyValue;
1129         LV2_URID midiEvent;
1130         LV2_URID patchProperty;
1131         LV2_URID patchValue;
1132         LV2_URID timePosition;
1133         LV2_URID timeBar;
1134         LV2_URID timeBarBeat;
1135         LV2_URID timeBeatUnit;
1136         LV2_URID timeBeatsPerBar;
1137         LV2_URID timeBeatsPerMinute;
1138         LV2_URID timeTicksPerBeat;
1139         LV2_URID timeFrame;
1140         LV2_URID timeSpeed;
1141 
1142         URIDs(const LV2_URID_Map* const uridMap)
1143             : _uridMap(uridMap),
1144               atomBlank(map(LV2_ATOM__Blank)),
1145               atomObject(map(LV2_ATOM__Object)),
1146               atomDouble(map(LV2_ATOM__Double)),
1147               atomFloat(map(LV2_ATOM__Float)),
1148               atomInt(map(LV2_ATOM__Int)),
1149               atomLong(map(LV2_ATOM__Long)),
1150               atomPath(map(LV2_ATOM__Path)),
1151               atomSequence(map(LV2_ATOM__Sequence)),
1152               atomString(map(LV2_ATOM__String)),
1153               atomURID(map(LV2_ATOM__URID)),
1154               dpfKeyValue(map(DISTRHO_PLUGIN_LV2_STATE_PREFIX "KeyValueState")),
1155               midiEvent(map(LV2_MIDI__MidiEvent)),
1156               patchProperty(map(LV2_PATCH__property)),
1157               patchValue(map(LV2_PATCH__value)),
1158               timePosition(map(LV2_TIME__Position)),
1159               timeBar(map(LV2_TIME__bar)),
1160               timeBarBeat(map(LV2_TIME__barBeat)),
1161               timeBeatUnit(map(LV2_TIME__beatUnit)),
1162               timeBeatsPerBar(map(LV2_TIME__beatsPerBar)),
1163               timeBeatsPerMinute(map(LV2_TIME__beatsPerMinute)),
1164               timeTicksPerBeat(map(LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat)),
1165               timeFrame(map(LV2_TIME__frame)),
1166               timeSpeed(map(LV2_TIME__speed)) {}
1167 
1168         inline LV2_URID map(const char* const uri) const
1169         {
1170             return _uridMap->map(_uridMap->handle, uri);
1171         }
1172     } fURIDs;
1173 
1174     // LV2 features
1175     const LV2_URID_Map* const fUridMap;
1176     const LV2_Worker_Schedule* const fWorker;
1177 
1178 #if DISTRHO_PLUGIN_WANT_STATE
1179     StringToStringMap fStateMap;
1180     bool* fNeededUiSends;
1181 
1182     void setState(const char* const key, const char* const newValue)
1183     {
1184         fPlugin.setState(key, newValue);
1185 
1186         // check if we want to save this key
1187         if (! fPlugin.wantStateKey(key))
1188             return;
1189 
1190         // check if key already exists
1191         for (StringToStringMap::iterator it=fStateMap.begin(), ite=fStateMap.end(); it != ite; ++it)
1192         {
1193             const String& dkey(it->first);
1194 
1195             if (dkey == key)
1196             {
1197                 it->second = newValue;
1198                 return;
1199             }
1200         }
1201 
1202         d_stderr("Failed to find plugin state with key \"%s\"", key);
1203     }
1204 
1205 # if DISTRHO_PLUGIN_WANT_STATEFILES
1206     UridToStringMap fUridStateFileMap;
1207 # endif
1208 #endif
1209 
1210     void updateParameterOutputsAndTriggers()
1211     {
1212         float curValue;
1213 
1214         for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
1215         {
1216             if (fPlugin.isParameterOutput(i))
1217             {
1218                 curValue = fLastControlValues[i] = fPlugin.getParameterValue(i);
1219 
1220                 setPortControlValue(i, curValue);
1221             }
1222             else if ((fPlugin.getParameterHints(i) & kParameterIsTrigger) == kParameterIsTrigger)
1223             {
1224                 // NOTE: host is responsible for auto-updating control port buffers
1225             }
1226         }
1227 
1228 #if DISTRHO_PLUGIN_WANT_LATENCY
1229         if (fPortLatency != nullptr)
1230             *fPortLatency = fPlugin.getLatency();
1231 #endif
1232     }
1233 
1234 #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
1235     bool writeMidi(const MidiEvent& midiEvent)
1236     {
1237         DISTRHO_SAFE_ASSERT_RETURN(fEventsOutData.port != nullptr, false);
1238 
1239         fEventsOutData.initIfNeeded(fURIDs.atomSequence);
1240 
1241         const uint32_t capacity = fEventsOutData.capacity;
1242         const uint32_t offset = fEventsOutData.offset;
1243 
1244         if (sizeof(LV2_Atom_Event) + midiEvent.size > capacity - offset)
1245             return false;
1246 
1247         LV2_Atom_Event* const aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fEventsOutData.port) + offset);
1248         aev->time.frames = midiEvent.frame;
1249         aev->body.type   = fURIDs.midiEvent;
1250         aev->body.size   = midiEvent.size;
1251         std::memcpy(LV2_ATOM_BODY(&aev->body),
1252                     midiEvent.size > MidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data,
1253                     midiEvent.size);
1254 
1255         fEventsOutData.growBy(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + midiEvent.size));
1256 
1257         return true;
1258     }
1259 
1260     static bool writeMidiCallback(void* ptr, const MidiEvent& midiEvent)
1261     {
1262         return ((PluginLv2*)ptr)->writeMidi(midiEvent);
1263     }
1264 #endif
1265 };
1266 
1267 // -----------------------------------------------------------------------
1268 
1269 static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, const char*, const LV2_Feature* const* features)
1270 {
1271     const LV2_Options_Option* options = nullptr;
1272     const LV2_URID_Map*       uridMap = nullptr;
1273     const LV2_Worker_Schedule* worker = nullptr;
1274 
1275     for (int i=0; features[i] != nullptr; ++i)
1276     {
1277         if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0)
1278             options = (const LV2_Options_Option*)features[i]->data;
1279         else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0)
1280             uridMap = (const LV2_URID_Map*)features[i]->data;
1281         else if (std::strcmp(features[i]->URI, LV2_WORKER__schedule) == 0)
1282             worker = (const LV2_Worker_Schedule*)features[i]->data;
1283     }
1284 
1285     if (options == nullptr)
1286     {
1287         d_stderr("Options feature missing, cannot continue!");
1288         return nullptr;
1289     }
1290 
1291     if (uridMap == nullptr)
1292     {
1293         d_stderr("URID Map feature missing, cannot continue!");
1294         return nullptr;
1295     }
1296 
1297 #if DISTRHO_PLUGIN_WANT_STATE
1298     if (worker == nullptr)
1299     {
1300         d_stderr("Worker feature missing, cannot continue!");
1301         return nullptr;
1302     }
1303 #endif
1304 
1305 #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
1306     mod_license_check(features, DISTRHO_PLUGIN_URI);
1307 #endif
1308 
1309     d_lastBufferSize = 0;
1310     bool usingNominal = false;
1311 
1312     for (int i=0; options[i].key != 0; ++i)
1313     {
1314         if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__nominalBlockLength))
1315         {
1316             if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
1317             {
1318                 d_lastBufferSize = *(const int*)options[i].value;
1319                 usingNominal = true;
1320             }
1321             else
1322             {
1323                 d_stderr("Host provides nominalBlockLength but has wrong value type");
1324             }
1325             break;
1326         }
1327 
1328         if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength))
1329         {
1330             if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
1331                 d_lastBufferSize = *(const int*)options[i].value;
1332             else
1333                 d_stderr("Host provides maxBlockLength but has wrong value type");
1334 
1335             // no break, continue in case host supports nominalBlockLength
1336         }
1337     }
1338 
1339     if (d_lastBufferSize == 0)
1340     {
1341         d_stderr("Host does not provide nominalBlockLength or maxBlockLength options");
1342         d_lastBufferSize = 2048;
1343     }
1344 
1345     d_lastSampleRate = sampleRate;
1346 
1347     return new PluginLv2(sampleRate, uridMap, worker, usingNominal);
1348 }
1349 
1350 #define instancePtr ((PluginLv2*)instance)
1351 
1352 static void lv2_connect_port(LV2_Handle instance, uint32_t port, void* dataLocation)
1353 {
1354     instancePtr->lv2_connect_port(port, dataLocation);
1355 }
1356 
1357 static void lv2_activate(LV2_Handle instance)
1358 {
1359     instancePtr->lv2_activate();
1360 }
1361 
1362 static void lv2_run(LV2_Handle instance, uint32_t sampleCount)
1363 {
1364     instancePtr->lv2_run(sampleCount);
1365 }
1366 
1367 static void lv2_deactivate(LV2_Handle instance)
1368 {
1369     instancePtr->lv2_deactivate();
1370 }
1371 
1372 static void lv2_cleanup(LV2_Handle instance)
1373 {
1374     delete instancePtr;
1375 }
1376 
1377 // -----------------------------------------------------------------------
1378 
1379 static uint32_t lv2_get_options(LV2_Handle instance, LV2_Options_Option* options)
1380 {
1381     return instancePtr->lv2_get_options(options);
1382 }
1383 
1384 static uint32_t lv2_set_options(LV2_Handle instance, const LV2_Options_Option* options)
1385 {
1386     return instancePtr->lv2_set_options(options);
1387 }
1388 
1389 // -----------------------------------------------------------------------
1390 
1391 #if DISTRHO_PLUGIN_WANT_PROGRAMS
1392 static const LV2_Program_Descriptor* lv2_get_program(LV2_Handle instance, uint32_t index)
1393 {
1394     return instancePtr->lv2_get_program(index);
1395 }
1396 
1397 static void lv2_select_program(LV2_Handle instance, uint32_t bank, uint32_t program)
1398 {
1399     instancePtr->lv2_select_program(bank, program);
1400 }
1401 #endif
1402 
1403 // -----------------------------------------------------------------------
1404 
1405 #if DISTRHO_PLUGIN_WANT_STATE
1406 static LV2_State_Status lv2_save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t, const LV2_Feature* const*)
1407 {
1408     return instancePtr->lv2_save(store, handle);
1409 }
1410 
1411 static LV2_State_Status lv2_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t, const LV2_Feature* const*)
1412 {
1413     return instancePtr->lv2_restore(retrieve, handle);
1414 }
1415 
1416 LV2_Worker_Status lv2_work(LV2_Handle instance, LV2_Worker_Respond_Function, LV2_Worker_Respond_Handle, uint32_t, const void* data)
1417 {
1418     return instancePtr->lv2_work(data);
1419 }
1420 
1421 LV2_Worker_Status lv2_work_response(LV2_Handle instance, uint32_t size, const void* body)
1422 {
1423     return instancePtr->lv2_work_response(size, body);
1424 }
1425 #endif
1426 
1427 // -----------------------------------------------------------------------
1428 
1429 #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
1430 static void* lv2_get_instance_pointer(LV2_Handle instance)
1431 {
1432     return instancePtr->lv2_get_instance_pointer();
1433 }
1434 #endif
1435 
1436 // -----------------------------------------------------------------------
1437 
1438 static const void* lv2_extension_data(const char* uri)
1439 {
1440     static const LV2_Options_Interface options = { lv2_get_options, lv2_set_options };
1441 
1442     if (std::strcmp(uri, LV2_OPTIONS__interface) == 0)
1443         return &options;
1444 
1445 #if DISTRHO_PLUGIN_WANT_PROGRAMS
1446     static const LV2_Programs_Interface programs = { lv2_get_program, lv2_select_program };
1447 
1448     if (std::strcmp(uri, LV2_PROGRAMS__Interface) == 0)
1449         return &programs;
1450 #endif
1451 
1452 #if DISTRHO_PLUGIN_WANT_STATE
1453     static const LV2_State_Interface state = { lv2_save, lv2_restore };
1454     static const LV2_Worker_Interface worker = { lv2_work, lv2_work_response, nullptr };
1455 
1456     if (std::strcmp(uri, LV2_STATE__interface) == 0)
1457         return &state;
1458     if (std::strcmp(uri, LV2_WORKER__interface) == 0)
1459         return &worker;
1460 #endif
1461 
1462 #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
1463     struct LV2_DirectAccess_Interface {
1464         void* (*get_instance_pointer)(LV2_Handle handle);
1465     };
1466 
1467     static const LV2_DirectAccess_Interface directaccess = { lv2_get_instance_pointer };
1468 
1469     if (std::strcmp(uri, DISTRHO_PLUGIN_LV2_STATE_PREFIX "direct-access") == 0)
1470         return &directaccess;
1471 #endif
1472 
1473 #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
1474     return mod_license_interface(uri);
1475 #else
1476     return nullptr;
1477 #endif
1478 }
1479 
1480 #undef instancePtr
1481 
1482 // -----------------------------------------------------------------------
1483 
1484 static const LV2_Descriptor sLv2Descriptor = {
1485     DISTRHO_PLUGIN_URI,
1486     lv2_instantiate,
1487     lv2_connect_port,
1488     lv2_activate,
1489     lv2_run,
1490     lv2_deactivate,
1491     lv2_cleanup,
1492     lv2_extension_data
1493 };
1494 
1495 // -----------------------------------------------------------------------
1496 
1497 END_NAMESPACE_DISTRHO
1498 
1499 DISTRHO_PLUGIN_EXPORT
1500 const LV2_Descriptor* lv2_descriptor(uint32_t index)
1501 {
1502     USE_NAMESPACE_DISTRHO
1503     return (index == 0) ? &sLv2Descriptor : nullptr;
1504 }
1505 
1506 // -----------------------------------------------------------------------
1507