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 
28 static int initmem;
29 
30 static int obxInit();
31 static int obxConfigure();
32 static int obxCallback(brightonWindow *, int, int, float);
33 /*static int keyCallback(void *, int, int, float); */
34 static int obxModCallback(brightonWindow *, int, int, float);
35 static int obxMidiCallback(brightonWindow *, int, int, float);
36 
37 extern guimain global;
38 
39 #include "brightonKeys.h"
40 #include "brightoninternals.h"
41 
42 #define FIRST_DEV 0
43 #define DEVICE_COUNT 65
44 #define ACTIVE_DEVS 43
45 #define OBX_DEVS 46 /* Have to account for the manual options. */
46 #define MEM_START (OBX_DEVS - 1)
47 #define RADIOSET_1 MEM_START
48 #define RADIOSET_2 (MEM_START + 1)
49 #define RADIOSET_3 (MEM_START + 2)
50 #define DISPLAY_DEV (DEVICE_COUNT - 1)
51 
52 #define KEY_PANEL 1
53 
54 /*
55  * This structure is for device definition. The structure is defined in
56  * include/brighton.h, further definitions in brighton/brightonDevtable.h and
57  * include/brightoninternals.h
58  *
59  *	typedef int (*brightonCallback)(int, float);
60  *	typedef struct BrightonLocations {
61  *		int device; 0=rotary, 1=scale, etc.
62  *		float relx, rely; relative position with regards to 1000 by 1000 window
63  *		float relw, relh; relative height.
64  *		int from, to;
65  *		brightonCallback callback; specific to this dev
66  *		char *image; bitmap. If zero take a device default.
67  *		int flags;
68  *	} brightonLocations;
69  *
70  * This example is for a obxBristol type synth interface.
71  */
72 #define S1 110
73 #define S2 17
74 #define S3 70
75 
76 #define BO 10
77 #define B2 6
78 
79 #define R1 200
80 #define R2 430
81 #define R3 600
82 #define R3b 600
83 #define R4 780
84 
85 #define C1 50
86 #define C2 66
87 #define C3 100
88 
89 #define C4 175
90 
91 #define C5 242
92 #define C6 300
93 #define C7 354
94 
95 #define C8 415
96 #define C9 475
97 #define C10 535
98 
99 #define C11 590
100 #define C12 650
101 #define C13 710
102 
103 #define C11b 750
104 #define C12b 800
105 #define C13b 850
106 
107 #define C14 775
108 #define C15 825
109 #define C16 875
110 #define C17 925
111 
112 /* memories */
113 #define MD 23
114 #define C20 (C8 + MD + MD/2)
115 #define C21 (C20 + MD)
116 #define C22 (C21 + MD)
117 #define C23 (C22 + MD)
118 #define C24 (C23 + MD)
119 #define C25 (C24 + MD)
120 #define C26 (C25 + MD)
121 #define C27 (C26 + MD)
122 
123 #define C28 (C27 + MD + MD/2)
124 #define C29 (C28 + MD)
125 #define C30 (C29 + MD)
126 #define C31 (C30 + MD)
127 #define C32 (C31 + MD)
128 #define C33 (C32 + MD)
129 #define C34 (C33 + MD)
130 #define C35 (C34 + MD)
131 
132 #define C36 (C35 + MD + MD/2)
133 
134 static brightonLocations locations[DEVICE_COUNT] = {
135 /* 0 - control */
136 	{"Glide", 0, C4, R1, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
137 		"bitmaps/knobs/alpharotary.xpm", 0},
138 	{"Unison", 2, C4 + B2, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
139 		"bitmaps/buttons/presson.xpm", 0},
140 	{"Osc2-Detune", 0, C4, R3b, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
141 		"bitmaps/knobs/alpharotary.xpm", 0},
142 /* 3 - mods */
143 	{"LFO-Freq", 0, C5, R1, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
144 		"bitmaps/knobs/alpharotary.xpm", 0},
145 	{"LFO-Sine", 2, C5 + B2, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
146 		"bitmaps/buttons/presson.xpm", 0},
147 	{"LFO-Square", 2, C5 + B2, R3, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
148 		"bitmaps/buttons/presson.xpm", 0},
149 	{"LFO-S/H", 2, C5 + B2, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
150 		"bitmaps/buttons/presson.xpm", 0},
151 
152 	{"LFO-FM-Depth", 0, C6, R1, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
153 		"bitmaps/knobs/alpharotary.xpm", 0},
154 	{"LFO-FM-Osc1", 2, C6 + B2, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
155 		"bitmaps/buttons/presson.xpm", 0},
156 	{"LFO-FM-Osc2", 2, C6 + B2, R3, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
157 		"bitmaps/buttons/presson.xpm", 0},
158 	{"LFO-FM-Filt", 2, C6 + B2, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
159 		"bitmaps/buttons/presson.xpm", 0},
160 
161 	{"LFO-PWM-Depth", 0, C7, R1, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
162 		"bitmaps/knobs/alpharotary.xpm", 0},
163 	{"LFO-PWM-Osc1", 2, C7 + B2, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
164 		"bitmaps/buttons/presson.xpm", 0},
165 	{"LFO-PWM-Osc2", 2, C7 + B2, R3, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
166 		"bitmaps/buttons/presson.xpm", 0},
167 /* 14 - oscillators: */
168 	{"Osc1-Transpose", 0, C8, R1, S1, S1, 0, 5, 0, "bitmaps/knobs/knob5.xpm",
169 		"bitmaps/knobs/alpharotary.xpm", 0},
170 	{"Osc-PW", 0, C9, R1, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
171 		"bitmaps/knobs/alpharotary.xpm", 0},
172 	{"Osc2-Tune", 0, C10, R1, S1, S1, 0, 47, 0, "bitmaps/knobs/knob5.xpm",
173 		"bitmaps/knobs/alpharotary.xpm", 0},
174 	{"Osc1-Saw", 2, C8 - 8, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
175 		"bitmaps/buttons/presson.xpm", 0},
176 	{"Osc1-PW-CLI!", 2, C8 + 17, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
177 		"bitmaps/buttons/presson.xpm", 0},
178 	{"Osc-CrossMod", 2, C9 - 8, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
179 		"bitmaps/buttons/presson.xpm", 0},
180 	{"Osc-Sync", 2, C9 + 17, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
181 		"bitmaps/buttons/presson.xpm", 0},
182 	{"Osc1-Saw", 2, C10 - 8, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
183 		"bitmaps/buttons/presson.xpm", 0},
184 	{"Osc1-Pulse", 2, C10 + 17, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
185 		"bitmaps/buttons/presson.xpm", 0},
186 /* 23 - filter */
187 	{"VCF-Cutoff", 0, C11, R1, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
188 		"bitmaps/knobs/alpharotary.xpm", 0},
189 	{"VCF-Resonance", 0, C12, R1, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
190 		"bitmaps/knobs/alpharotary.xpm", 0},
191 	{"VCF-ModLevel", 0, C13, R1, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
192 		"bitmaps/knobs/alpharotary.xpm", 0},
193 	{"MixOsc1", 2, C11 - 8, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
194 		"bitmaps/buttons/presson.xpm", 0},
195 	{"VCF-KBD", 2, C11 + 17, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
196 		"bitmaps/buttons/presson.xpm", 0},
197 	{"MixOsc2-Half", 2, C12 - 8, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
198 		"bitmaps/buttons/presson.xpm", 0},
199 	{"MixOsc2-Full", 2, C12 + 17, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
200 		"bitmaps/buttons/presson.xpm", 0},
201 	{"MixNoise-Half", 2, C13 - 8, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
202 		"bitmaps/buttons/presson.xpm", 0},
203 	{"MixNoise-Full", 2, C13 + 17, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
204 		"bitmaps/buttons/presson.xpm", 0},
205 /* 32 - envelope */
206 	{"VCF-Attack", 0, C14, R1, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
207 		"bitmaps/knobs/alpharotary.xpm", 0},
208 	{"VCF-Decay", 0, C15, R1, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
209 		"bitmaps/knobs/alpharotary.xpm", 0},
210 	{"VCF-Sustain", 0, C16, R1, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
211 		"bitmaps/knobs/alpharotary.xpm", 0},
212 	{"VCF-Release", 0, C17, R1, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
213 		"bitmaps/knobs/alpharotary.xpm", 0},
214 
215 	{"VCA-Attack", 0, C14, R2, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
216 		"bitmaps/knobs/alpharotary.xpm", 0},
217 	{"VCA-Decay", 0, C15, R2, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
218 		"bitmaps/knobs/alpharotary.xpm", 0},
219 	{"VCA-Sustain", 0, C16, R2, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
220 		"bitmaps/knobs/alpharotary.xpm", 0},
221 	{"VCA-Release", 0, C17, R2, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
222 		"bitmaps/knobs/alpharotary.xpm", 0},
223 
224 	/* According to the original, these are not saved. Volume will be, and */
225 	/* reset should be.. */
226 	{"MasterVolume", 0, C2 + BO, R1, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
227 		"bitmaps/knobs/alpharotary.xpm", 0},
228 	{"Reset", 2, C3 + BO, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
229 		"bitmaps/buttons/presson.xpm", 0},
230 /* Total 42 parameters. */
231 	{"Auto", 2, C1, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
232 		"bitmaps/buttons/presson.xpm", BRIGHTON_CHECKBUTTON},
233 	{"", 2, C2 + BO * 3/2, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
234 		"bitmaps/buttons/presson.xpm", 0},
235 /*	{"", 2, C3 + BO, R2, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm", */
236 /*		"bitmaps/buttons/presson.xpm", 0}, */
237 	{"", 0, C2 + BO, R3b, S1, S1, 0, 1, 0, "bitmaps/knobs/knob5.xpm",
238 		"bitmaps/knobs/alpharotary.xpm", BRIGHTON_NOTCH},
239 /*46 */
240 	/* Programmer */
241 	{"", 2, C8, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
242 		"bitmaps/buttons/presson.xpm", BRIGHTON_CHECKBUTTON},
243 
244 	{"", 2, C20, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
245 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
246 	{"", 2, C21, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
247 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
248 	{"", 2, C22, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
249 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
250 	{"", 2, C23, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
251 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
252 	{"", 2, C24, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
253 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
254 	{"", 2, C25, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
255 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
256 	{"", 2, C26, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
257 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
258 	{"", 2, C27, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
259 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
260 	{"", 2, C28, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
261 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
262 	{"", 2, C29, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
263 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
264 	{"", 2, C30, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
265 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
266 	{"", 2, C31, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
267 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
268 	{"", 2, C32, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
269 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
270 	{"", 2, C33, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
271 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
272 	{"", 2, C34, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
273 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
274 	{"", 2, C35, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
275 		"bitmaps/buttons/presson.xpm", BRIGHTON_RADIOBUTTON},
276 
277 	{"", 2, C36, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
278 		"bitmaps/buttons/presson.xpm", BRIGHTON_CHECKBUTTON},
279 
280 	{"", 2, C17 - 10, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
281 		"bitmaps/buttons/presson.xpm", BRIGHTON_CHECKBUTTON},
282 	{"", 2, C17 + MD, R4, S2, S3, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
283 		"bitmaps/buttons/presson.xpm", BRIGHTON_CHECKBUTTON},
284 };
285 
286 #define OBX_MODCOUNT 5
287 static brightonLocations obxMods[OBX_MODCOUNT] = {
288 	{"", 1, 385, 200, 100, 468, 0, 1, 0,
289 		"bitmaps/knobs/sliderblack.xpm", 0, BRIGHTON_CENTER},
290 	{"", 1, 520, 200, 100, 468, 0, 1, 0,
291 		"bitmaps/knobs/sliderblack.xpm", 0, 0},
292 
293 	{"", 2, 180, 800, 130, 140, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
294 		"bitmaps/buttons/presson.xpm", 0},
295 	{"", 2, 450, 800, 130, 140, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
296 		"bitmaps/buttons/presson.xpm", 0},
297 	{"", 2, 690, 800, 130, 140, 0, 1, 0, "bitmaps/buttons/pressoff.xpm",
298 		"bitmaps/buttons/presson.xpm", 0}
299 };
300 
301 /*
302  * This is a set of globals for the main window rendering. Again taken from
303  * include/brighton.h
304  */
305 brightonApp obxApp = {
306 	"obx",
307 	0, /* no blueprint on wood background. */
308 	"bitmaps/textures/metal6.xpm",
309 	BRIGHTON_STRETCH, /*flags */
310 	obxInit,
311 	obxConfigure, /* 3 callbacks, unused? */
312 	obxMidiCallback,
313 	destroySynth,
314 	{5, 100, 2, 2, 5, 520, 0, 0},
315 	770, 350, 0, 0,
316 	6, /* Panel count */
317 	{
318 		{
319 			"OBX",
320 			"bitmaps/blueprints/obx.xpm",
321 			"bitmaps/textures/metal6.xpm",
322 			BRIGHTON_STRETCH|BRIGHTON_REVERSE, /* flags */
323 			0,
324 			0,
325 			obxCallback,
326 			14, 130, 970, 520,
327 			DEVICE_COUNT,
328 			locations
329 		},
330 		{
331 			"Keyboard",
332 			0,
333 			"bitmaps/newkeys/kbg.xpm", /* flags */
334 			0x020|BRIGHTON_STRETCH,
335 			0,
336 			0,
337 			keyCallback,
338 			155, 690, 854, 290,
339 			KEY_COUNT,
340 			keys
341 		},
342 		{
343 			"Mods",
344 			"bitmaps/blueprints/obxmod.xpm",
345 			"bitmaps/textures/metal5.xpm", /* flags */
346 			0,
347 			0,
348 			0,
349 			obxModCallback, /* Needs to be obxModCallback */
350 			17, 690, 136, 290,
351 			OBX_MODCOUNT,
352 			obxMods
353 		},
354 		{
355 			"Logo",
356 			"bitmaps/blueprints/obxlogo.xpm",
357 			0,
358 			BRIGHTON_STRETCH, /*flags */
359 			0,
360 			0,
361 			0,
362 			15, 0, 970, 130,
363 			0,
364 			0
365 		},
366 		{
367 			"Edge",
368 			0,
369 			"bitmaps/images/rhodes.xpm",
370 			BRIGHTON_STRETCH|BRIGHTON_VERTICAL, /* flags */
371 			0,
372 			0,
373 			0,
374 			0, 0, 15, 1000,
375 			0,
376 			0
377 		},
378 		{
379 			"Edge",
380 			0,
381 			"bitmaps/images/rhodes.xpm",
382 			BRIGHTON_STRETCH|BRIGHTON_VERTICAL, /*flags */
383 			0,
384 			0,
385 			0,
386 			985, 0, 15, 1000,
387 			0,
388 			0
389 		},
390 	}
391 };
392 
393 static int
obxKeyLoadMemory(guiSynth * synth,char * algo,char * name,int location,int active,int skip,int flags)394 obxKeyLoadMemory(guiSynth *synth, char *algo, char *name, int location,
395 	int active, int skip, int flags)
396 {
397 	brightonEvent event;
398 
399 	synth->flags |= MEM_LOADING;
400 
401 	loadMemory(synth, "obx", 0, location, synth->mem.active, FIRST_DEV, 0);
402 
403 	/*
404 	 * We now need to force the PW of the two oscillators?
405 	 */
406 	bristolMidiSendMsg(synth->sid, synth->midichannel,
407 		0, 0, (int) synth->mem.param[15]);
408 	bristolMidiSendMsg(synth->sid, synth->midichannel,
409 		1, 0, (int) synth->mem.param[ACTIVE_DEVS-1]);
410 
411 	event.value = 0;
412 	brightonParamChange(synth->win, 0, ACTIVE_DEVS-1, &event);
413 
414 	synth->flags &= ~MEM_LOADING;
415 	return(0);
416 }
417 
418 static void
obxLoadMemory(guiSynth * synth,int fd,int chan,int c,int o,int v)419 obxLoadMemory(guiSynth *synth, int fd, int chan, int c, int o, int v)
420 {
421 	brightonEvent event;
422 
423 	synth->flags |= MEM_LOADING;
424 
425 	loadMemory(synth, "obx", 0, synth->bank * 10 + synth->location,
426 		synth->mem.active, FIRST_DEV, 0);
427 
428 	/*
429 	 * We now need to force the PW of the two oscillators?
430 	 */
431 	bristolMidiSendMsg(fd, chan, 0, 0, (int) synth->mem.param[15]);
432 	bristolMidiSendMsg(fd, chan, 1, 0, (int) synth->mem.param[ACTIVE_DEVS-1]);
433 
434 	event.value = 0;
435 	brightonParamChange(synth->win, 0, ACTIVE_DEVS-1, &event);
436 
437 	synth->flags &= ~MEM_LOADING;
438 }
439 
440 static int
obxMidiCallback(brightonWindow * win,int controller,int value,float n)441 obxMidiCallback(brightonWindow *win, int controller, int value, float n)
442 {
443 	guiSynth *synth = findSynth(global.synths, win);
444 
445 	printf("midi callback: %x, %i\n", controller, value);
446 
447 	switch(controller)
448 	{
449 		case MIDI_PROGRAM:
450 			printf("midi program: %x, %i\n", controller, value);
451 			synth->location = value;
452 /*			loadMemory(synth, "obx", 0, synth->bank + synth->location, */
453 /*				synth->mem.active, FIRST_DEV, 0); */
454 			obxLoadMemory(synth, global.controlfd, synth->midichannel, 0, 0, 0);
455 			break;
456 		case MIDI_BANK_SELECT:
457 			printf("midi banksel: %x, %i\n", controller, value);
458 			synth->bank = value;
459 			break;
460 	}
461 	return(0);
462 }
463 
464 static int narrow = 0;
465 static int osc2 = 0;
466 
467 static int
obxModCallback(brightonWindow * win,int panel,int index,float value)468 obxModCallback(brightonWindow *win, int panel, int index, float value)
469 {
470 	guiSynth *synth = findSynth(global.synths, win);
471 	int sendvalue;
472 
473 /* printf("obxModCallback(%x, %i, %i, %f)\n", synth, panel, index, value); */
474 
475 	/*
476 	 * If this is controller 0 it is the frequency control, otherwise a
477 	 * generic controller 1.
478 	 */
479 	switch (index) {
480 		case 0:
481 			if (narrow != 0)
482 				sendvalue = C_RANGE_MIN_1 / 2 +
483 					(int) (((value - 0.5) / 3) * C_RANGE_MIN_1);
484 			else
485 				sendvalue = (int) ((value * C_RANGE_MIN_1));
486 			if (osc2 == 0)
487 				bristolMidiSendMsg(global.controlfd, synth->sid, 0, 11,
488 					sendvalue);
489 			bristolMidiSendMsg(global.controlfd, synth->sid, 1, 11, sendvalue);
490 			break;
491 		case 1:
492 			/*
493 			 * Not sure why this should work, and it probably doesn't. It is
494 			 * the 'mod' controller but appears to affect Osc-1 tranpose
495 			 */
496 			if (narrow != 0)
497 				/*sendvalue = (int) ((value * C_RANGE_MIN_1)) >> 3; */
498 				sendvalue = C_RANGE_MIN_1 / 2 +
499 					(int) (((value - 0.5) / 3) * C_RANGE_MIN_1);
500 			else
501 				sendvalue = (int) ((value * C_RANGE_MIN_1));
502 			bristolMidiSendMsg(global.controlfd, synth->midichannel,
503 				2, 0, sendvalue);
504 			break;
505 		case 2: /* Narrow */
506 			if (value != 0.0)
507 				narrow = 4;
508 			else
509 				narrow = 0;
510 			break;
511 		case 3: /* Osc2 */
512 			/*
513 			 * This switch is a bit of a pain, it controls whether Osc-2 is
514 			 * affected by the pitchbend. This means we have to use another
515 			 * modulation method for case 0 above since the existing method
516 			 * is global. This is painful as it means we need another param
517 			 * on the prophetdco.....
518 			 * May remap the button for single/multi LFO?
519 			bristolMidiSendMsg(global.controlfd, synth->sid,
520 				126, 22, (int) value);
521 			 */
522 			osc2 = value;
523 			break;
524 		case 4: /* Transpose */
525 			if (value != 0.0)
526 				synth->transpose = 48;
527 			else
528 				synth->transpose = 36;
529 			break;
530 	}
531 	return(0);
532 }
533 
534 #define KEY_HOLD (FIRST_DEV + 43)
535 
536 static void
obxHold(guiSynth * synth)537 obxHold(guiSynth *synth)
538 {
539 	if ((synth->flags & OPERATIONAL) == 0)
540 		return;
541 
542 	/*printf("obxHold %x\n", synth); */
543 
544 	if (synth->mem.param[KEY_HOLD])
545 		bristolMidiSendMsg(global.controlfd, synth->sid,
546 			127, 0, BRISTOL_HOLD|1);
547 	else
548 		bristolMidiSendMsg(global.controlfd, synth->sid,
549 			127, 0, BRISTOL_HOLD|0);
550 }
551 
552 static int dreset = 0;
553 static int d1 = 0;
554 static int d2 = 0;
555 
556 /*
557  * If controller #41 has value zero then we configure the release rates, else
558  * we use the shortest release rate.
559  */
560 static void
obxDecay(void * synth,int fd,int chan,int c,int o,int v)561 obxDecay(void *synth, int fd, int chan, int c, int o, int v)
562 {
563 	if (c == 41)
564 	{
565 		if (v == 0)
566 		{
567 			/*
568 			 * Set values to their current settings
569 			 */
570 			dreset = 0;
571 			bristolMidiSendMsg(fd, chan, 3, 3, d1);
572 			bristolMidiSendMsg(fd, chan, 5, 3, d2);
573 		} else {
574 			/*
575 			 * Set values to minimum release time
576 			 */
577 			dreset = 1;
578 			bristolMidiSendMsg(fd, chan, 3, 3, 20);
579 			bristolMidiSendMsg(fd, chan, 5, 3, 20);
580 		}
581 	} else {
582 		if (dreset == 0)
583 			bristolMidiSendMsg(fd, chan, c, o, v);
584 
585 		if (c == 3)
586 			d1 = v;
587 		else
588 			d2 = v;
589 	}
590 }
591 
592 static int pwSelect = 0;
593 /*
594  * We need to see if for any given oscillator none of the wave buttons are
595  * selected. If this is the case then select triangle. Else disable tri and
596  * configure the selected values.
597  */
598 static void
obxWaveform(guiSynth * synth,int fd,int chan,int c,int o,int v)599 obxWaveform(guiSynth *synth, int fd, int chan, int c, int o, int v)
600 {
601 	/*
602 	 * See if this is the PW parameter.
603 	 */
604 	if (c == 15)
605 	{
606 		if (synth->flags & MEM_LOADING)
607 			return;
608 		synth->mem.param[15] = v;
609 		if (pwSelect == 0) {
610 			bristolMidiSendMsg(fd, chan, 0, 0, v);
611 		} else {
612 			synth->mem.param[ACTIVE_DEVS - 1] = v;
613 			bristolMidiSendMsg(fd, chan, 1, 0, v);
614 		}
615 		return;
616 	}
617 
618 	/*
619 	 * See if we need to set PW selector
620 	 */
621 	if (o == 6)
622 	{
623 		/*
624 		 * If the sqr is being selected, then PW will modify this oscillator,
625 		 * and if going off then it will cotrol the other
626 		 */
627 		if (v != 0)
628 			pwSelect = c;
629 		else
630 			pwSelect = 1 - c;
631 	}
632 
633 	/*
634 	 * If the value is '1' we can just set the desired wave and disable tri.
635 	 */
636 	if (v != 0)
637 	{
638 		bristolMidiSendMsg(fd, chan, c, o, v);
639 		bristolMidiSendMsg(fd, chan, c, 5, 0);
640 	} else {
641 		bristolMidiSendMsg(fd, chan, c, o, v);
642 		if (c == 0)
643 		{
644 			if ((synth->mem.param[17] == 0) &&
645 				(synth->mem.param[18] == 0))
646 				bristolMidiSendMsg(fd, chan, c, 5, 1);
647 		} else {
648 			if ((synth->mem.param[21] == 0) &&
649 				(synth->mem.param[22] == 0))
650 				bristolMidiSendMsg(fd, chan, c, 5, 1);
651 		}
652 	}
653 }
654 
655 static int
obxMidiSendMsg(void * synth,int fd,int chan,int c,int o,int v)656 obxMidiSendMsg(void *synth, int fd, int chan, int c, int o, int v)
657 {
658 	bristolMidiSendMsg(fd, chan, c, o, v);
659 	return(0);
660 }
661 
662 static void
multiTune(guiSynth * synth,int fd,int chan,int c,int o,int v)663 multiTune(guiSynth *synth, int fd, int chan, int c, int o, int v)
664 {
665 	brightonEvent event;
666 
667 	if (synth->flags & MEM_LOADING)
668 		return;
669 
670 	/*
671 	 * Configures all the tune settings to zero (ie, 0.5).
672 	 * We have master tune, id 44 and Osc-2 detune, id 2.
673 	 */
674 	event.type = BRIGHTON_FLOAT;
675 	event.value = 0.5;
676 	brightonParamChange(synth->win, synth->panel, FIRST_DEV + 2,
677 		&event);
678 	brightonParamChange(synth->win, synth->panel, FIRST_DEV + 44,
679 		&event);
680 }
681 
682 /*
683  * The OB-X does not have a lot of memories, just 8 banks of 8 memories. This
684  * is a bit sparse for the emulater but it keeps the interface easy. Will be
685  * two sets of buttons, one for the bank, one for the index, then load and
686  * save. Load and Save will be intermittent and the banks radio buttons.
687  */
688 static void
obxMemory(guiSynth * synth,int fd,int chan,int c,int o,int v)689 obxMemory(guiSynth *synth, int fd, int chan, int c, int o, int v)
690 {
691 	brightonEvent event;
692 
693 /*printf("obxMemory(%i, %i, %i, %i)\n", chan, c, o, v); */
694 
695 	switch (c) {
696 		case 16:
697 			/* Load */
698 			/*
699 			synth->flags |= MEM_LOADING;
700 			loadMemory(synth, "obx", 0, synth->bank * 10 + synth->location,
701 				synth->mem.active, FIRST_DEV, 0);
702 			 * We now need to force the PW of the two oscillators?
703 			bristolMidiSendMsg(fd, chan, 0, 0,
704 				(int) synth->mem.param[15]);
705 			bristolMidiSendMsg(fd, chan, 1, 0,
706 				(int) synth->mem.param[ACTIVE_DEVS-1]);
707 
708 			event.value = 0;
709 			brightonParamChange(synth->win, 0, ACTIVE_DEVS-1, &event);
710 
711 			synth->flags &= ~MEM_LOADING;
712 			 */
713 			obxLoadMemory(synth, fd, chan, c, o, v);
714 			break;
715 		case 17:
716 			/* Save */
717 			saveMemory(synth, "obx", 0, synth->bank * 10 + synth->location, 0);
718 			break;
719 		case 0:
720 		case 1:
721 		case 2:
722 		case 3:
723 		case 4:
724 		case 5:
725 		case 6:
726 		case 7:
727 			if (synth->dispatch[RADIOSET_1].other2)
728 			{
729 				synth->dispatch[RADIOSET_1].other2 = 0;
730 				return;
731 			}
732 
733 			if (synth->dispatch[RADIOSET_1].other1 != -1)
734 			{
735 				synth->dispatch[RADIOSET_1].other2 = 1;
736 
737 				if (synth->dispatch[RADIOSET_1].other1 != o)
738 					event.value = 0;
739 				else
740 					event.value = 1;
741 
742 				brightonParamChange(synth->win, synth->panel,
743 					synth->dispatch[RADIOSET_1].other1, &event);
744 			}
745 			synth->dispatch[RADIOSET_1].other1 = o;
746 
747 			synth->bank = c + 1;
748 
749 			break;
750 		case 8:
751 		case 9:
752 		case 10:
753 		case 11:
754 		case 12:
755 		case 13:
756 		case 14:
757 		case 15:
758 			if (synth->dispatch[RADIOSET_2].other2)
759 			{
760 				synth->dispatch[RADIOSET_2].other2 = 0;
761 				return;
762 			}
763 
764 			if (synth->dispatch[RADIOSET_2].other1 != -1)
765 			{
766 				synth->dispatch[RADIOSET_2].other2 = 1;
767 
768 				if (synth->dispatch[RADIOSET_2].other1 != o)
769 					event.value = 0;
770 				else
771 					event.value = 1;
772 
773 				brightonParamChange(synth->win, synth->panel,
774 					synth->dispatch[RADIOSET_2].other1, &event);
775 			}
776 			synth->dispatch[RADIOSET_2].other1 = o;
777 
778 			synth->location = c - 7;
779 
780 			break;
781 	}
782 
783 /*printf("	obxMemory(B: %i, L: %i, %i, %i)\n", */
784 /*synth->bank, synth->location, synth->bank * 8 + synth->location, o); */
785 }
786 
787 static void
obxMidi(guiSynth * synth,int fd,int chan,int c,int o,int v)788 obxMidi(guiSynth *synth, int fd, int chan, int c, int o, int v)
789 {
790 	int newchan;
791 
792 	if ((synth->flags & OPERATIONAL) == 0)
793 		return;
794 
795 	if (c == 1) {
796 		if ((newchan = synth->midichannel - 1) < 0)
797 		{
798 			synth->midichannel = 0;
799 			return;
800 		}
801 	} else {
802 		if ((newchan = synth->midichannel + 1) >= 16)
803 		{
804 			synth->midichannel = 15;
805 			return;
806 		}
807 	}
808 
809 	if (global.libtest == 0)
810 	{
811 		bristolMidiSendMsg(global.controlfd, synth->sid,
812 			127, 0, BRISTOL_MIDICHANNEL|newchan);
813 	}
814 
815 	synth->midichannel = newchan;
816 }
817 
818 /*
819  * For the sake of ease of use, links have been placed here to be called
820  * by any of the devices created. They would be better in some other file,
821  * perhaps with this as a dispatch.
822  *
823  * Param refers to the device index in the locations table given below.
824  */
825 static int
obxCallback(brightonWindow * win,int panel,int index,float value)826 obxCallback(brightonWindow *win, int panel, int index, float value)
827 {
828 	guiSynth *synth = findSynth(global.synths, win);
829 	int sendvalue;
830 
831 /* printf("obxCallback(%i, %f): %x\n", index, value, synth); */
832 
833 	if (synth == 0)
834 		return(0);
835 
836 	if ((index >= DEVICE_COUNT) || ((synth->flags & OPERATIONAL) == 0))
837 		return(0);
838 
839 	if (obxApp.resources[0].devlocn[index].to == 1.0)
840 		sendvalue = value * C_RANGE_MIN_1;
841 	else
842 		sendvalue = value;
843 
844 	synth->mem.param[index] = value;
845 
846 	if ((!global.libtest) || (index >= ACTIVE_DEVS))
847 		synth->dispatch[index].routine(synth,
848 			global.controlfd, synth->sid,
849 			synth->dispatch[index].controller,
850 			synth->dispatch[index].operator,
851 			sendvalue);
852 
853 #ifdef DEBUG
854 	else
855 		printf("dispatch[%x,%i](%i, %i, %i, %i, %i)\n", synth, index,
856 			global.controlfd, synth->sid,
857 			synth->dispatch[index].controller,
858 			synth->dispatch[index].operator,
859 			sendvalue);
860 #endif
861 
862 	return(0);
863 }
864 
865 /*
866  * Any location initialisation required to run the callbacks. For bristol, this
867  * will connect to the engine, and give it some base parameters.
868  * May need to generate some application specific menus.
869  * Will also then make specific requests to some of the devices to alter their
870  * rendering.
871  */
872 static int
obxInit(brightonWindow * win)873 obxInit(brightonWindow *win)
874 {
875 	guiSynth *synth = findSynth(global.synths, win);
876 	dispatcher *dispatch;
877 	int i;
878 
879 	if (synth == 0)
880 	{
881 		synth = findSynth(global.synths, 0);
882 		if (synth == 0)
883 		{
884 			printf("cannot init\n");
885 			return(0);
886 		}
887 	}
888 
889 	if ((initmem = synth->location) == 0)
890 		initmem = 11;
891 
892 	synth->win = win;
893 
894 	printf("Initialise the obx link to bristol: %p\n", synth->win);
895 
896 	synth->mem.param = (float *) brightonmalloc(DEVICE_COUNT * sizeof(float));
897 	synth->mem.count = DEVICE_COUNT;
898 	synth->mem.active = ACTIVE_DEVS;
899 	synth->dispatch = (dispatcher *)
900 		brightonmalloc(DEVICE_COUNT * sizeof(dispatcher));
901 	dispatch = synth->dispatch;
902 
903 	/*
904 	 * We really want to have three connection mechanisms. These should be
905 	 *	1. Unix named sockets.
906 	 *	2. UDP sockets.
907 	 *	3. MIDI pipe.
908 	 */
909 	if (!global.libtest)
910 	{
911 		if ((synth->sid = initConnection(&global, synth)) < 0)
912 			return(-1);
913 	}
914 
915 	for (i = 0; i < DEVICE_COUNT; i++)
916 		synth->dispatch[i].routine = obxMidiSendMsg;
917 
918 	/* Glide and Unison, done */
919 	dispatch[FIRST_DEV].controller = 126;
920 	dispatch[FIRST_DEV].operator = 0;
921 	dispatch[FIRST_DEV + 1].controller = 126;
922 	dispatch[FIRST_DEV + 1].operator = 1;
923 	dispatch[FIRST_DEV + 2].controller = 1;
924 	dispatch[FIRST_DEV + 2].operator = 10;
925 
926 	/* LFO - operator 2 parameters - Done */
927 	dispatch[FIRST_DEV + 3].controller = 2;
928 	dispatch[FIRST_DEV + 3].operator = 0;
929 	dispatch[FIRST_DEV + 4].controller = 126;
930 	dispatch[FIRST_DEV + 4].operator = 19;
931 	dispatch[FIRST_DEV + 5].controller = 126;
932 	dispatch[FIRST_DEV + 5].operator = 20;
933 	/* S/H - this should be a routing switch. */
934 	dispatch[FIRST_DEV + 6].controller = 126;
935 	dispatch[FIRST_DEV + 6].operator = 21;
936 
937 	/* Depth Osc/Osc/Filt - routing control/switches */
938 	dispatch[FIRST_DEV + 7].controller = 126;
939 	dispatch[FIRST_DEV + 7].operator = 4;
940 	dispatch[FIRST_DEV + 8].controller = 126;
941 	dispatch[FIRST_DEV + 8].operator = 5;
942 	dispatch[FIRST_DEV + 9].controller = 126;
943 	dispatch[FIRST_DEV + 9].operator = 6;
944 	dispatch[FIRST_DEV + 10].controller = 126;
945 	dispatch[FIRST_DEV + 10].operator = 7;
946 
947 	/* PWM Osc/Osc - routing control/switches */
948 	dispatch[FIRST_DEV + 11].controller = 126;
949 	dispatch[FIRST_DEV + 11].operator = 8;
950 	dispatch[FIRST_DEV + 12].controller = 126;
951 	dispatch[FIRST_DEV + 12].operator = 9;
952 	dispatch[FIRST_DEV + 13].controller = 126;
953 	dispatch[FIRST_DEV + 13].operator = 10;
954 
955 	/* Osc - Some routing switches. */
956 	dispatch[FIRST_DEV + 14].controller = 0;
957 	dispatch[FIRST_DEV + 14].operator = 1;
958 	/* PWM - needs to adjust both oscillators, so need a dispatcher. */
959 	dispatch[FIRST_DEV + 15].controller = 15;
960 	dispatch[FIRST_DEV + 15].operator = 1;
961 	dispatch[FIRST_DEV + 16].controller = 1;
962 	dispatch[FIRST_DEV + 16].operator = 9;
963 	/* Saw/Square. May need dispatch for tri when both off */
964 	dispatch[FIRST_DEV + 17].controller = 0;
965 	dispatch[FIRST_DEV + 17].operator = 4;
966 	dispatch[FIRST_DEV + 18].controller = 0;
967 	dispatch[FIRST_DEV + 18].operator = 6;
968 	/* Crossmod and sync - routing switches */
969 	dispatch[FIRST_DEV + 19].controller = 126;
970 	dispatch[FIRST_DEV + 19].operator = 11;
971 	dispatch[FIRST_DEV + 20].controller = 1;
972 	dispatch[FIRST_DEV + 20].operator = 7;
973 	/* Saw/Square. May need dispatch for tri when both off */
974 	dispatch[FIRST_DEV + 21].controller = 1;
975 	dispatch[FIRST_DEV + 21].operator = 4;
976 	dispatch[FIRST_DEV + 22].controller = 1;
977 	dispatch[FIRST_DEV + 22].operator = 6;
978 	/* Osc waveforms need a dispatcher to enable tri with both buttons off. */
979 	dispatch[FIRST_DEV + 15].routine =
980 		dispatch[FIRST_DEV + 17].routine =
981 		dispatch[FIRST_DEV + 18].routine =
982 		dispatch[FIRST_DEV + 21].routine =
983 		dispatch[FIRST_DEV + 22].routine =
984 			(synthRoutine) obxWaveform;
985 
986 	/* Filter - some routing switches */
987 	dispatch[FIRST_DEV + 23].controller = 4;
988 	dispatch[FIRST_DEV + 23].operator = 0;
989 	dispatch[FIRST_DEV + 24].controller = 4;
990 	dispatch[FIRST_DEV + 24].operator = 1;
991 	dispatch[FIRST_DEV + 25].controller = 4;
992 	dispatch[FIRST_DEV + 25].operator = 2;
993 	/* Routing switches. Need to check on KBD tracking though */
994 	dispatch[FIRST_DEV + 26].controller = 126;
995 	dispatch[FIRST_DEV + 26].operator = 12;
996 	dispatch[FIRST_DEV + 27].controller = 4;
997 	dispatch[FIRST_DEV + 27].operator = 3;
998 	dispatch[FIRST_DEV + 28].controller = 126;
999 	dispatch[FIRST_DEV + 28].operator = 14;
1000 	dispatch[FIRST_DEV + 29].controller = 126;
1001 	dispatch[FIRST_DEV + 29].operator = 15;
1002 	dispatch[FIRST_DEV + 30].controller = 126;
1003 	dispatch[FIRST_DEV + 30].operator = 16;
1004 	dispatch[FIRST_DEV + 31].controller = 126;
1005 	dispatch[FIRST_DEV + 31].operator = 17;
1006 
1007 	/* Envelopes */
1008 	dispatch[FIRST_DEV + 32].controller = 3;
1009 	dispatch[FIRST_DEV + 32].operator = 0;
1010 	dispatch[FIRST_DEV + 33].controller = 3;
1011 	dispatch[FIRST_DEV + 33].operator = 1;
1012 	dispatch[FIRST_DEV + 34].controller = 3;
1013 	dispatch[FIRST_DEV + 34].operator = 2;
1014 	dispatch[FIRST_DEV + 35].controller = 3;
1015 	dispatch[FIRST_DEV + 35].operator = 3;
1016 	dispatch[FIRST_DEV + 36].controller = 5;
1017 	dispatch[FIRST_DEV + 36].operator = 0;
1018 	dispatch[FIRST_DEV + 37].controller = 5;
1019 	dispatch[FIRST_DEV + 37].operator = 1;
1020 	dispatch[FIRST_DEV + 38].controller = 5;
1021 	dispatch[FIRST_DEV + 38].operator = 2;
1022 	dispatch[FIRST_DEV + 39].controller = 5;
1023 	dispatch[FIRST_DEV + 39].operator = 3;
1024 	/* We need a separate dispatcher for the decay, since the reset button */
1025 	/* will affect the value. */
1026 	dispatch[FIRST_DEV + 35].routine =
1027 		dispatch[FIRST_DEV + 39].routine =
1028 			(synthRoutine) obxDecay;
1029 
1030 	/* Master volume - gain of envelope? */
1031 	dispatch[FIRST_DEV + 40].controller = 5;
1032 	dispatch[FIRST_DEV + 40].operator = 4;
1033 	/* Reset of 'release' DONE */
1034 	dispatch[FIRST_DEV + 41].controller = 41;
1035 	dispatch[FIRST_DEV + 41].operator = 0;
1036 	dispatch[FIRST_DEV + 41].routine =
1037 		(synthRoutine) obxDecay;
1038 	/* Autotune */
1039 	dispatch[FIRST_DEV + 42].routine = (synthRoutine) multiTune;
1040 	/* Hold - DONE (stole from Juno.....) */
1041 	dispatch[FIRST_DEV + 43].routine = (synthRoutine) obxHold;
1042 	/* Master tune - Done. */
1043 	dispatch[FIRST_DEV + 44].controller = 126;
1044 	dispatch[FIRST_DEV + 44].operator = 2;
1045 
1046 /* Memories. */
1047 	dispatch[MEM_START + 0].controller = 16;
1048 	dispatch[MEM_START + 1].controller = 0;
1049 	dispatch[MEM_START + 2].controller = 1;
1050 	dispatch[MEM_START + 3].controller = 2;
1051 	dispatch[MEM_START + 4].controller = 3;
1052 	dispatch[MEM_START + 5].controller = 4;
1053 	dispatch[MEM_START + 6].controller = 5;
1054 	dispatch[MEM_START + 7].controller = 6;
1055 	dispatch[MEM_START + 8].controller = 7;
1056 	dispatch[MEM_START + 9].controller = 8;
1057 	dispatch[MEM_START + 10].controller = 9;
1058 	dispatch[MEM_START + 11].controller = 10;
1059 	dispatch[MEM_START + 12].controller = 11;
1060 	dispatch[MEM_START + 13].controller = 12;
1061 	dispatch[MEM_START + 14].controller = 13;
1062 	dispatch[MEM_START + 15].controller = 14;
1063 	dispatch[MEM_START + 16].controller = 15;
1064 	dispatch[MEM_START + 17].controller = 17;
1065 
1066 	dispatch[MEM_START + 0].operator = MEM_START + 0;
1067 	dispatch[MEM_START + 1].operator = MEM_START + 1;
1068 	dispatch[MEM_START + 2].operator = MEM_START + 2;
1069 	dispatch[MEM_START + 3].operator = MEM_START + 3;
1070 	dispatch[MEM_START + 4].operator = MEM_START + 4;
1071 	dispatch[MEM_START + 5].operator = MEM_START + 5;
1072 	dispatch[MEM_START + 6].operator = MEM_START + 6;
1073 	dispatch[MEM_START + 7].operator = MEM_START + 7;
1074 	dispatch[MEM_START + 8].operator = MEM_START + 8;
1075 	dispatch[MEM_START + 9].operator = MEM_START + 9;
1076 	dispatch[MEM_START + 10].operator = MEM_START + 10;
1077 	dispatch[MEM_START + 11].operator = MEM_START + 11;
1078 	dispatch[MEM_START + 12].operator = MEM_START + 12;
1079 	dispatch[MEM_START + 13].operator = MEM_START + 13;
1080 	dispatch[MEM_START + 14].operator = MEM_START + 14;
1081 	dispatch[MEM_START + 15].operator = MEM_START + 15;
1082 	dispatch[MEM_START + 16].operator = MEM_START + 16;
1083 	dispatch[MEM_START + 17].operator = MEM_START + 17;
1084 
1085 	dispatch[MEM_START + 0].routine =
1086 		dispatch[MEM_START + 1].routine =
1087 		dispatch[MEM_START + 2].routine =
1088 		dispatch[MEM_START + 3].routine =
1089 		dispatch[MEM_START + 4].routine =
1090 		dispatch[MEM_START + 5].routine =
1091 		dispatch[MEM_START + 6].routine =
1092 		dispatch[MEM_START + 7].routine =
1093 		dispatch[MEM_START + 8].routine =
1094 		dispatch[MEM_START + 9].routine =
1095 		dispatch[MEM_START + 10].routine =
1096 		dispatch[MEM_START + 11].routine =
1097 		dispatch[MEM_START + 12].routine =
1098 		dispatch[MEM_START + 13].routine =
1099 		dispatch[MEM_START + 14].routine =
1100 		dispatch[MEM_START + 15].routine =
1101 		dispatch[MEM_START + 16].routine =
1102 		dispatch[MEM_START + 17].routine =
1103 			(synthRoutine) obxMemory;
1104 
1105 	dispatch[FIRST_DEV + 63].routine = dispatch[FIRST_DEV + 64].routine =
1106 		(synthRoutine) obxMidi;
1107 	dispatch[FIRST_DEV + 63].controller = 1;
1108 	dispatch[FIRST_DEV + 64].controller = 2;
1109 
1110 	dispatch[RADIOSET_1].other1 = -1;
1111 	dispatch[RADIOSET_2].other1 = -1;
1112 
1113 	/* Tune/Gain osc-1/2 */
1114 	bristolMidiSendMsg(global.controlfd, synth->sid, 0, 2, 8192);
1115 	bristolMidiSendMsg(global.controlfd, synth->sid, 1, 2, 8192);
1116 	bristolMidiSendMsg(global.controlfd, synth->sid, 0, 3, C_RANGE_MIN_1);
1117 	bristolMidiSendMsg(global.controlfd, synth->sid, 1, 3, C_RANGE_MIN_1);
1118 	/* Gain on filter contour */
1119 	bristolMidiSendMsg(global.controlfd, synth->sid, 3, 4, C_RANGE_MIN_1);
1120 	/* Select alt filter and pole remix */
1121 	bristolMidiSendMsg(global.controlfd, synth->sid, 4, 4, 4);
1122 	bristolMidiSendMsg(global.controlfd, synth->sid, 4, 7, 4096);
1123 
1124 	return(0);
1125 }
1126 
1127 /*
1128  * This will be called to make any routine specific parameters available.
1129  */
1130 static int
obxConfigure(brightonWindow * win)1131 obxConfigure(brightonWindow *win)
1132 {
1133 	guiSynth *synth = findSynth(global.synths, win);
1134 	brightonEvent event;
1135 
1136 	if (synth == 0)
1137 	{
1138 		printf("problems going operational\n");
1139 		return(-1);
1140 	}
1141 
1142 	if (synth->flags & OPERATIONAL)
1143 		return(0);
1144 
1145 printf("going operational\n");
1146 
1147 	synth->flags |= OPERATIONAL;
1148 	synth->keypanel = 1;
1149 	synth->keypanel2 = -1;
1150 	synth->transpose = 36;
1151 
1152 	synth->bank = 0;
1153 	/* Don't load a memory, send a bank, location and load request. */
1154 	event.intvalue = 1;
1155 	brightonParamChange(synth->win, synth->panel,
1156 		MEM_START + 1, &event);
1157 	brightonParamChange(synth->win, synth->panel,
1158 		MEM_START + 9, &event);
1159 
1160 	multiTune(synth, 0,0,0,0,0);
1161 
1162 /*	loadMemory(synth, "obx", 0, 0, synth->mem.active, FIRST_DEV, 0); */
1163 	obxLoadMemory(synth, global.controlfd, synth->midichannel, 0, initmem, 0);
1164 
1165 	brightonPut(win,
1166 		"bitmaps/blueprints/obxshade.xpm", 0, 0, win->width, win->height);
1167 
1168 	/*
1169 	 * Hm. This is a hack for a few bits of bad rendering of a keyboard. Only
1170 	 * occurs on first paint, so we suppress the first paint, and then request
1171 	 * an expose here.
1172 	 */
1173 	event.type = BRIGHTON_EXPOSE;
1174 	event.intvalue = 1;
1175 	brightonParamChange(synth->win, KEY_PANEL, -1, &event);
1176 	configureGlobals(synth);
1177 
1178 	synth->loadMemory = (loadRoutine) obxKeyLoadMemory;
1179 
1180 	return(0);
1181 }
1182 
1183