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 #include <fcntl.h>
23 #include <strings.h>
24 #include <sys/time.h>
25 
26 #include "brightonMixer.h"
27 #include "brightoninternals.h"
28 
29 #define DISPLAY1 (FUNCTION_COUNT - 6)
30 #define DISPLAY2 (FUNCTION_COUNT - 5)
31 #define DISPLAY3 (FUNCTION_COUNT - 4)
32 #define DISPLAY4 (FUNCTION_COUNT - 3)
33 #define DISPLAY5 (FUNCTION_COUNT - 2)
34 #define DISPLAY6 (FUNCTION_COUNT - 1)
35 
36 #include "brighton.h"
37 #include "brightonMini.h"
38 #include "brightonMixer.h"
39 #include "brightonMixerMemory.h"
40 
41 static char text[128];
42 /*static char scratch[MAX_CHAN_COUNT][16]; */
43 static char memscratch[16];
44 
45 static char *removeInterface(guiSynth *);
46 static char *printInterface(guiSynth *);
47 static char *printTrackMenu(guiSynth *);
48 static char *printMidiMenu(guiSynth *);
49 static char *trackDown(guiSynth *);
50 static char *trackUp(guiSynth *);
51 static char *midiDown(guiSynth *);
52 static char *midiUp(guiSynth *);
53 static char *setTrackText(guiSynth *);
54 
55 static char *printMemMenu(guiSynth *);
56 static char *memoryBuildList(guiSynth *);
57 static char *memoryList(guiSynth *);
58 static char *memoryShowList(guiSynth *);
59 static char *memoryListUp(guiSynth *);
60 static char *memoryListDown(guiSynth *);
61 
62 static char *memorySel1(guiSynth *);
63 static char *memorySel2(guiSynth *);
64 static char *memorySel3(guiSynth *);
65 static char *memorySel4(guiSynth *);
66 
67 static char *songSel1(guiSynth *);
68 static char *songSel2(guiSynth *);
69 static char *songSel3(guiSynth *);
70 static char *songSel4(guiSynth *);
71 
72 static char *songList(guiSynth *);
73 static char *createSongDir(guiSynth *);
74 
75 extern int loadMixerMemory(guiSynth *, char *, int);
76 extern int saveMixerMemory(guiSynth *, char *);
77 extern void displayPanel(guiSynth *, char *, int, int, int);
78 extern int setMixerMemory(mixerMem *, int, int, float *, char *);
79 
80 /*
81  * Ok, fixed table sizes, but a kilo of memories will do for now.
82  */
83 #define MIXER_MEM_COUNT 1024
84 int memCount = -1, memIndex = 0;
85 char memList[MIXER_MEM_COUNT][32];
86 
87 guiSynth *theSynth;
88 
89 /*
90  * We should not really have to rely on timers within the GUI: The engine will
91  * evaluate RMS and Peak signal values for the channels, and save them. The
92  * Midi thread should take these values X times per second (ie, with a timer)
93  * and send a message to the GUI over the interface tap.
94  *
95  * Whenever the GUI gets a VU message it should update the VU meter display.
96  */
97 u_long vuInterval = 100000;
98 
99 /*
100  * Need a set of structures that allow a TitleBar strings, 5 substrings,
101  * 2 "next menus" for the Title, 2 "next menus" or otherwise functions.
102  */
103 typedef char *(*MenuFunc)(guiSynth *);
104 
105 typedef struct mLine {
106 	char title[32];
107 	int last, next;
108 	MenuFunc lmenuFunc;
109 	MenuFunc rmenuFunc;
110 } mLine;
111 
112 #define line1 line[0]
113 #define line2 line[1]
114 #define line3 line[2]
115 #define line4 line[3]
116 #define line5 line[4]
117 
118 typedef struct Menu {
119 	mLine title;
120 	mLine line[5];
121 } Menu;
122 
123 #define MENU_COUNT 32
124 
125 int currentMenu = -1;
126 int currentTrack = 0;
127 
setInt0()128 char *setInt0()
129 {
130 	vuInterval = 0;
131 	return(NULL);
132 }
133 
setInt50()134 char *setInt50()
135 {
136 	vuInterval = 50000;
137 	return(NULL);
138 }
139 
setInt100()140 char *setInt100()
141 {
142 	vuInterval = 100000;
143 	return(NULL);
144 }
145 
setInt200()146 char *setInt200()
147 {
148 	vuInterval = 200000;
149 	return(NULL);
150 }
151 
loadShim(guiSynth * synth)152 static char * loadShim(guiSynth *synth)
153 {
154 	loadMixerMemory(synth, memscratch, 0);
155 	return(NULL);
156 }
157 
saveShim(guiSynth * synth)158 static char * saveShim(guiSynth *synth)
159 {
160 	saveMixerMemory(synth, memscratch);
161 	return(NULL);
162 }
undoShim(guiSynth * synth)163 static char * undoShim(guiSynth *synth)
164 {
165 	loadMixerMemory(synth, "revert", 0);
166 	return(NULL);
167 }
168 
169 Menu functionMenu[MENU_COUNT] = {
170 	{
171 		{"       Main Menu            ", 3, 1, 0, 0},
172 		{{"Effects             Bus     ", 1, 2, 0, 0},
173 		{"Track                VU      ", 3, 12, 0, 0},
174 		{"Audio                Mem     ", 13, 14, 0, 0},
175 		{"Stats             Print     ", 15, -1, 0, printInterface},
176 		{"Midi                 Quit   ", 17, 16, 0, 0}},
177 	},
178 	{
179 		{"     Effects Menu           ", 0, 2, 0, 0},
180 		{{"Pre 1             Post 1    ", 4, 8, 0, 0},
181 		{"Pre 2            Post 2     ", 5, 9, 0, 0},
182 		{"Pre 3            Post 3     ", 6, 10, 0, 0},
183 		{"Pre 4            Post 4     ", 7, 11, 0, 0},
184 		{"                    Main       ", -1, 0, 0, 0}},
185 	},
186 	{
187 		{"       Bus Menu             ", 1, 3, 0, 0},
188 		{{"Effects             Bus     ", 1, 2, 0, 0},
189 		{"Stats                       ", 3, -1, 0, 0},
190 		{"                            ", -1, -1, 0, 0},
191 		{"                            ", -1, -1, 0, 0},
192 		{"                     Main    ", -1, 0, 0, 0}},
193 	},
194 	{
195 		{"       Track Menu           ", 2, 12, printTrackMenu, 0},
196 		{{"                            ", -1, -1, 0, 0},
197 		{"Text:                       ", -1, -1, 0, 0},
198 		{"Down                  UP    ", -1, -1, trackDown, trackUp},
199 		{"                            ", -1, -1, 0, 0},
200 		{"                     MAIN   ", -1, 0, setTrackText, 0}},
201 	},
202 /* 4: */
203 	{
204 		{"       Pre 1 Menu           ", 1, 1, 0, 0},
205 		{{"P 1                  P 4  ", -1, -1, 0, 0},
206 		{"P 2                  P 5  ", -1, -1, 0, 0},
207 		{"P 3                  P 6    ", -1, -1, 0, 0},
208 		{"Prev               Next    ", 11, 5, 0, 0},
209 		{"                    Main    ", -1, 0, 0, 0}},
210 	},
211 	{
212 		{"       Pre 2 Menu           ", 1, 1, 0, 0},
213 		{{"P 1                  P 4  ", -1, -1, 0, 0},
214 		{"P 2                  P 5  ", -1, -1, 0, 0},
215 		{"P 3                  P 6    ", -1, -1, 0, 0},
216 		{"Prev               next    ", 4, 6, 0, 0},
217 		{"                    Main    ", -1, 0, 0, 0}},
218 	},
219 	{
220 		{"       Pre 3 Menu           ", 1, 1, 0, 0},
221 		{{"P 1                  P 4  ", -1, -1, 0, 0},
222 		{"P 2                  P 5  ", -1, -1, 0, 0},
223 		{"P 3                  P 6    ", -1, -1, 0, 0},
224 		{"Prev               next    ", 5, 7, 0, 0},
225 		{"                    Main    ", -1, 0, 0, 0}},
226 	},
227 	{
228 		{"       Pre 4 Menu           ", 1, 1, 0, 0},
229 		{{"P 1                  P 4  ", -1, -1, 0, 0},
230 		{"P 2                  P 5  ", -1, -1, 0, 0},
231 		{"P 3                  P 6    ", -1, -1, 0, 0},
232 		{"Prev               next    ", 6, 8, 0, 0},
233 		{"                    Main    ", -1, 0, 0, 0}},
234 	},
235 /* 8: */
236 	{
237 		{"       Post 1 Menu          ", 1, 1, 0, 0},
238 		{{"P 1                  P 4  ", -1, -1, 0, 0},
239 		{"P 2                  P 5  ", -1, -1, 0, 0},
240 		{"P 3                  P 6    ", -1, -1, 0, 0},
241 		{"Prev               next    ", 7, 9, 0, 0},
242 		{"                    Main    ", -1, 0, 0, 0}},
243 	},
244 	{
245 		{"       Post 2 Menu          ", 1, 1, 0, 0},
246 		{{"P 1                  P 4  ", -1, -1, 0, 0},
247 		{"P 2                  P 5  ", -1, -1, 0, 0},
248 		{"P 3                  P 6    ", -1, -1, 0, 0},
249 		{"Prev               next    ", 8, 10, 0, 0},
250 		{"                    Main    ", -1, 0, 0, 0}},
251 	},
252 	{
253 		{"       Post 3 Menu          ", 1, 1, 0, 0},
254 		{{"P 1                  P 4  ", -1, -1, 0, 0},
255 		{"P 2                  P 5  ", -1, -1, 0, 0},
256 		{"P 3                  P 6    ", -1, -1, 0, 0},
257 		{"Prev               next    ", 9, 11, 0, 0},
258 		{"                    Main    ", -1, 0, 0, 0}},
259 	},
260 	{
261 		{"       Post 4 Menu          ", 1, 1, 0, 0},
262 		{{"P 1                  P 4  ", -1, -1, 0, 0},
263 		{"P 2                  P 5  ", -1, -1, 0, 0},
264 		{"P 3                  P 6    ", -1, -1, 0, 0},
265 		{"Prev               next    ", 10, 4, 0, 0},
266 		{"                    Main    ", -1, 0, 0, 0}},
267 	},
268 /* 12: */
269 	{
270 		{"       VU Menu             ", 3, 13, 0, 0},
271 		{{"Interval 50ms              ", -1, -1, setInt50, 0},
272 		{"Interval 100ms             ", -1, -1, setInt100, 0},
273 		{"Interval 200ms              ", -1, -1, setInt200, 0},
274 		{"                            ", -1, -1, 0, 0},
275 		{"Off                 MAIN    ", -1, 0, setInt0, 0}},
276 	},
277 	{
278 		{"       Audio Menu           ", 12, 14, 0, 0},
279 		{{"Effects             Bus     ", 0, 2, 0, 0},
280 		{"Stats                       ", 0, -1, 0, 0},
281 		{"                            ", -1, -1, 0, 0},
282 		{"                            ", -1, -1, 0, 0},
283 		{"                     MAIN    ", -1, 0, 0, 0}},
284 	},
285 	{
286 		{"       MEM Menu             ", 13, 15, printMemMenu, 0},
287 		{{"Name:                        ", -1, -1, 0, 0},
288 		{"Create Song                 ", -1, -1, createSongDir, 0},
289 		{"Load            Search   ", -1, 20, loadShim, memoryList},
290 		{"Save               Undo     ", -1, -1, saveShim, undoShim},
291 		{"Songs               MAIN   ", 21, 0, songList, 0}},
292 	},
293 	{
294 		{"       Stats Menu           ", 14, 0, 0, 0},
295 		{{"Effects             Bus     ", 0, 2, 0, 0},
296 		{"Stats                       ", 0, -1, 0, 0},
297 		{"                            ", -1, -1, 0, 0},
298 		{"                            ", -1, -1, 0, 0},
299 		{"                     MAIN    ", -1, 0, 0, 0}},
300 	},
301 /* 16: */
302 	{
303 		{"       Quit Menu         ", 0, 0, 0, 0},
304 		{{"                            ", -1, -1, 0, 0},
305 		{"                            ", -1, -1, 0, 0},
306 		{"      Really quit?          ", -1, -1, 0, 0},
307 		{"                            ", -1, -1, 0, 0},
308 		{"No                   Yes    ", 0, 3, 0, removeInterface}},
309 	},
310 	{
311 		{"       Midi Menu         ", 0, 0, printMidiMenu, 0},
312 		{{"                            ", -1, -1, 0, 0},
313 		{"Channel:                    ", -1, -1, 0, 0},
314 		{"                      Up    ", -1, -1, 0, midiUp},
315 		{"                      Down  ", -1, -1, 0, midiDown},
316 		{"                     Main   ", -1, 0, 0, 0}},
317 	},
318 	{
319 	},
320 	{
321 	},
322 /* 20: */
323 	{
324 		{"Back    Search    Main      ", 14, 0, 0, 0},
325 		{{"                            ", 14, 14, memorySel1, memorySel1},
326 		{"                            ", 14, 14, memorySel2, memorySel2},
327 		{"                            ", 14, 14, memorySel3, memorySel3},
328 		{"                            ", 14, 14, memorySel4, memorySel4},
329 		{"Down                  UP    ", 20, 20, memoryListUp, memoryListDown}},
330 	},
331 	{
332 		{"Back    Songs     Main      ", 14, 0, 0, 0},
333 		{{"                            ", 20, 20, songSel1, songSel1},
334 		{"                            ", 20, 20, songSel2, songSel2},
335 		{"                            ", 20, 20, songSel3, songSel3},
336 		{"                            ", 20, 20, songSel4, songSel4},
337 		{"Down                  UP    ", 21, 21, memoryListUp, memoryListDown}},
338 	},
339 	{
340 	},
341 	{
342 	},
343 /* 24: */
344 	{
345 	},
346 	{
347 	},
348 	{
349 	},
350 	{
351 	},
352 /* 28: */
353 	{
354 	},
355 	{
356 	},
357 	{
358 	},
359 	{
360 	}
361 };
362 
363 static void
displayMenu(guiSynth * synth,int panel,int menu)364 displayMenu(guiSynth *synth, int panel, int menu)
365 {
366 	if (functionMenu[currentMenu].title.lmenuFunc != 0)
367 	{
368 		/*
369 		 * If we have a left function to draw the display, it must do all the
370 		 * lines.
371 		 */
372 		functionMenu[menu].title.lmenuFunc(synth);
373 		return;
374 	} else if (functionMenu[currentMenu].title.rmenuFunc != 0) {
375 		displayPanel(synth,
376 			functionMenu[menu].title.rmenuFunc(synth),
377 			0, FUNCTION_PANEL, DISPLAY1);
378 	} else {
379 		displayPanel(synth,
380 			functionMenu[menu].title.title, 0, FUNCTION_PANEL, DISPLAY1);
381 	}
382 
383 	displayPanel(synth,
384 		functionMenu[menu].line1.title, 0, FUNCTION_PANEL, DISPLAY2);
385 	displayPanel(synth,
386 		functionMenu[menu].line2.title, 0, FUNCTION_PANEL, DISPLAY3);
387 	displayPanel(synth,
388 		functionMenu[menu].line3.title, 0, FUNCTION_PANEL, DISPLAY4);
389 	displayPanel(synth,
390 		functionMenu[menu].line4.title, 0, FUNCTION_PANEL, DISPLAY5);
391 	displayPanel(synth,
392 		functionMenu[menu].line5.title, 0, FUNCTION_PANEL, DISPLAY6);
393 }
394 
395 int
functionOp(guiSynth * synth,int panel,int index,int operator,float value)396 functionOp(guiSynth *synth, int panel, int index, int operator, float value)
397 {
398 	if ((synth->flags && OPERATIONAL) == 0)
399 		return(0);
400 
401 /*	printf("functionOp(%x, %i, %i, %i, %f)\n", */
402 /*		synth, panel, index, operator, value); */
403 
404 	if (currentMenu == -1)
405 	{
406 		/*
407 		 * This is to init to the first menu
408 		 */
409 		currentMenu = 0;
410 		displayMenu(synth, panel, currentMenu);
411 
412 		/*
413 		 * And use the chance to seed the interupts for the VU meter.
414 		 */
415 		theSynth = synth;
416 
417 		return(0);
418 	}
419 
420 	if ((index == 13) || (index == 24) || (index == 25))
421 	{
422 		/*
423 		 * memory buttons, 13 is 'rezero', 24 is load and 25 is save?
424 		 *
425 		 * These are bespoke since the generic synth memories use a single
426 		 * panel of parameters whilst the mixer needs many?
427 		 */
428 		if (index == 25)
429 		{
430 			if (memCount < 0)
431 				memoryBuildList(synth);
432 
433 			if (++memIndex > memCount)
434 				memIndex = 0;
435 
436 			sprintf(memscratch, "%s", memList[memIndex]);
437 			loadMixerMemory(synth, memList[memIndex], 0);
438 			currentMenu = 14;
439 			printMemMenu(synth);
440 
441 			return(0);
442 		}
443 		if (index == 24)
444 		{
445 			if (memCount < 0)
446 				memoryBuildList(synth);
447 
448 			if (--memIndex < 0)
449 				memIndex = memCount;
450 
451 			sprintf(memscratch, "%s", memList[memIndex]);
452 			loadMixerMemory(synth, memList[memIndex], 0);
453 			currentMenu = 14;
454 			printMemMenu(synth);
455 
456 			return(0);
457 		}
458 		if (index == 13)
459 		{
460 			loadMixerMemory(synth, "revert", 0);
461 			return(0);
462 		}
463 	}
464 
465 	if ((index >= DISPLAY1) && (index <= DISPLAY5))
466 	{
467 		/*
468 		 * If we have an event here it is going to be a keypress.
469 		 */
470 		if (currentMenu == 3)
471 		{
472 			int i;
473 			char scratch[32];
474 
475 			/*
476 			 * Track menu, this will be track naming text. Value will be an
477 			 * ascii char, put it at the end of the string. char 08 and 7f are
478 			 * delete, ie, remove a character.
479 			 *
480 			 * Then print it on line2.
481 			 */
482 			sprintf(scratch, "%s",
483 				getMixerMemory((mixerMem *) synth->mem.param,
484 					currentTrack + 4, 79));
485 			i = strlen(scratch);
486 
487 			if ((value == 0xff08) || (value == -1))
488 			{
489 				/*
490 				 * Should be backspace/delete
491 				 */
492 				if (i > 0)
493 					scratch[i - 1] = '\0';
494 			} else if (i == 15)
495 				/*
496 				 * If max length then return now
497 				 */
498 				return(0);
499 			else {
500 				scratch[i] = value;
501 				scratch[i + 1] = '\0';
502 			}
503 			setMixerMemory((mixerMem *) synth->mem.param,
504 				currentTrack + 4, 79, 0, scratch);
505 			sprintf(text, "Text: %s               ", scratch);
506 			displayPanel(synth, text, 0, FUNCTION_PANEL, DISPLAY3);
507 			setTrackText(synth);
508 
509 			return(0);
510 		}
511 		/*
512 		 * See if we are in the memory menu;
513 		 */
514 		else if (currentMenu == 14)
515 		{
516 			int i;
517 			/*
518 			 * Track menu, this will be track naming text. Value will be an
519 			 * ascii char, put it at the end of the string. char 08 and 7f are
520 			 * delete, ie, remove a character.
521 			 *
522 			 * Then print it on line2.
523 			 */
524 			i = strlen(memscratch);
525 
526 			if ((value == 0xff08) || (value == -1))
527 			{
528 				if (i > 0)
529 					memscratch[i - 1] = '\0';
530 			} else if (i == 15)
531 				return(0);
532 			else {
533 				memscratch[i] = value;
534 				memscratch[i + 1] = '\0';
535 			}
536 			sprintf(text, "Name: %s                 ", memscratch);
537 			displayPanel(synth, text, 0, FUNCTION_PANEL, DISPLAY2);
538 
539 			return(0);
540 		} else if ((currentMenu == 20) || (currentMenu == 21)) {
541 			int k, j, i = memIndex;
542 			/*
543 			 * This is the search window. Go through the memList looking for
544 			 * the next entry that starts with the given letter.
545 			 */
546 			for (j = 0; j <= memCount; j ++)
547 			{
548 				if (++i > memCount)
549 					i = 0;
550 
551 				if (memList[i][0] == value)
552 				{
553 					memIndex = i;
554 					memoryShowList(synth);
555 					return(0);
556 				}
557 			}
558 			/*
559 			 * If we get here then we could not find a match on the first
560 			 * letter. Lets see about the second letter (not sure why, or if
561 			 * it really makes sense
562 			 */
563 			i = memIndex;
564 			for (j = 0; j <= memCount; j ++)
565 			{
566 				if (++i > memCount)
567 					i = 0;
568 
569 				if (memList[i][1] == value)
570 				{
571 					memIndex = i;
572 					memoryShowList(synth);
573 					return(0);
574 				}
575 			}
576 			/*
577 			 * If that failed then I personally think we should look for any
578 			 * entry that contains the given character. We might consider
579 			 * dropping the last search.
580 			 */
581 			i = memIndex;
582 			for (j = 0; j <= memCount; j++)
583 			{
584 				if (++i > memCount)
585 					i = 0;
586 
587 				for (k = 0; memList[i][k] != '\0'; k++)
588 				{
589 					if (memList[i][k] == value)
590 					{
591 						memIndex = i;
592 						memoryShowList(synth);
593 						return(0);
594 					}
595 				}
596 			}
597 		}
598 
599 		return(0);
600 	}
601 
602 	/*
603 	 * Title back
604 	 *
605 	 * Apart from the title, the rest of the lines can be put into procedures
606 	 * so that we can call the code with an index, as it is now an array.
607 	 *
608 	 * This is damn ugly. How was it not made into a case or a structured
609 	 * array of calls?
610 	 */
611 	if (operator == 0)
612 	{
613 		if (functionMenu[currentMenu].title.last != -1)
614 		{
615 			currentMenu = functionMenu[currentMenu].title.last;
616 			displayMenu(synth, panel, currentMenu);
617 		}
618 	} else if (operator == 1) {
619 		/*
620 		 * Title forward
621 		 */
622 		if (functionMenu[currentMenu].title.next != -1)
623 		{
624 			currentMenu = functionMenu[currentMenu].title.next;
625 			displayMenu(synth, panel, currentMenu);
626 		}
627 	} else if (operator == 2) {
628 		/*
629 		 * Line 1 back
630 		 */
631 		if (functionMenu[currentMenu].line1.lmenuFunc != 0)
632 		{
633 			functionMenu[currentMenu].line1.lmenuFunc(synth);
634 
635 			return(0);
636 		}
637 		if (functionMenu[currentMenu].line1.last != -1)
638 		{
639 			currentMenu = functionMenu[currentMenu].line1.last;
640 			displayMenu(synth, panel, currentMenu);
641 		}
642 	} else if (operator == 7) {
643 		/*
644 		 * Line 1 forward
645 		 */
646 		if (functionMenu[currentMenu].line1.rmenuFunc != 0)
647 		{
648 			functionMenu[currentMenu].line1.rmenuFunc(synth);
649 
650 			return(0);
651 		}
652 		if (functionMenu[currentMenu].line1.next != -1)
653 		{
654 			currentMenu = functionMenu[currentMenu].line1.next;
655 			displayMenu(synth, panel, currentMenu);
656 		}
657 	} else if (operator == 3) {
658 		/*
659 		 * Line 2 back
660 		 */
661 		if (functionMenu[currentMenu].line2.lmenuFunc != 0)
662 		{
663 			functionMenu[currentMenu].line2.lmenuFunc(synth);
664 
665 			return(0);
666 		}
667 		if (functionMenu[currentMenu].line2.last != -1)
668 		{
669 			currentMenu = functionMenu[currentMenu].line2.last;
670 			displayMenu(synth, panel, currentMenu);
671 		}
672 	} else if (operator == 8) {
673 		/*
674 		 * Line 2 forward
675 		 */
676 		if (functionMenu[currentMenu].line2.rmenuFunc != 0)
677 		{
678 			functionMenu[currentMenu].line2.rmenuFunc(synth);
679 
680 			return(0);
681 		}
682 		if (functionMenu[currentMenu].line2.next != -1)
683 		{
684 			currentMenu = functionMenu[currentMenu].line2.next;
685 			displayMenu(synth, panel, currentMenu);
686 		}
687 	} else if (operator == 4) {
688 		/*
689 		 * Line 3 back
690 		 */
691 		if (functionMenu[currentMenu].line3.lmenuFunc != 0)
692 		{
693 			functionMenu[currentMenu].line3.lmenuFunc(synth);
694 
695 			return(0);
696 		}
697 		if (functionMenu[currentMenu].line3.last != -1)
698 		{
699 			currentMenu = functionMenu[currentMenu].line3.last;
700 			displayMenu(synth, panel, currentMenu);
701 		}
702 	} else if (operator == 9) {
703 		/*
704 		 * Line 3 forward
705 		 */
706 		if (functionMenu[currentMenu].line3.rmenuFunc != 0)
707 		{
708 			functionMenu[currentMenu].line3.rmenuFunc(synth);
709 
710 			return(0);
711 		}
712 		if (functionMenu[currentMenu].line3.next != -1)
713 		{
714 			currentMenu = functionMenu[currentMenu].line3.next;
715 			displayMenu(synth, panel, currentMenu);
716 		}
717 	} else if (operator == 5) {
718 		/*
719 		 * Line 4 back
720 		 */
721 		if (functionMenu[currentMenu].line4.lmenuFunc != 0)
722 		{
723 			functionMenu[currentMenu].line4.lmenuFunc(synth);
724 
725 			return(0);
726 		}
727 		if (functionMenu[currentMenu].line4.last != -1)
728 		{
729 			currentMenu = functionMenu[currentMenu].line4.last;
730 			displayMenu(synth, panel, currentMenu);
731 		}
732 	} else if (operator == 10) {
733 		if (functionMenu[currentMenu].line4.rmenuFunc != 0)
734 		{
735 			functionMenu[currentMenu].line4.rmenuFunc(synth);
736 
737 			return(0);
738 		}
739 		/*
740 		 * Line 4 forward
741 		 */
742 		if (functionMenu[currentMenu].line4.next != -1)
743 		{
744 			currentMenu = functionMenu[currentMenu].line4.next;
745 			displayMenu(synth, panel, currentMenu);
746 		}
747 	} else if (operator == 6) {
748 		/*
749 		 * Line 5 back
750 		 */
751 		if (functionMenu[currentMenu].line5.lmenuFunc != 0)
752 		{
753 			functionMenu[currentMenu].line5.lmenuFunc(synth);
754 
755 			return(0);
756 		}
757 		if (functionMenu[currentMenu].line5.last != -1)
758 		{
759 			currentMenu = functionMenu[currentMenu].line5.last;
760 			displayMenu(synth, panel, currentMenu);
761 		}
762 	} else if (operator == 11) {
763 		if (functionMenu[currentMenu].line5.rmenuFunc != 0)
764 		{
765 			functionMenu[currentMenu].line5.rmenuFunc(synth);
766 
767 			return(0);
768 		}
769 		/*
770 		 * Line 5 forward
771 		 */
772 		if (functionMenu[currentMenu].line5.next != -1)
773 		{
774 			currentMenu = functionMenu[currentMenu].line5.next;
775 			displayMenu(synth, panel, currentMenu);
776 		}
777 	}
778 	return(0);
779 }
780 
781 static char *
printInterface(guiSynth * synth)782 printInterface(guiSynth *synth)
783 {
784 	/*
785 	 * Export image to bitmap file.
786 	 */
787 	brightonXpmWrite(synth->win, "/tmp/mixer.xpm");
788 
789 	return(NULL);
790 }
791 
792 #warning - fixed track configuration at 16 tracks.
793 static char *
trackDown(guiSynth * synth)794 trackDown(guiSynth *synth)
795 {
796 	if (--currentTrack < 0)
797 		currentTrack = 15;
798 
799 	printTrackMenu(synth);
800 	return(NULL);
801 }
802 
803 static char *
trackUp(guiSynth * synth)804 trackUp(guiSynth *synth)
805 {
806 	if (++currentTrack == 16)
807 		currentTrack = 0;
808 
809 	printTrackMenu(synth);
810 	return(NULL);
811 }
812 
813 static char *
midiUp(guiSynth * synth)814 midiUp(guiSynth *synth)
815 {
816 	if (++synth->midichannel == 16)
817 		synth->midichannel = 15;
818 
819 	printMidiMenu(synth);
820 	return(NULL);
821 }
822 
823 static char *
midiDown(guiSynth * synth)824 midiDown(guiSynth *synth)
825 {
826 	if (--synth->midichannel < 0)
827 		synth->midichannel = 0;
828 
829 	printMidiMenu(synth);
830 	return(NULL);
831 }
832 
833 static char *
setTrackText(guiSynth * synth)834 setTrackText(guiSynth *synth)
835 {
836 	char scratch[32];
837 
838 	sprintf(scratch, "%s", getMixerMemory((mixerMem *) synth->mem.param, currentTrack + 4, 79));
839 
840 	displayPanel(synth, scratch, 0, currentTrack + 4, PARAM_COUNT - 1);
841 	/*
842 	 * Looks ugly? The issue is that the channels use contiguous store in the
843 	 * gui, but I have to separate this into the memories.
844 	 */
845 	setMixerMemory((mixerMem *) synth->mem.param, CHAN_PANEL, 79 + (currentTrack * 80), 0, scratch);
846 	return(NULL);
847 }
848 
849 static char *
printTrackMenu(guiSynth * synth)850 printTrackMenu(guiSynth *synth)
851 {
852 	char scratch[32];
853 
854 	if ((currentTrack + 4) < 0)
855 		return(NULL);
856 
857 	sprintf(scratch, "%s", getMixerMemory((mixerMem *) synth->mem.param, currentTrack + 4, 79));
858 
859 	/*
860 	 * Create text for track display
861 	 */
862 	sprintf(text, "       Track %i Menu           ", currentTrack + 1);
863 	displayPanel(synth, text, 0, FUNCTION_PANEL, DISPLAY1);
864 
865 	displayPanel(synth,
866 		functionMenu[3].line[0].title, 0, FUNCTION_PANEL, DISPLAY2);
867 
868 	sprintf(text, "Text: %s                         ", scratch);
869 	displayPanel(synth, text, 0, FUNCTION_PANEL, DISPLAY3);
870 
871 	displayPanel(synth,
872 		functionMenu[3].line[2].title, 0, FUNCTION_PANEL, DISPLAY4);
873 	displayPanel(synth,
874 		functionMenu[3].line[3].title, 0, FUNCTION_PANEL, DISPLAY5);
875 	displayPanel(synth,
876 		functionMenu[3].line[4].title, 0, FUNCTION_PANEL, DISPLAY6);
877 	return(NULL);
878 }
879 
880 
881 static char *
songSel1(guiSynth * synth)882 songSel1(guiSynth *synth)
883 {
884 	currentMenu = 20;
885 	/*
886 	 * Set the current song to the given name and then print the list of
887 	 * songs in that directory
888 	 */
889 	loadMixerMemory(synth, memList[memIndex], 1);
890 	memoryList(synth);
891 	return(NULL);
892 }
893 static char *
songSel2(guiSynth * synth)894 songSel2(guiSynth *synth)
895 {
896 	currentMenu = 20;
897 
898 	memIndex += 1;
899 	if (memIndex > memCount) memIndex -= memCount + 1;
900 	loadMixerMemory(synth, memList[memIndex], 1);
901 	memoryList(synth);
902 	return(NULL);
903 }
904 static char *
songSel3(guiSynth * synth)905 songSel3(guiSynth *synth)
906 {
907 	currentMenu = 20;
908 	memIndex += 2;
909 	if (memIndex > memCount) memIndex -= memCount + 1;
910 	loadMixerMemory(synth, memList[memIndex], 1);
911 	memoryList(synth);
912 	return(NULL);
913 }
914 static char *
songSel4(guiSynth * synth)915 songSel4(guiSynth *synth)
916 {
917 	currentMenu = 20;
918 	memIndex += 3;
919 	if (memIndex > memCount) memIndex -= memCount + 1;
920 	loadMixerMemory(synth, memList[memIndex], 1);
921 	memoryList(synth);
922 	return(NULL);
923 }
924 
925 static char *
createSongDir(guiSynth * synth)926 createSongDir(guiSynth *synth)
927 {
928 	loadMixerMemory(synth, memscratch, 2);
929 	return(NULL);
930 }
931 
932 static char *
memorySel1(guiSynth * synth)933 memorySel1(guiSynth *synth)
934 {
935 	currentMenu = 14;
936 
937 	sprintf(memscratch, "%s", memList[memIndex]);
938 
939 	printMemMenu(synth);
940 	return(NULL);
941 }
942 static char *
memorySel2(guiSynth * synth)943 memorySel2(guiSynth *synth)
944 {
945 	currentMenu = 14;
946 
947 	memIndex += 1;
948 	if (memIndex > memCount) memIndex -= memCount + 1;
949 	sprintf(memscratch, "%s", memList[memIndex]);
950 
951 	printMemMenu(synth);
952 	return(NULL);
953 }
954 static char *
memorySel3(guiSynth * synth)955 memorySel3(guiSynth *synth)
956 {
957 	currentMenu = 14;
958 
959 	memIndex += 2;
960 	if (memIndex > memCount) memIndex -= memCount + 1;
961 	sprintf(memscratch, "%s", memList[memIndex]);
962 
963 	printMemMenu(synth);
964 	return(NULL);
965 }
966 static char *
memorySel4(guiSynth * synth)967 memorySel4(guiSynth *synth)
968 {
969 	currentMenu = 14;
970 
971 	memIndex += 3;
972 	if (memIndex > memCount) memIndex -= memCount + 1;
973 	sprintf(memscratch, "%s", memList[memIndex]);
974 
975 	printMemMenu(synth);
976 	return(NULL);
977 }
978 
979 static char *
songBuildList(guiSynth * synth)980 songBuildList(guiSynth *synth)
981 {
982 	char *entry;
983 
984 	memCount = -1;
985 
986 	while ((entry = getMixerMemory((mixerMem *) synth->mem.param, MM_GETLIST, 1)) != 0)
987 		sprintf(memList[++memCount], "%s", entry);
988 	/*while ((entry = ((char *) mixerMemory(synth, MM_GET, MM_GETLIST, 1, 0)))
989 		!= 0)
990 		sprintf(memList[++memCount], "%s", entry); */
991 	return(NULL);
992 }
993 
994 static char *
memoryBuildList(guiSynth * synth)995 memoryBuildList(guiSynth *synth)
996 {
997 	char *entry;
998 
999 	memCount = -1;
1000 
1001 	while ((entry = (getMixerMemory((mixerMem *) synth->mem.param, MM_GETLIST, 0))) != 0)
1002 		sprintf(memList[++memCount], "%s", entry);
1003 	return(NULL);
1004 }
1005 
1006 static char *
songShowList(guiSynth * synth)1007 songShowList(guiSynth *synth)
1008 {
1009 	int mi = memIndex;
1010 
1011 	if (memCount < 0)
1012 		songBuildList(synth);
1013 
1014 	/*
1015 	 * Then show the memory entries in the panel from the list with the
1016 	 * given index
1017 	 */
1018 	sprintf(text, "%s", functionMenu[21].title.title);
1019 	displayPanel(synth, text, 0, FUNCTION_PANEL, DISPLAY1);
1020 
1021 	displayPanel(synth, memList[mi], 0, FUNCTION_PANEL, DISPLAY2);
1022 	if (mi++ >= memCount) mi = 0;
1023 	displayPanel(synth, memList[mi], 0, FUNCTION_PANEL, DISPLAY3);
1024 	if (mi++ >= memCount) mi = 0;
1025 	displayPanel(synth, memList[mi], 0, FUNCTION_PANEL, DISPLAY4);
1026 	if (mi++ >= memCount) mi = 0;
1027 	displayPanel(synth, memList[mi], 0, FUNCTION_PANEL, DISPLAY5);
1028 
1029 	displayPanel(synth,
1030 		functionMenu[21].line[4].title, 0, FUNCTION_PANEL, DISPLAY6);
1031 	return(NULL);
1032 }
1033 
1034 static char *
memoryShowList(guiSynth * synth)1035 memoryShowList(guiSynth *synth)
1036 {
1037 	int mi = memIndex;
1038 
1039 	if (memCount < 0)
1040 		memoryBuildList(synth);
1041 
1042 	/*
1043 	 * Then show the memory entries in the panel from the list with the
1044 	 * given index
1045 	 */
1046 	sprintf(text, "%s", functionMenu[20].title.title);
1047 	displayPanel(synth, text, 0, FUNCTION_PANEL, DISPLAY1);
1048 
1049 	displayPanel(synth, memList[mi], 0, FUNCTION_PANEL, DISPLAY2);
1050 	if (mi++ >= memCount) mi = 0;
1051 	displayPanel(synth, memList[mi], 0, FUNCTION_PANEL, DISPLAY3);
1052 	if (mi++ >= memCount) mi = 0;
1053 	displayPanel(synth, memList[mi], 0, FUNCTION_PANEL, DISPLAY4);
1054 	if (mi++ >= memCount) mi = 0;
1055 	displayPanel(synth, memList[mi], 0, FUNCTION_PANEL, DISPLAY5);
1056 
1057 	displayPanel(synth,
1058 		functionMenu[20].line[4].title, 0, FUNCTION_PANEL, DISPLAY6);
1059 	return(NULL);
1060 }
1061 
1062 static char *
songList(guiSynth * synth)1063 songList(guiSynth *synth)
1064 {
1065 	/*
1066 	 * We need to build a list of the memories in our default directory.
1067 	 * This should become a few routines, one that builds that list and two
1068 	 * that allow us to scroll up and down it.
1069 	 */
1070 	songBuildList(synth);
1071 
1072 	songShowList(synth);
1073 
1074 	currentMenu = 21;
1075 	return(NULL);
1076 }
1077 
1078 static char *
memoryList(guiSynth * synth)1079 memoryList(guiSynth *synth)
1080 {
1081 	/*
1082 	 * We need to build a list of the memories in our default directory.
1083 	 * This should become a few routines, one that builds that list and two
1084 	 * that allow us to scroll up and down it.
1085 	 */
1086 	memoryBuildList(synth);
1087 
1088 	memoryShowList(synth);
1089 
1090 	currentMenu = 20;
1091 	return(NULL);
1092 }
1093 
1094 static char *
memoryListDown(guiSynth * synth)1095 memoryListDown(guiSynth *synth)
1096 {
1097 	/*
1098 	 * Cycle upwards though our list and show the names.
1099 	 */
1100 	if (++memIndex > memCount)
1101 		memIndex = 0;
1102 
1103 	memoryShowList(synth);
1104 
1105 	return(NULL);
1106 }
1107 
1108 static char *
memoryListUp(guiSynth * synth)1109 memoryListUp(guiSynth *synth)
1110 {
1111 	/*
1112 	 * Cycle downwards though our list and show the names.
1113 	 */
1114 	if (--memIndex < 0)
1115 		memIndex = memCount;
1116 
1117 	memoryShowList(synth);
1118 
1119 	return(0);
1120 }
1121 
1122 static char *
printMemMenu(guiSynth * synth)1123 printMemMenu(guiSynth *synth)
1124 {
1125 	/*
1126 	 * Create text for track display
1127 	displayPanel(synth, "        Mem Menu              ",
1128 		0, FUNCTION_PANEL, DISPLAY1);
1129 	 */
1130 	displayPanel(synth, functionMenu[14].title.title,
1131 		0, FUNCTION_PANEL, DISPLAY1);
1132 
1133 	sprintf(text, "Name: %s                         ", memscratch);
1134 	displayPanel(synth, text, 0, FUNCTION_PANEL, DISPLAY2);
1135 
1136 	displayPanel(synth,
1137 		functionMenu[14].line[1].title, 0, FUNCTION_PANEL, DISPLAY3);
1138 	displayPanel(synth,
1139 		functionMenu[14].line[2].title, 0, FUNCTION_PANEL, DISPLAY4);
1140 	displayPanel(synth,
1141 		functionMenu[14].line[3].title, 0, FUNCTION_PANEL, DISPLAY5);
1142 	displayPanel(synth,
1143 		functionMenu[14].line[4].title, 0, FUNCTION_PANEL, DISPLAY6);
1144 	return(NULL);
1145 }
1146 
1147 static char *
printMidiMenu(guiSynth * synth)1148 printMidiMenu(guiSynth *synth)
1149 {
1150 	/*
1151 	 * Create text for track display
1152 	 */
1153 	displayPanel(synth, "       Midi Menu              ",
1154 		0, FUNCTION_PANEL, DISPLAY1);
1155 
1156 	displayPanel(synth,
1157 		functionMenu[17].line[0].title,
1158 		0, FUNCTION_PANEL, DISPLAY2);
1159 
1160 	sprintf(text, "Channel: %i                       ", synth->midichannel + 1);
1161 	displayPanel(synth, text, 0, FUNCTION_PANEL, DISPLAY3);
1162 
1163 	displayPanel(synth,
1164 		functionMenu[17].line[2].title, 0, FUNCTION_PANEL, DISPLAY4);
1165 	displayPanel(synth,
1166 		functionMenu[17].line[3].title, 0, FUNCTION_PANEL, DISPLAY5);
1167 	displayPanel(synth,
1168 		functionMenu[17].line[4].title, 0, FUNCTION_PANEL, DISPLAY6);
1169 	return(NULL);
1170 }
1171 
1172 static char *
removeInterface(guiSynth * synth)1173 removeInterface(guiSynth *synth)
1174 {
1175 	/*
1176 	 * Exit application, completely.
1177 	 */
1178 	brightonRemoveInterface(synth->win);
1179 	return(NULL);
1180 }
1181 
1182 brightonEvent event;
1183 
1184 int
doAlarm()1185 doAlarm()
1186 {
1187 	event.type = BRIGHTON_FLOAT;
1188 	event.value = 0.0;
1189 
1190 /*	brightonSendEvent((void *) theSynth->win, 2, DISPLAY1 - 1, &event); */
1191 	return(0);
1192 }
1193 
1194