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