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 rhodesInit();
30 static int rhodesConfigure();
31 static int rhodesCallback(brightonWindow *, int, int, float);
32 static int rhodesMidiCallback(brightonWindow *, int, int, float);
33 
34 extern guimain global;
35 
36 #include "brightonKeys.h"
37 
38 #define OPTS_PANEL 0
39 #define MOD_PANEL 1
40 #define MEM_PANEL 2
41 #define KEY_PANEL 3
42 
43 #define FIRST_DEV 0
44 
45 #define MOD_COUNT 4
46 #define OPTS_COUNT 12
47 #define MEM_COUNT 17
48 
49 #define OPTS_START 0
50 #define MOD_START OPTS_COUNT
51 #define MEM_START (MOD_COUNT + MOD_START)
52 
53 #define ACTIVE_DEVS (OPTS_COUNT + MOD_COUNT - 1)
54 #define DEVICE_COUNT (MOD_COUNT + OPTS_COUNT + MEM_COUNT)
55 #define DISPLAY_DEV (MEM_COUNT - 1)
56 #define MEM_MGT ACTIVE_DEVS
57 
58 #define MIDI_MGT (MEM_MGT + 12)
59 
60 extern int memCallback(brightonWindow * , int, int, float);
61 extern brightonLocations mem[];
62 
63 /*
64  * This structure is for device definition. The structure is defined in
65  * include/brighton.h, further definitions in brighton/brightonDevtable.h and
66  * include/brightoninternals.h
67  *
68  *	typedef int (*brightonCallback)(int, float);
69  *	typedef struct BrightonLocations {
70  *		int device; 0=rotary, 1=scale, etc.
71  *		float relx, rely; relative position with regards to 1000 by 1000 window
72  *		float relw, relh; relative height.
73  *		int from, to;
74  *		brightonCallback callback; specific to this dev
75  *		char *image; bitmap. If zero take a device default.
76  *		int flags;
77  *	} brightonLocations;
78  *
79  * This example is for a rhodesBristol type synth interface.
80  */
81 
82 #define R1 0
83 
84 #define W1 100
85 #define L1 600
86 
87 #define C1 40
88 #define C2 190
89 #define C3 340
90 #define C4 490
91 #define C5 700
92 #define C6 850
93 
94 static brightonLocations locations[MOD_COUNT] = {
95 	{"Bass", 0, 90, 100, 300, 600, 0, 1, 0, 0, 0, 0},
96 	{"Volume", 0, 123, 100, 300, 600, 0, 1, 0, 0, 0, 0},
97 	{"", 2, 50, 200, 30, 400, 0, 1, 0,
98 		"bitmaps/buttons/rockerwhite.xpm", 0, 0},
99 	{"Chorus", 0, 156, 100, 300, 600, 0, 1, 0, 0, 0, 0},
100 };
101 
102 #define S1 200
103 
104 /* Options should only be a few piano selectors, no programmers. */
105 static brightonLocations options[OPTS_COUNT] = {
106 	{"", 2, 100, 500, 50, 200, 0, 1, 0,
107 		"bitmaps/buttons/pressoff.xpm", "bitmaps/buttons/presson.xpm", 0},
108 	{"", 2, 200, 500, 50, 200, 0, 1, 0,
109 		"bitmaps/buttons/pressoff.xpm", "bitmaps/buttons/presson.xpm", 0},
110 	{"", 2, 300, 500, 50, 200, 0, 1, 0,
111 		"bitmaps/buttons/pressoff.xpm", "bitmaps/buttons/presson.xpm", 0},
112 	{"", 2, 400, 500, 50, 200, 0, 1, 0,
113 		"bitmaps/buttons/pressoff.xpm", "bitmaps/buttons/presson.xpm", 0},
114 	{"", 2, 500, 500, 50, 200, 0, 1, 0,
115 		"bitmaps/buttons/pressoff.xpm", "bitmaps/buttons/presson.xpm", 0},
116 	{"", 2, 600, 500, 50, 200, 0, 1, 0,
117 		"bitmaps/buttons/pressoff.xpm", "bitmaps/buttons/presson.xpm", 0},
118 	{"", 2, 700, 500, 50, 200, 0, 1, 0,
119 		"bitmaps/buttons/pressoff.xpm", "bitmaps/buttons/presson.xpm", 0},
120 	{"", 2, 800, 500, 50, 200, 0, 1, 0,
121 		"bitmaps/buttons/pressoff.xpm", "bitmaps/buttons/presson.xpm", 0},
122 	{"", 0, 100, 200, 60, 300, 0, 1, 0, "bitmaps/knobs/knobrednew.xpm",
123 		"bitmaps/knobs/alpharotary.xpm", 0},
124 	{"", 0, 200, 200, 60, 300, 0, 1, 0, "bitmaps/knobs/knobyellownew.xpm",
125 		"bitmaps/knobs/alpharotary.xpm", 0},
126 	{"", 0, 300, 200, 60, 300, 0, 1, 0, "bitmaps/knobs/knobgreennew.xpm",
127 		"bitmaps/knobs/alpharotary.xpm", 0},
128 	{"", 0, 400, 200, 60, 300, 0, 1, 0, "bitmaps/knobs/knobbluenew.xpm",
129 		"bitmaps/knobs/alpharotary.xpm", 0},
130 };
131 
132 /*
133  * This is a set of globals for the main window rendering. Again taken from
134  * include/brighton.h
135  */
136 brightonApp rhodesApp = {
137 	"rhodes",
138 	0, /* no blueprint on wood background. */
139 	"bitmaps/textures/leather.xpm",
140 	0,
141 	rhodesInit,
142 	rhodesConfigure, /* 3 callbacks */
143 	rhodesMidiCallback,
144 	0,
145 	{16, 0, 2, 2, 5, 520, 0, 1},
146 	750, 250, 0, 0,
147 	7, /* panel count */
148 	{
149 		{
150 			"Opts",
151 			"bitmaps/blueprints/rhodesopts.xpm",
152 			"bitmaps/textures/metal5.xpm", /* flags */
153 			0x020,
154 			0,
155 			0,
156 			rhodesCallback,
157 			19, 40, 600, 510,
158 			OPTS_COUNT,
159 			options
160 		},
161 		{
162 			"Mods",
163 			"bitmaps/blueprints/rhodes.xpm",
164 			"bitmaps/images/rhodesplate.xpm",
165 			BRIGHTON_STRETCH,
166 			0,
167 			0,
168 			rhodesCallback,
169 			12, 559, 976, 100,
170 			MOD_COUNT,
171 			locations
172 		},
173 		{
174 			"Mem",
175 			"bitmaps/blueprints/genmem.xpm",
176 			"bitmaps/textures/metal5.xpm", /* flags */
177 			0x020,
178 			0,
179 			0,
180 			memCallback,
181 			619, 40, 362, 510,
182 			MEM_COUNT,
183 			mem
184 		},
185 		{
186 			"Keyboard",
187 			0,
188 			"bitmaps/newkeys/dkbg.xpm", /* flags */
189 			0x020|BRIGHTON_STRETCH,
190 			0,
191 			0,
192 			keyCallback,
193 			52, 662, 900, 305,
194 			KEY_COUNT_6_OCTAVE,
195 			keys6octave
196 		},
197 		{
198 			"Rhodes",
199 			0,
200 			"bitmaps/images/rhodes.xpm",
201 			BRIGHTON_STRETCH, /* flags */
202 			0,
203 			0,
204 			0,
205 			12, 30, 976, 530,
206 			0,
207 			0
208 		},
209 		{
210 			"backing",
211 			0,
212 			"bitmaps/textures/metal6.xpm", /* flags */
213 			BRIGHTON_STRETCH,
214 			0,
215 			0,
216 			0,
217 			953, 662, 35, 310,
218 			0,
219 			0
220 		},
221 		{
222 			"backing",
223 			0,
224 			"bitmaps/textures/metal6.xpm", /* flags */
225 			BRIGHTON_STRETCH,
226 			0,
227 			0,
228 			0,
229 			12, 662, 40, 310,
230 			0,
231 			0
232 		},
233 	}
234 };
235 
236 /*static dispatcher dispatch[DEVICE_COUNT]; */
237 
238 static int
rhodesMidiSendMsg(void * synth,int fd,int chan,int c,int o,int v)239 rhodesMidiSendMsg(void *synth, int fd, int chan, int c, int o, int v)
240 {
241 /*printf("rhodesMidiSendMsg(%i, %i, %i)\n", c, o, v); */
242 	bristolMidiSendMsg(fd, chan, c, o, v);
243 	return(0);
244 }
245 
246 /*
247  * For the sake of ease of use, links have been placed here to be called
248  * by any of the devices created. They would be better in some other file,
249  * perhaps with this as a dispatch.
250  *
251  * Param refers to the device index in the locations table given below.
252  */
253 static int
rhodesCallback(brightonWindow * win,int panel,int index,float value)254 rhodesCallback(brightonWindow * win, int panel, int index, float value)
255 {
256 	guiSynth *synth = findSynth(global.synths, win);
257 	int sendvalue;
258 
259 /*	printf("rhodesCallback(%i, %i, %f): %x\n", panel, index, value, synth); */
260 
261 	if (synth == 0)
262 		return(0);
263 
264 	if ((index >= DEVICE_COUNT) || ((synth->flags & OPERATIONAL) == 0))
265 		return(0);
266 
267 	if (rhodesApp.resources[panel].devlocn[index].to == 1)
268 		sendvalue = value * C_RANGE_MIN_1;
269 	else
270 		sendvalue = value;
271 
272 	switch (panel) {
273 		case OPTS_PANEL:
274 			index += OPTS_START;
275 			break;
276 		case MOD_PANEL:
277 			index += MOD_START;
278 			break;
279 		case MEM_PANEL:
280 			index += MEM_START;
281 			break;
282 	}
283 
284 	synth->mem.param[index] = value;
285 
286 	if ((!global.libtest) || (index >= ACTIVE_DEVS))
287 		synth->dispatch[index].routine(synth,
288 			global.controlfd, synth->sid,
289 			synth->dispatch[index].controller,
290 			synth->dispatch[index].operator,
291 			sendvalue);
292 #ifdef DEBUG
293 	else
294 		printf("dispatch[%p,%i](%i, %i, %i, %i, %i)\n", synth, index,
295 			global.controlfd, synth->sid,
296 			synth->dispatch[index].controller,
297 			synth->dispatch[index].operator,
298 			sendvalue);
299 #endif
300 
301 	return(0);
302 }
303 
304 static void
rhodesProgramme(guiSynth * synth,int fd,int chan,int cont,int op,int value)305 rhodesProgramme(guiSynth *synth, int fd, int chan, int cont, int op, int value)
306 {
307 	brightonEvent event;
308 
309 	if (synth->dispatch[OPTS_START].other2)
310 	{
311 		synth->dispatch[OPTS_START].other2 = 0;
312 		synth->mem.param[synth->dispatch[OPTS_START].other1] = 0;
313 		return;
314 	}
315 
316 	if ((synth->flags & MEM_LOADING) == 0)
317 	{
318 		if (synth->dispatch[OPTS_START].other1 != -1)
319 		{
320 			synth->dispatch[OPTS_START].other2 = 1;
321 
322 			if (synth->dispatch[OPTS_START].other1 != op)
323 				event.value = 0;
324 			else
325 				event.value = 1;
326 
327 			brightonParamChange(synth->win, OPTS_PANEL,
328 				synth->dispatch[OPTS_START].other1, &event);
329 		}
330 		synth->dispatch[OPTS_START].other1 = op;
331 		synth->mem.param[op] = 1;
332 	} else
333 		return;
334 
335 	if (synth->flags & SUPPRESS)
336 		return;
337 
338 	if (value != 0)
339 	{
340 		float *memhold;
341 		float mem[256];
342 		int optr, ind;
343 
344 /*		printf("rhodesProgramme(%x, %i, %i, %i, %i, %i)\n", */
345 /*			synth, fd, chan, cont, op, value); */
346 
347 		/*
348 		 * Each of the 8 voices has an associated set of DX parameters. We
349 		 * need to get hold of these, and send them directly over our config
350 		 * interface tap - we cannot forward via the normal GUi interface since
351 		 * we do not have these parameters mapped.
352 		 *
353 		 * The memories are mapped as 6 operators, each with 20 parameters,
354 		 * of which 13 are active, and then we have 4 additional parameters for
355 		 * algo, pitch, glide and volume.
356 		 */
357 		memhold = &synth->mem.param[0];
358 
359 		synth->mem.param = &mem[0];
360 
361 		ind = 1000 + op;
362 
363 		/*
364 		 * Load the memory parameters with no callbacks. We have to force the
365 		 * loading since we are using 'rhodes' as our type, but the memories
366 		 * are actually typed as DX.
367 		 */
368 		if (loadMemory(synth, "rhodes", 0, ind, 148, 0,
369 			BRISTOL_NOCALLS|BRISTOL_FORCE) < 0)
370 		{
371 			printf("Memory not found, returning\n");
372 			synth->mem.param = memhold;
373 			synth->dispatch[OPTS_START].other1 = op;
374 			return;
375 		}
376 
377 		for (optr = 0; optr < 6; optr++)
378 		{
379 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
380 				126, optr * 10, mem[optr * 20] * C_RANGE_MIN_1);
381 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
382 				optr, 1, mem[optr * 20 + 1] * C_RANGE_MIN_1);
383 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
384 				optr, 0, mem[optr * 20 + 2]);
385 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
386 				optr, 6, mem[optr * 20 + 3] * C_RANGE_MIN_1);
387 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
388 				126, optr * 10 + 1, mem[optr * 20 + 4] * C_RANGE_MIN_1);
389 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
390 				optr, 2, mem[optr * 20 + 5] * C_RANGE_MIN_1);
391 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
392 				optr, 3, mem[optr * 20 + 6] * C_RANGE_MIN_1);
393 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
394 				optr, 4, mem[optr * 20 + 7] * C_RANGE_MIN_1);
395 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
396 				optr, 5, mem[optr * 20 + 8] * C_RANGE_MIN_1);
397 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
398 				optr, 7, mem[optr * 20 + 9] * C_RANGE_MIN_1);
399 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
400 				126, optr * 10 + 2, mem[optr * 20 + 10] * C_RANGE_MIN_1);
401 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
402 				126, optr * 10 + 3, mem[optr * 20 + 11] * C_RANGE_MIN_1);
403 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
404 				optr, 9, mem[optr * 20 + 12] * C_RANGE_MIN_1);
405 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
406 				optr, 10, mem[optr * 20 + 13] * C_RANGE_MIN_1);
407 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
408 				optr, 11, mem[optr * 20 + 14] * C_RANGE_MIN_1);
409 			rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
410 				optr, 12, mem[optr * 20 + 15] * C_RANGE_MIN_1);
411 		}
412 
413 		/*
414 		 * These go through all the algorithms, looking for a single nonzero
415 		 */
416 		for (ind = 0; ind < 24; ind++)
417 		{
418 			if (mem[120 + ind] != 0)
419 			{
420 				bristolMidiSendMsg(global.controlfd, synth->sid, 126, 101, ind);
421 				break;
422 			}
423 		}
424 
425 		rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
426 			126, 99, 0);
427 		rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
428 			126, 100, 0);
429 		rhodesMidiSendMsg(synth, global.controlfd, synth->sid,
430 			126, 102, C_RANGE_MIN_1);
431 
432 		synth->mem.param = memhold;
433 		synth->dispatch[OPTS_START].other1 = op;
434 	}
435 }
436 
437 static int
rhodesMidiCallback(brightonWindow * win,int command,int value,float v)438 rhodesMidiCallback(brightonWindow *win, int command, int value, float v)
439 {
440 	guiSynth *synth = findSynth(global.synths, win);
441 
442 	printf("midi callback: %x, %i\n", command, value);
443 
444 	switch(command)
445 	{
446 		case MIDI_PROGRAM:
447 			printf("midi program: %x, %i\n", command, value);
448 			synth->location = value;
449 
450 			rhodesProgramme(synth, global.controlfd, synth->sid,
451 				synth->dispatch[OPTS_START].controller,
452 				synth->dispatch[OPTS_START].operator, 1.0f);
453 
454 			break;
455 		case MIDI_BANK_SELECT:
456 			printf("midi banksel: %x, %i\n", command, value);
457 			synth->bank = value;
458 			break;
459 	}
460 	return(0);
461 }
462 
463 static void
rhodesPanelSwitch(guiSynth * id,int fd,int chan,int cont,int op,int value)464 rhodesPanelSwitch(guiSynth *id, int fd, int chan, int cont, int op, int value)
465 {
466 	brightonEvent event;
467 
468 	id->flags |= SUPPRESS;
469 /*printf("rhodesPanelSwitch()\n"); */
470 	/*
471 	 * If the sendvalue is zero, then withdraw the opts window, draw the
472 	 * slider window, and vice versa.
473 	 */
474 	if (value == 0)
475 	{
476 		event.type = BRIGHTON_EXPOSE;
477 		event.intvalue = 0;
478 		brightonParamChange(id->win, 0, -1, &event);
479 		event.intvalue = 0;
480 		brightonParamChange(id->win, 2, -1, &event);
481 		event.intvalue = 1;
482 		brightonParamChange(id->win, 4, -1, &event);
483 	} else {
484 		event.type = BRIGHTON_EXPOSE;
485 		event.intvalue = 0;
486 		brightonParamChange(id->win, 4, -1, &event);
487 		event.intvalue = 1;
488 		brightonParamChange(id->win, 0, -1, &event);
489 		event.intvalue = 1;
490 		brightonParamChange(id->win, 2, -1, &event);
491 	}
492 	id->flags &= ~SUPPRESS;
493 }
494 
495 static void
rhodesVolume(guiSynth * id,int fd,int chan,int cont,int op,int value)496 rhodesVolume(guiSynth *id, int fd, int chan, int cont, int op, int value)
497 {
498 /*printf("rhodesVolume(%i)\n", value); */
499 	bristolMidiSendMsg(global.controlfd, chan, 126, 102, value);
500 }
501 
502 static void
rhodesBoost(guiSynth * synth,int fd,int chan,int cont,int op,int value)503 rhodesBoost(guiSynth *synth, int fd, int chan, int cont, int op, int value)
504 {
505 /*printf("rhodesBoost(%i)\n", value); */
506 	bristolMidiControl(global.controlfd, synth->sid, 0, 1, value >> 7);
507 }
508 
509 static void
rhodesChorus(guiSynth * synth,int fd,int chan,int cont,int op,int value)510 rhodesChorus(guiSynth *synth, int fd, int chan, int cont, int op, int value)
511 {
512 /*printf("Rhodes chorus: %i\n", value); */
513 	bristolMidiSendMsg(global.controlfd, synth->sid, 123, 0, value);
514 	bristolMidiSendMsg(global.controlfd, synth->sid, 123, 3, value);
515 }
516 
517 /*
518  * Any location initialisation required to run the callbacks. For bristol, this
519  * will connect to the engine, and give it some base parameters.
520  * May need to generate some application specific menus.
521  * Will also then make specific requests to some of the devices to alter their
522  * rendering.
523  */
524 static int
rhodesInit(brightonWindow * win)525 rhodesInit(brightonWindow *win)
526 {
527 	guiSynth *synth = findSynth(global.synths, win);
528 	dispatcher *dispatch;
529 	int i;
530 
531 	if (synth == 0)
532 	{
533 		synth = findSynth(global.synths, 0);
534 		if (synth == 0)
535 		{
536 			printf("cannot init\n");
537 			return(0);
538 		}
539 	}
540 
541 	synth->win = win;
542 
543 	printf("Initialise the rhodes link to bristol: %p\n", synth->win);
544 
545 	synth->mem.param = (float *) brightonmalloc(DEVICE_COUNT * sizeof(float));
546 	synth->mem.count = DEVICE_COUNT;
547 	synth->mem.active = ACTIVE_DEVS;
548 	synth->dispatch = (dispatcher *)
549 		brightonmalloc(DEVICE_COUNT * sizeof(dispatcher));
550 	dispatch = synth->dispatch;
551 
552 	/*
553 	 * The rhodes is actually a DX algorithm but it may eventually use a
554 	 * wrapper in the engine such that the FM coding is fed into a chorus.
555 	synth->synthtype = BRISTOL_DX;
556 	 */
557 
558 	/*
559 	 * We really want to have three connection mechanisms. These should be
560 	 *	1. Unix named sockets.
561 	 *	2. UDP sockets.
562 	 *	3. MIDI pipe.
563 	 */
564 	if (!global.libtest)
565 		if ((synth->sid = initConnection(&global, synth)) < 0)
566 			return(-1);
567 
568 	for (i = 0; i < DEVICE_COUNT; i++)
569 		synth->dispatch[i].routine = rhodesMidiSendMsg;
570 
571 	synth->dispatch[MOD_START + 0].routine = (synthRoutine) rhodesBoost;
572 	synth->dispatch[MOD_START + 1].routine = (synthRoutine) rhodesVolume;
573 	synth->dispatch[MOD_START + 2].routine = (synthRoutine) rhodesPanelSwitch;
574 	synth->dispatch[MOD_START + 3].controller = 123;
575 	synth->dispatch[MOD_START + 3].operator = 0;
576 	synth->dispatch[MOD_START + 3].routine = (synthRoutine) rhodesChorus;
577 
578 	synth->dispatch[OPTS_START + 0].routine
579 		= synth->dispatch[OPTS_START + 1].routine
580 		= synth->dispatch[OPTS_START + 2].routine
581 		= synth->dispatch[OPTS_START + 3].routine
582 		= synth->dispatch[OPTS_START + 4].routine
583 		= synth->dispatch[OPTS_START + 5].routine
584 		= synth->dispatch[OPTS_START + 6].routine
585 		= synth->dispatch[OPTS_START + 7].routine
586 		= (synthRoutine) rhodesProgramme;
587 	synth->dispatch[OPTS_START + 0].operator = 0;
588 	synth->dispatch[OPTS_START + 1].operator = 1;
589 	synth->dispatch[OPTS_START + 2].operator = 2;
590 	synth->dispatch[OPTS_START + 3].operator = 3;
591 	synth->dispatch[OPTS_START + 4].operator = 4;
592 	synth->dispatch[OPTS_START + 5].operator = 5;
593 	synth->dispatch[OPTS_START + 6].operator = 6;
594 	synth->dispatch[OPTS_START + 7].operator = 7;
595 
596 	synth->dispatch[OPTS_START + 8].controller
597 		= synth->dispatch[OPTS_START + 9].controller
598 		= synth->dispatch[OPTS_START + 10].controller
599 		= synth->dispatch[OPTS_START + 11].controller = 123;
600 	synth->dispatch[OPTS_START + 8].operator = 0;
601 	synth->dispatch[OPTS_START + 9].operator = 1;
602 	synth->dispatch[OPTS_START + 10].operator = 2;
603 	synth->dispatch[OPTS_START + 11].operator = 3;
604 
605 	return(0);
606 }
607 
608 /*
609  * This will be called to make any routine specific parameters available.
610  */
611 static int
rhodesConfigure(brightonWindow * win)612 rhodesConfigure(brightonWindow *win)
613 {
614 	guiSynth *synth = findSynth(global.synths, win);
615 	brightonEvent event;
616 
617 	if (synth == 0)
618 	{
619 		printf("problems going operational\n");
620 		return(-1);
621 	}
622 
623 	if (synth->flags & OPERATIONAL)
624 		return(0);
625 
626 printf("going operational\n");
627 
628 	synth->flags |= OPERATIONAL;
629 	synth->keypanel = 3;
630 	synth->keypanel2 = -1;
631 	synth->transpose = 36;
632 /*	loadMemory(synth, "rhodes", 0, synth->location, synth->mem.active, */
633 /*		FIRST_DEV, BRISTOL_NOCALLS|BRISTOL_FORCE); */
634 
635 	rhodesProgramme(synth, global.controlfd, synth->sid,
636 		synth->dispatch[OPTS_START].controller,
637 		synth->dispatch[OPTS_START].operator, 1.0f);
638 
639 	displayPanelText(synth, "PRG", synth->location, MEM_PANEL, MEM_COUNT - 1);
640 
641 	/*
642 	 * Hm. This is a hack for a few bits of bad rendering of a keyboard. Only
643 	 * occurs on first paint, so we suppress the first paint, and then request
644 	 * an expose here.
645 	 */
646 	event.type = BRIGHTON_EXPOSE;
647 	event.intvalue = 1;
648 	brightonParamChange(synth->win, KEY_PANEL, -1, &event);
649 	event.type = BRIGHTON_FLOAT;
650 	event.value = 1;
651 	brightonParamChange(synth->win, 0, 0, &event);
652 	configureGlobals(synth);
653 
654 	event.type = BRIGHTON_FLOAT;
655 	event.value = 0.1;
656 	brightonParamChange(synth->win, OPTS_PANEL, 8, &event);
657 	brightonParamChange(synth->win, OPTS_PANEL, 9, &event);
658 	brightonParamChange(synth->win, OPTS_PANEL, 10, &event);
659 	event.value = 0.5;
660 	brightonParamChange(synth->win, OPTS_PANEL, 11, &event);
661 
662 	brightonPut(synth->win, "bitmaps/blueprints/rhodesshade.xpm",
663 		0, 0, synth->win->width, synth->win->height);
664 
665 	return(0);
666 }
667 
668