1 /*!
2  * @file midilfo_lv2.cpp
3  * @brief Implements an LV2 plugin inheriting from MidiLfo
4  *
5  *
6  *      Copyright 2009 - 2017 <qmidiarp-devel@lists.sourceforge.net>
7  *
8  *      This program is free software; you can redistribute it and/or modify
9  *      it under the terms of the GNU General Public License as published by
10  *      the Free Software Foundation; either version 2 of the License, or
11  *      (at your option) any later version.
12  *
13  *      This program is distributed in the hope that it will be useful,
14  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *      GNU General Public License for more details.
17  *
18  *      You should have received a copy of the GNU General Public License
19  *      along with this program; if not, write to the Free Software
20  *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  *      MA 02110-1301, USA.
22  *
23  */
24 
25 
26 #include <cstdio>
27 #include "midilfo_lv2.h"
28 
29 MidiLfoLV2::MidiLfoLV2 (
30     double sample_rate, const LV2_Feature *const *host_features )
31     :MidiLfo()
32 {
33     MidiEventID = 0;
34     sampleRate = sample_rate;
getpeereid(int sock,uid_t * uid,gid_t * gid)35     curFrame = 0;
36     inLfoFrame = 0;
37     inEventBuffer = NULL;
38     outEventBuffer = NULL;
39     getNextFrame(0);
40     mouseXCur = 0;
41     mouseYCur = 0;
42     mouseEvCur = 0;
43     tempo = 120.0f;
44     internalTempo = 120.0f;
45     lastMouseIndex = 0;
46 
47     transportBpm = 120.0f;
48     transportFramesDelta = 0;
49     curTick = 0;
50     tempoChangeTick = 0;
51     hostTransport = true;
52     transportSpeed = 0;
53     transportAtomReceived = false;
54 
55     dataChanged = true;
56     ui_up = false;
57 
58     getNextFrame(0);
59 
60     LV2_URID_Map *urid_map;
61 
62     /* Scan host features for URID map */
63 
64     for (int i = 0; host_features[i]; ++i) {
65         if (::strcmp(host_features[i]->URI, LV2_URID_URI "#map") == 0) {
66             urid_map = (LV2_URID_Map *) host_features[i]->data;
67             if (urid_map) {
68                 MidiEventID = urid_map->map(urid_map->handle, LV2_MIDI_EVENT_URI);
69                 break;
70             }
71         }
72     }
73     if (!urid_map) {
74         printf("Host does not support urid:map.\n");
75         return;
76     }
77 
78     lv2_atom_forge_init(&forge, urid_map);
79 
80     /* Map URIS */
81     QMidiArpURIs* const uris = &m_uris;
82     map_uris(urid_map, uris);
83     uridMap = urid_map;
84 }
85 
86 
87 MidiLfoLV2::~MidiLfoLV2 (void)
88 {
89 }
90 
91 void MidiLfoLV2::connect_port ( uint32_t port, void *seqdata )
92 {
93     switch(port) {
94     case 0:
95         inEventBuffer = (LV2_Atom_Sequence*)seqdata;
96         break;
97     case 1:
98         outEventBuffer = (const LV2_Atom_Sequence*)seqdata;
99         break;
100     default:
101         val[port - 2] = (float *) seqdata;
102         break;
103     }
104 }
105 
106 void MidiLfoLV2::updatePosAtom(const LV2_Atom_Object* obj)
107 {
108     if (!hostTransport) return;
109 
110     QMidiArpURIs* const uris = &m_uris;
111 
112     uint64_t pos1 = transportFramesDelta;
113     float bpm1 = tempo;
114     int speed1 = transportSpeed;
115 
116     // flag that the host sends transport information via atom port and
117     // that we will no longer process designated port events
118     transportAtomReceived = true;
119 
120     LV2_Atom *bpm = NULL, *speed = NULL, *pos = NULL;
121     lv2_atom_object_get(obj,
122                         uris->time_frame, &pos,
123                         uris->time_beatsPerMinute, &bpm,
124                         uris->time_speed, &speed,
125                         NULL);
126 
127     if (bpm && bpm->type == uris->atom_Float) bpm1 = ((LV2_Atom_Float*)bpm)->body;
128     if (pos && pos->type == uris->atom_Long)  pos1 = ((LV2_Atom_Long*)pos)->body;
129     if (speed && speed->type == uris->atom_Float) speed1 = ((LV2_Atom_Float*)speed)->body;
130 
131     updatePos(pos1, bpm1, speed1);
132 }
133 
134 void MidiLfoLV2::updatePos(uint64_t pos, float bpm, int speed, bool ignore_pos)
135 {
136     if (transportBpm != bpm) {
137         /* Tempo changed */
138         transportBpm = bpm;
139         tempo = transportBpm;
140         transportSpeed = 0;
141     }
142 
143     if (!ignore_pos) {
144         const float frames_per_beat = 60.0f / transportBpm * sampleRate;
145         transportFramesDelta = pos;
146         tempoChangeTick = pos * TPQN / frames_per_beat;
147     }
148     if (transportSpeed != speed) {
149         /* Speed changed, e.g. 0 (stop) to 1 (play) */
150         transportSpeed = speed;
151         curFrame = transportFramesDelta;
152         inLfoFrame = 0;
153         if (transportSpeed) {
154             setNextTick(tempoChangeTick);
155             getNextFrame(tempoChangeTick);
156         }
157     }
158     //printf("transportBpm %f, transportFramesDelta %d\n", transportBpm, transportFramesDelta);
159 }
160 
161 void MidiLfoLV2::run ( uint32_t nframes )
162 {
163     const uint32_t capacity = outEventBuffer->atom.size;
164     const QMidiArpURIs* uris = &m_uris;
165 
166     lv2_atom_forge_set_buffer(&forge, (uint8_t*)outEventBuffer, capacity);
167     lv2_atom_forge_sequence_head(&forge, &m_lv2frame, 0);
168 
169     updateParams();
170     if (isRecording) {
171         getData(&data);
172     }
173     sendWave();
174 
175     if (inEventBuffer) {
176         LV2_ATOM_SEQUENCE_FOREACH(inEventBuffer, event) {
177             // Control Atom Input
178             if (event && (event->body.type == uris->atom_Object
179                         || event->body.type == uris->atom_Blank)) {
180                 const LV2_Atom_Object* obj = (LV2_Atom_Object*)&event->body;
181                 if (obj->body.otype == uris->time_Position) {
182                     /* Received position information, update */
183                     if (hostTransport) updatePosAtom(obj);
184                 }
185                 else if (obj->body.otype == uris->ui_up) {
186                     /* UI was activated */
187                     ui_up = true;
188                     dataChanged = true;
189                 }
190                 else if (obj->body.otype == uris->ui_down) {
191                     /* UI was closed */
192                     ui_up = false;
193                 }
194                 else if (obj->body.otype == uris->flip_wave) {
195                     /* LFO wave was vertically flipped */
196                     flipWaveVertical();
197                     getData(&data);
198                     updateWaveForm(5);
199                     dataChanged = true;
200                 }
201             }
202             // MIDI Input
203             else if (event && event->body.type == MidiEventID) {
204                 uint8_t *di = (uint8_t *) LV2_ATOM_BODY(&event->body);
205                 MidiEvent inEv = {0, 0, 0, 0};
206                 if ( (di[0] & 0xf0) == 0x90 ) {
207                     inEv.type = EV_NOTEON;
208                     inEv.value = di[2];
209                 }
210                 else if ( (di[0] & 0xf0) == 0x80 ) {
211                     inEv.type = EV_NOTEON;
212                     inEv.value = 0;
213                 }
214                 else if ( (di[0] & 0xf0) == 0xb0 ) {
215                     inEv.type = EV_CONTROLLER;
216                     inEv.value = di[2];
217                 }
218                 else inEv.type = EV_NONE;
219 
220                 inEv.channel = di[0] & 0x0f;
221                 inEv.data=di[1];
222                 int tick = ((uint64_t)(curFrame - transportFramesDelta) * nframes
223                             +(uint64_t)(&event->time.frames) % nframes)
224                             *TPQN*tempo/nframes/60/sampleRate + tempoChangeTick;
225                 if (handleEvent(inEv, tick)) //if event is unmatched, forward it
226                     forgeMidiEvent((int)((uint64_t)(&event->time.frames) % nframes), di, 3);
227             }
228         }
229     }
230 
231 
232         // MIDI and Wave Control Output
233 
234     for (uint f = 0 ; f < nframes; f++) {
235         curTick = (uint64_t)(curFrame - transportFramesDelta)
236                         *TPQN*tempo/60/sampleRate + tempoChangeTick;
237         if ((curTick >= frame.at(inLfoFrame).tick)
238             && (transportSpeed)) {
239             if (!frame.at(inLfoFrame).muted && !isMuted) {
240                 unsigned char d[3];
241                 d[0] = 0xb0 + channelOut;
242                 d[1] = ccnumber;
243                 d[2] = frame.at(inLfoFrame).value;
244                 forgeMidiEvent(f, d, 3);
245                 *val[WaveOut] = (float)d[2] / 128;
246             }
247             inLfoFrame++;
248             inLfoFrame%=frameSize;
249             if (!inLfoFrame) {
250                 framePtr = getFramePtr();
251                 float pos = (float)framePtr;
252                 *val[CURSOR_POS] = pos;
253                 getNextFrame(curTick);
254             }
255         }
256         curFrame++;
257     }
258 }
259 
260 void MidiLfoLV2::forgeMidiEvent(uint32_t f, const uint8_t* const buffer, uint32_t size)
261 {
262     QMidiArpURIs* const uris = &m_uris;
263     LV2_Atom midiatom;
264     midiatom.type = uris->midi_MidiEvent;
265     midiatom.size = size;
266     lv2_atom_forge_frame_time(&forge, f);
267     lv2_atom_forge_raw(&forge, &midiatom, sizeof(LV2_Atom));
268     lv2_atom_forge_raw(&forge, buffer, size);
269     lv2_atom_forge_pad(&forge, sizeof(LV2_Atom) + size);
270 }
271 
272 void MidiLfoLV2::updateParams()
273 {
274     bool changed = false;
275 
276 
277     if (amp != *val[AMPLITUDE]) {
278         changed = true;
279         updateAmplitude(*val[AMPLITUDE]);
280     }
281 
282     if (offs != *val[OFFSET]) {
283         changed = true;
284         updateOffset(*val[OFFSET]);
285         *val[OFFSET] = offs;
286     }
287 
288     if (mouseXCur != *val[MOUSEX] || mouseYCur != *val[MOUSEY]
289                 || mouseEvCur != *val[MOUSEPRESSED]) {
290         int ix = 1;
291         int evtype = 0;
292         changed = true;
293         mouseXCur = *val[MOUSEX];
294         mouseYCur = *val[MOUSEY];
295         if ((mouseEvCur == 2) && (*val[MOUSEPRESSED] != 2) )
296             evtype = 1;
297         else if (*val[MOUSEPRESSED] != -1)
298             evtype = *val[MOUSEPRESSED];
299 
300         mouseEvCur = *val[MOUSEPRESSED];
301 
302         if (mouseEvCur == 2) return; // mouse was released
303         ix = mouseEvent(mouseXCur, mouseYCur, *val[MOUSEBUTTON], evtype);
304         if (evtype == 1) lastMouseIndex = ix; // if we have a new press event set last point index here
305     }
306 
307     if (res != lfoResValues[(int)*val[RESOLUTION]]) {
308         changed = true;
309         updateResolution(lfoResValues[(int)*val[RESOLUTION]]);
310     }
311 
312     if (size != lfoSizeValues[(int)*val[SIZE]]) {
313         changed = true;
314         updateSize(lfoSizeValues[(int)*val[SIZE]]);
315     }
316 
317     if (freq != lfoFreqValues[(int)*val[FREQUENCY]]) {
318         changed = true;
319         updateFrequency(lfoFreqValues[(int)*val[FREQUENCY]]);
320     }
321 
322     if (waveFormIndex != (int)*val[WAVEFORM]) {
323         changed = true;
324         updateWaveForm(*val[WAVEFORM]);
325     }
326 
327     if (curLoopMode != (*val[LOOPMODE])) updateLoop(*val[LOOPMODE]);
328     if (recordMode != ((bool)*val[RECORD])) {
329         setRecordMode((bool)*val[RECORD]);
330     }
331     if (deferChanges != ((bool)*val[DEFER])) deferChanges = ((bool)*val[DEFER]);
332     if (isMuted != (bool)*val[MUTE] && !parChangesPending) {
333         setMuted((bool)(*val[MUTE]));
334         changed = true;
335     }
336 
337     ccnumber =       (int)*val[CC_OUT];
338     ccnumberIn =     (int)*val[CC_IN];
339     enableNoteOff = (bool)*val[ENABLE_NOTEOFF];
340     restartByKbd =  (bool)*val[ENABLE_RESTARTBYKBD];
341     trigByKbd =     (bool)*val[ENABLE_TRIGBYKBD];
342     trigLegato =    (bool)*val[ENABLE_TRIGLEGATO];
343 
344     channelOut =      (int)*val[CH_OUT];
345     chIn =            (int)*val[CH_IN];
346     indexIn[0]   =   (int)*val[INDEX_IN1];
347     indexIn[1]   =   (int)*val[INDEX_IN2];
348     rangeIn[0]   =   (int)*val[RANGE_IN1];
349     rangeIn[1]   =   (int)*val[RANGE_IN2];
350 
351     if (internalTempo != *val[TEMPO]) {
352         internalTempo = *val[TEMPO];
353         initTransport();
354     }
355 
356     if (hostTransport != (bool)(*val[TRANSPORT_MODE])) {
357         hostTransport = (bool)(*val[TRANSPORT_MODE]);
358         initTransport();
359     }
360 
361     if (hostTransport && !transportAtomReceived) {
362         updatePos(  (uint64_t)*val[HOST_POSITION],
363                     (float)*val[HOST_TEMPO],
364                     (int)*val[HOST_SPEED],
365                     false);
366     }
367 
368     if (changed) {
369         getData(&data);
370         dataChanged = true;
371     }
372 }
373 
374 void MidiLfoLV2::initTransport()
375 {
376     if (!hostTransport) {
377         transportFramesDelta = curFrame;
378         if (curTick > 0) tempoChangeTick = curTick;
379         transportBpm = internalTempo;
380         tempo = internalTempo;
381         transportSpeed = 1;
382     }
383     else transportSpeed = 0;
384 
385     setNextTick(tempoChangeTick);
386     getNextFrame(tempoChangeTick);
387     inLfoFrame = 0;
388 }
389 
390 void MidiLfoLV2::sendWave()
391 {
392     if (!(dataChanged && ui_up)) return;
393     dataChanged = false;
394 
395     const QMidiArpURIs* uris = &m_uris;
396     int ct = res * size + 1; // last element in wave is an end tag
397     int tempArray[ct];
398 
399     for (int l1 = 0; l1 < ct; l1++) {
400         tempArray[l1]=data.at(l1).value*((data.at(l1).muted) ? -1 : 1);
401     }
402 
403     /* forge container object of type 'hex_customwave' */
404     LV2_Atom_Forge_Frame lv2frame;
405     lv2_atom_forge_frame_time(&forge, 0);
406     lv2_atom_forge_object(&forge, &lv2frame, 1, uris->hex_customwave);
407 
408     /* Send customWave to UI */
409     lv2_atom_forge_property_head(&forge, uris->hex_customwave, 0);
410     lv2_atom_forge_vector(&forge, sizeof(int), uris->atom_Int,
411         ct, tempArray);
412 
413     /* close-off frame */
414     lv2_atom_forge_pop(&forge, &lv2frame);
415 }
416 
417 static LV2_State_Status MidiLfoLV2_state_restore ( LV2_Handle instance,
418     LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle,
419     uint32_t flags, const LV2_Feature *const * )
420 {
421     MidiLfoLV2 *pPlugin = static_cast<MidiLfoLV2 *> (instance);
422 
423     if (pPlugin == NULL) return LV2_STATE_ERR_UNKNOWN;
424 
425     QMidiArpURIs* const uris = &pPlugin->m_uris;
426 
427     uint32_t type = uris->atom_String;
428 
429     if (type == 0) return LV2_STATE_ERR_BAD_TYPE;
430 
431     size_t size = 0;
432     int l1;
433     uint32_t key = uris->hex_mutemask;
434     if (!key) return LV2_STATE_ERR_NO_PROPERTY;
435 
436     const char *value1
437         = (const char *) (*retrieve)(handle, key, &size, &type, &flags);
438 
439     if (size < 2) return LV2_STATE_ERR_UNKNOWN;
440 
441     pPlugin->setFramePtr(0);
442     pPlugin->maxNPoints = (size - 1 ) / 2;
443 
444     for (l1 = 0; l1 <  pPlugin->maxNPoints; l1++) {
445         pPlugin->muteMask[l1] = (value1[2 * l1 + 1] == '1');
446     }
447 
448     key = uris->hex_customwave;
449     if (!key) return LV2_STATE_ERR_NO_PROPERTY;
450 
451     const char *value
452         = (const char *) (*retrieve)(handle, key, &size, &type, &flags);
453 
454     if (size < 2) return LV2_STATE_ERR_UNKNOWN;
455 
456     Sample sample;
457     int step = TPQN / pPlugin->res;
458     int lt = 0;
459     int min = 127;
460     for (l1 = 0; l1 <  pPlugin->maxNPoints; l1++) {
461         int hi = 0;
462         int lo = 0;
463         if (value[2*l1] <= '9' && value[2*l1] >= '0') hi = value[2*l1] - '0';
464         if (value[2*l1] <= 'f' && value[2*l1] >= 'a') hi = value[2*l1] - 'a' + 10;
465 
466         if (value[2*l1 + 1] <= '9' && value[2*l1 + 1] >= '0') lo = value[2*l1 + 1] - '0';
467         if (value[2*l1 + 1] <= 'f' && value[2*l1 + 1] >= 'a') lo = value[2*l1 + 1] - 'a' + 10;
468 
469         sample.value = hi * 16 + lo;
470         sample.tick = lt;
471         sample.muted = pPlugin->muteMask[l1];
472         pPlugin->customWave[l1] = sample;
473         if (sample.value < min) min = sample.value;
474         lt+=step;
475     }
476     pPlugin->cwmin = min;
477     pPlugin->getData(&pPlugin->data);
478     pPlugin->sendWave();
479 
480     return LV2_STATE_SUCCESS;
481 }
482 
483 static LV2_State_Status MidiLfoLV2_state_save ( LV2_Handle instance,
484     LV2_State_Store_Function store, LV2_State_Handle handle,
485     uint32_t flags, const LV2_Feature *const * )
486 {
487     MidiLfoLV2 *pPlugin = static_cast<MidiLfoLV2 *> (instance);
488 
489     if (pPlugin == NULL) return LV2_STATE_ERR_UNKNOWN;
490 
491     QMidiArpURIs* const uris = &pPlugin->m_uris;
492 
493     uint32_t type = uris->atom_String;
494 
495     if (type == 0) return LV2_STATE_ERR_BAD_TYPE;
496 
497     flags |= (LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
498 
499     const char hexmap[] = {'0', '1', '2', '3', '4', '5', '6', '7',
500                            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
501     int l1;
502     char bt[pPlugin->maxNPoints * 2 + 1];
503 
504     for (l1 = 0; l1 < pPlugin->maxNPoints; l1++) {
505         bt[2*l1] = hexmap[(pPlugin->customWave[l1].value  & 0xF0) >> 4];
506         bt[2*l1 + 1] = hexmap[pPlugin->customWave[l1].value  & 0x0F];
507     }
508     bt[pPlugin->maxNPoints * 2] = '\0';
509 
510     const char *value = bt;
511 
512     size_t size = strlen(value) + 1;
513 
514     uint32_t key = uris->hex_customwave;
515     if (!key) return LV2_STATE_ERR_NO_PROPERTY;
516 
517     store(handle, key, value, size, type, flags);
518 
519     for (l1 = 0; l1 < pPlugin->maxNPoints; l1++) {
520         bt[2*l1] = '0';
521         bt[2*l1 + 1] = hexmap[pPlugin->muteMask[l1]];
522     }
523 
524     const char *value1 = bt;
525 
526     size = strlen(value1) + 1;
527     key = uris->hex_mutemask;
528     if (!key) return LV2_STATE_ERR_NO_PROPERTY;
529 
530     LV2_State_Status result = (*store)(handle, key, value1, size, type, flags);
531 
532     return result;
533 }
534 
535 static const LV2_State_Interface MidiLfoLV2_state_interface =
536 {
537     MidiLfoLV2_state_save,
538     MidiLfoLV2_state_restore
539 };
540 
541 void MidiLfoLV2::activate (void)
542 {
543     initTransport();
544 }
545 
546 void MidiLfoLV2::deactivate (void)
547 {
548     transportSpeed = 0;
549 }
550 
551 static LV2_Handle MidiLfoLV2_instantiate (
552     const LV2_Descriptor *, double sample_rate, const char *,
553     const LV2_Feature *const *host_features )
554 {
555     return new MidiLfoLV2(sample_rate, host_features);
556 }
557 
558 static void MidiLfoLV2_connect_port (
559     LV2_Handle instance, uint32_t port, void *data )
560 {
561     MidiLfoLV2 *pPlugin = static_cast<MidiLfoLV2 *> (instance);
562     if (pPlugin)
563         pPlugin->connect_port(port, data);
564 }
565 
566 static void MidiLfoLV2_run ( LV2_Handle instance, uint32_t nframes )
567 {
568     MidiLfoLV2 *pPlugin = static_cast<MidiLfoLV2 *> (instance);
569     if (pPlugin)
570         pPlugin->run(nframes);
571 }
572 
573 static void MidiLfoLV2_activate ( LV2_Handle instance )
574 {
575     MidiLfoLV2 *pPlugin = static_cast<MidiLfoLV2 *> (instance);
576     if (pPlugin)
577         pPlugin->activate();
578 }
579 
580 static void MidiLfoLV2_deactivate ( LV2_Handle instance )
581 {
582     MidiLfoLV2 *pPlugin = static_cast<MidiLfoLV2 *> (instance);
583     if (pPlugin)
584         pPlugin->deactivate();
585 }
586 
587 static void MidiLfoLV2_cleanup ( LV2_Handle instance )
588 {
589     MidiLfoLV2 *pPlugin = static_cast<MidiLfoLV2 *> (instance);
590     if (pPlugin)
591         delete pPlugin;
592 }
593 
594 static const void *MidiLfoLV2_extension_data ( const char * uri)
595 {
596     static const LV2_State_Interface state_iface =
597                 { MidiLfoLV2_state_save, MidiLfoLV2_state_restore };
598     if (!strcmp(uri, LV2_STATE__interface)) {
599         return &state_iface;
600     }
601     else return NULL;
602 }
603 
604 static const LV2_Descriptor MidiLfoLV2_descriptor =
605 {
606     QMIDIARP_LFO_LV2_URI,
607     MidiLfoLV2_instantiate,
608     MidiLfoLV2_connect_port,
609     MidiLfoLV2_activate,
610     MidiLfoLV2_run,
611     MidiLfoLV2_deactivate,
612     MidiLfoLV2_cleanup,
613     MidiLfoLV2_extension_data
614 };
615 
616 LV2_SYMBOL_EXPORT const LV2_Descriptor *lv2_descriptor ( uint32_t index )
617 {
618     return (index == 0 ? &MidiLfoLV2_descriptor : NULL);
619 }
620 
621