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