1 
2 /*
3  *  Diverse Bristol audio routines.
4  *  Copyright (c) by Nick Copeland <nickycopeland@hotmail.com> 1996,2012
5  *
6  *
7  *   This program is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License as published by
9  *   the Free Software Foundation; either version 3 of the License, or
10  *   (at your option) any later version.
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 
23 #include <fcntl.h>
24 
25 #include "brighton.h"
26 #include "brightonMini.h"
27 #include "brightoninternals.h"
28 
29 static int solinaInit();
30 static int solinaConfigure();
31 static int solinaCallback(brightonWindow *, int, int, float);
32 static int midiCallback(brightonWindow *, int, int, float);
33 
34 extern guimain global;
35 static int dc, shade_id;
36 
37 #include "brightonKeys.h"
38 
39 #define OPTS_PANEL 0
40 #define MOD_PANEL 1
41 #define KEY_PANEL 2
42 #define FX_PANEL 4
43 #define MEM_PANEL 5
44 
45 #define OPTS_COUNT 16
46 #define FX_COUNT 1
47 #define MOD_COUNT 16
48 #define MEM_COUNT 14
49 
50 #define OPTS_START 0
51 #define FX_START OPTS_COUNT
52 #define MOD_START (FX_START + FX_COUNT)
53 #define MEM_START (MOD_COUNT + MOD_START)
54 
55 #define ACTIVE_DEVS (MOD_COUNT + FX_COUNT + OPTS_COUNT)
56 #define DEVICE_COUNT (ACTIVE_DEVS + MEM_COUNT)
57 
58 /*
59  * This structure is for device definition. The structure is defined in
60  * include/brighton.h, further definitions in brighton/brightonDevtable.h and
61  * include/brightoninternals.h
62  *
63  *	typedef int (*brightonCallback)(int, float);
64  *	typedef struct BrightonLocations {
65  *		int device; 0=rotary, 1=scale, etc.
66  *		float relx, rely; relative position with regards to 1000 by 1000 window
67  *		float relw, relh; relative height.
68  *		int from, to;
69  *		brightonCallback callback; specific to this dev
70  *		char *image; bitmap. If zero take a device default.
71  *		int flags;
72  *	} brightonLocations;
73  *
74  * This example is for a solinaBristol type synth interface.
75  */
76 
77 #define R1 400
78 
79 #define W1 75
80 #define W2 20
81 #define L1 300
82 #define L2 250
83 
84 #define C0 310
85 
86 #define C1 355
87 #define C2 380
88 
89 #define C3 410
90 #define C4 500
91 #define C5 590
92 #define C6 680
93 
94 #define C7 760
95 #define C8 785
96 #define C9 810
97 #define C10 835
98 
99 static brightonLocations panelControls[OPTS_COUNT] = {
100 	{"BassString", 2, C1, R1, W2, L2, 0, 1, 0, "bitmaps/buttons/solinaOff.xpm",
101 		"bitmaps/buttons/solinaOn.xpm", 0},
102 	{"BassHorn", 2, C2, R1, W2, L2, 0, 1, 0, "bitmaps/buttons/solinaOff.xpm",
103 		"bitmaps/buttons/solinaOn.xpm", 0},
104 
105 	{"BassGain", 1, C3, R1, W1, L1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm",
106 		0, BRIGHTON_VERTICAL|BRIGHTON_REVERSE},
107 	{"Tuning", 1, C4, R1, W1, L1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm",
108 		0, BRIGHTON_VERTICAL|BRIGHTON_NOTCH|BRIGHTON_REVERSE},
109 	{"Crescendo", 1, C5, R1, W1, L1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm",
110 		0, BRIGHTON_VERTICAL|BRIGHTON_REVERSE},
111 	{"Sustain", 1, C6, R1, W1, L1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm",
112 		0, BRIGHTON_VERTICAL|BRIGHTON_REVERSE},
113 
114 	{"String-16", 2, C7, R1, W2, L2, 0, 1, 0, "bitmaps/buttons/solinaOff.xpm",
115 		"bitmaps/buttons/solinaOn.xpm", 0},
116 	{"Horn-16", 2, C9, R1, W2, L2, 0, 1, 0, "bitmaps/buttons/solinaOff.xpm",
117 		"bitmaps/buttons/solinaOn.xpm", 0},
118 	{"String-8", 2, C8, R1, W2, L2, 0, 1, 0, "bitmaps/buttons/solinaOff.xpm",
119 		"bitmaps/buttons/solinaOn.xpm", 0},
120 	{"Horn-8", 2, C10, R1, W2, L2, 0, 1, 0, "bitmaps/buttons/solinaOff.xpm",
121 		"bitmaps/buttons/solinaOn.xpm", 0},
122 
123 	{"MasterVolume", 0, C0, R1 - 100, 400, 400, 0, 1, 0, 0, 0, 0},
124 	{"", 0, C0, R1 - 100, 400, 400, 0, 1, 0, 0, 0, BRIGHTON_WITHDRAWN},
125 	{"", 0, C0, R1 - 100, 400, 400, 0, 1, 0, 0, 0, BRIGHTON_WITHDRAWN},
126 	{"", 0, C0, R1 - 100, 400, 400, 0, 1, 0, 0, 0, BRIGHTON_WITHDRAWN},
127 	{"", 0, C0, R1 - 100, 400, 400, 0, 1, 0, 0, 0, BRIGHTON_WITHDRAWN},
128 	{"", 0, C0, R1 - 100, 400, 400, 0, 1, 0, 0, 0, BRIGHTON_WITHDRAWN},
129 };
130 
131 #define S1 200
132 
133 #define oW1 20
134 #define oL1 700
135 
136 #define oC1 39
137 #define oC2 103
138 #define oC3 152
139 #define oC4 203
140 
141 #define oC5 280
142 #define oC6 330
143 
144 #define oC7 742
145 #define oC8 790
146 #define oC9 842
147 #define oC10 891
148 #define oC11 942
149 
150 #define oC12 600
151 #define oC13 650
152 #define oC14 700
153 
154 #define oC15 510
155 #define oC16 560
156 
157 #define oR1 100
158 #define oR2 300
159 #define oR3 500
160 #define oR4 700
161 
162 static brightonLocations options[MOD_COUNT] = {
163 	{"Chorus-D1", 1, oC7, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm",
164 		0, 0},
165 	{"Chorus-D1", 1, oC8, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm",
166 		0, 0},
167 	{"Chorus-Speed", 1, oC9, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm",
168 		0, 0},
169 	{"On Wet/Dry", 1, oC10, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm",
170 		0, 0},
171 	{"Off Wet/Dry", 1, oC11, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm",
172 		0, 0},
173 
174 	{"Osc Detune", 1, oC2, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm",
175 		0, BRIGHTON_REVERSE|BRIGHTON_NOTCH},
176 	{"PulseWidth", 1, oC3, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm", 0, 0},
177 
178 	/* The remaining envelope parameters */
179 	{"Decay", 1, oC5, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm", 0, 0},
180 	{"Sustain", 1, oC6, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm", 0, 0},
181 
182 	/* These should be PWM and LFO, and LFO to OSC? */
183 	{"PulseWidthMod", 1, oC4, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm", 0, 0},
184 	{"LFO Rate", 1, oC1, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm", 0, 0},
185 
186 	/* Reverb */
187 	{"Reverb Feedback", 1, oC12, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm", 0, 0},
188 	{"Reverb Crossover", 1, oC13, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm", 0, 0},
189 	{"Reverb Depth", 1, oC14, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm", 0, 0},
190 
191 	/* Vibrato and tremelo */
192 	{"Vibraro", 1, oC15, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm", 0, 0},
193 	{"Tremelo", 1, oC16, oR1, oW1, oL1, 0, 1, 0, "bitmaps/knobs/sliderred.xpm", 0, 0},
194 };
195 
196 #define mR1 200
197 #define mR2 450
198 #define mR3 700
199 
200 #define mC1 100
201 #define mC2 283
202 #define mC3 466
203 #define mC4 649
204 #define mC5 835
205 
206 #define mC11 100
207 #define mC12 255
208 #define mC13 410
209 #define mC14 565
210 #define mC15 720
211 #define mC16 874
212 
213 #define S3 100
214 #define S4 80
215 #define S5 120
216 #define S6 150
217 
218 static
219 brightonLocations mem[MEM_COUNT] = {
220 	/* memories */
221 	{"", 2, mC1, mR1, S3, S5, 0, 1, 0,
222 		"bitmaps/buttons/solinaOff.xpm",
223 		"bitmaps/buttons/solinaOn.xpm", 0},
224 	{"", 2, mC2, mR1, S3, S5, 0, 1, 0,
225 		"bitmaps/buttons/solinaOff.xpm",
226 		"bitmaps/buttons/solinaOn.xpm", 0},
227 	{"", 2, mC3, mR1, S3, S5, 0, 1, 0,
228 		"bitmaps/buttons/solinaOff.xpm",
229 		"bitmaps/buttons/solinaOn.xpm", 0},
230 	{"", 2, mC4, mR1, S3, S5, 0, 1, 0,
231 		"bitmaps/buttons/solinaOff.xpm",
232 		"bitmaps/buttons/solinaOn.xpm", 0},
233 	{"", 2, mC5, mR1, S3, S5, 0, 1, 0,
234 		"bitmaps/buttons/solinaOff.xpm",
235 		"bitmaps/buttons/solinaOn.xpm", 0},
236 	{"", 2, mC1, mR2, S3, S5, 0, 1, 0,
237 		"bitmaps/buttons/solinaOff.xpm",
238 		"bitmaps/buttons/solinaOn.xpm", 0},
239 	{"", 2, mC2, mR2, S3, S5, 0, 1, 0,
240 		"bitmaps/buttons/solinaOff.xpm",
241 		"bitmaps/buttons/solinaOn.xpm", 0},
242 	{"", 2, mC3, mR2, S3, S5, 0, 1, 0,
243 		"bitmaps/buttons/solinaOff.xpm",
244 		"bitmaps/buttons/solinaOn.xpm", 0},
245 	{"", 2, mC4, mR2, S3, S5, 0, 1, 0,
246 		"bitmaps/buttons/solinaOff.xpm",
247 		"bitmaps/buttons/solinaOn.xpm", 0},
248 	{"", 2, mC5, mR2, S3, S5, 0, 1, 0,
249 		"bitmaps/buttons/solinaOff.xpm",
250 		"bitmaps/buttons/solinaOn.xpm", 0},
251 	/* mem U/D, midi U/D, Load + Save */
252 	{"", 2, mC1, mR3, S4, S6, 0, 1, 0,
253 		"bitmaps/buttons/pressoffg.xpm",
254 		"bitmaps/buttons/pressong.xpm", BRIGHTON_CHECKBUTTON},
255 	{"", 2, mC2, mR3, S4, S6, 0, 1, 0,
256 		"bitmaps/buttons/pressoffg.xpm",
257 		"bitmaps/buttons/pressong.xpm", BRIGHTON_CHECKBUTTON},
258 	{"", 2, mC5, mR3, S4, S6, 0, 1, 0,
259 		"bitmaps/buttons/pressoff.xpm",
260 		"bitmaps/buttons/presson.xpm", 0},
261 	{"", 2, mC3, mR3, S4, S6, 0, 1, 0,
262 		"bitmaps/buttons/pressoffo.xpm",
263 		"bitmaps/buttons/pressono.xpm", BRIGHTON_CHECKBUTTON},
264 };
265 
266 static
267 brightonLocations fx[FX_COUNT] = {
268 	{"FX on/off", 2, 300, 400, 400, 150, 0, 1, 0, "bitmaps/buttons/solinaOff.xpm",
269 		"bitmaps/buttons/solinaOn.xpm", 0},
270 };
271 
272 /*
273  * Should try and make this one as generic as possible, and try to use it as
274  * a general memory routine. has Midi u/d, mem u/d, load/save and a display.
275  */
276 static int
memCallback(brightonWindow * win,int panel,int index,float value)277 memCallback(brightonWindow* win, int panel, int index, float value)
278 {
279 	guiSynth *synth = findSynth(global.synths, win);
280 
281 /* printf("memCallback(%i, %i, %f) %i, %s\n", panel, index, value, */
282 /* synth->mem.active, synth->resources->name); */
283 
284 	if (synth->flags & SUPPRESS)
285 		return(0);
286 
287 	/*
288 	 * The first ten buttons are exclusive highlighting, we use the first mem
289 	 * pointer to handle this.
290 	 */
291 	if (synth->dispatch[MEM_START].other2)
292 	{
293 		synth->dispatch[MEM_START].other2 = 0;
294 		return(0);
295 	}
296 
297 	if (index == 13)
298 	{
299 		if (brightonDoubleClick(dc)) {
300 			synth->location = synth->dispatch[MEM_START].other1;
301 			saveMemory(synth, "solina", 0, synth->bank + synth->location, 0);
302 		}
303 		return(0);
304 	}
305 
306 	if (index < 10)
307 	{
308 		int i;
309 		brightonEvent event;
310 
311 		event.command = BRIGHTON_PARAMCHANGE;
312 		event.type = BRIGHTON_FLOAT;
313 		event.value = 0;
314 
315 		/*
316 		 * This is a numeric. We need to force exclusion.
317 		 */
318 		if (synth->dispatch[MEM_START].other1 != -1)
319 		{
320 			synth->dispatch[MEM_START].other2 = 1;
321 
322 			if (synth->dispatch[MEM_START].other1 != index)
323 				event.value = 0;
324 			else
325 				event.value = 1;
326 
327 			brightonParamChange(synth->win, panel,
328 				synth->dispatch[MEM_START].other1, &event);
329 		}
330 
331 		synth->location = index;
332 		loadMemory(synth, "solina", 0, synth->bank + synth->location,
333 			synth->mem.active, 0, BRISTOL_NOCALLS|BRISTOL_FORCE);
334 
335 		/*
336 		 * We have loaded the memory but cannot call the devices as they have
337 		 * various panels.
338 		 */
339 		for (i = 0; i < OPTS_COUNT; i++)
340 		{
341 			event.value = synth->mem.param[i];
342 			brightonParamChange(synth->win, OPTS_PANEL, i, &event);
343 		}
344 
345 		event.value = synth->mem.param[i];
346 		brightonParamChange(synth->win, FX_PANEL, 0, &event);
347 
348 		for (; i < ACTIVE_DEVS; i++)
349 		{
350 			event.value = synth->mem.param[i];
351 			brightonParamChange(synth->win, MOD_PANEL, i - MOD_START, &event);
352 		}
353 
354 		synth->dispatch[MEM_START].other1 = index;
355 	} else {
356 		int newchan;
357 
358 		/*
359 		 * This is a control button.
360 		 */
361 		switch(index) {
362 			case 10:
363 				/*
364 				 * Midi Down
365 				 */
366 				if ((newchan = synth->midichannel - 1) < 0)
367 				{
368 					synth->midichannel = 0;
369 					return(0);
370 				}
371 
372 				if (global.libtest)
373 				{
374 					printf("midi chan %i\n", newchan);
375 					synth->midichannel = newchan;
376 					return(0);
377 				}
378 
379 				bristolMidiSendMsg(global.controlfd, synth->sid,
380 					127, 0, BRISTOL_MIDICHANNEL|newchan);
381 
382 				synth->midichannel = newchan;
383 				break;
384 			case 11:
385 				/*
386 				 * Midi Up
387 				 */
388 				if ((newchan = synth->midichannel + 1) > 15)
389 				{
390 					synth->midichannel = 15;
391 					return(0);
392 				}
393 
394 				if (global.libtest)
395 				{
396 					printf("midi chan %i\n", newchan);
397 					synth->midichannel = newchan;
398 					return(0);
399 				}
400 
401 				bristolMidiSendMsg(global.controlfd, synth->sid,
402 					127, 0, BRISTOL_MIDICHANNEL|newchan);
403 
404 				synth->midichannel = newchan;
405 				break;
406 		}
407 	}
408 
409 	return(0);
410 }
411 
412 /*
413  * This is a set of globals for the main window rendering. Again taken from
414  * include/brighton.h
415  */
416 brightonApp solinaApp = {
417 	"solina",
418 	0, /* no blueprint on wood background. */
419 	"bitmaps/textures/metal5.xpm",
420 	BRIGHTON_STRETCH,
421 	solinaInit,
422 	solinaConfigure, /* 3 callbacks */
423 	midiCallback,
424 	destroySynth,
425 	{-1, 0, 2, 2, 5, 520, 0, 0},
426 	600, 200, 0, 0,
427 	8, /* panel count */
428 	{
429 		{
430 			"Mods",
431 			"bitmaps/blueprints/solinapanel.xpm",
432 			"bitmaps/textures/metal6.xpm", /* flags */
433 			BRIGHTON_STRETCH|BRIGHTON_VERTICAL|BRIGHTON_REVERSE,
434 			0,
435 			0,
436 			solinaCallback,
437 			15, 390, 970, 180,
438 			OPTS_COUNT,
439 			panelControls
440 		},
441 		{
442 			"Opts",
443 			"bitmaps/blueprints/solinamods.xpm",
444 			"bitmaps/textures/metal5.xpm", /* flags */
445 			0x020,
446 			0,
447 			0,
448 			solinaCallback,
449 			17, 9, 967, 381,
450 			MOD_COUNT,
451 			options
452 		},
453 		{
454 			"Keyboard",
455 			0,
456 			"bitmaps/keys/kbg.xpm", /* flags */
457 			0x020|BRIGHTON_STRETCH,
458 			0,
459 			0,
460 			keyCallback,
461 			187, 580, 740, 400,
462 			KEY_COUNT_4OCTAVE,
463 			keys4octave
464 		},
465 		{
466 			"Solina",
467 			0,
468 			"bitmaps/textures/wood6.xpm",
469 			0, /* flags */
470 			0,
471 			0,
472 			0,
473 			17, 9, 967, 381,
474 			0,
475 			0
476 		},
477 		{
478 			"Effects switch",
479 			0,
480 			"bitmaps/textures/metal5.xpm",
481 			0,
482 			0,
483 			0,
484 			solinaCallback,
485 			930, 570, 53, 400,
486 			FX_COUNT,
487 			fx
488 		},
489 		{
490 			"Memory Panel",
491 			0,
492 			"bitmaps/textures/metal5.xpm",
493 			0,
494 			0,
495 			0,
496 			solinaCallback,
497 			17, 570, 168, 400,
498 			MEM_COUNT,
499 			mem
500 		},
501 		{
502 			"Wood Side",
503 			0,
504 			"bitmaps/textures/wood.xpm",
505 			BRIGHTON_STRETCH|BRIGHTON_VERTICAL, /* flags */
506 			0,
507 			0,
508 			0,
509 			0, 0, 15, 1000,
510 			0,
511 			0
512 		},
513 		{
514 			"Wood Side",
515 			0,
516 			"bitmaps/textures/wood.xpm",
517 			BRIGHTON_STRETCH|BRIGHTON_VERTICAL, /* flags */
518 			0,
519 			0,
520 			0,
521 			985, 0, 15, 1000,
522 			0,
523 			0
524 		},
525 	}
526 };
527 
528 /*static dispatcher dispatch[DEVICE_COUNT]; */
529 
530 static int
midiCallback(brightonWindow * win,int controller,int value,float n)531 midiCallback(brightonWindow *win, int controller, int value, float n)
532 {
533 	guiSynth *synth = findSynth(global.synths, win);
534 
535 	printf("midi callback: %x, %i\n", controller, value);
536 
537 	switch(controller)
538 	{
539 		case MIDI_PROGRAM:
540 			printf("midi program: %x, %i\n", controller, value);
541 			synth->location = value;
542 			loadMemory(synth, synth->resources->name, 0,
543 				synth->bank + synth->location, synth->mem.active, 0, 0);
544 			break;
545 		case MIDI_BANK_SELECT:
546 			printf("midi banksel: %x, %i\n", controller, value);
547 			synth->bank = value;
548 			break;
549 	}
550 	return(0);
551 }
552 
553 static void
panelSwitch(guiSynth * id,int fd,int chan,int cont,int op,int value)554 panelSwitch(guiSynth *id, int fd, int chan, int cont, int op, int value)
555 {
556 	brightonEvent event;
557 
558 	/*
559 	 * If the sendvalue is zero, then withdraw the opts window, draw the
560 	 * slider window, and vice versa.
561 	 */
562 	if (value == 0)
563 	{
564 		event.type = BRIGHTON_EXPOSE;
565 		event.intvalue = 0;
566 		brightonParamChange(id->win, 1, -1, &event);
567 		event.intvalue = 1;
568 		brightonParamChange(id->win, 3, -1, &event);
569 
570 		shade_id = brightonPut(id->win,
571 			"bitmaps/blueprints/solinashade.xpm", 0, 0, id->win->width,
572 				id->win->height);
573 	} else {
574 		event.type = BRIGHTON_EXPOSE;
575 		event.intvalue = 0;
576 		brightonParamChange(id->win, 3, -1, &event);
577 		event.intvalue = 1;
578 		brightonParamChange(id->win, 1, -1, &event);
579 
580 		brightonRemove(id->win, shade_id);
581 	}
582 }
583 
584 static int
solinaMidiNull(void * synth,int fd,int chan,int c,int o,int v)585 solinaMidiNull(void *synth, int fd, int chan, int c, int o, int v)
586 {
587 /*	printf("%i, %i, %i\n", c, o, v); */
588 	return(0);
589 }
590 
591 static int
solinaMidiDetune(guiSynth * synth,int fd,int chan,int c,int o,int v)592 solinaMidiDetune(guiSynth *synth, int fd, int chan, int c, int o, int v)
593 {
594 	if ((v = 8192 - v) >= 8192)
595 		v = 8191;
596 	if (v <= -8191)
597 		v = -8191;
598 
599 	bristolMidiSendMsg(global.controlfd, synth->sid, 0, 2, 8192);
600 	bristolMidiSendMsg(global.controlfd, synth->sid, 1, 2, 8192 + v);
601 	bristolMidiSendMsg(global.controlfd, synth->sid, 2, 2, 8192 - v);
602 	return(0);
603 }
604 
605 static int
solinaMidiPW(guiSynth * synth,int fd,int chan,int c,int o,int v)606 solinaMidiPW(guiSynth *synth, int fd, int chan, int c, int o, int v)
607 {
608 	bristolMidiSendMsg(global.controlfd, synth->sid, 0, 0, v / 2);
609 	bristolMidiSendMsg(global.controlfd, synth->sid, 1, 0, v * 3 / 4);
610 	bristolMidiSendMsg(global.controlfd, synth->sid, 2, 0, v);
611 	return(0);
612 }
613 
614 static int
solinaMidiFX(guiSynth * synth,int fd,int chan,int c,int o,int v)615 solinaMidiFX(guiSynth *synth, int fd, int chan, int c, int o, int v)
616 {
617 	/*
618 	 * See if the effect is turned on. If so change the wet dry, otherwise
619 	 * set wet/dry to 0
620 	 */
621 	if (synth->mem.param[FX_START] == 0.0) {
622 		bristolMidiSendMsg(fd, chan, 98, 3,
623 			(int) (synth->mem.param[MOD_START + 4] * C_RANGE_MIN_1));
624 		bristolMidiSendMsg(fd, chan, 99, 3,
625 			(int) (synth->mem.param[MOD_START + 4] * C_RANGE_MIN_1));
626 	} else {
627 		bristolMidiSendMsg(fd, chan, 98, 3,
628 			(int) (synth->mem.param[MOD_START + 3] * C_RANGE_MIN_1));
629 		bristolMidiSendMsg(fd, chan, 99, 3,
630 			(int) (synth->mem.param[MOD_START + 3] * C_RANGE_MIN_1));
631 	}
632 
633 	return(0);
634 }
635 
636 static int
solinaMidiSendMsg(void * synth,int fd,int chan,int c,int o,int v)637 solinaMidiSendMsg(void *synth, int fd, int chan, int c, int o, int v)
638 {
639 /*	printf("%i, %i, %i\n", c, o, v); */
640 	bristolMidiSendMsg(fd, chan, c, o, v);
641 	return(0);
642 }
643 
644 /*
645  * For the sake of ease of use, links have been placed here to be called
646  * by any of the devices created. They would be better in some other file,
647  * perhaps with this as a dispatch.
648  *
649  * Param refers to the device index in the locations table given below.
650  */
651 static int
solinaCallback(brightonWindow * win,int panel,int index,float value)652 solinaCallback(brightonWindow *win, int panel, int index, float value)
653 {
654 	guiSynth *synth = findSynth(global.synths, win);
655 	int sendvalue;
656 
657 	if (synth == 0)
658 		return(0);
659 
660 	if ((index >= DEVICE_COUNT) || ((synth->flags & OPERATIONAL) == 0))
661 		return(0);
662 
663 	if (solinaApp.resources[panel].devlocn[index].to == 1)
664 		sendvalue = value * C_RANGE_MIN_1;
665 	else
666 		sendvalue = value;
667 
668 	switch (panel) {
669 		case OPTS_PANEL:
670 			break;
671 		case FX_PANEL:
672 			index+=FX_START;
673 			break;
674 		case MOD_PANEL:
675 			index+=MOD_START;
676 			break;
677 		case MEM_PANEL:
678 			if (index == 12)
679 				panelSwitch(synth, 0, 0, 0, 0, value);
680 			else
681 				memCallback(win, panel, index, value);
682 			return(0);
683 	}
684 
685 	synth->mem.param[index] = value;
686 
687 	if ((!global.libtest) || (index >= ACTIVE_DEVS))
688 		synth->dispatch[index].routine(synth,
689 			global.controlfd, synth->sid,
690 			synth->dispatch[index].controller,
691 			synth->dispatch[index].operator,
692 			sendvalue);
693 #ifdef DEBUG
694 	else
695 		printf("dispatch[%p,%i](%i, %i, %i, %i, %i)\n", synth, index,
696 			global.controlfd, synth->sid,
697 			synth->dispatch[index].controller,
698 			synth->dispatch[index].operator,
699 			sendvalue);
700 #endif
701 
702 	return(0);
703 }
704 
705 /*
706  * Any location initialisation required to run the callbacks. For bristol, this
707  * will connect to the engine, and give it some base parameters.
708  * May need to generate some application specific menus.
709  * Will also then make specific requests to some of the devices to alter their
710  * rendering.
711  */
712 static int
solinaInit(brightonWindow * win)713 solinaInit(brightonWindow* win)
714 {
715 	guiSynth *synth = findSynth(global.synths, win);
716 	dispatcher *dispatch;
717 	int i;
718 
719 	if (synth == 0)
720 	{
721 		synth = findSynth(global.synths, 0);
722 		if (synth == 0)
723 		{
724 			printf("cannot init\n");
725 			return(0);
726 		}
727 	}
728 
729 	synth->win = win;
730 
731 	printf("Initialise the solina link to bristol: %p\n", synth->win);
732 
733 	synth->mem.param = (float *) brightonmalloc(DEVICE_COUNT * sizeof(float));
734 	synth->mem.count = DEVICE_COUNT;
735 	synth->mem.active = ACTIVE_DEVS;
736 	synth->dispatch = (dispatcher *)
737 		brightonmalloc(DEVICE_COUNT * sizeof(dispatcher));
738 	dispatch = synth->dispatch;
739 
740 	/*
741 	 * We really want to have three connection mechanisms. These should be
742 	 *	1. Unix named sockets.
743 	 *	2. UDP sockets.
744 	 *	3. MIDI pipe.
745 	 */
746 	if (!global.libtest)
747 		if ((synth->sid = initConnection(&global, synth)) < 0)
748 			return(-1);
749 
750 	for (i = 0; i < DEVICE_COUNT; i++)
751 		synth->dispatch[i].routine = solinaMidiNull;
752 
753 	/* Bass oscillator */
754 	synth->dispatch[OPTS_START + 0].controller = 126; /* harmonic mix */
755 	synth->dispatch[OPTS_START + 0].operator = 14;
756 	synth->dispatch[OPTS_START + 1].controller = 126;
757 	synth->dispatch[OPTS_START + 1].operator = 15;
758 	synth->dispatch[OPTS_START + 2].controller = 2;
759 	synth->dispatch[OPTS_START + 2].operator = 3;
760 
761 	synth->dispatch[OPTS_START + 3].controller = 126; /* Global tune */
762 	synth->dispatch[OPTS_START + 3].operator = 1;
763 	synth->dispatch[OPTS_START + 4].controller = 3; /* Env - 2 parameters */
764 	synth->dispatch[OPTS_START + 4].operator = 0;
765 	synth->dispatch[OPTS_START + 5].controller = 3;
766 	synth->dispatch[OPTS_START + 5].operator = 3;
767 	synth->dispatch[OPTS_START + 6].controller = 126; /* Harmonics - 4 params */
768 	synth->dispatch[OPTS_START + 6].operator = 10;
769 	synth->dispatch[OPTS_START + 7].controller = 126;
770 	synth->dispatch[OPTS_START + 7].operator = 11;
771 	synth->dispatch[OPTS_START + 8].controller = 126;
772 	synth->dispatch[OPTS_START + 8].operator = 12;
773 	synth->dispatch[OPTS_START + 9].controller = 126;
774 	synth->dispatch[OPTS_START + 9].operator = 13;
775 	synth->dispatch[OPTS_START + 10].controller = 3; /* Volume */
776 	synth->dispatch[OPTS_START + 10].operator = 4; /* Volume */
777 
778 	synth->dispatch[OPTS_START + 0].routine
779 		= synth->dispatch[OPTS_START + 1].routine
780 		= synth->dispatch[OPTS_START + 2].routine
781 		= synth->dispatch[OPTS_START + 3].routine
782 		= synth->dispatch[OPTS_START + 4].routine
783 		= synth->dispatch[OPTS_START + 5].routine
784 		= synth->dispatch[OPTS_START + 6].routine
785 		= synth->dispatch[OPTS_START + 7].routine
786 		= synth->dispatch[OPTS_START + 8].routine
787 		= synth->dispatch[OPTS_START + 9].routine
788 		= synth->dispatch[OPTS_START + 10].routine
789 		= solinaMidiSendMsg;
790 
791 	synth->dispatch[FX_START + 0].controller = 98; /* Effects wet/dry */
792 	synth->dispatch[FX_START + 0].operator = 3;
793 
794 	synth->dispatch[MOD_START + 0].routine
795 		= synth->dispatch[MOD_START + 1].routine
796 		= synth->dispatch[MOD_START + 2].routine
797 		= synth->dispatch[MOD_START + 3].routine
798 		= synth->dispatch[MOD_START + 4].routine
799 		= synth->dispatch[MOD_START + 7].routine
800 		= synth->dispatch[MOD_START + 8].routine
801 		= synth->dispatch[MOD_START + 9].routine
802 		= synth->dispatch[MOD_START + 10].routine
803 		= synth->dispatch[MOD_START + 11].routine
804 		= synth->dispatch[MOD_START + 12].routine
805 		= synth->dispatch[MOD_START + 13].routine
806 		= synth->dispatch[MOD_START + 14].routine
807 		= synth->dispatch[MOD_START + 15].routine
808 			= solinaMidiSendMsg;
809 
810 	synth->dispatch[MOD_START + 0].controller = 98; /* Effects */
811 	synth->dispatch[MOD_START + 0].operator = 0;
812 	synth->dispatch[MOD_START + 1].controller = 98; /* Effects */
813 	synth->dispatch[MOD_START + 1].operator = 1;
814 	synth->dispatch[MOD_START + 2].controller = 98; /* Effects */
815 	synth->dispatch[MOD_START + 2].operator = 2;
816 	synth->dispatch[MOD_START + 3].controller = 98; /* Effects */
817 	synth->dispatch[MOD_START + 3].operator = 3;
818 	synth->dispatch[MOD_START + 4].controller = 98; /* Effects */
819 	synth->dispatch[MOD_START + 4].operator = 3;
820 
821 	synth->dispatch[MOD_START + 11].controller = 99; /* Effects */
822 	synth->dispatch[MOD_START + 11].operator = 0;
823 	synth->dispatch[MOD_START + 12].controller = 99; /* Effects */
824 	synth->dispatch[MOD_START + 12].operator = 1;
825 	synth->dispatch[MOD_START + 13].controller = 99; /* Effects */
826 	synth->dispatch[MOD_START + 13].operator = 2;
827 	synth->dispatch[MOD_START + 14].controller = 126; /* Vib */
828 	synth->dispatch[MOD_START + 14].operator = 7;
829 	synth->dispatch[MOD_START + 15].controller = 126; /* Trem */
830 	synth->dispatch[MOD_START + 15].operator = 8;
831 
832 	synth->dispatch[MOD_START + 5].routine
833 		= (synthRoutine) solinaMidiDetune;
834 	synth->dispatch[MOD_START + 6].routine
835 		= (synthRoutine) solinaMidiPW;
836 
837 	synth->dispatch[MOD_START + 3].routine
838 		= synth->dispatch[MOD_START + 4].routine
839 		= synth->dispatch[FX_START + 0].routine
840 			= (synthRoutine) solinaMidiFX;
841 
842 	synth->dispatch[MOD_START + 7].controller = 3; /* Env - 2 parameters */
843 	synth->dispatch[MOD_START + 7].operator = 1;
844 	synth->dispatch[MOD_START + 8].controller = 3;
845 	synth->dispatch[MOD_START + 8].operator = 2;
846 
847 	synth->dispatch[MOD_START + 9].controller = 126; /* PWM and LFO */
848 	synth->dispatch[MOD_START + 9].operator = 3;
849 	synth->dispatch[MOD_START + 10].controller = 5;
850 	synth->dispatch[MOD_START + 10].operator = 0;
851 
852 	/*
853 	 * These will be replaced by some opts controllers. We need to tie the
854 	 * envelope parameters for decay, sustain. We need to fix a few parameters
855 	 * of the oscillators too - transpose, tune and gain.
856 	 */
857 	bristolMidiSendMsg(global.controlfd, synth->sid, 3, 1, 10);
858 	bristolMidiSendMsg(global.controlfd, synth->sid, 3, 2, 16382);
859 
860 	/* Oscillators */
861 	bristolMidiSendMsg(global.controlfd, synth->sid, 0, 3, 16383);
862 	bristolMidiSendMsg(global.controlfd, synth->sid, 1, 3, 16383);
863 	bristolMidiSendMsg(global.controlfd, synth->sid, 1, 1, 3);
864 	bristolMidiSendMsg(global.controlfd, synth->sid, 2, 1, 1);
865 
866 	return(0);
867 }
868 
869 /*
870  * This will be called to make any routine specific parameters available.
871  */
872 static int
solinaConfigure(brightonWindow * win)873 solinaConfigure(brightonWindow *win)
874 {
875 	guiSynth *synth = findSynth(global.synths, win);
876 	brightonEvent event;
877 
878 	if (synth == 0)
879 	{
880 		printf("problems going operational\n");
881 		return(-1);
882 	}
883 
884 	if (synth->flags & OPERATIONAL)
885 		return(0);
886 
887 printf("going operational\n");
888 
889 	synth->flags |= OPERATIONAL;
890 	synth->keypanel = 2;
891 	synth->keypanel2 = -1;
892 	synth->transpose = 36;
893 	loadMemory(synth, "solina", 0, synth->location, synth->mem.active, 0, 0);
894 
895 	/*
896 	 * Hm. This is a hack for a few bits of bad rendering of a keyboard. Only
897 	 * occurs on first paint, so we suppress the first paint, and then request
898 	 * an expose here.
899 	 */
900 	event.type = BRIGHTON_EXPOSE;
901 	event.intvalue = 1;
902 	brightonParamChange(synth->win, KEY_PANEL, -1, &event);
903 	configureGlobals(synth);
904 
905 	shade_id = brightonPut(synth->win,
906 		"bitmaps/blueprints/solinashade.xpm", 0, 0, synth->win->width,
907 			synth->win->height);
908 
909 	/* Fix the pulsewidths of the first two osc */
910 	bristolMidiSendMsg(global.controlfd, synth->sid, 0, 0, 8192);
911 	bristolMidiSendMsg(global.controlfd, synth->sid, 1, 0, 4096);
912 	/* detune all oscs just a small amount */
913 	bristolMidiSendMsg(global.controlfd, synth->sid, 0, 2, 8192);
914 	bristolMidiSendMsg(global.controlfd, synth->sid, 1, 2, 8292);
915 	bristolMidiSendMsg(global.controlfd, synth->sid, 2, 2, 8092);
916 
917 	/* Disable velocity tracking */
918 	bristolMidiSendMsg(global.controlfd, synth->sid, 3, 5, 0);
919 	/* Configure a split point */
920 	bristolMidiSendMsg(global.controlfd, synth->sid, 126, 5, 47);
921 	bristolMidiSendMsg(global.controlfd, synth->sid, 126, 6, 35);
922 
923 	event.command = BRIGHTON_PARAMCHANGE;
924 	event.type = BRIGHTON_FLOAT;
925 	event.value = 1;
926 	brightonParamChange(synth->win, MEM_PANEL, 0, &event);
927 
928 	event.command = BRIGHTON_PARAMCHANGE;
929 	event.type = BRIGHTON_FLOAT;
930 	event.value = 0;
931 	brightonParamChange(synth->win, KEY_PANEL, 0, &event);
932 
933 	dc = brightonGetDCTimer(win->dcTimeout);
934 
935 	return(0);
936 }
937 
938