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