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  * Notes from the Voyager manual:
24  *
25  * Two filter modes:
26  *
27  * 	1. Dual parallel LP, stereo separation, both resonant
28  * 	2. Serial HPF/LPF, mono, HPF is non resonant.
29  *
30  * Currently the filter switch is for key envelope velocity. Drop velocity on
31  * this env and use the correct option to select the filter type.
32  *
33  * The mod busses are passed through:
34  *
35  * 	1. Wheel Mod
36  * 	2. On/Off Pedal
37  *
38  * Release is a scaler of the actual release time. Affects both envelopes.
39  *
40  * Key modes, from control panel (mono only):
41  *
42  * 	1. Lowest
43  * 	2. Highest
44  * 	3. Last key
45  * 	4. First key
46  *
47  * Trigger modes, from control panel (mono only):
48  *
49  * 	1. Single
50  * 	2. Multi
51  */
52 
53 #include <fcntl.h>
54 
55 #include "brighton.h"
56 #include "brightonMini.h"
57 #include "brightoninternals.h"
58 
59 int explorerInit();
60 int explorerConfigure();
61 int explorerCallback(brightonWindow *, int, int, float);
62 static int midiCallback(brightonWindow *, int, int, float);
63 
64 extern guimain global;
65 
66 extern int empty;
67 
68 #include "brightonKeys.h"
69 
70 #define KEY_PANEL 1
71 
72 #define FIRST_DEV 0
73 #define DEVICE_COUNT 77
74 #define ACTIVE_DEVS 56
75 #define MEM_START (ACTIVE_DEVS + 1)
76 
77 #define DISPLAY1 (DEVICE_COUNT - 2)
78 #define DISPLAY2 (DEVICE_COUNT - 1)
79 
80 #define S1 85
81 
82 #define B1 15
83 #define B2 110
84 #define B3 37
85 #define B4 42
86 
87 #define R14 200
88 #define R24 400
89 #define R34 600
90 #define R44 800
91 
92 #define R15 200
93 #define R25 350
94 #define R35 500
95 #define R45 650
96 #define R55 800
97 
98 #define C1 25
99 #define C2 90
100 #define C3 155
101 #define C4 220
102 #define C5 285
103 #define C6 350
104 #define C6I 395
105 
106 #define C7 615
107 #define C8 665
108 #define C9 742
109 #define C10 810
110 #define C11 875
111 #define C12 945
112 
113 /*
114  * This structure is for device definition. The structure is defined in
115  * include/brighton.h, further definitions in brighton/brightonDevtable.h and
116  * include/brightoninternals.h
117  *
118  *	typedef int (*brightonCallback)(int, float);
119  *	typedef struct BrightonLocations {
120  *		int device; 0=rotary, 1=scale, etc.
121  *		float relx, rely; relative position with regards to 1000 by 1000 window
122  *		float relw, relh; relative height.
123  *		int from, to;
124  *		brightonCallback callback; specific to this dev
125  *		char *image; bitmap. If zero take a device default.
126  *		int flags;
127  *	} brightonLocations;
128  *
129  * This example is for a explorerBristol type synth interface.
130  */
131 static brightonLocations locations[DEVICE_COUNT] = {
132 
133 /* LFO and control */
134 	{"LFO-Freq", 0, C1 - 7, R14 - 20, S1 + 40, S1 + 40, 0, 1, 0, 0, 0, 0},
135 	{"LFO-Sync", 2, C1 - 5, R24 + 25, B3, B4, 0, 3, 0,
136 		"bitmaps/buttons/rockerblue.xpm", 0, 0},
137 	{"GLOBAL TUNE", 0, C1, R34, S1, S1, 0, 1, 0, 0, 0, BRIGHTON_NOTCH},
138 	{"Glide", 0, C1, R44, S1, S1, 0, 1, 0, 0, 0, 0},
139 /* Routing */
140 	{"Mod1-Source", 0, C2, R14, S1, S1, 0, 4, 0, 0, 0, 0},
141 	{"Mod1-Shape", 0, C2, R24, S1, S1, 0, 3, 0, 0, 0, 0},
142 	{"Mod1-Dest", 0, C2, R34, S1, S1, 0, 5, 0, 0, 0, 0},
143 	{"Mod1-Gain", 0, C2, R44, S1, S1, 0, 1, 0, 0, 0, 0},
144 	{"Mod2-Source", 0, C3, R14, S1, S1, 0, 4, 0, 0, 0, 0},
145 	{"Mod2-Shape", 0, C3, R24, S1, S1, 0, 3, 0, 0, 0, 0},
146 	{"Mod2-Dest", 0, C3, R34, S1, S1, 0, 5, 0, 0, 0, 0},
147 	{"Mod2-Gain", 0, C3, R44, S1, S1, 0, 1, 0, 0, 0, 0},
148 /* Oscillators */
149 	{"Osc1-Transpose", 0, C4, R24, S1, S1, 0, 5, 0, 0, 0, 0},
150 	{"Osc1-Waveform", 0, C4, R34, S1, S1, 0, 1, 0, 0, 0, 0},
151 	{"Osc2-Tuning", 0, C5 - 7, R14 - 20, S1 + 40, S1 + 40, 0, 1, 0, 0, 0, BRIGHTON_NOTCH},
152 	{"Osc2-Transpose", 0, C5, R24, S1, S1, 0, 5, 0, 0, 0, 0},
153 	{"Osc2-Waveform", 0, C5, R34, S1, S1, 0, 1, 0, 0, 0, 0},
154 	{"Osc3-Tuning", 0, C6 - 7, R14 - 20, S1 + 40, S1 + 40, 0, 1, 0, 0, 0, BRIGHTON_NOTCH},
155 	{"Osc3-Transpose", 0, C6, R24, S1, S1, 0, 5, 0, 0, 0, 0},
156 	{"Osc3-Waveform", 0, C6, R34, S1, S1, 0, 1, 0, 0, 0, 0},
157 /* Osc mod switches */
158 	{"Sync-1/2", 2, C4, R44 + 10, B1, B2, 0, 1, 0, 0, 0, BRIGHTON_VERTICAL},
159 	{"FM-1/3", 2, C4 + 40, R44 + 10, B1, B2, 0, 1, 0, 0, 0, BRIGHTON_VERTICAL},
160 	{"KBD-3", 2, C4 + 95, R44 + 10, B1, B2, 0, 1, 0, 0, 0, BRIGHTON_VERTICAL},
161 	{"Freq-3", 2, C4 + 135, R44 + 10, B1, B2, 0, 1, 0, 0, 0, BRIGHTON_VERTICAL},
162 /* Mixer */
163 	{"Mix-EXT", 0, C7, R15, S1, S1, 0, 1, 0, 0, 0, 0},
164 	{"Mix-O1", 0, C7, R25, S1, S1, 0, 1, 0, 0, 0, 0},
165 	{"Mix-O2", 0, C7, R35, S1, S1, 0, 1, 0, 0, 0, 0},
166 	{"Mix-O3", 0, C7, R45, S1, S1, 0, 1, 0, 0, 0, 0},
167 	{"Mix-NSE", 0, C7, R55, S1, S1, 0, 1, 0, 0, 0, 0},
168 	{"Mix-Ext-off", 2, C8, R15 + 25, B3, B4, 0, 1, 0,
169 		"bitmaps/buttons/rockerblue.xpm", 0, 0},
170 	{"Mix-O1-off", 2, C8, R25 + 25, B3, B4, 0, 1, 0,
171 		"bitmaps/buttons/rockerblue.xpm", 0, 0},
172 	{"Mix-O2-off", 2, C8, R35 + 25, B3, B4, 0, 1, 0,
173 		"bitmaps/buttons/rockerblue.xpm", 0, 0},
174 	{"Mix-O3-off", 2, C8, R45 + 25, B3, B4, 0, 1, 0,
175 		"bitmaps/buttons/rockerblue.xpm", 0, 0},
176 	{"Mix-Nse-off", 2, C8, R55 + 25, B3, B4, 0, 1, 0,
177 		"bitmaps/buttons/rockerblue.xpm", 0, 0},
178 /* Filter */
179 	{"VCF-Cutoff", 0, C9 - 7, R15 - 25, S1 + 40, S1 + 40, 0, 1, 0, 0, 0, 0},
180 	{"VCF-Space", 0, C9, R25, S1, S1, 0, 1, 0, 0, 0, 0},
181 	{"VCF-Res", 0, C9, R35, S1, S1, 0, 1, 0, 0, 0, 0},
182 	{"VCF-KBD", 0, C9, R45, S1, S1, 0, 1, 0, 0, 0, 0},
183 	{"VCF-Mode", 2, C9, R55 + 25, B3, B4, 0, 1, 0, 0, 0, 0},
184 /* Filter envelope */
185 	{"VCF-Attack", 0, C10, R15, S1, S1, 0, 1, 0, 0, 0, 0},
186 	{"VCF-Decay", 0, C10, R25, S1, S1, 0, 1, 0, 0, 0, 0},
187 	{"VCF-Sustain", 0, C10, R35, S1, S1, 0, 1, 0, 0, 0, 0},
188 	{"VCF-Release", 0, C10, R45, S1, S1, 0, 1, 0, 0, 0, 0},
189 	{"VCF-EnvLevel", 0, C10, R55, S1, S1, 0, 1, 0, 0, 0, 0},
190 /* Amp Envelope */
191 	{"VCA-Attack", 0, C11, R15, S1, S1, 0, 1, 0, 0, 0, 0},
192 	{"VCA-Decay", 0, C11, R25, S1, S1, 0, 1, 0, 0, 0, 0},
193 	{"VCA-Sustain", 0, C11, R35, S1, S1, 0, 1, 0, 0, 0, 0},
194 	{"VCA-Release", 0, C11, R45, S1, S1, 0, 1, 0, 0, 0, 0},
195 	{"VCA-Veloc", 2, C11, R55 + 25, B3, B4, 0, 1, 0, 0, 0, 0},
196 /* Vol, on/off, glide and release */
197 	{"Volume", 0, C12 - 7, R15 - 25 , S1 + 40, S1 + 40, 0, 1, 0, 0, 0, 0},
198 	{"On/Off", 2, C12 - 4, R25 + 25, B3, B4, 0, 1, 0, 0, 0, 0},
199 	{"LFO-Multi", 2, C12 - 4, R35 + 25, B3, B4, 0, 1, 0,
200 		"bitmaps/buttons/rockerwhite.xpm", 0, 0},
201 	{"Glide-On", 2, C12 - 4, R45 + 25, B3, B4, 0, 1, 0,
202 		"bitmaps/buttons/rockerwhite.xpm", 0, 0},
203 	{"Release-On", 2, C12 - 4, R55 + 25, B3, B4, 0, 1, 0,
204 		"bitmaps/buttons/rockerwhite.xpm", 0, 0},
205 	{"Reserved", 5, 405, 410, 180, 518, 0, 1, 0, "bitmaps/buttons/pointer.xpm", 0, 0},
206 	{"Reserved", 5, 405, 410, 180, 518, 0, 1, 0, "bitmaps/buttons/pointer.xpm", 0,
207 		BRIGHTON_WITHDRAWN},
208 /* logo */
209 	{"", 4, 762, 1037, 240, 140, 0, 1, 0, "bitmaps/images/explorer.xpm", 0, 0},
210 
211 /* memories */
212 	{"", 2, 418, 225, 17, 78, 0, 1.01, 0,
213 		"bitmaps/buttons/pressoff.xpm",
214 		"bitmaps/buttons/presson.xpm", 0},
215 	{"", 2, 436, 225, 17, 78, 0, 1.01, 0,
216 		"bitmaps/buttons/pressoff.xpm",
217 		"bitmaps/buttons/presson.xpm", 0},
218 	{"", 2, 454, 225, 17, 78, 0, 1.01, 0,
219 		"bitmaps/buttons/pressoff.xpm",
220 		"bitmaps/buttons/presson.xpm", 0},
221 	{"", 2, 472, 225, 17, 78, 0, 1.01, 0,
222 		"bitmaps/buttons/pressoff.xpm",
223 		"bitmaps/buttons/presson.xpm", 0},
224 	{"", 2, 490, 225, 17, 78, 0, 1.01, 0,
225 		"bitmaps/buttons/pressoff.xpm",
226 		"bitmaps/buttons/presson.xpm", 0},
227 	{"", 2, 418, 308, 17, 78, 0, 1.01, 0,
228 		"bitmaps/buttons/pressoff.xpm",
229 		"bitmaps/buttons/presson.xpm", 0},
230 	{"", 2, 436, 308, 17, 78, 0, 1.01, 0,
231 		"bitmaps/buttons/pressoff.xpm",
232 		"bitmaps/buttons/presson.xpm", 0},
233 	{"", 2, 454, 308, 17, 78, 0, 1.01, 0,
234 		"bitmaps/buttons/pressoff.xpm",
235 		"bitmaps/buttons/presson.xpm", 0},
236 	{"", 2, 472, 308, 17, 78, 0, 1.01, 0,
237 		"bitmaps/buttons/pressoff.xpm",
238 		"bitmaps/buttons/presson.xpm", 0},
239 	{"", 2, 490, 308, 17, 78, 0, 1.01, 0,
240 		"bitmaps/buttons/pressoff.xpm",
241 		"bitmaps/buttons/presson.xpm", 0},
242 	{"", 2, 510, 228, 15, 70, 0, 1.01, 0,
243 		"bitmaps/buttons/pressoffg.xpm",
244 		"bitmaps/buttons/pressong.xpm", BRIGHTON_CHECKBUTTON},
245 	{"", 2, 510, 309, 15, 70, 0, 1.01, 0,
246 		"bitmaps/buttons/pressoffo.xpm",
247 		"bitmaps/buttons/pressono.xpm", BRIGHTON_CHECKBUTTON},
248 	{"", 2, 540, 70, 16, 78, 0, 1.01, 0,
249 		"bitmaps/buttons/pressoff.xpm",
250 		"bitmaps/buttons/presson.xpm", BRIGHTON_CHECKBUTTON},
251 	{"", 2, 540, 145, 16, 78, 0, 1.01, 0,
252 		"bitmaps/buttons/pressoff.xpm",
253 		"bitmaps/buttons/presson.xpm", BRIGHTON_CHECKBUTTON},
254 	{"", 2, 540, 227, 16, 78, 0, 1.01, 0,
255 		"bitmaps/buttons/pressoff.xpm",
256 		"bitmaps/buttons/presson.xpm", 0},
257 	{"", 2, 540, 308, 16, 78, 0, 1.01, 0,
258 		"bitmaps/buttons/pressoff.xpm",
259 		"bitmaps/buttons/presson.xpm", 0},
260 	/* mem up down */
261 	{"", 2, 402, 228, 15, 70, 0, 1.01, 0,
262 		"bitmaps/buttons/pressoffg.xpm",
263 		"bitmaps/buttons/pressong.xpm", BRIGHTON_CHECKBUTTON},
264 	{"", 2, 402, 311, 15, 70, 0, 1.01, 0,
265 		"bitmaps/buttons/pressoffg.xpm",
266 		"bitmaps/buttons/pressong.xpm", BRIGHTON_CHECKBUTTON},
267 	/* displays */
268 	{"", 3, 403, 90, 128, 63, 0, 1, 0, 0,
269 		"bitmaps/images/alphadisplay3.xpm", 0},
270 	{"", 3, 403, 150, 128, 63, 0, 1, 0, 0, 0, 0}
271 };
272 /*
273  * This is a set of globals for the main window rendering. Again taken from
274  * include/brighton.h
275  */
276 brightonApp explorerApp = {
277 	"explorer",
278 	0, /* no blueprint on wood background. */
279 	"bitmaps/textures/wood2.xpm",
280 	0, /* or BRIGHTON_STRETCH, default is tesselate */
281 	explorerInit,
282 	explorerConfigure, /* 3 callbacks, unused? */
283 	midiCallback,
284 	destroySynth,
285 	{1, 100, 2, 2, 5, 520, 0, 0},
286 	817, 472, 0, 0,
287 	7, /* one panel only */
288 	{
289 		{
290 			"Explorer",
291 			"bitmaps/blueprints/explorer.xpm",
292 			"bitmaps/textures/metal6.xpm",
293 			BRIGHTON_STRETCH, /* flags */
294 			0,
295 			explorerConfigure,
296 			explorerCallback,
297 			25, 25, 950, 532,
298 			DEVICE_COUNT,
299 			locations
300 		},
301 		{
302 			"Keyboard",
303 			0,
304 			"bitmaps/newkeys/ekbg.xpm", /* flags */
305 			0x020|BRIGHTON_STRETCH,
306 			0,
307 			0,
308 			keyCallback,
309 			140, 675, 840, 300,
310 			KEY_COUNT_3OCTAVE,
311 			keys3octave
312 		},
313 		{
314 			"Mods",
315 			"bitmaps/blueprints/mods.xpm",
316 			"bitmaps/textures/metal6.xpm", /* flags */
317 			BRIGHTON_STRETCH,
318 			0,
319 			0,
320 			modCallback,
321 			15, 675, 125, 300,
322 			2,
323 			mods
324 		},
325 		{
326 			"SP0",
327 			0,
328 			"bitmaps/textures/wood2.xpm",
329 			BRIGHTON_STRETCH|BRIGHTON_VERTICAL, /* flags */
330 			0,
331 			0,
332 			0,
333 			930, 675, 60, 300,
334 			0,
335 			0
336 		},
337 		{
338 			"SP1",
339 			0,
340 			"bitmaps/textures/wood2.xpm",
341 			BRIGHTON_STRETCH|BRIGHTON_VERTICAL, /* flags */
342 			0,
343 			0,
344 			0,
345 			0, 0, 15, 1000,
346 			0,
347 			0
348 		},
349 		{
350 			"SP2",
351 			0,
352 			"bitmaps/textures/wood2.xpm",
353 			BRIGHTON_STRETCH|BRIGHTON_VERTICAL, /* flags */
354 			0,
355 			0,
356 			0,
357 			985, 0, 15, 1000,
358 			0,
359 			0
360 		},
361 	}
362 };
363 
364 /*static dispatcher dispatch[DEVICE_COUNT]; */
365 
366 static int
midiCallback(brightonWindow * win,int controller,int value,float n)367 midiCallback(brightonWindow *win, int controller, int value, float n)
368 {
369 	guiSynth *synth = findSynth(global.synths, win);
370 
371 	printf("midi callback: %x, %i\n", controller, value);
372 
373 	switch(controller)
374 	{
375 		case MIDI_PROGRAM:
376 			printf("midi program: %x, %i\n", controller, value);
377 			synth->location = value + synth->bank * 10;
378 			if (loadMemory(synth, "explorer", 0, synth->location,
379 				synth->mem.active, FIRST_DEV, BRISTOL_STAT) < 0)
380 				displayText(synth, "FRE", synth->location, DISPLAY1);
381 			else
382 				displayText(synth, "PRG", synth->location, DISPLAY1);
383 			break;
384 		case MIDI_BANK_SELECT:
385 			printf("midi banksel: %x, %i\n", controller, value);
386 			synth->bank = value;
387 			synth->location = (synth->location % 10) + value * 10;
388 			if (loadMemory(synth, "explorer", 0, synth->location,
389 				synth->mem.active, FIRST_DEV, BRISTOL_STAT) < 0)
390 				displayText(synth, "FRE", synth->location, DISPLAY1);
391 			else
392 				displayText(synth, "PRG", synth->location, DISPLAY1);
393 			break;
394 	}
395 	return(0);
396 }
397 
398 static int
explorerMidiSendMsg(void * synth,int fd,int chan,int c,int o,int v)399 explorerMidiSendMsg(void *synth, int fd, int chan, int c, int o, int v)
400 {
401 	bristolMidiSendMsg(fd, chan, c, o, v);
402 	return(0);
403 }
404 
405 static void
explorerMemory(guiSynth * synth,int fd,int chan,int c,int o,int v)406 explorerMemory(guiSynth *synth, int fd, int chan, int c, int o, int v)
407 {
408 /*	printf("explorerMemory(%i %i %i %i %i)\n", fd, chan, c, o, v); */
409 
410 	if (synth->flags & MEM_LOADING)
411 		return;
412 	if ((synth->flags & OPERATIONAL) == 0)
413 		return;
414 
415 	if (synth->dispatch[MEM_START].other2)
416 	{
417 		synth->dispatch[MEM_START].other2 = 0;
418 		return;
419 	}
420 
421 	switch (c) {
422 		default:
423 		case 0:
424 			if (synth->dispatch[MEM_START].other1 != -1)
425 			{
426 				brightonEvent event;
427 				synth->dispatch[MEM_START].other2 = 1;
428 
429 				if (synth->dispatch[MEM_START].other1 != c)
430 					event.value = 0;
431 				else
432 					event.value = 1;
433 
434 				brightonParamChange(synth->win, synth->panel,
435 					synth->dispatch[MEM_START].other1, &event);
436 			}
437 			synth->dispatch[MEM_START].other1 = c;
438 
439 			synth->location = synth->location * 10 + o;
440 
441 			if (synth->location >= 1000)
442 				synth->location = o;
443 
444 			if (loadMemory(synth, "explorer", 0, synth->location,
445 				synth->mem.active, FIRST_DEV, BRISTOL_STAT) < 0)
446 				displayText(synth, "FRE", synth->location, DISPLAY1);
447 			else
448 				displayText(synth, "PRG", synth->location, DISPLAY1);
449 			break;
450 		case 1:
451 			if (loadMemory(synth, "explorer", 0, synth->location,
452 				synth->mem.active, FIRST_DEV, 0) < 0)
453 				displayText(synth, "FRE", synth->location, DISPLAY2);
454 			else
455 				displayText(synth, "PRG", synth->location, DISPLAY2);
456 /*			synth->location = 0; */
457 			break;
458 		case 2:
459 			saveMemory(synth, "explorer", 0, synth->location, FIRST_DEV);
460 			displayText(synth, "PRG", synth->location, DISPLAY2);
461 /*			synth->location = 0; */
462 			break;
463 		case 3:
464 			while (loadMemory(synth, "explorer", 0, ++synth->location,
465 				synth->mem.active, FIRST_DEV, 0) < 0)
466 			{
467 				if (synth->location > 999)
468 					synth->location = -1;
469 			}
470 			displayText(synth, "PRG", synth->location, DISPLAY2);
471 			break;
472 		case 4:
473 			while (loadMemory(synth, "explorer", 0, --synth->location,
474 				synth->mem.active, FIRST_DEV, 0) < 0)
475 			{
476 				if (synth->location < 0)
477 					synth->location = 999;
478 			}
479 			displayText(synth, "PRG", synth->location, DISPLAY2);
480 			break;
481 	}
482 }
483 
484 /*
485  * For the sake of ease of use, links have been placed here to be called
486  * by any of the devices created. They would be better in some other file,
487  * perhaps with this as a dispatch.
488  *
489  * Param refers to the device index in the locations table given below.
490  */
491 int
explorerCallback(brightonWindow * win,int panel,int index,float value)492 explorerCallback(brightonWindow * win, int panel, int index, float value)
493 {
494 	guiSynth *synth = findSynth(global.synths, win);
495 	int sendvalue;
496 
497 /* printf("explorerCallback(%i, %i, %f)\n", panel, index, value); */
498 
499 	if (synth == 0)
500 		return(0);
501 
502 	if ((index >= DEVICE_COUNT) || ((synth->flags & OPERATIONAL) == 0))
503 		return(0);
504 	if (index >= DEVICE_COUNT)
505 		return(0);
506 
507 	if (explorerApp.resources[0].devlocn[index].to == 1.0)
508 		sendvalue = value * (CONTROLLER_RANGE - 1);
509 	else
510 		sendvalue = value;
511 
512 	synth->mem.param[index] = value;
513 
514 	if ((!global.libtest) || (index >= ACTIVE_DEVS))
515 		synth->dispatch[index].routine(synth,
516 			global.controlfd, synth->sid,
517 			synth->dispatch[index].controller,
518 			synth->dispatch[index].operator,
519 			sendvalue);
520 	else
521 		printf("dispatch[%p,%i](%i, %i, %i, %i, %i)\n", synth, index,
522 			global.controlfd, synth->sid,
523 			synth->dispatch[index].controller,
524 			synth->dispatch[index].operator,
525 			sendvalue);
526 	return(0);
527 }
528 
529 static void
explorerMidi(guiSynth * synth,int fd,int chan,int c,int o,int v)530 explorerMidi(guiSynth *synth, int fd, int chan, int c, int o, int v)
531 {
532 	printf("explorerMidi(%i %i %i %i %i)\n", fd, chan, c, o, v);
533 
534 	if ((synth->flags & OPERATIONAL) == 0)
535 		return;
536 
537 	if (synth->dispatch[MEM_START + 14].other1 == MEM_START + 14)
538 	{
539 		int newchan;
540 
541 		if (c == 1) {
542 			if ((newchan = synth->midichannel - 1) < 0)
543 			{
544 				synth->midichannel = 0;
545 				return;
546 			}
547 		} else {
548 			if ((newchan = synth->midichannel + 1) >= 16)
549 			{
550 				synth->midichannel = 15;
551 				return;
552 			}
553 		}
554 
555 		if (global.libtest == 0)
556 			bristolMidiSendMsg(global.controlfd, synth->sid,
557 				127, 0, BRISTOL_MIDICHANNEL|newchan);
558 
559 		synth->midichannel = newchan;
560 
561 		displayText(synth, "CHAN", synth->midichannel + 1, DISPLAY1);
562 	} else {
563 		if (c == 1) {
564 			while (locations[--synth->dispatch[MEM_START + 15].other2].name[0]
565 				== '\0')
566 			{
567 				if (synth->dispatch[MEM_START + 15].other2 < 0)
568 					synth->dispatch[MEM_START + 15].other2 = 49;
569 			}
570 		} else {
571 			while (locations[++synth->dispatch[MEM_START + 15].other2].name[0]
572 				== '\0')
573 			{
574 				if (synth->dispatch[MEM_START + 15].other2 >= 49)
575 					synth->dispatch[MEM_START + 15].other2 = 0;
576 			}
577 		}
578 		displayText(synth,
579 			locations[synth->dispatch[MEM_START + 15].other2].name,
580 			synth->dispatch[MEM_START + 15].other2,
581 			DISPLAY2);
582 		if (synth->dispatch[MEM_START + 15].other1 == 1)
583 		{
584 /*printf("PANEL X SELECTOR %i %i = %i %i\n", */
585 /*synth->dispatch[MEM_START + 15].other1, */
586 /*synth->dispatch[MEM_START + 15].other2, */
587 /*synth->dispatch[synth->dispatch[MEM_START + 15].other2].controller, */
588 /*synth->dispatch[synth->dispatch[MEM_START + 15].other2].operator); */
589 			synth->dispatch[54].controller =
590 				synth->dispatch[
591 					synth->dispatch[MEM_START + 15].other2].controller;
592 			synth->dispatch[54].operator =
593 				synth->dispatch[
594 					synth->dispatch[MEM_START + 15].other2].operator;
595 		} else {
596 /*printf("PANEL Y SELECTOR %i %i = %i %i\n", */
597 /*synth->dispatch[MEM_START + 15].other1, */
598 /*synth->dispatch[MEM_START + 15].other2, */
599 /*synth->dispatch[synth->dispatch[MEM_START + 15].other2].controller, */
600 /*synth->dispatch[synth->dispatch[MEM_START + 15].other2].operator); */
601 			synth->dispatch[55].controller =
602 				synth->dispatch[
603 					synth->dispatch[MEM_START + 15].other2].controller;
604 			synth->dispatch[55].operator =
605 				synth->dispatch[
606 					synth->dispatch[MEM_START + 15].other2].operator;
607 		}
608 	}
609 }
610 
611 static void
explorerPanelSelect(guiSynth * synth,int fd,int chan,int c,int o,int v)612 explorerPanelSelect(guiSynth *synth, int fd, int chan, int c, int o, int v)
613 {
614 
615 /*	printf("explorerPanelSelect(%x, %i, %i, %i, %i, %i\n", */
616 /*		synth, fd, chan, c, o, v); */
617 /* dispatch[MEM_START + 14] = dispatch[MEM_START + 15] */
618 
619 	if (synth->dispatch[MEM_START + 14].other2)
620 	{
621 		synth->dispatch[MEM_START + 14].other2 = 0;
622 		return;
623 	}
624 
625 	if (synth->dispatch[MEM_START + 14].other1 != -1)
626 	{
627 		brightonEvent event;
628 		synth->dispatch[MEM_START + 14].other2 = 1;
629 
630 		if (synth->dispatch[MEM_START + 14].other1 != c)
631 			event.value = 0;
632 		else
633 			event.value = 1;
634 
635 		brightonParamChange(synth->win, synth->panel,
636 			synth->dispatch[MEM_START + 14].other1, &event);
637 	}
638 	displayText(synth, "CHAN", synth->midichannel + 1, DISPLAY1);
639 
640 	if (c == MEM_START + 15)
641 	{
642 		if (synth->dispatch[MEM_START + 15].other1 > 1)
643 			synth->dispatch[MEM_START + 15].other1 = 0;
644 
645 		switch (synth->dispatch[MEM_START + 15].other1) {
646 			case 0:
647 			default:
648 				displayText(synth, "PAN-X",
649 					synth->dispatch[MEM_START + 15].other2, DISPLAY1);
650 				break;
651 			case 1:
652 				displayText(synth, "PAN-Y",
653 					synth->dispatch[MEM_START + 15].other2, DISPLAY1);
654 				break;
655 		}
656 		synth->dispatch[MEM_START + 15].other1++;
657 	}
658 	synth->dispatch[MEM_START + 14].other1 = c;
659 }
660 
661 /*
662 static void
663 explorerOsc3Transpose(guiSynth *synth)
664 {
665 	if (synth->mem.param[23] != 0)
666 		bristolMidiSendMsg(global.controlfd, synth->sid, 2, 1,
667 			(int) (synth->mem.param[18] / 4));
668 	else
669 		bristolMidiSendMsg(global.controlfd, synth->sid, 2, 1,
670 			(int) synth->mem.param[18]);
671 }
672 */
673 
674 static void
explorerFilterMode(guiSynth * synth,int fd,int chan,int o,int c,int v)675 explorerFilterMode(guiSynth *synth, int fd, int chan, int o, int c, int v)
676 {
677 	/*
678 	 * If value is zero we need to configure two H/LPF and clear the MODE
679 	 * flag (12/12). Otherwise set the flag and configure C/HPF, H/LPF.
680 	 */
681 	if (v == 0) {
682 		/*
683 		printf("LPF/LPF\n");
684 		 * FIlter 1 must change to type 4, Houvilainen LPF.
685 		 */
686 		bristolMidiSendMsg(global.controlfd, synth->sid, 4, 4, 4);
687 		bristolMidiSendMsg(global.controlfd, synth->sid, 4, 6, 0);
688 	} else {
689 		/*
690 		printf("HPF/LPF\n");
691 		 * FIlter 1 must change to type 0, Chamberlain and HPF
692 		 */
693 		bristolMidiSendMsg(global.controlfd, synth->sid, 4, 4, 0);
694 		bristolMidiSendMsg(global.controlfd, synth->sid, 4, 6, 2);
695 	}
696 
697 	/* And the main routing flag for filter stereo panning */
698 	bristolMidiSendMsg(global.controlfd, synth->sid, 12, 12, v);
699 }
700 
701 static void
explorerFilter(guiSynth * synth,int fd,int chan,int o,int c,int v)702 explorerFilter(guiSynth *synth, int fd, int chan, int o, int c, int v)
703 {
704 	int value;
705 
706 	/* See if this is the key track or mod */
707 	if (c == 3)
708 	{
709 		bristolMidiSendMsg(global.controlfd, synth->sid, 4, c, v);
710 		bristolMidiSendMsg(global.controlfd, synth->sid, 9, c, v);
711 
712 		return;
713 	}
714 
715 	if (c == 1)
716 	{
717 		/* Res goes to both LPF but not to the HPF. */
718 		bristolMidiSendMsg(global.controlfd, synth->sid, 4, c, v);
719 		bristolMidiSendMsg(global.controlfd, synth->sid, 9, c, v);
720 
721 		return;
722 	}
723 
724 	/*
725 	 * We have mod and res that just goes to each filter.
726 	 *
727 	 * Cutoff and spare are a function of the eachother.
728 	 */
729 	bristolMidiSendMsg(global.controlfd, synth->sid, 9, 0,
730 		(int) (synth->mem.param[34] * C_RANGE_MIN_1));
731 
732 	value = (synth->mem.param[34] + (synth->mem.param[35] - 0.5f))
733 		* C_RANGE_MIN_1;
734 
735 	if (value > C_RANGE_MIN_1)
736 		value = C_RANGE_MIN_1;
737 	else if (value < 0)
738 		value = 0;
739 
740 	bristolMidiSendMsg(global.controlfd, synth->sid, 4, 0, value);
741 /*	bristolMidiSendMsg(global.controlfd, synth->sid, 4, 0, */
742 /*		(int) (synth->mem.param[35] * C_RANGE_MIN_1)); */
743 }
744 
745 static void
explorerRelease(guiSynth * synth,int fd,int chan,int o,int c,int v)746 explorerRelease(guiSynth *synth, int fd, int chan, int o, int c, int v)
747 {
748 	if ((c == 3) || (c == 5)) {
749 		/* Filter/APM env release */
750 		if (synth->mem.param[53] != 0)
751 			bristolMidiSendMsg(global.controlfd, synth->sid, c, 3, v);
752 		else
753 			bristolMidiSendMsg(global.controlfd, synth->sid, c, 3, v / 10);
754 	} else {
755 		/* Selection switch */
756 		if (synth->mem.param[53] != 0)
757 		{
758 			bristolMidiSendMsg(global.controlfd, synth->sid, 3, 3,
759 				(int) (synth->mem.param[42] * C_RANGE_MIN_1));
760 			bristolMidiSendMsg(global.controlfd, synth->sid, 5, 3,
761 				(int) (synth->mem.param[47] * C_RANGE_MIN_1));
762 		} else {
763 			bristolMidiSendMsg(global.controlfd, synth->sid, 3, 3,
764 				(int) (synth->mem.param[42] * C_RANGE_MIN_1 / 10));
765 			bristolMidiSendMsg(global.controlfd, synth->sid, 5, 3,
766 				(int) (synth->mem.param[47] * C_RANGE_MIN_1 / 10));
767 		}
768 	}
769 }
770 
771 static void
explorerGlide(guiSynth * synth)772 explorerGlide(guiSynth *synth)
773 {
774 	if (synth->mem.param[52] != 0)
775 		bristolMidiSendMsg(global.controlfd, synth->sid, 11, 0,
776 			(int) (synth->mem.param[3] * C_RANGE_MIN_1));
777 	else
778 		bristolMidiSendMsg(global.controlfd, synth->sid, 11, 0, 0);
779 }
780 
781 /*
782  * Any location initialisation required to run the callbacks. For bristol, this
783  * will connect to the engine, and give it some base parameters.
784  * May need to generate some application specific menus.
785  * Will also then make specific requests to some of the devices to alter their
786  * rendering.
787  */
788 int
explorerInit(brightonWindow * win)789 explorerInit(brightonWindow *win)
790 {
791 	guiSynth *synth = findSynth(global.synths, win);
792 	dispatcher *dispatch;
793 	int i;
794 
795 	if (synth == 0)
796 	{
797 		synth = findSynth(global.synths, 0);
798 		if (synth == 0)
799 		{
800 			printf("cannot init\n");
801 			return(0);
802 		}
803 	}
804 
805 	synth->win = win;
806 
807 	printf("Initialise the explorer link to bristol: %p\n", synth->win);
808 
809 	synth->mem.param = (float *) brightonmalloc(DEVICE_COUNT * sizeof(float));
810 	synth->mem.count = DEVICE_COUNT;
811 	synth->mem.active = ACTIVE_DEVS;
812 	synth->dispatch = (dispatcher *)
813 		brightonmalloc(DEVICE_COUNT * sizeof(dispatcher));
814 	dispatch = synth->dispatch;
815 
816 	/*
817 	 * We really want to have three connection mechanisms. These should be
818 	 *	1. Unix named sockets.
819 	 *	2. UDP sockets.
820 	 *	3. MIDI pipe.
821 	 */
822 	if (!global.libtest)
823 		if ((synth->sid = initConnection(&global, synth)) < 0)
824 			return(-1);
825 
826 	for (i = 0; i < DEVICE_COUNT; i++)
827 		synth->dispatch[i].routine = explorerMidiSendMsg;
828 
829 	/* tune/glide */
830 	dispatch[0].controller = 8;
831 	dispatch[0].operator = 0;
832 	dispatch[1].controller = 8;
833 	dispatch[1].operator = 1;
834 	dispatch[2].controller = 10;
835 	dispatch[2].operator = 0;
836 	dispatch[3].routine = (synthRoutine) explorerGlide;
837 
838 	/* Bus mods */
839 	dispatch[4].controller = 15;
840 	dispatch[4].operator = 0;
841 	dispatch[5].controller = 15;
842 	dispatch[5].operator = 1;
843 	dispatch[6].controller = 15;
844 	dispatch[6].operator = 2;
845 	dispatch[7].controller = 15;
846 	dispatch[7].operator = 3;
847 	dispatch[8].controller = 16;
848 	dispatch[8].operator = 0;
849 	dispatch[9].controller = 16;
850 	dispatch[9].operator = 1;
851 	dispatch[10].controller = 16;
852 	dispatch[10].operator = 2;
853 	dispatch[11].controller = 16;
854 	dispatch[11].operator = 3;
855 
856 	/* Oscillators */
857 	dispatch[12].controller = 0;
858 	dispatch[12].operator = 1;
859 	dispatch[13].controller = 0;
860 	dispatch[13].operator = 0;
861 	dispatch[14].controller = 1;
862 	dispatch[14].operator = 2;
863 	dispatch[15].controller = 1;
864 	dispatch[15].operator = 1;
865 	dispatch[16].controller = 1;
866 	dispatch[16].operator = 0;
867 	dispatch[17].controller = 2;
868 	dispatch[17].operator = 2;
869 	dispatch[18].controller = 2;
870 	dispatch[18].operator = 1;
871 	dispatch[19].controller = 2;
872 	dispatch[19].operator = 0;
873 	/* Osc options */
874 	dispatch[20].controller = 12;
875 	dispatch[20].operator = 9;
876 	dispatch[21].controller = 12;
877 	dispatch[21].operator = 10;
878 	dispatch[22].controller = 12;
879 	dispatch[22].operator = 0;
880 	dispatch[23].controller = 12;
881 	dispatch[23].operator = 8;
882 
883 	/* MIXER */
884 	dispatch[24].controller = 14;
885 	dispatch[24].operator = 0;
886 	dispatch[25].controller = 0;
887 	dispatch[25].operator = 3;
888 	dispatch[26].controller = 1;
889 	dispatch[26].operator = 3;
890 	dispatch[27].controller = 2;
891 	dispatch[27].operator = 3;
892 	dispatch[28].controller = 12;
893 	dispatch[28].operator = 13;
894 
895 	/* mixer flags */
896 	dispatch[29].controller = 12;
897 	dispatch[29].operator = 5;
898 	dispatch[30].controller = 12;
899 	dispatch[30].operator = 2;
900 	dispatch[31].controller = 12;
901 	dispatch[31].operator = 3;
902 	dispatch[32].controller = 12;
903 	dispatch[32].operator = 4;
904 	dispatch[33].controller = 12;
905 	dispatch[33].operator = 6;
906 
907 	/* Filter */
908 	dispatch[34].controller = 4;
909 	dispatch[34].operator = 0;
910 	dispatch[35].controller = 12;
911 	dispatch[35].operator = 12;
912 	dispatch[36].controller = 4;
913 	dispatch[36].operator = 1;
914 	dispatch[37].controller = 4;
915 	dispatch[37].operator = 3;
916 
917 	/* Filter spacing is now in the emulater, not the filter. We also need a */
918 	/* filter param dispatcher to configure the two filters together. */
919 	/* Dispatcher */
920 	dispatch[34].routine =
921 		dispatch[35].routine =
922 		dispatch[36].routine =
923 		dispatch[37].routine = (synthRoutine) explorerFilter;
924 
925 	dispatch[38].controller = 12;
926 	dispatch[38].operator = 12;
927 	dispatch[38].routine = (synthRoutine) explorerFilterMode;
928 
929 	/* Filter ADSR */
930 	dispatch[39].controller = 3;
931 	dispatch[39].operator = 0;
932 	dispatch[40].controller = 3;
933 	dispatch[40].operator = 1;
934 	dispatch[41].controller = 3;
935 	dispatch[41].operator = 2;
936 	dispatch[42].controller = 3;
937 	dispatch[42].operator = 3;
938 	dispatch[42].routine = (synthRoutine) explorerRelease;
939 
940 	/* velocity from filter control */
941 	dispatch[43].controller = 12;
942 	dispatch[43].operator = 11;
943 
944 	/* Amp ADSR */
945 	dispatch[44].controller = 5;
946 	dispatch[44].operator = 0;
947 	dispatch[45].controller = 5;
948 	dispatch[45].operator = 1;
949 	dispatch[46].controller = 5;
950 	dispatch[46].operator = 2;
951 	dispatch[47].controller = 5;
952 	dispatch[47].operator = 3;
953 	dispatch[47].routine = (synthRoutine) explorerRelease;
954 	dispatch[48].controller = 5;
955 	dispatch[48].operator = 5;
956 
957 	/* volume, on/off */
958 	dispatch[49].controller = 5;
959 	dispatch[49].operator = 4;
960 	dispatch[50].controller = 12;
961 	dispatch[50].operator = 1;
962 	dispatch[51].controller = 12;
963 	dispatch[51].operator = 7;
964 	dispatch[52].routine = (synthRoutine) explorerGlide;
965 	dispatch[53].controller = 6;
966 	dispatch[53].routine = (synthRoutine) explorerRelease;
967 
968 	/* Touch panel */
969 	dispatch[54].controller = 8;
970 	dispatch[54].operator = 0;
971 	dispatch[55].controller = 4;
972 	dispatch[55].operator = 0;
973 
974 	/* memory */
975 	dispatch[MEM_START].operator = 0;
976 	dispatch[MEM_START].controller = MEM_START;
977 	dispatch[MEM_START + 1].operator = 1;
978 	dispatch[MEM_START + 1].controller = MEM_START + 1;
979 	dispatch[MEM_START + 2].operator = 2;
980 	dispatch[MEM_START + 2].controller = MEM_START + 2;
981 	dispatch[MEM_START + 3].operator = 3;
982 	dispatch[MEM_START + 3].controller = MEM_START + 3;
983 	dispatch[MEM_START + 4].operator = 4;
984 	dispatch[MEM_START + 4].controller = MEM_START + 4;
985 	dispatch[MEM_START + 5].operator = 5;
986 	dispatch[MEM_START + 5].controller = MEM_START + 5;
987 	dispatch[MEM_START + 6].operator = 6;
988 	dispatch[MEM_START + 6].controller = MEM_START + 6;
989 	dispatch[MEM_START + 7].operator = 7;
990 	dispatch[MEM_START + 7].controller = MEM_START + 7;
991 	dispatch[MEM_START + 8].operator = 8;
992 	dispatch[MEM_START + 8].controller = MEM_START + 8;
993 	dispatch[MEM_START + 9].operator = 9;
994 	dispatch[MEM_START + 9].controller = MEM_START + 9;
995 
996 	dispatch[MEM_START + 10].controller = 1;
997 	dispatch[MEM_START + 11].controller = 2;
998 	dispatch[MEM_START + 16].controller = 3;
999 	dispatch[MEM_START + 17].controller = 4;
1000 
1001 	dispatch[MEM_START + 0].routine = dispatch[MEM_START + 1].routine =
1002 	dispatch[MEM_START + 2].routine = dispatch[MEM_START + 3].routine =
1003 	dispatch[MEM_START + 4].routine = dispatch[MEM_START + 5].routine =
1004 	dispatch[MEM_START + 6].routine = dispatch[MEM_START + 7].routine =
1005 	dispatch[MEM_START + 8].routine = dispatch[MEM_START + 9].routine =
1006 	dispatch[MEM_START + 10].routine = dispatch[MEM_START + 11].routine =
1007 	dispatch[MEM_START + 16].routine = dispatch[MEM_START + 17].routine =
1008 		(synthRoutine) explorerMemory;
1009 
1010 	/* midi */
1011 	dispatch[MEM_START + 12].controller = 2;
1012 	dispatch[MEM_START + 13].controller = 1;
1013 	dispatch[MEM_START + 12].routine = dispatch[MEM_START + 13].routine =
1014 		(synthRoutine) explorerMidi;
1015 
1016 	/* midi/panel selectors */
1017 	dispatch[MEM_START + 14].controller = MEM_START + 14;
1018 	dispatch[MEM_START + 15].controller = MEM_START + 15;
1019 	dispatch[MEM_START + 14].routine = dispatch[MEM_START + 15].routine =
1020 		(synthRoutine) explorerPanelSelect;
1021 
1022 	/* No velocity on filter contour, fixed gain */
1023 	bristolMidiSendMsg(global.controlfd, synth->sid, 7, 0, 16000);
1024 	bristolMidiSendMsg(global.controlfd, synth->sid, 3, 5, 0);
1025 	bristolMidiSendMsg(global.controlfd, synth->sid, 3, 4, 16383);
1026 
1027 	return(0);
1028 }
1029 
1030 /*
1031  * This will be called to make any routine specific parameters available.
1032  */
1033 int
explorerConfigure(brightonWindow * win)1034 explorerConfigure(brightonWindow *win)
1035 {
1036 	guiSynth *synth = findSynth(global.synths, win);
1037 	brightonEvent event;
1038 
1039 	if (synth == 0)
1040 	{
1041 		printf("problems going operational\n");
1042 		return(-1);
1043 	}
1044 
1045 	if (synth->flags & OPERATIONAL)
1046 		return(0);
1047 
1048 	printf("going operational\n");
1049 
1050 	synth->flags |= OPERATIONAL;
1051 	synth->keypanel = 1;
1052 	synth->keypanel2 = -1;
1053 	synth->transpose = 36;
1054 
1055 	displayText(synth, "CHAN", synth->midichannel + 1, DISPLAY1);
1056 
1057 	loadMemory(synth, "explorer", 0, synth->location, synth->mem.active,
1058 		FIRST_DEV, 0);
1059 	displayText(synth, "PRG", synth->location, DISPLAY2);
1060 
1061 	brightonPut(win,
1062 		"bitmaps/blueprints/explorershade.xpm", 0, 0, win->width, win->height);
1063 
1064 	/*
1065 	 * Hm. This is a hack for a few bits of bad rendering of a keyboard. Only
1066 	 * occurs on first paint, so we suppress the first paint, and then request
1067 	 * an expose here.
1068 	 */
1069 	event.type = BRIGHTON_EXPOSE;
1070 	event.intvalue = 1;
1071 	brightonParamChange(synth->win, KEY_PANEL, -1, &event);
1072 	configureGlobals(synth);
1073 
1074 	return(0);
1075 }
1076 
1077