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