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 #include <stdio.h>
22 #include <stdlib.h>
23 #include <fcntl.h>
24 #include <string.h>
25 
26 #include "brightoninternals.h"
27 #include "brightonMini.h"
28 #include "brightonKeys.h"
29 #include "brightondev.h"
30 #include "bristolmidi.h"
31 #include "bristolmessages.h"
32 
33 /*
34  * These should also go into the window structure.....
35  */
36 static int confflag = 0;
37 static brightonDevice *confdev[BRIGHTON_GANG_COUNT];
38 static float confval[BRIGHTON_GANG_COUNT];
39 
40 extern guimain global;
41 
42 extern void printBrightonHelp(int);
43 extern void printBrightonReadme();
44 extern void brightonSetCLIcode(char *);
45 extern void brightonGetCLIcodes(int);
46 
47 //static int width = 0, height = 0;
48 
49 /*
50  * kbdmap now burried in the brightonWindow structure.
51  *
52  * This is an array of MIDI note numbers indexed by ASCII keyboard key number
53  * and works for top row of qwerty only: azerty, qwertz, dvorak keyboards, etc,
54  * will need their own mapping (text configuration) files.
55  *
56  * Oops, in 0.20.4 this became qwerty key to button index in the GUI piano
57  * keyboard starting from zero.
58  */
59 #define KM_KEY 0
60 #define KM_CHAN 1
61 
62 /*
63  * This is for note on/off events, it keeps a map to supress keyrepeat events.
64  *
65  * It does not always work since the events are on/off sequentially so it has
66  * been extended such that window enter/leave call XAutoRepeatOff/On().
67  * A better solution would be for devices to supply their repeat functionality
68  * and have it set per device. For example buttons probably don't want this
69  * but continuous controllers do.
70  *
71  * This does not need to be in the window structure as we only have a single
72  * computer keyboard.
73  */
74 static int kbdstate[128] = {
75 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
77 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
78 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
79 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
80 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
81 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
82 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
83 };
84 
85 char *pheader = "#\n\
86 # This the the MIDI controller profile, it keeps controller remappings for\n\
87 # converting one controller ID to another, and then defines which controllers\n\
88 # are tracked by which GUI devices. It may be edited manually, in which case\n\
89 # changes are maintained but the GUI can also alter the controller tracking\n\
90 # by typing <Control><Middle Mouse Button>, the moving the desired control.\n\
91 # This file is saved whenever a GUI memory is saved.\n\
92 #\n\
93 # The file contains Controller Mapping (one controller to another, for example\n\
94 # breath controller maps to footpedal, etc), Key Mappings for QWERTY to MIDI\n\
95 # note events, and Continuous Controller mappings that allow a control surface\n\
96 # to drive the GUI.\n\
97 #\n\
98 # Remap format is \"CM: MidiCC   MidiCC\"\n\
99 # Keyboard map format is \"KM: ASCII   MIDI_note [MIDI_chan]\"\n\
100 # Control format is \"CC: MidiCC   panel/index [value]\"\n\
101 #\n\
102 # The values are integers from 0 to 16384, the fine resolution controller\n\
103 # value for the throw of this controller. If in doubt use the value 16383,\n\
104 # it is only relevant for ganging controllers.\n\
105 #\n\n";
106 
107 /*
108  * This will parse for a key from the ASCII keyboard and map it to a MIDI note
109  * allowing the keyboard to then play the synth.
110  */
111 static void
brightonMapKeyboard(brightonWindow * bwin,brightonApp * app,int channel,char * param)112 brightonMapKeyboard(brightonWindow *bwin, brightonApp *app,
113 int channel, char *param)
114 {
115 	int from, to, chan;
116 
117 	from = param[0];
118 
119 	if ((param = index(param, ' ')) == NULL)
120 		return;
121 
122 	to = atoi(param);
123 
124 	if ((param = index(++param, ' ')) == NULL)
125 	{
126 /*		printf("Keymap %c to %i on def channel 0\n", from, to); */
127 		bwin->kbdmap[from][KM_KEY] = to;
128 		bwin->kbdmap[from][KM_CHAN] = 0;
129 		return;
130 	}
131 
132 	chan = atoi(++param);
133 
134 	bwin->kbdmap[from][KM_KEY] = to;
135 	bwin->kbdmap[from][KM_CHAN] = chan;
136 
137 /*	printf("Keymap %c to %i on channel %i\n", from, to, chan); */
138 }
139 
140 static void
brightonMapControl(brightonWindow * bwin,brightonApp * app,int channel,char * param)141 brightonMapControl(brightonWindow *bwin, brightonApp *app,
142 int channel, char *param)
143 {
144 	int from, to;
145 
146 	from = atoi(param);
147 
148 	if ((param = index(param, ' ')) == NULL)
149 	{
150 		if ((param = index(param, 9)) == NULL)
151 		{
152 /*			printf("failed to get target\n"); */
153 			return;
154 		}
155 	}
156 	to = atoi(param);
157 
158 	if ((from < 0) || (from > 127)
159 		|| (to < 0) || (to > 127))
160 		return;
161 
162 	bwin->midimap[from] = to;
163 
164 	printf("Mapped %i to %i\n", from, to);
165 }
166 
167 static void
brightonSetNRPControl(brightonWindow * bwin,brightonApp * app,int channel,char * param)168 brightonSetNRPControl(brightonWindow *bwin, brightonApp *app,
169 int channel, char *param)
170 {
171 	int cc, panel, ind, i;
172 	char *pp;
173 	brightonIResource *p;
174 	float value = 0.2;
175 
176 	cc = atoi(param);
177 
178 	if ((pp = index(param, ' ')) == NULL)
179 	{
180 		if ((pp = index(param, 9)) == NULL)
181 		{
182 /*			printf("failed to get panel\n"); */
183 			return;
184 		}
185 	}
186 	panel = atoi(pp);
187 
188 	if ((pp = index(param, '/')) == NULL)
189 	{
190 /*		printf("failed to get index\n"); */
191 		return;
192 	}
193 	ind = atoi(++pp);
194 
195 	if ((index(pp, ' ')) == NULL)
196 	{
197 		if ((pp = index(pp, 9)) == NULL)
198 		{
199 			//printf("failed to get value\n");
200 			value = 1.0;
201 		} else {
202 			printf("got number: %s\n", pp);
203 			value = ((float) atoi(pp)) / 16384.0;
204 		}
205 	} else {
206 		pp = index(pp, ' ');
207 		value = ((float) atoi(pp)) / 16384.0;
208 	}
209 
210 	/*
211 	 * We need some error checking
212 	 */
213 	if ((cc < 0) || (cc > bwin->nrpcount)
214 		|| (panel < 0) || (panel >= app->nresources)
215 		|| (ind < 0) || (ind >= app->resources[panel].ndevices))
216 		return;
217 	/*
218 	 * We now have what looks to be a valid tuple cc/panel/index. Find
219 	 * the configuration code for that device and plug it into our
220 	 * dispatcher.
221 	 */
222 
223 	p = (brightonIResource *) &bwin->app->resources[panel];
224 
225 	for (i = 0; i < bwin->nrpcount; i++)
226 	{
227 		if (bwin->nrpcontrol[i].device == NULL)
228 		{
229 			bwin->nrpcontrol[i].device
230 				= ((struct brightonDevice *) p->devlocn[ind].dev);
231 			bwin->nrpcontrol[i].nrp = cc;
232 			break;
233 		}
234 	}
235 }
236 
237 static void
brightonSetControl(brightonWindow * bwin,brightonApp * app,int channel,char * param)238 brightonSetControl(brightonWindow *bwin, brightonApp *app,
239 int channel, char *param)
240 {
241 	int cc, panel, ind, i;
242 	char *pp;
243 	brightonIResource *p;
244 	float value = 0.2, maxvalue = 0.0;
245 
246 	cc = atoi(param);
247 
248 	if ((pp = index(param, ' ')) == NULL)
249 	{
250 		if ((pp = index(param, 9)) == NULL)
251 		{
252 /*			printf("failed to get panel\n"); */
253 			return;
254 		}
255 	}
256 	panel = atoi(pp);
257 
258 	if ((pp = index(param, '/')) == NULL)
259 	{
260 /*		printf("failed to get index\n"); */
261 		return;
262 	}
263 	ind = atoi(++pp);
264 
265 	if ((pp = index(param, '/')) == NULL)
266 	{
267 /*		printf("failed to get index\n"); */
268 		return;
269 	}
270 	ind = atoi(++pp);
271 
272 	if ((index(pp, ' ')) == NULL)
273 	{
274 		if ((pp = index(pp, 9)) == NULL)
275 		{
276 			printf("failed to get value\n");
277 			value = 1.0;
278 		} else {
279 			printf("got number: %s\n", pp);
280 			value = ((float) atoi(pp)) / 16384.0;
281 		}
282 	} else {
283 		pp = index(pp, ' ');
284 		value = ((float) atoi(pp)) / 16384.0;
285 	}
286 
287 /*printf("%i %i of max %i %i\n", panel, ind, app->nresources, */
288 /*app->resources[panel].ndevices); */
289 
290 	/*
291 	 * We need some error checking
292 	 */
293 	if ((cc < 0) || (cc > 127)
294 		|| (panel < 0) || (panel >= app->nresources)
295 		|| (ind < 0) || (ind >= app->resources[panel].ndevices))
296 		return;
297 	/*
298 	 * We now have what looks to be a valid tuple cc/panel/index. Find
299 	 * the configuration code for that device and plug it into our
300 	 * dispatcher.
301 	 */
302 	p = (brightonIResource *) &bwin->app->resources[panel];
303 	/*
304 	 * This should not be indexed by the controller rather the device. That
305 	 * way we can gang controls. Since the only data we have is the cc and
306 	 * a device, we should limit the number of calls to perhaps 8?
307 	 */
308 	for (i = 0; i < BRIGHTON_GANG_COUNT; i++)
309 	{
310 		if (bwin->midicontrol[cc][i] == NULL)
311 		{
312 			bwin->midicontrol[cc][i]
313 				= ((struct brightonDevice *) p->devlocn[ind].dev);
314 			bwin->midicontrolval[cc][i] = value;
315 /*				= ((brightonDevice *) p->devlocn[ind].dev)->value; */
316 			break;
317 		}
318 	}
319 
320 	if (i == BRIGHTON_GANG_COUNT)
321 	{
322 		bwin->midicontrol[cc][(i = BRIGHTON_GANG_COUNT - 1)]
323 			= ((struct brightonDevice *) p->devlocn[ind].dev);
324 		bwin->midicontrolval[cc][i] = value;
325 	}
326 
327 	/*
328 	 * Build our scaling value
329 	 */
330 	for (i = 0; i < BRIGHTON_GANG_COUNT; i++)
331 	{
332 		if (bwin->midicontrolval[cc][i] > maxvalue)
333 			maxvalue = bwin->midicontrolval[cc][i];
334 	}
335 
336 	if (maxvalue == 0.0)
337 		bwin->midicontrolscaler[cc] = 1.0;
338 	else
339 		bwin->midicontrolscaler[cc] = 1.0 / maxvalue;
340 
341 /*
342 	for (i = 0; i < BRIGHTON_GANG_COUNT; i++)
343 		if (bwin->midicontrol[cc][i] != NULL)
344 			printf("MIDI CC %i->%i/%i@%x (index %i: %f scaled by %f)\n",
345 				cc,
346 				((brightonDevice *) bwin->midicontrol[cc][i])->panel,
347 				((brightonDevice *) bwin->midicontrol[cc][i])->index,
348 				(size_t) bwin->midicontrol[cc][i],
349 				i,
350 				bwin->midicontrolval[cc][i],
351 				bwin->midicontrolscaler[cc]);
352 */
353 }
354 
355 /*
356  * Parse configuration file. Read the panel and index numbers for the devices
357  * and find the actual device configure code for the controllers.
358  *
359  * This will also read the midi controller value mapping file.
360  */
361 void
brightonReadConfiguration(brightonWindow * bwin,brightonApp * app,int channel,char * synth,char * filename)362 brightonReadConfiguration(brightonWindow *bwin, brightonApp *app,
363 int channel, char *synth, char *filename)
364 {
365 	FILE *fd;
366 	char path[1024];
367 	char param[256];
368 	int kmnotdone = 1, i;
369 
370 	printf("Read Configuration: %s %s\n", synth, filename);
371 
372 	/*
373 	 * The build the value mapping table
374 	 */
375 	bristolMidiValueMappingTable(bwin->valuemap, bwin->midimap, synth);
376 
377 	/*
378 	 * We are going to look for a cached file. If we cannot find it then we
379 	 * will look for a factory version
380 	 */
381 	if (filename == NULL)
382 		sprintf(path, "%s/memory/profiles/%s", getBristolCache(synth), synth);
383 	else
384 		sprintf(path, "%s", filename);
385 
386 	if ((fd = fopen(path, "r")) == NULL)
387 	{
388 		/*
389 		 * If we could not read an explicit profile then return.
390 		 */
391 		if (filename != NULL)
392 			return;
393 
394 		sprintf(path, "%s/memory/profiles/%s", getenv("BRISTOL"), synth);
395 
396 		if ((fd = fopen(path, "r")) == NULL)
397 		{
398 			/*
399 			 * So, no profile. Build a default mapping.
400 			 */
401 			for (i = 0; i < 256; i++) {
402 				bwin->kbdmap[i][KM_KEY] = -1;
403 				bwin->kbdmap[i][KM_CHAN] = 0;
404 			}
405 
406 			/*
407 			 * This maps the top and bottom rows such that the bottom two rows
408 			 * are from the first key on the GUI keyboard and the top row the
409 			 * upper octaves of the keyboards.
410 			 */
411 			bwin->kbdmap['\\'][KM_KEY] = 0;
412 			bwin->kbdmap['a'][KM_KEY] = 1;
413 			bwin->kbdmap['z'][KM_KEY] = 2;
414 			bwin->kbdmap['s'][KM_KEY] = 3;
415 			bwin->kbdmap['x'][KM_KEY] = 4;
416 			bwin->kbdmap['c'][KM_KEY] = 5;
417 			bwin->kbdmap['f'][KM_KEY] = 6;
418 			bwin->kbdmap['v'][KM_KEY] = 7;
419 			bwin->kbdmap['g'][KM_KEY] = 8;
420 			bwin->kbdmap['b'][KM_KEY] = 9;
421 			bwin->kbdmap['h'][KM_KEY] = 10;
422 			bwin->kbdmap['n'][KM_KEY] = 11;
423 			bwin->kbdmap['m'][KM_KEY] = 12;
424 			bwin->kbdmap['k'][KM_KEY] = 13;
425 			bwin->kbdmap[','][KM_KEY] = 14;
426 			bwin->kbdmap['l'][KM_KEY] = 15;
427 			bwin->kbdmap['.'][KM_KEY] = 16;
428 			bwin->kbdmap['/'][KM_KEY] = 17;
429 			bwin->kbdmap['\''][KM_KEY] = 18;
430 			bwin->kbdmap['q'][KM_KEY] = 24;
431 			bwin->kbdmap['2'][KM_KEY] = 25;
432 			bwin->kbdmap['w'][KM_KEY] = 26;
433 			bwin->kbdmap['3'][KM_KEY] = 27;
434 			bwin->kbdmap['e'][KM_KEY] = 28;
435 			bwin->kbdmap['r'][KM_KEY] = 29;
436 			bwin->kbdmap['5'][KM_KEY] = 30;
437 			bwin->kbdmap['t'][KM_KEY] = 31;
438 			bwin->kbdmap['6'][KM_KEY] = 32;
439 			bwin->kbdmap['y'][KM_KEY] = 33;
440 			bwin->kbdmap['7'][KM_KEY] = 34;
441 			bwin->kbdmap['u'][KM_KEY] = 35;
442 			bwin->kbdmap['i'][KM_KEY] = 36;
443 			bwin->kbdmap['9'][KM_KEY] = 37;
444 			bwin->kbdmap['o'][KM_KEY] = 38;
445 			bwin->kbdmap['0'][KM_KEY] = 39;
446 			bwin->kbdmap['p'][KM_KEY] = 40;
447 			bwin->kbdmap['['][KM_KEY] = 41;
448 			bwin->kbdmap['='][KM_KEY] = 42;
449 			bwin->kbdmap[']'][KM_KEY] = 43;
450 
451 			return;
452 		}
453 	}
454 
455 	/*
456 	 * So we got a file.
457 	 */
458 	while (fgets(param, 256, fd) != NULL)
459 	{
460 		if (param[0] == '#')
461 			continue;
462 
463 /*		printf("read line %s", param); */
464 
465 		if (strncmp(param, "CC", 2) == 0)
466 			brightonSetControl(bwin, app, channel, &param[4]);
467 
468 		if (strncmp(param, "CLI", 3) == 0)
469 			brightonSetCLIcode(&param[5]);
470 
471 		if (strncmp(param, "NRP", 3) == 0)
472 			brightonSetNRPControl(bwin, app, channel, &param[5]);
473 
474 		if (strncmp(param, "CM", 2) == 0)
475 			brightonMapControl(bwin, app, channel, &param[4]);
476 
477 		if (strncmp(param, "KM", 2) == 0)
478 		{
479 			/*
480 			 * If this is the first keymap in this file then clear out the
481 			 * existing table. This has the benefit that profiles that did not
482 			 * contain keymaps will inherit the existing ones however if they
483 			 * do contain maps then previous maps will be cleared out when new
484 			 * ones are defined. We only do this once and only if we find a
485 			 * KM mapping entry.
486 			 */
487 			if (kmnotdone)
488 			{
489 				for (i = 0; i < 256; i++) {
490 					bwin->kbdmap[i][KM_KEY] = -1;
491 					bwin->kbdmap[i][KM_CHAN] = 0;
492 				}
493 				kmnotdone = 0;
494 			}
495 			brightonMapKeyboard(bwin, app, channel, &param[4]);
496 		}
497 	}
498 
499 	fclose(fd);
500 
501 	if (kmnotdone)
502 	{
503 		for (i = 0; i < 256; i++) {
504 			bwin->kbdmap[i][KM_KEY] = -1;
505 			bwin->kbdmap[i][KM_CHAN] = 0;
506 		}
507 
508 		/*
509 		 * This maps the top and bottom rows such that the bottom two rows
510 		 * are from the first key on the GUI keyboard and the top row the
511 		 * upper octaves of the keyboards.
512 		 */
513 		bwin->kbdmap['\\'][KM_KEY] = 0;
514 		bwin->kbdmap['a'][KM_KEY] = 1;
515 		bwin->kbdmap['z'][KM_KEY] = 2;
516 		bwin->kbdmap['s'][KM_KEY] = 3;
517 		bwin->kbdmap['x'][KM_KEY] = 4;
518 		bwin->kbdmap['c'][KM_KEY] = 5;
519 		bwin->kbdmap['f'][KM_KEY] = 6;
520 		bwin->kbdmap['v'][KM_KEY] = 7;
521 		bwin->kbdmap['g'][KM_KEY] = 8;
522 		bwin->kbdmap['b'][KM_KEY] = 9;
523 		bwin->kbdmap['h'][KM_KEY] = 10;
524 		bwin->kbdmap['n'][KM_KEY] = 11;
525 		bwin->kbdmap['m'][KM_KEY] = 12;
526 		bwin->kbdmap['k'][KM_KEY] = 13;
527 		bwin->kbdmap[','][KM_KEY] = 14;
528 		bwin->kbdmap['l'][KM_KEY] = 15;
529 		bwin->kbdmap['.'][KM_KEY] = 16;
530 		bwin->kbdmap['/'][KM_KEY] = 17;
531 		bwin->kbdmap['\''][KM_KEY] = 18;
532 		bwin->kbdmap['q'][KM_KEY] = 24;
533 		bwin->kbdmap['2'][KM_KEY] = 25;
534 		bwin->kbdmap['w'][KM_KEY] = 26;
535 		bwin->kbdmap['3'][KM_KEY] = 27;
536 		bwin->kbdmap['e'][KM_KEY] = 28;
537 		bwin->kbdmap['r'][KM_KEY] = 29;
538 		bwin->kbdmap['5'][KM_KEY] = 30;
539 		bwin->kbdmap['t'][KM_KEY] = 31;
540 		bwin->kbdmap['6'][KM_KEY] = 32;
541 		bwin->kbdmap['y'][KM_KEY] = 33;
542 		bwin->kbdmap['7'][KM_KEY] = 34;
543 		bwin->kbdmap['u'][KM_KEY] = 35;
544 		bwin->kbdmap['i'][KM_KEY] = 36;
545 		bwin->kbdmap['9'][KM_KEY] = 37;
546 		bwin->kbdmap['o'][KM_KEY] = 38;
547 		bwin->kbdmap['0'][KM_KEY] = 39;
548 		bwin->kbdmap['p'][KM_KEY] = 40;
549 		bwin->kbdmap['['][KM_KEY] = 41;
550 		bwin->kbdmap['='][KM_KEY] = 42;
551 		bwin->kbdmap[']'][KM_KEY] = 43;
552 	}
553 }
554 
555 /*
556  * Save a configuration file. This should take the panel and index numbers for
557  * each of the devices in the table, for a specific MIDI channel, and write
558  * them out to a file with the controller ID.
559  */
560 void
brightonWriteConfiguration(brightonWindow * bwin,char * synth,int channel,char * filename)561 brightonWriteConfiguration(brightonWindow *bwin, char *synth, int channel,
562 char *filename)
563 {
564 	int j, i, fd, null;
565 	char path[256];
566 	char param[256];
567 
568 	if (global.synths->flags & REQ_MIDI_DEBUG)
569 		printf("Write CC Configuration file: %s\n", synth);
570 
571 	if (filename == NULL)
572 		sprintf(path, "%s/memory/profiles/%s", getBristolCache(synth), synth);
573 	else
574 		sprintf(path, "%s", filename);
575 
576 	if ((fd = open(path, O_WRONLY|O_TRUNC|O_CREAT, 0644)) < 0)
577 	{
578 		/*
579 		 * If we were requested to write a specific file but couldn't (implies
580 		 * permissions or path?) then return.
581 		 */
582 		if (filename != NULL)
583 			return;
584 
585 		sprintf(path, "%s/memory/profiles/%s", getenv("BRISTOL"), synth);
586 		/*
587 		 * We are unlikey to have write permissions on the factory set, however
588 		 * with no alternative we will have a go
589 		 */
590 		if ((fd = open(path, O_WRONLY|O_TRUNC|O_CREAT, 0644)) < 0)
591 			return;
592 	}
593 
594 	/*
595 	 * This could be cleaned up a bit
596 	 */
597 	null = write(fd, pheader, strlen(pheader));
598 
599 	for (i = 0; i < 128; i++)
600 	{
601 		if (bwin->midimap[i] == i)
602 			continue;
603 
604 		sprintf(param, "CM: %i	   %i\n", i, bwin->midimap[i]);
605 		if (global.synths->flags & REQ_MIDI_DEBUG)
606 			printf("%s", param);
607 		null = write(fd, param, strlen(param));
608 	}
609 
610 	for (i = 0; i < 128; i++)
611 	{
612 		for (j = 0; j < BRIGHTON_GANG_COUNT; j++)
613 		{
614 			if (bwin->midicontrol[i][j] != 0)
615 			{
616 				sprintf(param, "CC: %i	   %i/%i %i\n",
617 					i,
618 					((brightonDevice *) bwin->midicontrol[i][j])->panel,
619 					((brightonDevice *) bwin->midicontrol[i][j])->index,
620 					(int) (bwin->midicontrolval[i][j] * 16384));
621 				if (global.synths->flags & REQ_MIDI_DEBUG)
622 					printf("%s", param);
623 				null = write(fd, param, strlen(param));
624 			}
625 		}
626 	}
627 
628 	for (i = 0; i < bwin->nrpcount; i++)
629 	{
630 		if (bwin->nrpcontrol[i].device != NULL)
631 		{
632 			sprintf(param, "NRP: %i	   %i/%i\n",
633 				bwin->nrpcontrol[i].nrp,
634 				((brightonDevice *) bwin->nrpcontrol[i].device)->panel,
635 				((brightonDevice *) bwin->nrpcontrol[i].device)->index);
636 			if (global.synths->flags & REQ_MIDI_DEBUG)
637 				printf("%s", param);
638 			null = write(fd, param, strlen(param));
639 		}
640 	}
641 
642 	brightonGetCLIcodes(fd);
643 
644 	for (i = 0; i < 256; i++)
645 	{
646 		if (bwin->kbdmap[i][KM_KEY] >= 0)
647 		{
648 			sprintf(param, "KM: %c %i %i\n",
649 				i, bwin->kbdmap[i][KM_KEY], bwin->kbdmap[i][KM_CHAN]);
650 			null = write(fd, param, strlen(param));
651 		}
652 	}
653 
654 	close(fd);
655 }
656 
657 extern char *gplwarranty;
658 extern char *gplconditions;
659 
660 void
brightonControlShiftKeyInput(brightonWindow * cid,int asckey,int on,int flags)661 brightonControlShiftKeyInput(brightonWindow *cid, int asckey, int on, int flags)
662 {
663 	guiSynth *synth = findSynth(global.synths, cid);
664 
665 	if ((synth->flags & REQ_DEBUG_MASK) >= REQ_DEBUG_2)
666 		printf("control shift key handler\n");
667 }
668 
669 static void
brightonFillRatios(brightonWindow * win)670 brightonFillRatios(brightonWindow *win)
671 {
672 	float wfact, hfact;
673 
674 	wfact = ((float) win->display->width) * 0.95
675 		/ ((float) win->template->width);
676 	hfact = ((float) win->display->height) * 0.95
677 		/ ((float) win->template->height);
678 
679 	if (hfact > wfact) {
680 		win->maxw = win->display->width * 0.95;
681 		win->minw = win->template->width;
682 		win->minh = win->template->height;
683 		win->maxh = win->template->height * wfact;
684 	} else {
685 		win->maxh = win->display->height * 0.95;
686 		win->minw = win->template->width;
687 		win->minh = win->template->height;
688 		win->maxw = win->template->width * hfact;
689 	}
690 }
691 
692 void
brightonShiftKeyInput(brightonWindow * cid,int asckey,int on,int flags)693 brightonShiftKeyInput(brightonWindow *cid, int asckey, int on, int flags)
694 {
695 	guiSynth *synth = findSynth(global.synths, cid);
696 
697 	if ((synth->flags & REQ_DEBUG_MASK) >= REQ_DEBUG_2)
698 		printf("shift key handler\n");
699 
700 	switch (asckey) {
701 		case '=': /* size up */
702 		{
703 			int nw, nh;
704 
705 			if ((synth->flags & REQ_DEBUG_MASK) >= REQ_DEBUG_3)
706 				printf("Increase window size\n");
707 
708 			if ((nw = synth->win->width * 1.1)
709 				> (synth->win->display->width * 0.9))
710 				return;
711 			if ((nh = synth->win->height * 1.1)
712 				> (synth->win->display->height * 0.9))
713 				return;
714 
715 			synth->win->template->width = nw;
716 			synth->win->template->height = nh;
717 			brightonFillRatios(synth->win);
718 
719 			brightonRequestResize(synth->win,
720 				synth->win->minw,
721 				synth->win->minh);
722 			break;
723 		}
724 		case '-': /* size down */
725 		{
726 			int nw, nh;
727 
728 			if ((synth->flags & REQ_DEBUG_MASK) >= REQ_DEBUG_3)
729 				printf("Decrease window size\n");
730 
731 			if ((nw = synth->win->width * 0.9)
732 				< (synth->win->display->width * 0.1))
733 				return;
734 			if ((nh = synth->win->height * 0.9)
735 				< (synth->win->display->height * 0.1))
736 				return;
737 
738 			synth->win->template->width = nw;
739 			synth->win->template->height = nh;
740 			brightonFillRatios(synth->win);
741 
742 			brightonRequestResize(synth->win,
743 				synth->win->minw,
744 				synth->win->minh);
745 			break;
746 		}
747 		/*
748 		 * Put some stuff in to return to normal size, full screen, etc
749 		 */
750 		case 65293: /* size switch - this is native return key */
751 			if ((synth->win->width >= (synth->win->display->width * 0.9))
752 				|| (synth->win->height >= (synth->win->display->height * 0.9)))
753 			{
754 			/* Go native size */
755 				if ((synth->flags & REQ_DEBUG_MASK) >= REQ_DEBUG_3)
756 					printf("t: %i %i\nw: %i %i\nd: %i %i\n",
757 						synth->win->template->width,
758 						synth->win->template->height,
759 						synth->win->width,
760 						synth->win->height,
761 						synth->win->display->width,
762 						synth->win->display->height);
763 
764 				if ((synth->win->minw == 0) || (synth->win->maxw == 0))
765 					brightonFillRatios(synth->win);
766 
767 				brightonRequestResize(synth->win,
768 					synth->win->minw,
769 					synth->win->minh);
770 
771 				if ((synth->flags & REQ_DEBUG_MASK) >= REQ_DEBUG_1)
772 					printf("go %i %i\n",
773 						synth->win->minw,
774 						synth->win->minh);
775 			} else {
776 			/* Go full screen */
777 				if ((synth->flags & REQ_DEBUG_MASK) >= REQ_DEBUG_3)
778 					printf("t: %i %i\nw: %i %i\nd: %i %i\n",
779 						synth->win->minw,
780 						synth->win->minh,
781 						synth->win->width,
782 						synth->win->height,
783 						synth->win->display->width,
784 						synth->win->display->height);
785 
786 				if ((synth->win->minw == 0) || (synth->win->maxw == 0))
787 					brightonFillRatios(synth->win);
788 
789 				synth->win->display->flags |= BRIGHTON_ANTIALIAS_5;
790 
791 				brightonRequestResize(synth->win,
792 					synth->win->maxw,
793 					synth->win->maxh);
794 
795 				if ((synth->flags & REQ_DEBUG_MASK) >= REQ_DEBUG_1)
796 					printf("go %i %i\n",
797 						synth->win->maxw,
798 						synth->win->maxh);
799 			}
800 			break;
801 	}
802 }
803 
804 /*
805  * This is called with key press and the control pressed
806  */
807 void
brightonControlKeyInput(brightonWindow * cid,int asckey,int on)808 brightonControlKeyInput(brightonWindow *cid, int asckey, int on)
809 {
810 	guiSynth *synth = findSynth(global.synths, cid);
811 
812 	if ((synth->flags & REQ_DEBUG_MASK) >= REQ_DEBUG_2)
813 		printf("control key event %i/%i\n", asckey, on);
814 
815 	/*
816 	 * So, we are going to be looking for diverse key settings to do some stuff.
817 	 *
818 	 * ^S: save
819 	 * ^L: (re)load
820 	 * ^R: restore previous = ^L?
821 	 * ^H: help
822 	 * ^?: help
823 	 *
824 	 * ^W: show warranty
825 	 * ^C: show GLP copying conditions
826 	 *
827 	 * plus: BME Axxe B3 Juno Odyssey Poly6 monopoly Pro10 Pro52 Pro5 RR Solina
828 	 *	voxM2
829 	 * mult: Bass CS80 granular OBXa(s) OBX(s) Poly800(s) pro1 Sid/2(s) Sonic6
830 	 *	Stratus
831 	 * locn: 2600 DX(s) Explorer MemoryMoog Mini MS20 mg1 rBass Rhodes(s) SAKs
832 	 *	vox
833 	 * odds: bitone(+100) Jupiter (+mw)
834 	 */
835 	switch (asckey) {
836 		case '+': /* mem up */
837 		case '=': /* mem up */
838 //brightonRequestResize(synth->win, synth->win->width *= 1.1,
839 //synth->win->height*=1.1);
840 			if ((synth->flags & REQ_DEBUG_MASK) > REQ_DEBUG_2)
841 				printf("mem up\n");
842 			if (synth->loadMemory != NULL)
843 				synth->loadMemory(synth, synth->resources->name, 0,
844 					synth->cmem + 1, synth->mem.active, 0, 0);
845 			else
846 				loadMemory(synth, synth->resources->name, 0,
847 					synth->cmem + 1, synth->mem.active, 0, 0);
848 			break;
849 		case '-': /* mem down */
850 		case '_': /* mem down */
851 //brightonRequestResize(synth->win, synth->win->width *= 0.9,
852 //synth->win->height*=0.9);
853 			if ((synth->flags & REQ_DEBUG_MASK) > REQ_DEBUG_2)
854 				printf("mem down\n");
855 			if (synth->loadMemory != NULL)
856 				synth->loadMemory(synth, synth->resources->name, 0,
857 					synth->cmem - 1 < 0? 0: synth->cmem - 1,
858 					synth->mem.active, 0, 0);
859 			else
860 				loadMemory(synth, synth->resources->name, 0,
861 					synth->cmem - 1 < 0? 0: synth->cmem - 1,
862 					synth->mem.active, 0, 0);
863 			break;
864 		case 'h': /* help */
865 		case '/': /* help */
866 			printBrightonHelp(synth->synthtype);
867 			break;
868 		case 'r': /* readme */
869 			printBrightonReadme();
870 			break;
871 		case 'k':
872 			printf("Keyboard shortcuts\n");
873 			printf("  <Ctrl> 's' - save settings to current memory\n");
874 			printf("  <Ctrl> 'l' - (re)load current memory\n");
875 			printf("  <Ctrl> 'u' - (re)load current memory (undo)\n");
876 			printf("  <Ctrl> '-' - load memory down\n");
877 			printf("  <Ctrl> '+' - load memory up\n");
878 			printf("  <Ctrl> 'x' - exchange current with previous memory\n");
879 			printf("  <Ctrl> 'g' - GNU GPL copying conditions\n");
880 			printf("  <Ctrl> 'h' - print emulator information\n");
881 			printf("  <Ctrl> 'r' - print readme information\n");
882 			printf("  <Ctrl> 'p' - screendump to /tmp/<synth>.xpm\n");
883 			printf("  <Ctrl> 't' - toggle opacity\n");
884 			printf("  <Ctrl> 'o' - decrease opacity of patch layer\n");
885 			printf("  <Ctrl> 'O' - increase opacity of patch layer\n");
886 			printf("  <Ctrl> 'w' - GNU GPL warranty\n");
887 			printf("  UpArrow    - controller motion up (shift key accelerator)\n");
888 			printf("  DownArrow  - controller motion down (shift key accelerator)\n");
889 			printf("  RightArrow - controller motion up (shift key accelerator)\n");
890 			printf("  LeftArrow  - controller motion down (shift key accelerator)\n");
891 			break;
892 		case 's': /* Save */
893 			if ((synth->flags & REQ_DEBUG_MASK) > REQ_DEBUG_2)
894 				printf("excepted save memory\n");
895 			if (synth->saveMemory != NULL)
896 				synth->saveMemory(synth, synth->resources->name, 0,
897 					synth->cmem, 0);
898 			else
899 				saveMemory(synth, synth->resources->name, 0,
900 					synth->cmem, 0);
901 			break;
902 		case 'l': /* load */
903 		case 'u': /* load */
904 			if ((synth->flags & REQ_DEBUG_MASK) > REQ_DEBUG_2)
905 				printf("excepted Control load memory: %s\n",
906 					synth->resources->name);
907 			if (synth->loadMemory != NULL)
908 				synth->loadMemory(synth, synth->resources->name, 0,
909 					synth->cmem, synth->mem.active, 0, 0);
910 			else
911 				loadMemory(synth, synth->resources->name, 0,
912 					synth->cmem, synth->mem.active, 0, 0);
913 			break;
914 		case 'x': /* Toggle */
915 		{
916 			int cmem;
917 
918 			if ((synth->flags & REQ_DEBUG_MASK) > REQ_DEBUG_2)
919 				printf("excepted Control switch memory: %s\n",
920 					synth->resources->name);
921 
922 			cmem = synth->cmem;
923 
924 			if (synth->loadMemory != NULL)
925 				synth->loadMemory(synth, synth->resources->name, 0,
926 					synth->lmem, synth->mem.active, 0, 0);
927 			else
928 				loadMemory(synth, synth->resources->name, 0,
929 					synth->lmem, synth->mem.active, 0, 0);
930 			synth->lmem = cmem;
931 			break;
932 		}
933 		case 'w': /* Warranty */
934 			printf("%s", gplwarranty);
935 			break;
936 		case 'g': /* Conditions */
937 			printf("%s", gplconditions);
938 			break;
939 	}
940 }
941 
942 /*
943  * We now want a set of keyboard mappings that can be defined, perhaps also
944  * one per synth and probably also in the same controller mappings file.
945  *
946  * Due to the may X11 does the key mapping then we will get multiple key events
947  * for presses - the key repeat is interpretted as KeyOff/KeyOn, and they KBD
948  * will be monophonic as a newly pressed key will replace the previously held
949  * one. For best results we would need to disable key repeat on entering the
950  * window. FFS.
951  */
952 void
brightonKeyInput(brightonWindow * cid,int asckey,int on)953 brightonKeyInput(brightonWindow *cid, int asckey, int on)
954 {
955 	guiSynth *synth = findSynth(global.synths, cid);
956 	brightonEvent event;
957 
958 	event.type = BRIGHTON_FLOAT;
959 	event.value = 1.0;
960 
961 	if ((asckey < 0) || (asckey > 255))
962 		return;
963 
964 	if ((cid->kbdmap[asckey][KM_KEY] < 0)
965 		|| (cid->kbdmap[asckey][KM_KEY] > 127))
966 		return;
967 
968 	/*
969 	 * In release -121 this just sent the MIDI note on/off to start the voices
970 	 * but by popular demand (my sole vote) this should preferably cause the
971 	 * GUI keyboard to track the qwerty. This means, preferably, the API should
972 	 * send the keycode to the synth? That is not easy, we could better tack
973 	 * it in here.
974 	 *
975 	 * We need some generic call back to the synth (the right synth) with the
976 	 * key number and midi channel. Hm, that would work but still would not
977 	 * change the graphics as that needs a call to the GUI.
978 	 */
979 	if (on) {
980 		/* Filter out key repeat. */
981 		if ((kbdstate[cid->kbdmap[asckey][KM_KEY]]
982 			& (1 << cid->kbdmap[asckey][KM_CHAN])) == 0)
983 		{
984 			/*
985 			 * We have some logic required here. Firstly, if the keypanel is
986 			 * denoted as -1 then there isn't one (hammond module, ARP2600,
987 			 * synthi) so use native MIDI events. If the midi channel is
988 			 * zero this is the first keypanel. Otherwise the second.
989 			 *
990 			 * This is all slightly damaged (0.20.3) since calls directly to
991 			 * the midi interface did not use transpose and those to the GUI
992 			 * did. That will be changed, tranpose will be an actual call to
993 			 * bristol, dropped here, but will have to change most of the
994 			 * profile files that give me the qwerty mappings. I want to change
995 			 * those anyway to mimic some other well known qwerty mappings.
996 			 */
997 			if (synth->keypanel < 0)
998 				bristolMidiSendMsg(global.controlfd,
999 					synth->midichannel + cid->kbdmap[asckey][KM_CHAN],
1000 					BRISTOL_EVENT_KEYON, 0, cid->kbdmap[asckey][KM_KEY]);
1001 			else {
1002 				if ((cid->kbdmap[asckey][KM_CHAN] == 0)
1003 					|| (synth->keypanel2 < 0))
1004 					brightonParamChange(synth->win, synth->keypanel,
1005 						cid->kbdmap[asckey][KM_KEY], &event);
1006 				else {
1007 					if (synth->keypanel2 > 0)
1008 						brightonParamChange(synth->win, synth->keypanel2,
1009 							cid->kbdmap[asckey][KM_KEY], &event);
1010 				}
1011 			}
1012 			kbdstate[cid->kbdmap[asckey][KM_KEY]] |= 1 << cid->kbdmap[asckey][KM_CHAN];
1013 		}
1014 	} else {
1015 		event.value = 0.0;
1016 
1017 		if (synth->keypanel < 0)
1018 			bristolMidiSendMsg(global.controlfd,
1019 				synth->midichannel + cid->kbdmap[asckey][KM_CHAN],
1020 				BRISTOL_EVENT_KEYOFF, 0, cid->kbdmap[asckey][KM_KEY]);
1021 		else {
1022 			if ((cid->kbdmap[asckey][KM_CHAN] == 0)
1023 				|| (synth->keypanel2 < 0))
1024 				brightonParamChange(synth->win, synth->keypanel,
1025 					cid->kbdmap[asckey][KM_KEY], &event);
1026 			else {
1027 				if (synth->keypanel2 > 0)
1028 					brightonParamChange(synth->win, synth->keypanel2,
1029 						cid->kbdmap[asckey][KM_KEY], &event);
1030 			}
1031 		}
1032 		kbdstate[cid->kbdmap[asckey][KM_KEY]] &= ~(1 << cid->kbdmap[asckey][KM_CHAN]);
1033 	}
1034 }
1035 
1036 /*
1037  * Since this is going to have a graphical response to a MIDI event we need
1038  * to flag that the library should be idle, then forward the event to have the
1039  * keyboard mapping change, then re-enable the interface. If this is not done
1040  * then events may 'double strike', once in the engine and again here in the
1041  * GUI. Eventually we want to have this link optional so as not to waste CPU
1042  * cycles for live work.
1043  */
1044 void
brightonMidiNoteEvent(guimain * global,bristolMidiMsg * msg)1045 brightonMidiNoteEvent(guimain *global, bristolMidiMsg *msg)
1046 {
1047 	brightonEvent event;
1048 	int flag;
1049 
1050 	if (global->home == NULL)
1051 		return;
1052 
1053 	event.type = BRIGHTON_FLOAT;
1054 	event.value = 1.0;
1055 
1056 	if (global->synths->flags & REQ_MIDI_DEBUG)
1057 		printf("brightonMidiNoteEvent(%i, %i) %i\n",
1058 			msg->command, msg->params.key.key, msg->channel);
1059 
1060 	/*
1061 	 * This tracking can only work for the first synth on the list. That is
1062 	 * currently not an issue since the list is probably only one entry. That
1063 	 * will have to change when we integrate GUI menuing to start more
1064 	 * emulations.
1065 	 *
1066 	 * Anyway, NO_KEYTRACK can stay as a global parameter, after that we will
1067 	 * have to scan for MIDI channel matching.
1068 	if ((global->synths == NULL) || (global->synths->flags & NO_KEYTRACK))
1069 	 */
1070 	if (global->synths->flags & NO_KEYTRACK)
1071 		return;
1072 
1073 	flag = global->libtest;
1074 
1075 	global->libtest = 1;
1076 	if (global->manual != 0)
1077 		global->manual->libtest = 1;
1078 
1079 	if (msg->command == MIDI_NOTE_ON) {
1080 		/*
1081 		if ((msg->params.key.key < global->synths->lowkey)
1082 			|| (msg->params.key.key > global->synths->highkey))
1083 			return;
1084 		*/
1085 
1086 		if (msg->params.key.velocity == 0)
1087 			event.value = 0.0;
1088 		else
1089 			event.value = ((float) msg->params.key.velocity) / 127;
1090 
1091 		if (msg->channel == global->synths->midichannel)
1092 			brightonParamChange(global->synths->win, global->synths->keypanel,
1093 				msg->params.key.key - global->synths->transpose, &event);
1094 		else if ((global->synths->keypanel2 >= 0)
1095 			&& (msg->channel == global->synths->midichannel + 1))
1096 			brightonParamChange(global->synths->win, global->synths->keypanel2,
1097 				msg->params.key.key - global->synths->transpose, &event);
1098 	} else {
1099 		/*
1100 		if ((msg->params.key.key < global->synths->lowkey)
1101 			|| (msg->params.key.key > global->synths->highkey))
1102 			return;
1103 		*/
1104 
1105 		event.value = 0.0;
1106 		if (msg->channel == global->synths->midichannel)
1107 			brightonParamChange(global->synths->win, global->synths->keypanel,
1108 				msg->params.key.key - global->synths->transpose, &event);
1109 		else if ((global->synths->keypanel2 >= 0)
1110 			&& (msg->channel == global->synths->midichannel + 1))
1111 			brightonParamChange(global->synths->win, global->synths->keypanel2,
1112 				msg->params.key.key - global->synths->transpose, &event);
1113 	}
1114 
1115 	global->libtest = flag;
1116 	if (global->manual != 0)
1117 		global->manual->libtest = flag;
1118 
1119 	return;
1120 }
1121 
1122 void
brightonChangeParam(guiSynth * synth,int panel,int ind,float value)1123 brightonChangeParam(guiSynth *synth, int panel, int ind, float value)
1124 {
1125 	brightonEvent event;
1126 	brightonIResource *p;
1127 
1128 	event.type = BRIGHTON_FLOAT;
1129 	event.type = BRIGHTON_PARAMCHANGE;
1130 	event.value = value;
1131 
1132 	if (panel < 0) return;
1133 	if (panel >= synth->win->app->nresources) return;
1134 	if (ind < 0) return;
1135 	if (ind >= synth->win->app->resources[panel].ndevices) return;
1136 
1137 	p = (brightonIResource *) &synth->win->app->resources[panel];
1138 
1139 	if ((p->devlocn[ind].type == 2) &&
1140 		(~p->devlocn[ind].flags & BRIGHTON_THREEWAY))
1141 	{
1142 		if (value < ((brightonDevice *)
1143 			synth->win->app->resources[panel].devlocn[ind].dev)->value)
1144 			event.value = 0.0f;
1145 		else
1146 			event.value = 1.0f;
1147 	}
1148 
1149 	if (event.value < 0)
1150 		event.value = 0.0f;
1151 	if (event.value > p->devlocn[ind].to)
1152 		event.value = p->devlocn[ind].to;
1153 
1154 	/*
1155 	 * This might look odd, but if the 'to' is not 1.0 then the
1156 	 * interface expects 'N' integral steps so we have to round
1157 	 * value here. We perhaps should use 'truncf()'.
1158 	if (p->devlocn[ind].to != 1.0)
1159 		event.value = (float)
1160 			((int) (event.value * p->devlocn[ind].to));
1161 	 */
1162 
1163 	/*
1164 	 * See if we need to reverse the value already, and to scale
1165 	 * it to a native controller range. There are other cases, such
1166 	 * as "from > to" without the REVERSE flag, etc. Will address
1167 	 * them on a case by case basis.
1168 	if (p->devlocn[ind].flags & BRIGHTON_REVERSE)
1169 		event.value = 1.0 - event.value;
1170 printf("\r%f %f %f", value, event.value, p->devlocn[ind].to);
1171 	 */
1172 
1173 	brightonParamChange(synth->win, panel, ind, &event);
1174 	/*
1175 printf(" %f\n\r",
1176 ((brightonDevice *) synth->win->app->resources[panel].devlocn[ind].dev)->value);
1177 */
1178 }
1179 
1180 /*
1181  * Common dispatch routine for controller to GUI events. Needs to find the
1182  * right synth, not trivial - may have multiple on this channel, then needs to
1183  * call parsing and mapping for each.
1184  */
1185 void
brightonMidiInput(bristolMidiMsg * msg,guimain * global)1186 brightonMidiInput(bristolMidiMsg *msg, guimain *global)
1187 {
1188 	int i, j;
1189 	float maxvalue = 0.0;
1190 	guiSynth *synth;
1191 
1192 	if (global->synths == 0)
1193 		return;
1194 
1195 	if (global->synths->flags & REQ_MIDI_DEBUG)
1196 		printf("brightonMidiInput: %x %i: from %i, cfg %i\n",
1197 		msg->command,
1198 		msg->channel,
1199 		msg->params.bristol.from,
1200 		global->controlfd);
1201 
1202 	if (msg->command == MIDI_SYSTEM)
1203 	{
1204 		int memHold = global->synths->cmem;
1205 
1206 		if (global->synths->flags & REQ_MIDI_DEBUG)
1207 			printf("brightonMidiInput sysex\n");
1208 		/*
1209 		printf("brightonMidiInput sysex: %i %i, %i\n",
1210 			msg->command,
1211 			msg->channel,
1212 			global->synths->midichannel);
1213 		 * We need to see if anybody is waiting for a message
1214 		 */
1215 		if (msg->params.bristol.msgType >= 8) {
1216 			switch (msg->params.bristolt2.operation)
1217 			{
1218 				case BRISTOL_MT2_WRITE:
1219 					/*
1220 					 * The brighton load/save routines do not really handle
1221 					 * alternative locations, they all rotate around the cache.
1222 					 *
1223 					 * To support Jack here, and LADI later, then just save the
1224 					 * LADI memory file and copy it to wherever it was asked
1225 					 * to be put.
1226 					 */
1227 					printf("bsm save request to \"%s\"\n",
1228 						msg->params.bristolt2.data);
1229 
1230 					global->synths->cmem = global->synths->ladimem;
1231 					brightonControlKeyInput(global->synths->win, 's', 0);
1232 
1233 					bristolMemoryExport(global->synths->ladimem,
1234 						msg->params.bristolt2.data,
1235 						global->synths->resources->name);
1236 
1237 					global->synths->cmem = memHold;
1238 					break;
1239 				case BRISTOL_MT2_READ:
1240 					printf("bsm load request from \"%s\"\n",
1241 						msg->params.bristolt2.data);
1242 
1243 					bristolMemoryImport(global->synths->ladimem,
1244 						msg->params.bristolt2.data,
1245 						global->synths->resources->name);
1246 
1247 					global->synths->cmem = global->synths->ladimem;
1248 					brightonControlKeyInput(global->synths->win, 'l', 0);
1249 
1250 					global->synths->cmem = memHold;
1251 					break;
1252 			}
1253 		} else if (msg->params.bristol.operator == BRISTOL_LADI) {
1254 			if (msg->params.bristol.controller == BRISTOL_LADI_SAVE_REQ) {
1255 				printf("LADI save state request\n");
1256 				global->synths->cmem = global->synths->ladimem;
1257 
1258 				brightonControlKeyInput(global->synths->win, 's', 0);
1259 
1260 				global->synths->cmem = memHold;
1261 			}
1262 
1263 			if (msg->params.bristol.controller == BRISTOL_LADI_LOAD_REQ) {
1264 				printf("LADI load state request\n");
1265 				global->synths->cmem = global->synths->ladimem;
1266 
1267 				brightonControlKeyInput(global->synths->win, 'l', 0);
1268 
1269 				global->synths->cmem = memHold;
1270 			}
1271 		}
1272 
1273 		bristolMidiPost(msg);
1274 		return;
1275 	}
1276 
1277 	if (global == NULL)
1278 		return;
1279 
1280 #warning that we need to scan the synths to match the MIDI channel
1281 	if ((synth = global->synths) == NULL)
1282 		return;
1283 
1284 	if (~synth->flags & OPERATIONAL)
1285 		return;
1286 
1287 	if (global->synths->flags & REQ_DEBUG_3)
1288 		printf("not sysex: %x\n", msg->command);
1289 
1290 	/*
1291 	 * We should consider what to do with channel changes, but we are not
1292 	 * responsible for those. This is what the controller sent although we
1293 	 * could copy the values across from one table to the other?
1294 	 *
1295 	 * We should also consider an interface to allow for note on/off events,
1296 	 * it would need to register with panel ID and transpose.
1297 	 * We should also consider an interface to allow for pitch wheel
1298 	 * reregistration.
1299 	 */
1300 	if (((msg->command & MIDI_COMMAND_MASK)	== MIDI_NOTE_ON)
1301 		|| ((msg->command & MIDI_COMMAND_MASK)  == MIDI_NOTE_OFF))
1302 	{
1303 		if (global->synths->flags & REQ_DEBUG_3)
1304 			printf("note event: %x\n", msg->command);
1305 		brightonMidiNoteEvent(global, msg);
1306 		return;
1307 	}
1308 
1309 	if (msg->command != MIDI_CONTROL)
1310 	{
1311 		if (msg->command == MIDI_PROGRAM)
1312 		{
1313 			/*
1314 			printf("need a callback for this: prg %i\n",
1315 				msg->params.program.p_id);
1316 			 * So who should have the callback. It is really a window function
1317 			 * however it only has callbacks for X Events, not MIDI events.
1318 			 *
1319 			 * This callback template is not used, it requires a window, then
1320 			 * a couple of ints and a float. Should we use controller and
1321 			 * value?
1322 			 */
1323 			if ((msg->channel == synth->midichannel)
1324 				&& (synth->win->template->callback != 0))
1325                 synth->win->template->callback(synth->win,
1326 					msg->command, msg->params.program.p_id, 0);
1327 		}
1328 		return;
1329 	}
1330 
1331 	/*
1332 	 * At this point there are only control messages left. I want to have a
1333 	 * mapping of the controller value as well as the controller mapping and
1334 	 * the value should be translated first.
1335 	bristolMidiToGM2(synth->win, msg);
1336 	 */
1337 //printf("PRE: %f\n", msg->params.controller.c_val);
1338 	bristolMidiToGM2(synth->win->GM2values, synth->win->midimap,
1339 		synth->win->valuemap, msg);
1340 //printf("POST: %f\n", msg->params.controller.c_val);
1341 
1342 	/*
1343 	 * This should search the synth list, here we just assume one synth per
1344 	 * GUI and that is damaged for dual manual synths. Only affects the GUI.
1345 	 * We should search for the MIDI channel by sid and sid2 - if sid2 then
1346 	 * the event is potentially for the second manual.
1347 	 */
1348 	if (msg->channel != synth->midichannel)
1349 		return;
1350 
1351 /*printf("Midi Ctrl: %i\n", msg->GM2.c_id); */
1352 
1353 	if ((msg->params.controller.c_id ==  MIDI_GM_DATAENTRY_F)
1354 		&& (synth->flags & REQ_MIDI_DEBUG))
1355 	{
1356 		/*
1357 		 * The GM2 conversions bury the controller ID in coarse for
1358 		 * the NRP operations.
1359 		 */
1360 		printf("found nrp: %i value %i\n",
1361 			(synth->win->GM2values[MIDI_GM_NRP] << 7)
1362 				+ synth->win->GM2values[MIDI_GM_NRP_F],
1363 			(synth->win->GM2values[MIDI_GM_DATAENTRY] << 7)
1364 				+ synth->win->GM2values[MIDI_GM_DATAENTRY_F]);
1365 
1366 		printf("	%i %i %i %i: %i %i/%f (%i)\n",
1367 			synth->win->GM2values[MIDI_GM_NRP],
1368 			synth->win->GM2values[MIDI_GM_NRP_F],
1369 			synth->win->GM2values[MIDI_GM_DATAENTRY],
1370 			synth->win->GM2values[MIDI_GM_DATAENTRY_F],
1371 			msg->GM2.coarse, msg->GM2.intvalue, msg->GM2.value,
1372 			msg->GM2.c_id);
1373 	}
1374 
1375 	if (confflag > 0) {
1376 		/*
1377 		 * Skip NRP/RP/DE if we have not allowed NRP
1378 		 */
1379 		if ((msg->params.controller.c_id == MIDI_GM_DATAENTRY) ||
1380 			(msg->params.controller.c_id == MIDI_GM_NRP) ||
1381 			(msg->params.controller.c_id == MIDI_GM_NRP_F) ||
1382 			(msg->params.controller.c_id == MIDI_GM_RP_F))
1383 			return;
1384 
1385 		/*
1386 		 * React to MIDI_GM_DATAENTRY_F, find NRP, find value, decide where
1387 		 * to dispatch.
1388 		 */
1389 		if ((msg->GM2.c_id == MIDI_GM_NRP)
1390 			&& (msg->params.controller.c_id == MIDI_GM_DATAENTRY_F))
1391 		{
1392 			confflag = 0;
1393 
1394 			if (~synth->flags & GUI_NRP)
1395 			{
1396 				printf("NRP Registration Requests require -gnrp\n");
1397 				return;
1398 			}
1399 
1400 			if (synth->flags & REQ_MIDI_DEBUG)
1401 			{
1402 				/*
1403 				 * The GM2 conversions bury the controller ID in coarse for
1404 				 * the NRP operations.
1405 				 */
1406 				printf("register nrp: %i value %i\n",
1407 					(synth->win->GM2values[MIDI_GM_NRP] << 7)
1408 						+ synth->win->GM2values[MIDI_GM_NRP_F],
1409 					(synth->win->GM2values[MIDI_GM_DATAENTRY] << 7)
1410 						+ synth->win->GM2values[MIDI_GM_DATAENTRY_F]);
1411 
1412 				printf("	%i %i %i %i: %i %i\n",
1413 					synth->win->GM2values[MIDI_GM_NRP],
1414 					synth->win->GM2values[MIDI_GM_NRP_F],
1415 					synth->win->GM2values[MIDI_GM_DATAENTRY],
1416 					synth->win->GM2values[MIDI_GM_DATAENTRY_F],
1417 					msg->GM2.coarse, msg->GM2.intvalue);
1418 			}
1419 			/*
1420 			 * Now need to decide what to do. Firstly, drop ganging of NRP for
1421 			 * the time being, may build a second table of NRP registrations
1422 			 * where the table contains N entries only. We will insert this
1423 			 * NRP into the first free entry, then later when we are given NRP
1424 			 * messages we will search for them in this table.
1425 			 *
1426 			 * In the longer term we need to rewrite this to get rid of the
1427 			 * internal MIDI references, convert MIDI CC/RP/NRP, etc, into
1428 			 * an internal format in the library and then handle them here in
1429 			 * a common fashion. Perhaps this table will do that however then
1430 			 * it would need to support ganging.
1431 			 */
1432 			/*
1433 			 * Until we have ganging support, clear any old registrations.
1434 			 */
1435 			for (i = 0; i < synth->win->nrpcount; i++)
1436 			{
1437 				if ((synth->win->nrpcontrol[i].nrp == msg->GM2.coarse)
1438 					&& (synth->win->nrpcontrol[i].device != NULL))
1439 				{
1440 					printf("NRP Controller Registration Cleared: %i@%p\n",
1441 						synth->win->nrpcontrol[i].nrp,
1442 						synth->win->nrpcontrol[i].device);
1443 					synth->win->nrpcontrol[i].nrp = -1;
1444 					synth->win->nrpcontrol[i].device = NULL;
1445 				}
1446 			}
1447 
1448 			if (confdev[0] == NULL)
1449 				return;
1450 
1451 			for (i = 0; i < synth->win->nrpcount; i++)
1452 			{
1453 				if (synth->win->nrpcontrol[i].device == NULL)
1454 				{
1455 					synth->win->nrpcontrol[i].nrp = msg->GM2.coarse;
1456 					synth->win->nrpcontrol[i].device
1457 						= (struct brightonDevice *) confdev[0];
1458 					printf("NRP Controller Registration Honoured: %i@%p\n",
1459 						synth->win->nrpcontrol[i].nrp,
1460 						synth->win->nrpcontrol[i].device);
1461 					confdev[0] = 0;
1462 					return;
1463 				}
1464 			}
1465 		}
1466 
1467 		if (msg->GM2.c_id >= 127)
1468 		{
1469 			/* This should not happen so flag it */
1470 			printf("Current support limited to first 128 RP/NRP\n");
1471 			confflag = 0;
1472 			return;
1473 		}
1474 
1475 		/*
1476 		 * Link this CC to the given device, by MIDI channel? This also
1477 		 * needs to be made into a GM-2 controller (perhaps that should
1478 		 * be buried in the MIDI MSG structure - native and GM-2?)
1479 		 */
1480 		for (j = 0; j < BRIGHTON_GANG_COUNT; j++)
1481 		{
1482 			if (confdev[j] == 0)
1483 				continue;
1484 
1485 			for (i = 0; i < BRIGHTON_GANG_COUNT; i++)
1486 			{
1487 				if ((brightonDevice *)
1488 					synth->win->midicontrol[msg->GM2.c_id][i]
1489 						== confdev[j])
1490 				{
1491 					printf("Controller Registration Cleared: %i -> %i/%i@%p\n",
1492 						msg->GM2.c_id, confdev[j]->panel,
1493 						confdev[j]->index, confdev[j]);
1494 					synth->win->midicontrol[msg->GM2.c_id][i] = 0;
1495 					break;
1496 				} else {
1497 					if (synth->win->midicontrol[msg->GM2.c_id][i] != 0)
1498 					{
1499 						if (synth->win->midicontrolval[msg->GM2.c_id][i]
1500 							> maxvalue)
1501 							maxvalue = synth->win->midicontrolval[msg->GM2.c_id][i];
1502 
1503 						continue;
1504 					}
1505 
1506 					synth->win->midicontrol[msg->GM2.c_id][i]
1507 						= (struct brightonDevice *) confdev[j];
1508 					synth->win->midicontrolval[msg->GM2.c_id][i]
1509 						= confval[j];
1510 /*						= ((brightonDevice *) confdev[j])->value; */
1511 
1512 					printf("Controller Registration Honoured: %i -> %i/%i@%p %f\n",
1513 						msg->GM2.c_id, confdev[j]->panel,
1514 						confdev[j]->index, confdev[j], confval[j]);
1515 /*					if (synth->win->midicontrolval[msg->GM2.c_id][i] */
1516 /*						> maxvalue) */
1517 /*						maxvalue = synth->win->midicontrolval[msg->GM2.c_id][i]; */
1518 					break;
1519 				}
1520 			}
1521 		}
1522 
1523 		confflag = 0;
1524 		for (i = 0; i < BRIGHTON_GANG_COUNT; i++)
1525 		{
1526 			if (synth->win->midicontrolval[msg->GM2.c_id][i]
1527 				> maxvalue)
1528 				maxvalue = synth->win->midicontrolval[msg->GM2.c_id][i];
1529 			confdev[i] = 0;
1530 		}
1531 		/*
1532 		 * We now have a max value, we need to work on a scaler such that
1533 		 * this gang will scale to max
1534 		 */
1535 		if (maxvalue == 0.0f)
1536 		{
1537 			synth->win->midicontrolscaler[msg->GM2.c_id] = 1.0;
1538 		} else {
1539 			synth->win->midicontrolscaler[msg->GM2.c_id] = 1.0 / maxvalue;
1540 		}
1541 	} else {
1542 		brightonEvent event;
1543 
1544 		if ((msg->params.controller.c_id == MIDI_GM_DATAENTRY) ||
1545 			(msg->params.controller.c_id == MIDI_GM_NRP) ||
1546 			(msg->params.controller.c_id == MIDI_GM_NRP_F) ||
1547 			(msg->params.controller.c_id == MIDI_GM_RP) ||
1548 			(msg->params.controller.c_id == MIDI_GM_RP_F))
1549 			return;
1550 
1551 		if (msg->GM2.c_id == MIDI_GM_NRP)
1552 		{
1553 			if (~synth->flags & GUI_NRP)
1554 				return;
1555 
1556 			if (synth->flags & REQ_MIDI_DEBUG)
1557 				printf("NRP Message %i\n", msg->GM2.coarse);
1558 
1559 			for (i = 0; i < synth->win->nrpcount; i++)
1560 			{
1561 				if (synth->win->nrpcontrol[i].nrp == msg->GM2.coarse)
1562 				{
1563 					brightonIResource *p;
1564 					int panel, cc, ind, channel;
1565 
1566 					if (synth->flags & REQ_MIDI_DEBUG)
1567 						printf("Found %i@%p\n",
1568 							synth->win->nrpcontrol[i].nrp,
1569 							synth->win->nrpcontrol[i].device);
1570 
1571 					panel = ((brightonDevice *)
1572 						synth->win->nrpcontrol[i].device)->panel;
1573 
1574 					ind = ((brightonDevice *)
1575 						synth->win->nrpcontrol[i].device)->index;
1576 
1577 					cc = msg->GM2.c_id;
1578 					channel = msg->channel;
1579 
1580 					event.value = msg->GM2.value;
1581 					event.command = event.type = BRIGHTON_PARAMCHANGE;
1582 
1583 					p = (brightonIResource *)
1584 						&synth->win->app->resources[panel];
1585 
1586 				/*
1587 				 * See if we need to reverse the value already, and to scale
1588 				 * it to a native controller range. There are other cases, such
1589 				 * as "from > to" without the REVERSE flag, etc. Will address
1590 				 * them on a case by case basis.
1591 				 */
1592 				if (p->devlocn[ind].flags & BRIGHTON_REVERSE)
1593 					event.value = 1.0 - event.value;
1594 				/*
1595 				 * This might look odd, but if the 'to' is not 1.0 then the
1596 				 * interface expects 'N' integral steps so we have to round
1597 				 * value here. We perhaps should use 'truncf()'.
1598 				 */
1599 				if (p->devlocn[ind].to != 1.0)
1600 					event.value = (float)
1601 						((int) (event.value * p->devlocn[ind].to));
1602 
1603 				/*
1604 				if (((brightonDevice *)
1605 					synth->win->midicontrol[msg->GM2.c_id][i])->device
1606 					== 1)
1607 					event.value = 1.0 - event.value;
1608 				 */
1609 
1610 /*			printf( */
1611 /*				"synth->win->midicontrol[%i][%i]->%x(%x, &event): %f\n", */
1612 /*				msg->GM2.c_id, */
1613 /*				msg->channel, */
1614 /*				synth->win->midicontrol[msg->GM2.c_id]->configure, */
1615 /*				synth->win->midicontrol[msg->GM2.c_id], */
1616 /*				event.value); */
1617 
1618 				((brightonDevice *)
1619 					synth->win->nrpcontrol[i].device)->configure(
1620 					synth->win->nrpcontrol[i].device, &event);
1621 				}
1622 
1623 			}
1624 			return;
1625 		}
1626 
1627 		/*
1628 		 * If this was bank select pass it to the synth
1629 		 */
1630 		if (msg->GM2.c_id == 0)
1631 		{
1632 			if ((msg->channel == synth->midichannel)
1633 				&& (synth->win->template->callback != 0))
1634                 synth->win->template->callback(synth->win,
1635 					MIDI_BANK_SELECT, msg->GM2.intvalue, 0);
1636 			return;
1637 		}
1638 
1639 		/*
1640 		 * This next routine should use a parser on the message that will
1641 		 * build a GM-2 value into the msg, this will take care of things like
1642 		 * controllers that have fine and coarse resolution and will suitably
1643 		 * adjust the value to a suitable float, also changing the controller
1644 		 * number if this is the fine adjustment of a coarse control. This
1645 		 * may already have been done by the library?
1646 		 */
1647 		for (i = 0; i < BRIGHTON_GANG_COUNT; i++)
1648 		{
1649 			if (synth->win->midicontrol[msg->GM2.c_id][i] != 0)
1650 			{
1651 				brightonIResource *p;
1652 				int panel, cc, ind, channel;
1653 
1654 				panel = ((brightonDevice *)
1655 					synth->win->midicontrol[msg->GM2.c_id][i])->panel;
1656 				ind = ((brightonDevice *)
1657 					synth->win->midicontrol[msg->GM2.c_id][i])->index;
1658 				cc = msg->GM2.c_id;
1659 				channel = msg->channel;
1660 
1661 				/*
1662 				 * This value needs to be scaled according to the limits that
1663 				 * were set by the original registration. We should check for
1664 				 * max values.
1665 				 */
1666 /*				event.value = msg->GM2.value; */
1667 				if ((event.value = msg->GM2.value *
1668 					synth->win->midicontrolval[msg->GM2.c_id][i] *
1669 					synth->win->midicontrolscaler[msg->GM2.c_id])
1670 					> 1.0)
1671 					event.value = 1.0;
1672 				event.command = event.type = BRIGHTON_PARAMCHANGE;
1673 
1674 				p = (brightonIResource *)
1675 					&synth->win->app->resources[panel];
1676 
1677 				/*
1678 				 * See if we need to reverse the value already, and to scale
1679 				 * it to a native controller range. There are other cases, such
1680 				 * as "from > to" without the REVERSE flag, etc. Will address
1681 				 * them on a case by case basis.
1682 				 */
1683 				if (p->devlocn[ind].flags & BRIGHTON_REVERSE)
1684 					event.value = 1.0 - event.value;
1685 				/*
1686 				 * This might look odd, but if the 'to' is not 1.0 then the
1687 				 * interface expects 'N' integral steps so we have to round
1688 				 * value here. We perhaps should use 'truncf()'.
1689 				 */
1690 				if (p->devlocn[ind].to != 1.0)
1691 					event.value = (float)
1692 						((int) (event.value * p->devlocn[ind].to));
1693 
1694 				/*
1695 				if (((brightonDevice *)
1696 					synth->win->midicontrol[msg->GM2.c_id][i])->device
1697 					== 1)
1698 					event.value = 1.0 - event.value;
1699 				 */
1700 
1701 /*			printf( */
1702 /*				"synth->win->midicontrol[%i][%i]->%x(%x, &event): %f\n", */
1703 /*				msg->GM2.c_id, */
1704 /*				msg->channel, */
1705 /*				synth->win->midicontrol[msg->GM2.c_id]->configure, */
1706 /*				synth->win->midicontrol[msg->GM2.c_id], */
1707 /*				event.value); */
1708 
1709 				((brightonDevice *)
1710 					synth->win->midicontrol[msg->GM2.c_id][i])->configure(
1711 					synth->win->midicontrol[msg->GM2.c_id][i], &event);
1712 			}
1713 
1714 		}
1715 	}
1716 }
1717 
1718 /*
1719  * Common dispatch routine for Event selection to controller events.
1720  */
1721 void
brightonRegisterController(brightonDevice * dev)1722 brightonRegisterController(brightonDevice *dev)
1723 {
1724 	int i;
1725 
1726 	for (i = 0; i < BRIGHTON_GANG_COUNT; i++)
1727 	{
1728 		if (confdev[i] == dev)
1729 		{
1730 			printf("Controller Registration %i Cleared: ? -> %i/%i@%p\n",
1731 				i, dev->panel, dev->index, dev);
1732 
1733 			confdev[i] = 0;
1734 			if (--confflag <= 0)
1735 			{
1736 				confflag = 0;
1737 				for (i = 0; i < BRIGHTON_GANG_COUNT; i++)
1738 					confdev[i] = 0;
1739 			}
1740 
1741 			return;
1742 		}
1743 	}
1744 
1745 	/*
1746 	 * This should go into a table. Then, when we get the target controller
1747 	 * we change the device value and consider a paramchange message to be
1748 	 * sent to update the GUI (and send the value?).
1749 	confflag = 0;
1750 	confdev = dev;
1751 	 */
1752 	for (i = 0; i < BRIGHTON_GANG_COUNT; i++)
1753 	{
1754 		if (confdev[i] == 0)
1755 		{
1756 			confdev[i] = dev;
1757 
1758 			if (dev->device == 1)
1759 				confval[i] = 1.0 - dev->value;
1760 			else
1761 				confval[i] = dev->value;
1762 
1763 			if (confval[i] == 0.0)
1764 				confval[i] = 1.0;
1765 
1766 			break;
1767 		}
1768 	}
1769 	if (++confflag >= BRIGHTON_GANG_COUNT)
1770 	{
1771 		confflag = BRIGHTON_GANG_COUNT;
1772 		confdev[BRIGHTON_GANG_COUNT - 1] = dev;
1773 	}
1774 
1775 	printf("Controller Registration %i Request: ? -> %i/%i@%p %f\n",
1776 		i, dev->panel, dev->index, dev, dev->value);
1777 }
1778 
1779