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 #include <sys/types.h>
26 #include <dirent.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 
30 #include "bristol.h"
31 #include "bristolmidi.h"
32 #include "brightonMixer.h"
33 #include "brightonMixerMemory.h"
34 
35 #include "brighton.h"
36 #include "brightonMini.h"
37 
38 static mixerMem *new = NULL, *prev = NULL;
39 static char songDir[32] = "default";
40 
41 static DIR *memlist = NULL;
42 static struct dirent *entry;
43 
44 extern guimain global;
45 extern void displayPanel(guiSynth *, char *, int, int, int);
46 
47 /*
48  * Most of this is actually borrowed from brightonroutines.c, but since the
49  * mixer operations are a little central to the whole application have chosen
50  * to make it bespoke
51  */
saveMixerMemory(guiSynth * synth,char * name)52 int saveMixerMemory(guiSynth *synth, char *name)
53 {
54 	char path[256];
55 	int fd;
56 
57 	sprintf(path, "%s/memory/%s/%s/%s.mem",
58 		getBristolCache("midicontrollermap"), "mixer", songDir, name);
59 	sprintf(synth->mem.algo, "mixer");
60 	if (name == NULL)
61 		sprintf(synth->mem.name, "no name");
62 	else
63 		sprintf(synth->mem.name, "%s", name);
64 
65 	if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0660)) < 0)
66 		return(-1);
67 
68 	if (write(fd, &synth->mem, sizeof(struct Memory) - sizeof(float *)) < 0)
69 		printf("write failed 1\n");
70 	if (write(fd, synth->mem.param, sizeof(mixerMem)) < 0)
71 		printf("write failed 1\n");
72 
73 	close(fd);
74 
75 	return(0);
76 }
77 
78 static int
doLoadMixerMemory(guiSynth * synth)79 doLoadMixerMemory(guiSynth *synth)
80 {
81 	brightonEvent event;
82 	int channel, param;
83 
84 	event.type = BRIGHTON_FLOAT;
85 
86 	/*
87 	 * Now we have the parameters loaded we need to start sending off events
88 	 * to the GUI to draw the mixer, that will notify the engine and set the
89 	 * parameters here again (as an undesirable sideffect);
90 	 *
91 	 * Going to start with the steroe bus section as it is (comparatively) easy.
92 	 */
93 	for (channel = 0; channel < 4; channel++)
94 	{
95 		event.value = new->vbus[channel].clear.vol;
96 		brightonParamChange(synth->win, BUS_PANEL,
97 			240 + channel * 3, &event);
98 
99 		event.value = new->vbus[channel].clear.left;
100 		brightonParamChange(synth->win, BUS_PANEL,
101 			240 + channel * 3 + 1, &event);
102 
103 		event.value = new->vbus[channel].clear.right;
104 		brightonParamChange(synth->win, BUS_PANEL,
105 			240 + channel * 3 + 2, &event);
106 	}
107 
108 	/*
109 	 * Effects bussing section
110 	 */
111 	for (channel = 0; channel < 8; channel++)
112 	{
113 		/*
114 		 * Six events for the continuous controllers
115 		 */
116 		for (param = 0; param < 6; param++)
117 		{
118 			event.value = new->bus[channel].b.opaque[param];
119 			brightonParamChange(synth->win, BUS_PANEL,
120 				channel * 30 + param, &event);
121 		}
122 
123 		/*
124 		 * One event for the FX select
125 		new->bus[channel].b.clear.algorithm;
126 		 */
127 		event.value = 1.01;
128 		if (new->bus[channel].b.clear.algorithm < 0)
129 		{
130 			brightonParamChange(synth->win, BUS_PANEL,
131 				channel * 30 + 6, &event);
132 			event.value = 0.0;
133 			brightonParamChange(synth->win, BUS_PANEL,
134 				channel * 30 + 6, &event);
135 		} else {
136 			if (new->bus[channel].b.clear.algorithm !=
137 				prev->bus[channel].b.clear.algorithm)
138 				brightonParamChange(synth->win, BUS_PANEL,
139 					channel * 30 + 6 + new->bus[channel].b.clear.algorithm,
140 						&event);
141 		}
142 
143 		/*
144 		 * Sixteen events for the output busses.
145 		 */
146 		for (param = 0; param < 16; param++)
147 		{
148 			/*
149 			if (new->bus[channel].b.clear.outputSelect[param] <= 0)
150 				event.value = 0.0;
151 			else
152 				event.value = 1.01;
153 			*/
154 			event.value = new->bus[channel].b.clear.outputSelect[param];
155 			brightonParamChange(synth->win, BUS_PANEL,
156 				channel * 30 + 14 + param, &event);
157 		}
158 	}
159 
160 	/*
161 	 * And the channels themselves.
162  	 */
163 	for (channel = 0; channel < new->chancount; channel++)
164 	{
165 		/*
166 		 * One event for the input selection. There are several logical states:
167 		 * 1. New track has selection - call it.
168 		 * 2. New Track has no selection - clear the previous one.
169 	 	 */
170 		if (new->chan[channel].inputSelect >= 0)
171 		{
172 			/*
173 			 * Only apply if the parameter has changed
174 			 */
175 			if (new->chan[channel].inputSelect
176 				!= prev->chan[channel].inputSelect)
177 			{
178 				event.value = 1.0;
179 				brightonParamChange(synth->win, channel + 4,
180 					new->chan[channel].inputSelect, &event);
181 			}
182 		} else {
183 			event.value = 1.0;
184 			brightonParamChange(synth->win, channel + 4, 0, &event);
185 			event.value = 0.0;
186 			brightonParamChange(synth->win, channel + 4, 0, &event);
187 		}
188 
189 		/*
190 		 * Presend bus selections
191 		 */
192 		for (param = 0; param < 4; param++)
193 		{
194 			event.value = new->chan[channel].preSend[param];
195 			brightonParamChange(synth->win, channel + 4,
196 				16 + param, &event);
197 		}
198 
199 		/*
200 		 * Dynamics algorithm selection
201 		 */
202 		if (new->chan[channel].dynamics >= 0)
203 		{
204 			if (new->chan[channel].dynamics != prev->chan[channel].dynamics)
205 			{
206 				event.value = 1.01;
207 				brightonParamChange(synth->win, channel + 4,
208 					20 + new->chan[channel].dynamics, &event);
209 			}
210 		} else {
211 			event.value = 1.01;
212 			brightonParamChange(synth->win, channel + 4,
213 				20, &event);
214 			event.value = 0.0;
215 			brightonParamChange(synth->win, channel + 4,
216 				20, &event);
217 		}
218 
219 		/*
220 		 * Filter algorithm selection
221 		 */
222 		if (new->chan[channel].filter >= 0)
223 		{
224 			if (new->chan[channel].filter != prev->chan[channel].filter)
225 			{
226 				event.value = 1.01;
227 				brightonParamChange(synth->win, channel + 4,
228 					23 + new->chan[channel].filter, &event);
229 			}
230 		} else {
231 			event.value = 1.01;
232 			brightonParamChange(synth->win, channel + 4,
233 				23, &event);
234 			event.value = 0.0;
235 			brightonParamChange(synth->win, channel + 4,
236 				23, &event);
237 		}
238 
239 		/*
240 		 * Postsend bus selections
241 		 */
242 		for (param = 0; param < 4; param++)
243 		{
244 			event.value = new->chan[channel].postSend[param];
245 			brightonParamChange(synth->win, channel + 4,
246 				27 + param, &event);
247 		}
248 
249 		/*
250 		 * FX algorithm selection
251 		 */
252 		if (new->chan[channel].fxAlgo >= 0)
253 		{
254 			if (new->chan[channel].fxAlgo != prev->chan[channel].fxAlgo)
255 			{
256 				event.value = 1.01;
257 				brightonParamChange(synth->win, channel + 4,
258 					31 + new->chan[channel].fxAlgo, &event);
259 			}
260 		} else {
261 			event.value = 1.01;
262 			brightonParamChange(synth->win, channel + 4,
263 				31, &event);
264 			event.value = 0.0;
265 			brightonParamChange(synth->win, channel + 4,
266 				31, &event);
267 		}
268 
269 		/*
270 		 * Continuous controllers
271 		 */
272 		for (param = 0; param < 17; param++)
273 		{
274 			event.value = new->chan[channel].p.opaque[param];
275 			brightonParamChange(synth->win, channel + 4,
276 				38 + param, &event);
277 		}
278 
279 		event.value = new->chan[channel].mute;
280 		brightonParamChange(synth->win, channel + 4, 55, &event);
281 		event.value = new->chan[channel].solo;
282 		brightonParamChange(synth->win, channel + 4, 56, &event);
283 		event.value = new->chan[channel].boost;
284 		brightonParamChange(synth->win, channel + 4, 57, &event);
285 
286 		/*
287 		 * Output select
288 		 */
289 		for (param = 0; param < 16; param++)
290 		{
291 			event.value = new->chan[channel].outputSelect[param];
292 			brightonParamChange(synth->win, channel + 4,
293 				58 + param, &event);
294 		}
295 
296 		/*
297 		 * vBus selection
298 		 */
299 		if (new->chan[channel].stereoBus >= 0)
300 		{
301 			if (new->chan[channel].stereoBus != prev->chan[channel].stereoBus)
302 			{
303 				event.value = 1.01;
304 				brightonParamChange(synth->win, channel + 4,
305 					74 + new->chan[channel].stereoBus, &event);
306 			}
307 		} else {
308 			event.value = 1.01;
309 			brightonParamChange(synth->win, channel + 4,
310 				74, &event);
311 			event.value = 0.0;
312 			brightonParamChange(synth->win, channel + 4,
313 				74, &event);
314 		}
315 
316 		event.value = new->chan[channel].p.clear.vol;
317 		brightonParamChange(synth->win, channel + 4, 78, &event);
318 
319 		displayPanel(synth, new->chan[channel].scratch, 0, channel + 4, 79);
320 		sprintf(((mixerMem *) synth->mem.param)->chan[channel].scratch, "%s", new->chan[channel].scratch);
321 	}
322 
323 	return(0);
324 }
325 
326 /*
327  * Saving the memory is reasonably trivial. Reading it back is a little more
328  * work since we have to call the parameter routines to set the values.
329  */
loadMixerMemory(guiSynth * synth,char * name,int param)330 int loadMixerMemory(guiSynth *synth, char *name, int param)
331 {
332 	char path[256];
333 	int fd;
334 
335 	if (param == 1)
336 	{
337 		sprintf(songDir, "%s", name);
338 		return(0);
339 	}
340 	if (param == 2)
341 	{
342 		if (strlen(name) != 0)
343 		{
344 			sprintf(path, "%s/memory/%s/%s", getBristolCache("midicontrollermap"), "mixer", name);
345 			mkdir(path, 0755);
346 		}
347 		return(0);
348 	}
349 
350 	if (strcmp(name, "revert") == 0)
351 	{
352 		mixerMem *t;
353 
354 		bcopy(prev, new, sizeof(mixerMem));
355 		t = prev;
356 		prev = (mixerMem *) synth->mem.param;
357 		synth->mem.param = (float *) t;
358 
359 		doLoadMixerMemory(synth);
360 
361 		return(0);
362 	}
363 
364 	sprintf(path, "%s/memory/%s/%s/%s.mem",
365 		getBristolCache("midicontrollermap"), "mixer", songDir, name);
366 
367 	if ((fd = open(path, O_RDONLY, 0770)) < 0)
368 	{
369 		sprintf(path, "%s/memory/%s/%s/%s.mem",
370 			global.home, "mixer", songDir, name);
371 		if ((fd = open(path, O_RDONLY, 0770)) < 0)
372 			return(-1);
373 	}
374 
375 	if (read(fd, &synth->mem.algo[0], 32) < 0)
376 		printf("read failed\n");
377 	if (read(fd, &synth->mem.name[0], 32) < 0)
378 		printf("read failed\n");
379 
380 	if (read(fd, new, 2 * sizeof(int)) < 0)
381 		printf("read failed\n");
382 
383 	if (read(fd, new, sizeof(mixerMem)) < 0)
384 		printf("read failed\n");
385 
386 	bcopy(synth->mem.param, prev, sizeof(mixerMem));
387 
388 	doLoadMixerMemory(synth);
389 
390 	close(fd);
391 
392 	return(0);
393 }
394 
395 /*
396  * Get a memory structure, null it out, put in a few details and give it back
397  */
398 void *
initMixerMemory(int count)399 initMixerMemory(int count)
400 {
401 	int i;
402 	mixerMem *m;
403 
404 	if ((m = (mixerMem *) malloc(sizeof(mixerMem))) == NULL)
405 		return(0);
406 	if ((new = (mixerMem *) malloc(sizeof(mixerMem))) == NULL)
407 		return(0);
408 	if ((prev = (mixerMem *) malloc(sizeof(mixerMem))) == NULL)
409 		return(0);
410 
411 	bzero(m, sizeof(mixerMem));
412 
413 	sprintf(&m->name[0], "no name");
414 	m->version = MIXER_VERSION;
415 	m->chancount = count;
416 
417 	for (i = 0; i < MAX_CHAN_COUNT; i++)
418 	{
419 		m->chan[i].inputSelect = -1;
420 		m->chan[i].dynamics = -1;
421 		m->chan[i].filter = -1;
422 		m->chan[i].fxAlgo = -1;
423 		m->chan[i].stereoBus = -1;
424 		sprintf(&m->chan[i].scratch[0], "Trk: %i", i + 1);
425 	}
426 	for (i = 0; i < MAX_VBUS_COUNT; i++)
427 		m->bus[i].b.clear.algorithm = -1;
428 
429 	bcopy(m, prev, sizeof(mixerMem));
430 
431 	return(m);
432 }
433 
434 char *
getMixerMemory(mixerMem * m,int op,int param)435 getMixerMemory(mixerMem *m, int op, int param)
436 {
437 	char path[256], *dotptr;
438 
439 	switch(op)
440 	{
441 		case MM_GETLIST:
442 			if (memlist == 0)
443 			{
444 				/*
445 				 * See if we want to list songs or memories in a song dir
446 				 */
447 				if (param == 1)
448 					sprintf(path, "%s/memory/%s",
449 						global.home, "mixer");
450 				else
451 					sprintf(path, "%s/memory/%s/%s",
452 						global.home, "mixer", songDir);
453 
454 				if ((memlist = opendir(path)) == NULL)
455 					return(0);
456 			}
457 
458 			if ((entry = readdir(memlist)) == 0)
459 			{
460 				closedir(memlist);
461 				memlist = NULL;
462 				return(0);
463 			}
464 
465 			while (entry->d_name[0] == '.')
466 			{
467 				if ((entry = readdir(memlist)) == 0)
468 				{
469 					closedir(memlist);
470 					memlist = NULL;
471 					return(0);
472 				}
473 			}
474 
475 			if ((dotptr = index(entry->d_name, '.')) != NULL)
476 				*dotptr = '\0';
477 
478 			/*
479 			 * Call a set of routines that will open the directory and then
480 			 * return its contents until finnished.
481 			 */
482 			return(entry->d_name);
483 		default:
484 			if (param == 79) {
485 				return(&m->chan[op - 4].scratch[0]);
486 			}
487 	}
488 
489 	return(0);
490 }
491 
492 int
setMixerMemory(mixerMem * m,int op,int param,float * value,char * text)493 setMixerMemory(mixerMem *m, int op, int param, float *value, char *text)
494 {
495 	int channel = 0, offset = 0;
496 
497 	switch(op)
498 	{
499 		case VBUS_PANEL:
500 			/*
501 			 * We expect parameters from 0 to 12, they will translate to
502 			 * The bus:v/l/r
503 			 */
504 			channel = param / 3;
505 			offset = param % 3;
506 
507 			m->vbus[channel].opaque[offset] = *value;
508 
509 			break;
510 		case BUS_PANEL:
511 			/*
512 			 * but parameters are opaque but I want to separate them out
513 			 * here since the functions will be unique in the engine.
514 			 */
515 			channel = param / 30;
516 			offset = param % 30;
517 
518 			if (offset < 6)
519 				/*
520 				 * Continuous controllers
521 				 */
522 				m->bus[channel].b.opaque[offset] = *value;
523 			else if (offset < 14) {
524 				/*
525 				 * FX Selector, single value
526 				 */
527 				if (*value == 0)
528 					m->bus[channel].b.clear.algorithm = -1;
529 				else
530 					m->bus[channel].b.clear.algorithm = offset - 6;
531 			} else if (offset < 30) {
532 				/*
533 				 * Output channel selection
534 				 */
535 				m->bus[channel].b.clear.outputSelect[offset - 14] = *value;
536 			}
537 
538 			break;
539 		default:
540 			channel = op - 4;
541 			offset = param;
542 
543 			if (offset < 16) {
544 				/*
545 				 * Input channel selection radio buttons
546 				 */
547 				if (*value == 0) {
548 					m->chan[channel].inputSelect = -1;
549 				} else {
550 					m->chan[channel].inputSelect = offset;
551 				}
552 			} else if (offset < 20) {
553 				/*
554 				 * Presend bus selection.
555 				 */
556 				m->chan[channel].preSend[offset - 16] = *value;
557 			} else if (offset < 23) {
558 				/*
559 				 * Dynamics also radio button selection.
560 				 */
561 				if (*value == 0) {
562 					m->chan[channel].dynamics = -1;
563 				} else {
564 					m->chan[channel].dynamics = offset - 20;
565 				}
566 			} else if (offset < 27) {
567 				/*
568 				 * Filter algo radio button selection.
569 				 */
570 				if (*value == 0) {
571 					m->chan[channel].filter = -1;
572 				} else {
573 					m->chan[channel].filter = offset - 23;
574 				}
575 			} else if (offset < 31) {
576 				/*
577 				 * Postsend bus selection.
578 				 */
579 				m->chan[channel].postSend[offset - 27] = *value;
580 			} else if (offset < 38) {
581 				/*
582 				 * Effect radio button selection.
583 				 */
584 				if (*value == 0) {
585 					m->chan[channel].fxAlgo = -1;
586 				} else {
587 					m->chan[channel].fxAlgo = offset - 31;
588 				}
589 			} else if (offset < 55) {
590 				/*
591 				 * The continuous controllers less fader
592 				 */
593 				m->chan[channel].p.opaque[offset - 38] = *value;
594 			} else if (offset == 55) {
595 				m->chan[channel].mute = *value;
596 			} else if (offset == 56) {
597 				m->chan[channel].solo = *value;
598 			} else if (offset == 57) {
599 				m->chan[channel].boost = *value;
600 			} else if (offset < 74) {
601 				m->chan[channel].outputSelect[offset - 58] = *value;
602 			} else if (offset < 78) {
603 				/*
604 				 * vBus radio buttons
605 				 */
606 				if (*value == 0) {
607 					m->chan[channel].stereoBus = -1;
608 				} else {
609 					m->chan[channel].stereoBus = offset - 74;
610 				}
611 			} else if (offset == 78) {
612 				m->chan[channel].p.clear.vol = *value;
613 			} else if (offset == 79) {
614 				if (text != NULL)
615 					sprintf(m->chan[channel].scratch, "%s", text);
616 			}
617 			break;
618 	}
619 	return(0);
620 }
621 
622 
623 /*
624  * loadMemory, saveMemory, initMemory, get/setMemory?
625  */
626 /* wow. the return type of this varies depending on op.  no.  -DR */
627 int
mixerMemory(guiSynth * synth,int op,int subop,int param,void * value)628 mixerMemory(guiSynth *synth, int op, int subop, int param, void *value)
629 {
630 	switch(op) {
631 		case MM_SAVE:
632 			return(saveMixerMemory(synth, value));
633 		case MM_LOAD:
634 			return(loadMixerMemory(synth, value, param));
635 		case MM_INIT:
636 			/*
637 			 * This was orginally a rather dumb typecast
638 			return((int) initMixerMemory(param));
639 			 * Need to review all of this code as the mixer gets rolled out
640 			 */
641 			return(0);
642 		case MM_SET:
643 			return(setMixerMemory((mixerMem *) synth->mem.param,
644 				subop, param, value, NULL));
645 		/*
646 		 * This will be moved into a separate call.
647 		case MM_GET:
648 			return(getMixerMemory((mixerMem *) synth->mem.param,
649 				subop, param, value));
650 		 */
651 	}
652 	return(0);
653 }
654 
655