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, ¶m[4]);
467
468 if (strncmp(param, "CLI", 3) == 0)
469 brightonSetCLIcode(¶m[5]);
470
471 if (strncmp(param, "NRP", 3) == 0)
472 brightonSetNRPControl(bwin, app, channel, ¶m[5]);
473
474 if (strncmp(param, "CM", 2) == 0)
475 brightonMapControl(bwin, app, channel, ¶m[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, ¶m[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