1 /* B.Schaffl
2 * MIDI Pattern Delay Plugin
3 *
4 * Copyright (C) 2018 - 2020 by Sven Jähnichen
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #include "BSchaffl.hpp"
22
23 #include <cstdio>
24 #include <string>
25 #include <ctime>
26 #include <stdexcept>
27 #include <algorithm>
28 #include "BUtilities/stof.hpp"
29 #include "SharedData.hpp"
30
31 #define LIM(g , min, max) ((g) > (max) ? (max) : ((g) < (min) ? (min) : (g)))
32
33 static SharedData sharedData[4] = {SharedData(), SharedData(), SharedData(), SharedData()};
34
BSchaffl(double samplerate,const LV2_Feature * const * features)35 BSchaffl::BSchaffl (double samplerate, const LV2_Feature* const* features) :
36 map(NULL),
37 rate(samplerate), bpm(120.0f), speed(1), bar (0), barBeat (0),
38 beatsPerBar (4), beatUnit (4), positionSeq (0.0),
39 latencySeq (0.0), latencyFr (0),
40 refFrame(0),
41 uiOn (false),
42 actStep (-1),
43 mcg (time (0)),
44 distribution (0.0, 1.0),
45 midiData (),
46 input(NULL), output(NULL),
47 sharedDataNr (0),
48 controllerPtrs {nullptr}, controllers {0.0f},
49 stepPositions {0.0},
50 shape {Shape<MAXNODES>()},
51 message (),
52 notify_shape (true),
53 notify_sharedData (false),
54 notify_controllers {false}
55
56 {
57 // Init array members
58 std::fill (stepAutoPositions, stepAutoPositions + MAXSTEPS - 1, true);
59 std::fill (stepRnds, stepRnds + MAXSTEPS - 1, 1.0);
60
61 shape.setDefaultShape ();
62
63 //Scan host features for URID map
64 LV2_URID_Map* m = NULL;
65 for (int i = 0; features[i]; ++i)
66 {
67 if (strcmp(features[i]->URI, LV2_URID__map) == 0)
68 {
69 m = (LV2_URID_Map*) features[i]->data;
70 }
71 }
72 if (!m) throw std::invalid_argument ("Host does not support urid:map");
73
74 //Map URIS
75 map = m;
76 getURIs (m, &uris);
77
78 // Initialize forge
79 lv2_atom_forge_init (&forge,map);
80
81 recalculateAutoPositions ();
82 }
83
~BSchaffl()84 BSchaffl::~BSchaffl ()
85 {
86 if ((sharedDataNr > 0) && (sharedDataNr <= 4)) sharedData[sharedDataNr - 1].unlink (this);
87 }
88
connect_port(uint32_t port,void * data)89 void BSchaffl::connect_port(uint32_t port, void *data)
90 {
91 switch (port) {
92 case INPUT:
93 input = (LV2_Atom_Sequence*) data;
94 break;
95 case OUTPUT:
96 output = (LV2_Atom_Sequence*) data;
97 break;
98 default:
99 if ((port >= CONTROLLERS) && (port < CONTROLLERS + NR_CONTROLLERS))
100 {
101 controllerPtrs[port - CONTROLLERS] = (float*) data;
102 }
103 }
104 }
105
run(uint32_t n_samples)106 void BSchaffl::run (uint32_t n_samples)
107 {
108
109 // Check ports
110 if ((!input) || (!output)) return;
111 for (int i = 0; i < NR_CONTROLLERS; ++i)
112 {
113 if (!controllerPtrs[i]) return;
114 }
115
116 // Update controller values
117 for (int i = 0; i < LATENCY; ++i)
118 {
119
120 float newValue = getControllerInput (sharedDataNr, i);
121 if (newValue != controllers[i])
122 {
123 setController (i, newValue);
124 if ((sharedDataNr >= 1) && (sharedDataNr <= 4)) notify_controllers[i] = true;
125 }
126 }
127
128 // Update shape
129 if ((sharedDataNr > 0) && (sharedDataNr <= 4) && (shape != sharedData[sharedDataNr - 1].shape))
130 {
131 shape = sharedData[sharedDataNr - 1].shape;
132 notify_shape = true;
133 }
134
135 recalculateLatency();
136 *controllerPtrs[LATENCY] = latencyFr;
137 if (latencyFr > 192000) message.setMessage (LATENCY_MAX_MSG);
138 else message.deleteMessage (LATENCY_MAX_MSG);
139
140 // Prepare forge buffer and initialize atom sequence
141 const uint32_t space = output->atom.size;
142 lv2_atom_forge_set_buffer(&forge, (uint8_t*) output, space);
143 lv2_atom_forge_sequence_head(&forge, &frame, 0);
144
145 uint32_t last_t =0;
146
147 // Process audio data
148 LV2_ATOM_SEQUENCE_FOREACH (input, ev)
149 {
150 if ((ev->body.type == uris.atom_Object) || (ev->body.type == uris.atom_Blank))
151 {
152 bool scheduleUpdatePosition = false;
153
154 const LV2_Atom_Object* obj = (const LV2_Atom_Object*)&ev->body;
155
156 // GUI on
157 if (obj->body.otype == uris.bschaffl_uiOn)
158 {
159 uiOn = true;
160 notify_shape = true;
161 notify_sharedData = true;
162 std::fill (notify_controllers, notify_controllers + NR_CONTROLLERS, true);
163 }
164
165 // GUI off
166 else if (obj->body.otype == uris.bschaffl_uiOff) uiOn = false;
167
168 // Linked / unlinked to shared data
169 else if (obj->body.otype == uris.bschaffl_sharedDataLinkEvent)
170 {
171 LV2_Atom *oNr = NULL;
172
173 lv2_atom_object_get
174 (
175 obj,
176 uris.bschaffl_sharedDataNr, &oNr,
177 NULL
178 );
179
180 if (oNr && (oNr->type == uris.atom_Int))
181 {
182 const int nr = ((LV2_Atom_Int*)oNr)->body;
183
184 if ((nr >= 0) && (nr <= 4) && (nr != sharedDataNr))
185 {
186 if (sharedDataNr != 0) sharedData[sharedDataNr - 1].unlink (this);
187
188 if ((nr != 0) && sharedData[nr - 1].empty())
189 {
190 for (int i = 0; i < NR_CONTROLLERS; ++i) sharedData[nr - 1].set (i, controllers[i]);
191 }
192
193 if (nr != 0) sharedData[nr - 1].link (this);
194 sharedDataNr = nr;
195 notify_sharedData = true;
196
197 for (int i = 0; i < NR_CONTROLLERS; ++i)
198 {
199 float newValue = getControllerInput (sharedDataNr, i);
200 if (newValue != controllers[i])
201 {
202 setController (i, newValue);
203 notify_controllers[i] = true;
204 }
205 }
206 }
207 }
208 }
209
210 // Controller changed
211 else if ((obj->body.otype == uris.bschaffl_controllerEvent) && (sharedDataNr != 0))
212 {
213 LV2_Atom *oNr = NULL, *oVal = NULL;
214
215 lv2_atom_object_get
216 (
217 obj,
218 uris.bschaffl_controllerNr, &oNr,
219 uris.bschaffl_controllerValue, &oVal,
220 NULL
221 );
222
223 if (oNr && (oNr->type == uris.atom_Int) && oVal && (oVal->type == uris.atom_Float))
224 {
225 const int nr = ((LV2_Atom_Int*)oNr)->body;
226
227 if ((nr >= 0) && (nr < NR_CONTROLLERS))
228 {
229 const float val = controllerLimits[nr].validate(((LV2_Atom_Float*)oVal)->body);
230 if ((sharedDataNr > 0) && (sharedDataNr <= 4)) sharedData[sharedDataNr - 1].set (nr, val);
231 setController (nr, val);
232 }
233 }
234 }
235
236 // Update time/position data
237 else if (obj->body.otype == uris.time_Position)
238 {
239 LV2_Atom *oBbeat = NULL, *oBpm = NULL, *oSpeed = NULL, *oBpb = NULL, *oBu = NULL, *oBar = NULL;
240
241 lv2_atom_object_get
242 (
243 obj,
244 uris.time_barBeat, &oBbeat,
245 uris.time_beatsPerMinute, &oBpm,
246 uris.time_beatsPerBar, &oBpb,
247 uris.time_beatUnit, &oBu,
248 uris.time_bar, &oBar,
249 uris.time_speed, &oSpeed,
250 NULL);
251
252 // BPM changed?
253 if (oBpm && (oBpm->type == uris.atom_Float) && (((LV2_Atom_Float*)oBpm)->body != bpm))
254 {
255 bpm = ((LV2_Atom_Float*)oBpm)->body;
256 scheduleUpdatePosition = true;
257 if (bpm < 1.0) message.setMessage (JACK_STOP_MSG);
258 else message.deleteMessage (JACK_STOP_MSG);
259 }
260
261 // Beats per bar changed?
262 if (oBpb && (oBpb->type == uris.atom_Float) && (((LV2_Atom_Float*)oBpb)->body > 0) && (((LV2_Atom_Float*)oBpb)->body != beatsPerBar))
263 {
264 beatsPerBar = ((LV2_Atom_Float*)oBpb)->body;
265 scheduleUpdatePosition = true;
266 }
267
268 // BeatUnit changed?
269 if (oBu && (oBu->type == uris.atom_Int) && (((LV2_Atom_Int*)oBu)->body > 0) && (((LV2_Atom_Int*)oBu)->body != beatUnit))
270 {
271 beatUnit = ((LV2_Atom_Int*)oBu)->body;
272 scheduleUpdatePosition = true;
273 }
274
275 // Speed changed?
276 if (oSpeed && (oSpeed->type == uris.atom_Float) && (((LV2_Atom_Float*)oSpeed)->body != speed))
277 {
278 speed = ((LV2_Atom_Float*)oSpeed)->body;
279 if (speed == 0.0) message.setMessage (JACK_STOP_MSG);
280 else message.deleteMessage (JACK_STOP_MSG);
281 }
282
283 // Bar position changed
284 if (oBar && (oBar->type == uris.atom_Long) && (bar != (((LV2_Atom_Long*)oBar)->body)))
285 {
286 bar = ((LV2_Atom_Long*)oBar)->body;
287 scheduleUpdatePosition = true;
288 }
289
290 // Beat position changed ?
291 if (oBbeat && (oBbeat->type == uris.atom_Float) && (((LV2_Atom_Float*)oBbeat)->body != barBeat))
292 {
293 barBeat = ((LV2_Atom_Float*)oBbeat)->body;
294 scheduleUpdatePosition = true;
295 }
296
297 if (scheduleUpdatePosition)
298 {
299 // Hard set new position if new data received
300 //fprintf(stderr, "BSchaffl.lv2: Change position %f -> ", positionSeq);
301 positionSeq = getSequenceFromBeats (barBeat + beatsPerBar * bar);
302 //fprintf(stderr, "%f\n", positionSeq);
303 refFrame = ev->time.frames;
304 }
305
306 recalculateLatency();
307 }
308
309 // Shape changed notifications
310 else if (obj->body.otype == uris.bschaffl_shapeEvent)
311 {
312 LV2_Atom *oData = NULL;
313 lv2_atom_object_get (obj,
314 uris.bschaffl_shapeData, &oData,
315 NULL);
316
317 if (oData && (oData->type == uris.atom_Vector))
318 {
319 const LV2_Atom_Vector* vec = (const LV2_Atom_Vector*) oData;
320 if (vec->body.child_type == uris.atom_Float)
321 {
322 shape.clearShape ();
323 const uint32_t vecSize = (uint32_t) ((oData->size - sizeof(LV2_Atom_Vector_Body)) / (7 * sizeof (float)));
324 float* data = (float*) (&vec->body + 1);
325 for (unsigned int i = 0; (i < vecSize) && (i < MAXNODES); ++i)
326 {
327 Node node;
328 node.nodeType = NodeType (int (data[i * 7]));
329 node.point.x = data[i * 7 + 1];
330 node.point.y = data[i * 7 + 2];
331 node.handle1.x = data[i * 7 + 3];
332 node.handle1.y = data[i * 7 + 4];
333 node.handle2.x = data[i * 7 + 5];
334 node.handle2.y = data[i * 7 + 6];
335 shape.appendRawNode (node);
336 }
337 shape.validateShape();
338
339 if ((sharedDataNr > 0) && (sharedDataNr <=4)) sharedData[sharedDataNr - 1].shape = shape;
340 }
341 }
342 }
343 }
344
345 // Read incoming MIDI events
346 else if (ev->body.type == uris.midi_Event)
347 {
348 const uint8_t* const msg = (const uint8_t*)(ev + 1);
349 MidiData midi = {{0, 0, 0}, 0, 0, 0, 0, false};
350 midi.size = LIM (ev->body.size, 0, 3);
351 memcpy (midi.msg, msg, midi.size);
352
353 // Filter channel and message
354 bool process = filterMsg (midi.msg[0]) && (controllers[MIDI_CH_FILTER + (midi.msg[0] & 0x0F)] != 0.0f);
355
356 // Calculate position within sequence
357 const double inputSeq = positionSeq +
358 getSequenceFromFrame (ev->time.frames - refFrame, speed) +
359 (controllers[TIME_COMPENS] != 1.0f ? latencySeq : 0);
360 const float inputSeqPos = MODFL (inputSeq);
361
362 // Calulate step
363 const int nrOfSteps = controllers[NR_OF_STEPS];
364 const int step = LIM (double (nrOfSteps) * inputSeqPos, 0, nrOfSteps - 1);
365
366 // Update step
367 if ((actStep < 0) || (step != actStep))
368 {
369 // Sequence just started: Re-randomize sequence
370 if (step < actStep)
371 {
372 for (int i = 0; i < nrOfSteps; ++i) randomizeStep (i);
373 }
374
375 actStep = step;
376 }
377
378 // Calulate fractional position within step
379 const float iprev = float (step) / float (nrOfSteps);
380 const float inext = (step >= nrOfSteps - 1 ? 1.0f : float (step + 1) / float (nrOfSteps));
381 const float ifrac = (iprev != inext ? (inputSeqPos - iprev) / (inext - iprev) : 0.0f);
382
383 // Calculate output position
384 const float qrange = (controllers[QUANT_POS] != 0.0f ? controllers[QUANT_RANGE] : 0.0);
385 const float oprev = getStepStart (step);
386 const float onext = getStepEnd (step);
387 const float ofrac = (ifrac <= qrange ? 0.0f : (1.0f - ifrac < qrange ? 1.0f : ifrac));
388 const float outputSeqPos = oprev + ofrac * (onext - oprev);
389 const float origin = inputSeq + latencySeq;
390 const float shift = (outputSeqPos - inputSeqPos) * controllers[SWING_PROCESS];
391 midi.shiftSeq = (process? shift : 0);
392
393 // Garbage collection
394 // Removes data from queue which are scheduled to a time point later than the latest possible time point
395 const float maxProcSeq = origin + onext - inputSeqPos;
396 const float maxSeq = (origin > maxProcSeq ? origin : maxProcSeq);
397 clearMidiData (maxSeq);
398
399 // MIDI NOTE_ON and NOTE_OFF
400 if
401 (
402 (
403 ((midi.msg[0] & 0xF0) == 0x80) ||
404 ((midi.msg[0] & 0xF0) == 0x90)
405 ) &&
406 process
407 )
408 {
409 // Map step (smart quantization)
410 const float mrange = (controllers[QUANT_MAP] != 0.0f ? controllers[QUANT_RANGE] : 0.0);
411 const int map =
412 (
413 (midi.msg[0] & 0xF0) == 0x80 ?
414 (ifrac < mrange ? ((step + nrOfSteps - 1) % nrOfSteps) : step) :
415 (1.0 - ifrac < mrange ? ((step + 1) % nrOfSteps) : step)
416 );
417
418 // Calculate and set amp
419 float aswing = ((map % 2) == 0 ? controllers[AMP_SWING] : 1.0 / controllers[AMP_SWING]);
420 aswing = LIM (aswing, 0, 1);
421 const float rnd = 1.0f + controllers[AMP_RANDOM] * (2.0f * distribution (mcg) - 1.0f);
422 float amp =
423 (
424 controllers[AMP_MODE] == 0.0f ?
425 controllers[STEP_LEV + map] * rnd * aswing :
426 LIM (shape.getMapValue (inputSeqPos), 0.0, 1.0) * rnd
427 );
428
429 // NOTE_OFF
430 if ((midi.msg[0] & 0xF0) == 0x80)
431 {
432 const int nr =
433 (
434 (controllers[NOTE_OFF_AMP] == 0) || controllers[NOTE_POSITION_STR] || controllers[NOTE_VALUE_STR] ?
435 getNoteOnMsg (midi.msg[0] & 0x0F, midi.msg[1]) :
436 -1
437 );
438 const float s1 = (nr >= 0 ? midiData[nr].shiftSeq : shift);
439
440 // Use note on amp ? Look for corresponding NOTE_ON
441 if (controllers[NOTE_OFF_AMP] == 0)
442 {
443 if (nr >= 0) amp = midiData[nr].amp;
444 }
445
446 // Calculate shift
447 midi.positionSeq = origin +
448 (
449 controllers[NOTE_POSITION_STR] ?
450 (controllers[NOTE_VALUE_STR] ? 0 : shift - s1) :
451 (controllers[NOTE_VALUE_STR] ? s1 : shift)
452 );
453
454 // Handle overlapping notes
455 if
456 (
457 (nr >= 0) &&
458 (controllers[NOTE_POSITION_STR] || controllers[NOTE_VALUE_STR]) &&
459 (controllers[NOTE_OVERLAP] == OVERLAP_MERGE)
460 )
461 {
462 const int noteOffNr = getNoteOffMsg (midi.msg[0] & 0x0F, midi.msg[1], nr);
463
464 if (noteOffNr >= 0)
465 {
466 // Nested notes: Ignore inner NOTE_OFF
467 if (midi.positionSeq <= midiData[noteOffNr].positionSeq)
468 {
469 midi.msg[0] = 0;
470 }
471
472 // Overlapping notes: Remove inner NOTE_OFF
473 else
474 {
475 /*fprintf
476 (
477 stderr,
478 "BSchaffl.lv2: Remove MIDI signal from #%i %i (%i,%i) to %f (shift = %f, latency = %f)\n",
479 noteOffNr,
480 midiData[noteOffNr].msg[0],
481 midiData[noteOffNr].msg[1],
482 midiData[noteOffNr].msg[2],
483 midiData[noteOffNr].positionSeq,
484 midiData[noteOffNr].shiftSeq,
485 latencySeq
486 );*/
487
488 midiData.erase (&midiData.iterator[noteOffNr]);
489 }
490 }
491
492 }
493 }
494
495 // NOTE_ON ?
496 else
497 {
498 //Store amp
499 midi.amp = amp;
500
501 // Calculate shift
502 if (controllers[NOTE_POSITION_STR]) midi.positionSeq = origin;
503 else midi.positionSeq = origin + shift;
504
505 // Handle overlapping notes
506 if (controllers[NOTE_POSITION_STR] || controllers[NOTE_VALUE_STR])
507 {
508 // Split: Insert or move NOTE_OFF just before new NOTE_ON
509 if (controllers[NOTE_OVERLAP] == OVERLAP_SPLIT)
510 {
511 const int noteOnNr = getNoteOnMsg (midi.msg[0] & 0x0F, midi.msg[1]);
512 if (noteOnNr >= 0)
513 {
514 const int noteOffNr = getNoteOffMsg (midi.msg[0] & 0x0F, midi.msg[1], noteOnNr);
515 const MidiData noteOff =
516 (
517 noteOffNr >= 0 ?
518 MidiData
519 {
520 {0x80 || (midi.msg[0] & 0x0F), midi.msg[1], midiData[noteOffNr].msg[2]},
521 midiData[noteOffNr].size,
522 midi.positionSeq,
523 midi.shiftSeq,
524 midiData[noteOffNr].amp,
525 midiData[noteOffNr].inactive
526 } :
527 MidiData
528 {
529 {0x80 || (midi.msg[0] & 0x0F), midi.msg[1], midi.msg[2]},
530 midi.size,
531 midi.positionSeq,
532 midi.shiftSeq,
533 midi.amp,
534 midi.inactive
535 }
536 );
537
538 if ((noteOffNr >= 0) && (midi.positionSeq < midiData[noteOffNr].positionSeq))
539 {
540 // Remome old NOTE_OFF
541 /*fprintf
542 (
543 stderr,
544 "BSchaffl.lv2: Remove MIDI signal from #%i %i (%i,%i) to %f (shift = %f, latency = %f)\n",
545 noteOffNr,
546 midiData[noteOffNr].msg[0],
547 midiData[noteOffNr].msg[1],
548 midiData[noteOffNr].msg[2],
549 midiData[noteOffNr].positionSeq,
550 midiData[noteOffNr].shiftSeq,
551 latencySeq
552 );*/
553
554 midiData.erase (&midiData.iterator[noteOffNr]);
555
556 // Insert NOTE_OFF
557 queueMidiData (noteOff);
558 }
559
560 }
561 }
562
563 // Merge: Ignore new NOTE_ON
564 else if (controllers[NOTE_OVERLAP] == OVERLAP_MERGE)
565 {
566 const int nr = getNoteOnMsg (midi.msg[0] & 0x0F, midi.msg[1]);
567 if (nr >= 0)
568 {
569 const int noteOffNr = getNoteOffMsg (midi.msg[0] & 0x0F, midi.msg[1], nr);
570 if ((noteOffNr < 0) || (midi.positionSeq < midiData[noteOffNr].positionSeq))
571 {
572 midi.msg[0] = 0;
573 }
574 }
575 }
576 }
577 }
578
579 // Apply amp
580 const float proc = controllers[AMP_PROCESS];
581 const float invel = float (midi.msg[2]);
582 const float outvel = invel + (invel * amp - invel) * proc;
583 midi.msg[2] = LIM (outvel, 0, 127);
584 }
585
586 else midi.positionSeq = origin + midi.shiftSeq;
587
588 // Store MIDI data
589 if (midi.msg[0]) queueMidiData (midi);
590 }
591
592 play (last_t, ev->time.frames);
593 last_t = ev->time.frames;
594 }
595
596 // Play remaining samples
597 if (last_t < n_samples) play (last_t, n_samples);
598
599 // Update position in case of no new barBeat submitted on next call
600 double relSeq = getSequenceFromFrame (n_samples - refFrame, speed);
601 positionSeq += relSeq;
602 refFrame = 0;
603
604 // Send collected data to GUI
605 if (uiOn)
606 {
607 if (message.isScheduled ()) notifyMessageToGui();
608 notifyStatusToGui();
609 if (notify_sharedData) notifySharedDataNrToGui();
610 for (int i = 0; i < NR_CONTROLLERS; ++i) if (notify_controllers[i]) notifyControllerToGui (i);
611 if (notify_shape) notifyShapeToGui();
612 }
613
614 // Close off sequence
615 lv2_atom_forge_pop(&forge, &frame);
616 }
617
play(uint32_t start,uint32_t end)618 void BSchaffl::play (uint32_t start, uint32_t end)
619 {
620 const double startSeq = positionSeq + getSequenceFromFrame (start - refFrame, speed) + (controllers[TIME_COMPENS] != 1.0f ? latencySeq : 0);
621 const double endSeq = positionSeq + getSequenceFromFrame (end - refFrame, speed) + (controllers[TIME_COMPENS] != 1.0f ? latencySeq : 0);
622
623 // Send midi data to output
624 for (unsigned int i = 0; i < midiData.size; ++i)
625 {
626 if ((midiData[i].positionSeq <= endSeq) && (!midiData[i].inactive))
627 {
628 // Calculate frame
629 int64_t frame = start;
630 double seq = midiData[i].positionSeq;
631 if (seq >= startSeq)
632 {
633 frame = start + getFrameFromSequence (seq - startSeq, speed);
634 //frame = LIM (frame, 0, end);
635 }
636
637 // Send MIDI
638 LV2_Atom midiatom;
639 midiatom.type = uris.midi_Event;
640 midiatom.size = midiData[i].size;
641 lv2_atom_forge_frame_time (&forge, frame);
642 lv2_atom_forge_raw (&forge, &midiatom, sizeof (LV2_Atom));
643 lv2_atom_forge_raw (&forge, &midiData[i].msg, midiatom.size);
644 lv2_atom_forge_pad (&forge, sizeof (LV2_Atom) + midiatom.size);
645
646 midiData[i].inactive = true;
647
648 /*fprintf
649 (
650 stderr, "BSchaffl.lv2 @ %f: Send Midi #%i %i (%i, %i) (frame = %li) \n",
651 seq,
652 i,
653 midiData[i].msg[0],
654 midiData[i].msg[1],
655 midiData[i].msg[2],
656 frame
657 );*/
658 }
659 }
660
661 // Remove sent data
662 for (MidiData** it = midiData.begin(); (it < midiData.end()) && ((**it).positionSeq <= endSeq); )
663 {
664 if ((**it).inactive)
665 {
666 // NOTE_OFF ?
667 if (((**it).msg[0] & 0xF0) == 0x80)
668 {
669 // Erase corresponding NOTE_ON
670 uint8_t ch = (**it).msg[0] & 0x0F;
671 uint8_t note = (**it).msg[1];
672 for (MidiData** nit = midiData.begin(); nit < it; )
673 {
674 if
675 (
676 (((**nit).msg[0] & 0xF0) == 0x90) &&
677 (((**nit).msg[0] & 0x0F) == ch) &&
678 ((**nit).msg[1] == note)
679 )
680 {
681 nit = midiData.erase (nit);
682 --it;
683 }
684
685 else ++nit;
686 }
687
688 // Erase NOTE_OFF and go to next it
689 it = midiData.erase (it);
690 }
691
692 // NOTE_ON ? Next it
693 else if (((**it).msg[0] & 0xF0) == 0x90) ++it;
694
695 // Otherwise erase and go to next it
696 else it = midiData.erase (it);
697
698 }
699
700 // Otherwise next it
701 else ++it;
702 }
703 }
704
getControllerInput(const int sdNr,const int ctrlNr)705 float BSchaffl::getControllerInput (const int sdNr, const int ctrlNr)
706 {
707 // Sync with control ports
708 if ((sdNr == 0) && controllerPtrs[ctrlNr]) return controllerLimits[ctrlNr].validate (*controllerPtrs[ctrlNr]);
709
710 // Otherwise sync with globally shared data
711 if (sdNr <= 4) return controllerLimits[ctrlNr].validate (sharedData[sdNr - 1].get (ctrlNr));
712
713 return controllerLimits[ctrlNr].min;
714 }
715
setController(const int ctrlNr,const float value)716 void BSchaffl::setController (const int ctrlNr, const float value)
717 {
718 controllers[ctrlNr] = value;
719
720 if (ctrlNr == SWING) recalculateAutoPositions();
721
722 else if (ctrlNr == NR_OF_STEPS) recalculateAutoPositions();
723
724 else if ((ctrlNr >= STEP_POS) && (ctrlNr < STEP_POS + MAXSTEPS - 1))
725 {
726 const int step = ctrlNr - STEP_POS;
727 if (value == 0.0f)
728 {
729 if (!stepAutoPositions[step])
730 {
731 stepAutoPositions[step] = true;
732 recalculateAutoPositions();
733 }
734 }
735
736 else if (stepPositions[step] != value)
737 {
738 stepAutoPositions[step] = false;
739 stepPositions[step] = value;
740 recalculateAutoPositions();
741 }
742 }
743 }
744
randomizeStep(const int step)745 void BSchaffl::randomizeStep (const int step)
746 {
747 const int nrOfSteps = controllers[NR_OF_STEPS];
748 if ((step < nrOfSteps - 1) && (step >= 0))
749 {
750 // Randomize 0.0 .. 2.0
751 float rnd = 1.0f + controllers[SWING_RANDOM] * (2.0f * float (rand()) / float (RAND_MAX) - 1.0f);
752
753 // Prevent overlap with antecessor
754 if ((step >= 1) && (rnd < stepRnds[step - 1] - 1.0f)) rnd = stepRnds[step - 1] - 1.0f;
755
756 stepRnds[step] = rnd;
757 }
758 }
759
getStepStart(const int step)760 double BSchaffl::getStepStart (const int step)
761 {
762 const int nrOfSteps = controllers[NR_OF_STEPS];
763 const int s = step % nrOfSteps;
764 if (s == 0) return 0.0;
765 else
766 {
767 const float rnd = stepRnds[s - 1];
768 return
769 (
770 rnd < 1.0f ?
771 (
772 s - 1 > 0 ?
773 stepPositions[s - 1] - (1.0f - rnd) * (stepPositions[s - 1] - stepPositions[s - 2]) :
774 stepPositions[s - 1] - (1.0f - rnd) * stepPositions[s - 1]
775 ) :
776 (
777 s - 1 < nrOfSteps - 2 ?
778 stepPositions[s - 1] + (rnd - 1.0f) * (stepPositions[s] - stepPositions[s - 1]) :
779 stepPositions[s - 1] + (rnd - 1.0f) * (1.0f - stepPositions[s - 1])
780 )
781 );
782 }
783 }
784
getStepEnd(const int step)785 double BSchaffl::getStepEnd (const int step)
786 {
787 const int nrOfSteps = controllers[NR_OF_STEPS];
788 const int s = step % nrOfSteps;
789 if (s == nrOfSteps - 1) return 1.0;
790 else return getStepStart (s + 1);
791 }
792
getNoteOnMsg(const uint8_t ch,const uint8_t note,int start) const793 int BSchaffl::getNoteOnMsg (const uint8_t ch, const uint8_t note, int start) const
794 {
795 for (int i = ((start >= 0) && (start < int (midiData.size)) ? start : midiData.size - 1); i >= 0; --i)
796 {
797 if
798 (
799 ((midiData[i].msg[0] & 0xF0) == 0x90) &&
800 ((midiData[i].msg[0] & 0x0F) == ch) &&
801 (midiData[i].msg[1] == note)
802 ) return i;
803 }
804
805 return -1;
806 }
807
getNoteOffMsg(const uint8_t ch,const uint8_t note,int start) const808 int BSchaffl::getNoteOffMsg (const uint8_t ch, const uint8_t note, int start) const
809 {
810 for (int i = ((start >= 0) && (start < int (midiData.size)) ? start : 0); i < int (midiData.size); ++i)
811 {
812 if
813 (
814 ((midiData[i].msg[0] & 0xF0) == 0x80) &&
815 ((midiData[i].msg[0] & 0x0F) == ch) &&
816 (midiData[i].msg[1] == note)
817 ) return i;
818 }
819
820 return -1;
821 }
822
clearMidiData(const float maxSeq)823 void BSchaffl::clearMidiData (const float maxSeq)
824 {
825 while ((!midiData.empty()) && (midiData.back().positionSeq > maxSeq))
826 {
827 /*fprintf
828 (
829 stderr,
830 "BSchaffl.lv2 @: Remove MIDI signal %i (%i,%i) from %f (maxSeq = %f)\n",
831 midiData.back().msg[0],
832 midiData.back().msg[1],
833 midiData.back().msg[2],
834 midiData.back().positionSeq,
835 maxSeq
836 );*/
837
838 midiData.pop_back();
839 }
840 }
841
queueMidiData(const MidiData & midi)842 void BSchaffl::queueMidiData (const MidiData& midi)
843 {
844 for (MidiData** m = midiData.end(); m >= midiData.begin(); --m)
845 {
846 if ((m == midiData.begin()) || ((**(m - 1)).positionSeq <= midi.positionSeq))
847 {
848 midiData.insert (m, midi);
849 break;
850 }
851 }
852
853 /*fprintf
854 (
855 stderr,
856 "BSchaffl.lv2: Schedule MIDI signal #%li %i (%i,%i) to %f (shift = %f, latency = %f)\n",
857 midiData.size,
858 midi.msg[0],
859 midi.msg[1],
860 midi.msg[2],
861 midi.positionSeq,
862 midi.shiftSeq,
863 latencySeq
864 );*/
865 }
866
getSequenceFromBeats(const double beats)867 double BSchaffl::getSequenceFromBeats (const double beats)
868 {
869 if (controllers[SEQ_LEN_VALUE] == 0.0) return 0.0;
870
871 switch (int (controllers[SEQ_LEN_BASE]))
872 {
873 case SECONDS: return (bpm ? beats / (controllers[SEQ_LEN_VALUE] * (bpm / 60.0)) : 0.0);
874 case BEATS: return beats / controllers[SEQ_LEN_VALUE];
875 case BARS: return (beatsPerBar ? beats / (controllers[SEQ_LEN_VALUE] * beatsPerBar) : 0.0);
876 default: return 0.0;
877 }
878 }
879
getBeatsFromSequence(const double sequence)880 double BSchaffl::getBeatsFromSequence (const double sequence)
881 {
882 if (controllers[SEQ_LEN_VALUE] == 0.0) return 0.0;
883
884 switch (int (controllers[SEQ_LEN_BASE]))
885 {
886 case SECONDS: return (bpm ? sequence * (controllers[SEQ_LEN_VALUE] * (bpm / 60.0)) : 0.0);
887 case BEATS: return sequence * controllers[SEQ_LEN_VALUE];
888 case BARS: return (beatsPerBar ? sequence * (controllers[SEQ_LEN_VALUE] * beatsPerBar) : 0.0);
889 default: return 0.0;
890 }
891 }
892
getSequenceFromFrame(const int64_t frames,float speed)893 double BSchaffl::getSequenceFromFrame (const int64_t frames, float speed)
894 {
895 if (controllers[SEQ_LEN_VALUE] == 0.0) return 0.0;
896
897 switch (int (controllers[SEQ_LEN_BASE]))
898 {
899 case SECONDS: return (rate ? frames * (1.0 / rate) / controllers[SEQ_LEN_VALUE] : 0.0);
900 case BEATS: return (rate ? frames * speed * bpm / (60.0 * rate * controllers[SEQ_LEN_VALUE]) : 0.0);
901 case BARS: return (rate && beatsPerBar ? frames * speed * bpm / (60.0 * rate * controllers[SEQ_LEN_VALUE] * beatsPerBar) : 0.0);
902 default: return 0.0;
903 }
904 }
905
getFrameFromSequence(const double sequence,float speed)906 int64_t BSchaffl::getFrameFromSequence (const double sequence, float speed)
907 {
908 if (controllers[SEQ_LEN_VALUE] == 0.0) return 0.0;
909
910 switch (int (controllers[SEQ_LEN_BASE]))
911 {
912 case SECONDS: return sequence * rate * controllers[SEQ_LEN_VALUE];
913 case BEATS: return (speed && bpm ? 60 * sequence * rate * controllers[SEQ_LEN_VALUE] / (speed * bpm) : 0.0);
914 case BARS: return (speed && bpm ? 60.0 * sequence * beatsPerBar * rate * controllers[SEQ_LEN_VALUE] / (speed * bpm) : 0.0);
915 default: return 0.0;
916 }
917 }
918
filterMsg(const uint8_t msg)919 bool BSchaffl::filterMsg (const uint8_t msg)
920 {
921 uint8_t msgGroup = msg / 16;
922 return
923 (
924 msgGroup < 8 ?
925 false :
926 (
927 msgGroup == 8 ?
928 (controllers[MSG_FILTER_NOTE] != 0.0f) :
929 (controllers[MSG_FILTER_NOTE + msgGroup - 9] != 0.0f)
930 )
931 );
932 }
933
recalculateLatency()934 void BSchaffl::recalculateLatency ()
935 {
936 if (controllers[USR_LATENCY] != 0.0f)
937 {
938 latencyFr = controllers[USR_LATENCY_FR];
939 latencySeq = getSequenceFromFrame (latencyFr);
940 }
941
942 else
943 {
944 double qLatencySeq = (controllers[QUANT_POS] != 0.0f ? controllers[QUANT_RANGE] / controllers[NR_OF_STEPS] : 0.0);
945
946 latencySeq = 0;
947 const int nrSteps = controllers[NR_OF_STEPS];
948 for (int i = 0; i < nrSteps - 1; ++i)
949 {
950 const double inStartSeq = double (i) / double (nrSteps);
951 const double outStartSeq = (i == 0 ? 0.0 : stepPositions[i - 1]);
952 const double rndSeq = (i == 0 ? 0.0 : controllers[SWING_RANDOM] * (stepPositions[i - 1] - (i == 1 ? 0.0 : stepPositions[i - 2])));
953 const double diffSeq = inStartSeq - (outStartSeq - rndSeq);
954 if (diffSeq > latencySeq) latencySeq = diffSeq;
955 }
956
957 latencySeq += qLatencySeq;
958 latencyFr = getFrameFromSequence (latencySeq);
959 }
960 }
961
recalculateAutoPositions()962 void BSchaffl::recalculateAutoPositions ()
963 {
964 int nrMarkers = controllers[NR_OF_STEPS] - 1;
965 int start = 0;
966 for (int i = 0; i < nrMarkers; ++i)
967 {
968 if (stepAutoPositions[i])
969 {
970 if ((i == nrMarkers - 1) || (!stepAutoPositions[i + 1]))
971 {
972 double s = 2.0 * controllers[SWING] / (controllers[SWING] + 1.0);
973 double anc = (start == 0 ? 0 : stepPositions[start - 1]);
974 double suc = (i == nrMarkers - 1 ? 1 : stepPositions[i + 1]);
975 double diff = suc - anc;
976 double dist = i - start + 1.0 + (int (i - start) & 1 ? ((start & 1) ? 2.0 - s : s) : 1.0);
977 double step = (diff < 0 ? 0 : diff / dist);
978 for (int j = start; j <= i; ++j)
979 {
980 double f = ((j & 1) ? 2.0 - s : s);
981 anc += f * step;
982 stepPositions[j] = anc;
983 }
984 }
985 }
986 else start = i + 1;
987 }
988 }
989
notifyControllerToGui(const int nr)990 void BSchaffl::notifyControllerToGui (const int nr)
991 {
992 // Send notifications
993 LV2_Atom_Forge_Frame frame;
994 lv2_atom_forge_frame_time (&forge, 0);
995 lv2_atom_forge_object (&forge, &frame, 0, uris.bschaffl_controllerEvent);
996 lv2_atom_forge_key (&forge, uris.bschaffl_controllerNr);
997 lv2_atom_forge_int (&forge, nr);
998 lv2_atom_forge_key (&forge, uris.bschaffl_controllerValue);
999 lv2_atom_forge_float (&forge, controllers[nr]);
1000 lv2_atom_forge_pop (&forge, &frame);
1001 notify_controllers[nr] = false;
1002 }
1003
notifySharedDataNrToGui()1004 void BSchaffl::notifySharedDataNrToGui ()
1005 {
1006 // Send notifications
1007 LV2_Atom_Forge_Frame frame;
1008 lv2_atom_forge_frame_time (&forge, 0);
1009 lv2_atom_forge_object (&forge, &frame, 0, uris.bschaffl_sharedDataLinkEvent);
1010 lv2_atom_forge_key (&forge, uris.bschaffl_sharedDataNr);
1011 lv2_atom_forge_int (&forge, sharedDataNr);
1012 lv2_atom_forge_pop (&forge, &frame);
1013 notify_sharedData = false;
1014 }
1015
notifyStatusToGui()1016 void BSchaffl::notifyStatusToGui ()
1017 {
1018 // Calculate step
1019 int outStep = 0;
1020 const double seqPos = fmod (positionSeq - (controllers[TIME_COMPENS] == 1.0f ? latencySeq : 0), 1.0);
1021 while ((outStep < controllers[NR_OF_STEPS] - 1) && (seqPos > getStepEnd (outStep))) ++outStep;
1022
1023 // Calculate latency in ms
1024 const float latencyMs = float (latencyFr) * 1000.0f / rate;
1025
1026 // Send notifications
1027 LV2_Atom_Forge_Frame frame;
1028 lv2_atom_forge_frame_time (&forge, 0);
1029 lv2_atom_forge_object (&forge, &frame, 0, uris.bschaffl_statusEvent);
1030 lv2_atom_forge_key (&forge, uris.bschaffl_step);
1031 lv2_atom_forge_int (&forge, outStep);
1032 lv2_atom_forge_key (&forge, uris.bschaffl_latency);
1033 lv2_atom_forge_float (&forge, latencyMs);
1034 lv2_atom_forge_key (&forge, uris.bschaffl_rate);
1035 lv2_atom_forge_double (&forge, rate);
1036 lv2_atom_forge_pop (&forge, &frame);
1037 }
1038
notifyShapeToGui()1039 void BSchaffl::notifyShapeToGui ()
1040 {
1041 size_t size = shape.size ();
1042
1043 // Load shapeBuffer
1044 float shapeBuffer[MAXNODES * 7];
1045 for (unsigned int i = 0; i < size; ++i)
1046 {
1047 Node node = shape.getRawNode (i);
1048 shapeBuffer[i * 7] = (float)node.nodeType;
1049 shapeBuffer[i * 7 + 1] = (float)node.point.x;
1050 shapeBuffer[i * 7 + 2] = (float)node.point.y;
1051 shapeBuffer[i * 7 + 3] = (float)node.handle1.x;
1052 shapeBuffer[i * 7 + 4] = (float)node.handle1.y;
1053 shapeBuffer[i * 7 + 5] = (float)node.handle2.x;
1054 shapeBuffer[i * 7 + 6] = (float)node.handle2.y;
1055 }
1056
1057 // Notify shapeBuffer
1058 LV2_Atom_Forge_Frame frame;
1059 lv2_atom_forge_frame_time(&forge, 0);
1060 lv2_atom_forge_object(&forge, &frame, 0, uris.bschaffl_shapeEvent);
1061 lv2_atom_forge_key(&forge, uris.bschaffl_shapeData);
1062 lv2_atom_forge_vector(&forge, sizeof(float), uris.atom_Float, (uint32_t) (7 * size), &shapeBuffer);
1063 lv2_atom_forge_pop(&forge, &frame);
1064
1065 notify_shape = false;
1066 }
1067
notifyMessageToGui()1068 void BSchaffl::notifyMessageToGui ()
1069 {
1070 uint32_t messageNr = message.loadMessage ();
1071
1072 // Send notifications
1073 LV2_Atom_Forge_Frame frame;
1074 lv2_atom_forge_frame_time(&forge, 0);
1075 lv2_atom_forge_object(&forge, &frame, 0, uris.notify_messageEvent);
1076 lv2_atom_forge_key(&forge, uris.notify_message);
1077 lv2_atom_forge_int(&forge, messageNr);
1078 lv2_atom_forge_pop(&forge, &frame);
1079 }
1080
state_save(LV2_State_Store_Function store,LV2_State_Handle handle,uint32_t flags,const LV2_Feature * const * features)1081 LV2_State_Status BSchaffl::state_save (LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const* features)
1082 {
1083 // Save shared data
1084 store (handle, uris.bschaffl_sharedDataNr, &sharedDataNr, sizeof(sharedDataNr), uris.atom_Int, LV2_STATE_IS_POD);
1085 if (sharedDataNr != 0)
1086 {
1087 Atom_Controllers atom;
1088 for (int i = 0; i < NR_CONTROLLERS; ++i) atom.data[i] = sharedData[sharedDataNr - 1].get (i);
1089 atom.body.child_type = uris.atom_Float;
1090 atom.body.child_size = sizeof(float);
1091 store (handle, uris.bschaffl_controllers, &atom, NR_CONTROLLERS * sizeof (float) + sizeof(LV2_Atom_Vector_Body), uris.atom_Vector, LV2_STATE_IS_POD);
1092 }
1093
1094 // Save shape
1095 char shapesDataString[0x8010] = "Shape data:\n";
1096
1097 for (unsigned int nd = 0; nd < shape.size (); ++nd)
1098 {
1099 char valueString[160];
1100 Node node = shape.getNode (nd);
1101 snprintf
1102 (
1103 valueString,
1104 126,
1105 "typ:%d; ptx:%f; pty:%f; h1x:%f; h1y:%f; h2x:%f; h2y:%f",
1106 int (node.nodeType),
1107 node.point.x,
1108 node.point.y,
1109 node.handle1.x,
1110 node.handle1.y,
1111 node.handle2.x,
1112 node.handle2.y
1113 );
1114 if (nd < shape.size ()) strcat (valueString, ";\n");
1115 else strcat (valueString, "\n");
1116 strcat (shapesDataString, valueString);
1117 }
1118
1119 store (handle, uris.bschaffl_shapeData, shapesDataString, strlen (shapesDataString) + 1, uris.atom_String, LV2_STATE_IS_POD);
1120
1121 return LV2_STATE_SUCCESS;
1122 }
1123
state_restore(LV2_State_Retrieve_Function retrieve,LV2_State_Handle handle,uint32_t flags,const LV2_Feature * const * features)1124 LV2_State_Status BSchaffl::state_restore (LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const* features)
1125 {
1126 size_t size;
1127 uint32_t type;
1128 uint32_t valflags;
1129
1130 // Restore sharedData
1131 if (sharedDataNr != 0) sharedData[sharedDataNr - 1].unlink (this);
1132 sharedDataNr = 0;
1133 const void* sharedDataNrData = retrieve (handle, uris.bschaffl_sharedDataNr, &size, &type, &valflags);
1134 if (sharedDataNrData && (type == uris.atom_Int))
1135 {
1136 const int nr = *(int*)sharedDataNrData;
1137 sharedDataNr = nr;
1138 if (nr != 0) sharedData[nr - 1].link (this);
1139 }
1140
1141 if ((sharedDataNr >= 0) && (sharedDataNr <= 4))
1142 {
1143 const void* controllersData = retrieve (handle, uris.bschaffl_controllers, &size, &type, &valflags);
1144 if (controllersData && (type == uris.atom_Vector) && (sharedDataNr > 0))
1145 {
1146 const Atom_Controllers* atom = (const Atom_Controllers*) controllersData;
1147 if (atom->body.child_type == uris.atom_Float)
1148 {
1149 for (int i = 0; i < NR_CONTROLLERS; ++i) sharedData[sharedDataNr - 1].set (i, atom->data[i]);
1150 }
1151 }
1152 }
1153
1154 notify_sharedData = true;
1155
1156 for (int i = 0; i < NR_CONTROLLERS; ++i)
1157 {
1158 float newValue = getControllerInput (sharedDataNr, i);
1159 if (newValue != controllers[i])
1160 {
1161 setController (i, newValue);
1162 notify_controllers[i] = true;
1163 }
1164 }
1165
1166 // Restore shape
1167 const void* shapesData = retrieve (handle, uris.bschaffl_shapeData, &size, &type, &valflags);
1168 if (shapesData && (type == uris.atom_String))
1169 {
1170 // Clear old shape first
1171 shape.clearShape();
1172
1173 // Parse retrieved data
1174 std::string shapesDataString = (char*) shapesData;
1175 const std::string keywords[7] = {"typ:", "ptx:", "pty:", "h1x:", "h1y:", "h2x:", "h2y:"};
1176 while (!shapesDataString.empty())
1177 {
1178 // Look for next "typ:"
1179 size_t strPos = shapesDataString.find ("typ:");
1180 size_t nextPos = 0;
1181 if (strPos == std::string::npos) break; // No "typ:" found => end
1182 if (strPos + 4 > shapesDataString.length()) break; // Nothing more after id => end
1183 shapesDataString.erase (0, strPos + 4);
1184
1185 int typ;
1186 try {typ = BUtilities::stof (shapesDataString, &nextPos);}
1187 catch (const std::exception& e)
1188 {
1189 fprintf (stderr, "BSchaffl.lv2: Restore shape incomplete. Can't parse shape node type from \"%s...\"", shapesDataString.substr (0, 63).c_str());
1190 break;
1191 }
1192
1193 if (nextPos > 0) shapesDataString.erase (0, nextPos);
1194
1195 // Look for shape data
1196 Node node = {(NodeType) typ, {0, 0}, {0, 0}, {0, 0}};
1197 for (int i = 1; i < 7; ++i)
1198 {
1199 strPos = shapesDataString.find (keywords[i]);
1200 if (strPos == std::string::npos) continue; // Keyword not found => next keyword
1201 if (strPos + 4 >= shapesDataString.length()) // Nothing more after keyword => end
1202 {
1203 shapesDataString ="";
1204 break;
1205 }
1206 if (strPos > 0) shapesDataString.erase (0, strPos + 4);
1207 float val;
1208 try {val = BUtilities::stof (shapesDataString, &nextPos);}
1209 catch (const std::exception& e)
1210 {
1211 fprintf (stderr, "BSchaffl.lv2: Restore shape incomplete. Can't parse %s from \"%s...\"",
1212 keywords[i].substr(0,3).c_str(), shapesDataString.substr (0, 63).c_str());
1213 break;
1214 }
1215
1216 if (nextPos > 0) shapesDataString.erase (0, nextPos);
1217 switch (i)
1218 {
1219 case 1: node.point.x = val;
1220 break;
1221 case 2: node.point.y = val;
1222 break;
1223 case 3: node.handle1.x = val;
1224 break;
1225 case 4: node.handle1.y = val;
1226 break;
1227 case 5: node.handle2.x = val;
1228 break;
1229 case 6: node.handle2.y = val;
1230 break;
1231 default:break;
1232 }
1233 }
1234
1235 // Set data
1236 shape.appendNode (node);
1237 }
1238
1239 // Validate shape
1240 if ((shape.size () < 2) || (!shape.validateShape ())) shape.setDefaultShape ();
1241 if ((sharedDataNr > 0) && (sharedDataNr <=4)) sharedData[sharedDataNr - 1].shape = shape;
1242
1243 // Force GUI notification
1244 notify_shape = true;
1245 }
1246
1247 return LV2_STATE_SUCCESS;
1248 }
1249
instantiate(const LV2_Descriptor * descriptor,double samplerate,const char * bundle_path,const LV2_Feature * const * features)1250 static LV2_Handle instantiate (const LV2_Descriptor* descriptor, double samplerate, const char* bundle_path, const LV2_Feature* const* features)
1251 {
1252 // New instance
1253 BSchaffl* instance;
1254 try {instance = new BSchaffl(samplerate, features);}
1255 catch (std::exception& exc)
1256 {
1257 fprintf (stderr, "BSchaffl.lv2: Plugin instantiation failed. %s\n", exc.what ());
1258 return NULL;
1259 }
1260
1261 if (!instance)
1262 {
1263 fprintf(stderr, "BSchaffl.lv2: Plugin instantiation failed.\n");
1264 return NULL;
1265 }
1266
1267 if (!instance->map)
1268 {
1269 fprintf(stderr, "BSchaffl.lv2: Host does not support urid:map.\n");
1270 delete (instance);
1271 return NULL;
1272 }
1273
1274 return (LV2_Handle)instance;
1275 }
1276
connect_port(LV2_Handle instance,uint32_t port,void * data)1277 static void connect_port (LV2_Handle instance, uint32_t port, void *data)
1278 {
1279 BSchaffl* inst = (BSchaffl*) instance;
1280 if (inst) inst->connect_port (port, data);
1281 }
1282
run(LV2_Handle instance,uint32_t n_samples)1283 static void run (LV2_Handle instance, uint32_t n_samples)
1284 {
1285 BSchaffl* inst = (BSchaffl*) instance;
1286 if (inst) inst->run (n_samples);
1287 }
1288
state_save(LV2_Handle instance,LV2_State_Store_Function store,LV2_State_Handle handle,uint32_t flags,const LV2_Feature * const * features)1289 static LV2_State_Status state_save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags,
1290 const LV2_Feature* const* features)
1291 {
1292 BSchaffl* inst = (BSchaffl*)instance;
1293 if (!inst) return LV2_STATE_SUCCESS;
1294
1295 return inst->state_save (store, handle, flags, features);
1296 }
1297
state_restore(LV2_Handle instance,LV2_State_Retrieve_Function retrieve,LV2_State_Handle handle,uint32_t flags,const LV2_Feature * const * features)1298 static LV2_State_Status state_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t flags,
1299 const LV2_Feature* const* features)
1300 {
1301 BSchaffl* inst = (BSchaffl*)instance;
1302 if (!inst) return LV2_STATE_SUCCESS;
1303
1304 return inst->state_restore (retrieve, handle, flags, features);
1305 }
1306
cleanup(LV2_Handle instance)1307 static void cleanup (LV2_Handle instance)
1308 {
1309 BSchaffl* inst = (BSchaffl*) instance;
1310 if (inst) delete inst;
1311 }
1312
extension_data(const char * uri)1313 static const void* extension_data(const char* uri)
1314 {
1315 static const LV2_State_Interface state = {state_save, state_restore};
1316 if (!strcmp(uri, LV2_STATE__interface)) return &state;
1317 return NULL;
1318 }
1319
1320 static const LV2_Descriptor descriptor =
1321 {
1322 BSCHAFFL_URI,
1323 instantiate,
1324 connect_port,
1325 NULL, //activate,
1326 run,
1327 NULL, //deactivate,
1328 cleanup,
1329 extension_data
1330 };
1331
1332 // LV2 Symbol Export
lv2_descriptor(uint32_t index)1333 LV2_SYMBOL_EXPORT const LV2_Descriptor* lv2_descriptor(uint32_t index)
1334 {
1335 switch (index)
1336 {
1337 case 0: return &descriptor;
1338 default: return NULL;
1339 }
1340 }
1341