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 <string.h>
24 #include <strings.h>
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <signal.h>
32 #include <unistd.h>
33 
34 #include "bristol.h"
35 #include "brightoninternals.h"
36 #include "brightonMini.h"
37 
38 extern guimain global;
39 
40 extern void brightonMidiInput(bristolMidiMsg *, guimain *);
41 
42 struct sockaddr address;
43 
44 /*
45  * Free any memory we have have used up, close the link to the control socket
46  * potentially sending a disconnect request.
47  */
48 void
cleanupBristolQuietly()49 cleanupBristolQuietly()
50 {
51 	/*
52 	 * This comes from a sigpipe only. This means we have lost our socket to
53 	 * to the engine OR our socket to the X server, which is a bit of a bummer
54 	 * since in one case we want to send a message to the engine but if it
55 	 * is this socket that failed we will then get a SIGPIPE again.
56 	 *
57 	 * Put the signal back on default handling and then call the normal
58 	 * cleanup routines. If this was the engine socket then we will then die
59 	 * reasonably gracefully.....
60 	global.controlfd = -1;
61 	cleanupBristol();
62 	 */
63 	signal(SIGPIPE, SIG_DFL);
64 	signal(SIGINT, SIG_DFL);
65 	cleanupBristol();
66 }
67 
68 void
cleanupBristol()69 cleanupBristol()
70 {
71 	bristolMidiMsg msg;
72 
73 	close(0);
74 
75 	if (global.synths->win != 0)
76 		global.synths->win->flags |= BRIGHTON_EXITING;
77 
78 	if (global.synths->flags & REQ_DEBUG_MASK)
79 		printf("cleanupBrighton()\n");
80 
81 	if (global.libtest)
82 	{
83 		global.flags |= REQ_EXIT;
84 		return;
85 	}
86 
87 	if (global.controlfd < 0)
88 	{
89 		global.flags |= REQ_EXIT;
90 		return;
91 	}
92 
93 	/*
94 	 * We don't need to clean out every synth, we need to cleanout the second
95 	 * manual if it is configured, then the controlfd
96 	bristolMidiSendNRP(global.controlfd, global.synths->sid,
97 		BRISTOL_NRP_MIDI_GO, 0);
98 	 */
99 
100 	if ((global.manualfd != 0) && (global.manualfd != global.controlfd))
101 	{
102 		bristolMidiSendMsg(global.manualfd, global.synths->sid2,
103 			127, 0, BRISTOL_EXIT_ALGO);
104 		if (global.synths->flags & REQ_DEBUG_MASK)
105 			printf("Secondary layer removed\n");
106 		/* OK, so sleep is lax, we used to wait for a message */
107 		bristolMidiRead(global.controlfd, &msg);
108 	}
109 
110 	/* The engine has to restart MIDI processing after the exit */
111 	bristolMidiSendNRP(global.controlfd, global.synths->sid,
112 		BRISTOL_NRP_MIDI_GO, 0);
113 
114 	bristolMidiSendMsg(global.controlfd, global.synths->sid,
115 		127, 0, BRISTOL_EXIT_ALGO);
116 	if (global.synths->flags & REQ_DEBUG_MASK)
117 		printf("Primary layer removed\n");
118 	/* We used to wait for a message however it is of no interest now */
119 	//bristolMidiRead(global.controlfd, &msg);
120 
121 	usleep(250000);
122 
123 	if ((global.manualfd != 0) && (global.manualfd != global.controlfd))
124 		bristolMidiClose(global.manualfd);
125 	bristolMidiClose(global.controlfd);
126 
127 	printf("brighton exiting\n");
128 
129 	//BAutoRepeat(global.synths->win->display, 1);
130 
131 	//sleep(1);
132 	global.flags |= REQ_EXIT;
133 
134 	//exit(0);
135 }
136 
137 int
destroySynth(brightonWindow * win)138 destroySynth(brightonWindow* win)
139 {
140 	guiSynth *synth = findSynth(global.synths, win);
141 	bristolMidiMsg msg;
142 
143 	printf("destroySynth(%p): %i\n", win, synth->sid);
144 
145 	/*
146 	 * Since we registered two synths, we now need to remove the upper
147 	 * manual.
148 	 */
149 	bristolMidiSendMsg(global.controlfd, synth->sid, 127, 0,
150 		BRISTOL_EXIT_ALGO);
151 
152 	if (bristolMidiRead(global.controlfd, &msg) < 0)
153 		printf("socket closed\n");
154 
155 	return(0);
156 }
157 
158 void
displayPanel(guiSynth * synth,char * text,int value,int panel,int index)159 displayPanel(guiSynth *synth, char *text, int value, int panel, int index)
160 {
161 	brightonEvent event;
162 	char display[32];
163 
164 	memset(&event, 0, sizeof(brightonEvent));
165 
166 	sprintf(display, "%s", text);
167 	event.type = BRIGHTON_MEM;
168 	event.m = (void *) &display[0];
169 	brightonParamChange(synth->win, panel, index, &event);
170 }
171 
172 int
displayPanelText(guiSynth * synth,char * text,int value,int panel,int index)173 displayPanelText(guiSynth *synth, char *text, int value, int panel, int index)
174 {
175 	brightonEvent event;
176 	char display[32];
177 
178 	memset(&event, 0, sizeof(brightonEvent));
179 
180 	sprintf(display, "%s: %i", text, value);
181 	event.type = BRIGHTON_MEM;
182 	event.m = (void *) &display[0];
183 	brightonParamChange(synth->win, panel, index, &event);
184 
185 	return(0);
186 }
187 
188 int
displayText(guiSynth * synth,char * text,int value,int index)189 displayText(guiSynth *synth, char *text, int value, int index)
190 {
191 	brightonEvent event;
192 	char display[32];
193 
194 	memset(&event, 0, sizeof(brightonEvent));
195 
196 	sprintf(display, "%s: %i", text, value);
197 	event.type = BRIGHTON_MEM;
198 	event.m = (void *) &display[0];
199 	brightonParamChange(synth->win, synth->panel, index, &event);
200 
201 	return(0);
202 }
203 
204 guiSynth *
findSynth(guiSynth * synth,brightonWindow * win)205 findSynth(guiSynth *synth, brightonWindow* win)
206 {
207 /*printf("findSynth(%x, %x)\n", synth, reference); */
208 	if (synth == 0)
209 		return(0);
210 
211 	if (synth->win == win)
212 		return(synth);
213 
214 	return(findSynth(synth->next, win));
215 }
216 
217 static char *myHome = NULL;
218 
219 char *
oldgetBristolCache()220 oldgetBristolCache()
221 {
222 	/*
223 	 * See if we have a valid private directory, if we do not find one then
224 	 * create it.
225 	 */
226 	if (myHome == NULL)
227 	{
228 		struct stat statbuf;
229 		char *envcache;
230 		char path[1024];
231 
232 		myHome = (char *) calloc(1024, 1);
233 
234 		/*
235 		 * See if we have an env configured if so see if it exists, if not
236 		 * create a tree.
237 		 *
238 		 * If this fails then use $HOME/.bristol and create the tree.
239 		 *
240 		 * If these fail then fall back to the factory tree.
241 		 */
242 
243 		if ((envcache = getenv("BRISTOL_CACHE")) != NULL)
244 		{
245 			/*
246 			 * See if we can access the cache.
247 			 */
248 			if (stat(envcache, &statbuf) == 0) {
249 				/*
250 				 * If we have the cache, is it formatted and do we have
251 				 * permissions? There are several cases:
252 				 *	We own it and have rw permissions.
253 				 *	Somebody else owns it but we have write permissions
254 				 *	We are in the group and have write permissions.
255 				 * I think we should only take the first option since otherwise
256 				 * we can create memories that other users may not be able to
257 				 * access due to our umask.
258 				 */
259 				sprintf(path, "%s/memory", envcache);
260 
261 				if (stat(path, &statbuf) == 0) {
262 					if (((statbuf.st_uid != getuid())
263 						|| ((statbuf.st_mode & 0600) != 0600)))
264 						envcache = NULL;
265 					else
266 						strcpy(myHome, envcache);
267 				} else {
268 					if (mkdir(path, 0755) != 0)
269 						envcache = NULL;
270 					else {
271 						sprintf(path, "%s/memory/profiles", envcache);
272 						mkdir(path, 0755);
273 						strcpy(myHome, envcache);
274 					}
275 				}
276 			} else {
277 				/*
278 				 * So, we have an env variable but cannot access it. See if we
279 				 * can create it.
280 				 */
281 				if (mkdir(envcache, 0755) != 0)
282 					envcache = NULL;
283 				else {
284 					sprintf(path, "%s/memory", envcache);
285 					mkdir(path, 0755);
286 					sprintf(path, "%s/memory/profiles", envcache);
287 					mkdir(path, 0755);
288 
289 					strcpy(myHome, envcache);
290 				}
291 			}
292 		}
293 
294 		/*
295 		 * If the cache is still null it means either we do not have an
296 		 * environment variable or it is not accessible.
297 		 */
298 		if (envcache == NULL)
299 		{
300 			/* This obviously won't happen often, but anyway: */
301 			if ((envcache = getenv("HOME")) == NULL)
302 			{
303 				if (envcache == NULL)
304 					envcache = global.home;
305 			} else {
306 				/*
307 				 * Use home directory. If we do not have a tree then create it
308 				 * again.
309 				 */
310 				sprintf(path, "%s/.bristol", envcache);
311 
312 				sprintf(myHome, "%s", path);
313 
314 				if (stat(path, &statbuf) != 0) {
315 					mkdir(path, 0755);
316 					sprintf(path, "%s/.bristol/memory", envcache);
317 					mkdir(path, 0755);
318 					sprintf(path, "%s/.bristol/memory/profiles", envcache);
319 					mkdir(path, 0755);
320 				}
321 			}
322 		}
323 	}
324 
325 	return(myHome);
326 }
327 
328 extern char *getBristolCache(char *);
329 
330 int
getMemoryLocation(char * algo,char * name,int location,int perms)331 getMemoryLocation(char *algo, char *name, int location, int perms)
332 {
333 	char path[256], *ppath, *ext = "mem";
334 	int fd;
335 
336 	/*
337 	 * This should look for a private copy, and if not found then look for
338 	 * a public copy.
339 	 */
340 	if ((name != 0) && (name[0] == '/'))
341 		sprintf(path, "%s", name);
342 	else {
343 		struct stat statbuf;
344 
345 		/*
346 		 * So this should get us our memory location. We need to look and see
347 		 * if we have a directory for this emulation and create it if not.
348 		 */
349 		ppath = getBristolCache(algo);
350 		sprintf(path, "%s/memory/%s", ppath, algo);
351 
352 		if (stat(path, &statbuf) != 0)
353 		{
354 			/*
355 			 * If we cannot stat the private location then we really ought to
356 			 * look and see if .bristol exists. If so then we should create a
357 			 * tree to include memory/algo and return it
358 			 */
359 			mkdir(path, 0755);
360 		}
361 
362 		if (name != NULL)
363 			ext = name;
364 
365 		sprintf(path, "%s/memory/%s/%s%i.%s", ppath, algo, algo, location, ext);
366 	}
367 
368 	if ((fd = open(path, perms, 0600)) < 0)
369 	{
370 		//printf("%s\n", path);
371 		sprintf(path, "%s/memory/%s/%s%i.%s",
372 			global.home, algo, algo, location, ext);
373 		return(open(path, perms, 0660));
374 	}
375 
376 	//printf("%s\n", path);
377 
378 	return(fd);
379 }
380 
381 #define RECOPY_MAX_FILE 1024 * 1024
382 
383 static void
bsmCopy(char * src,char * dst)384 bsmCopy(char *src, char *dst)
385 {
386 	char buffer[RECOPY_MAX_FILE];
387 	int srcfd, dstfd, count;
388 
389 	srcfd = open(src, O_RDONLY);
390 
391 	if ((count = read(srcfd, buffer, RECOPY_MAX_FILE)) > 0)
392 	{
393 		dstfd = open(dst, O_WRONLY|O_TRUNC|O_CREAT, 0644);
394 		count = write(dstfd, buffer, count);
395 		close(dstfd);
396 	}
397 
398 	close(srcfd);
399 }
400 
401 /*
402  * The next two will copy files into and out of the bristol cache. Read is only
403  * really used on system startup if a session file has been given by Jack SM but
404  * it could be more general. Write will copy cache files out to wherever they
405  * have been requested.
406  */
407 int
bristolMemoryExport(int source,char * dst,char * algo)408 bristolMemoryExport(int source, char *dst, char *algo)
409 {
410 	char srcpath[1024];
411 	char fpath[1024];
412 
413 	snprintf(srcpath, 1024, "%s/memory/%s/%s%i.mem",
414 		getBristolCache(algo), algo, algo, source);
415 	bsmCopy(srcpath, dst);
416 
417 	printf("Export %s to %s\n", srcpath, dst);
418 
419 	snprintf(srcpath, 1024, "%s/memory/%s/%s%i.seq",
420 		getBristolCache(algo), algo, algo, source);
421 	snprintf(fpath, 1024, "%s.seq", dst);
422 	bsmCopy(srcpath, fpath);
423 
424 	snprintf(fpath, 1024, "%s.prof", dst);
425 	brightonWriteConfiguration(
426 		global.synths->win,
427 		algo,
428 		global.synths->midichannel,
429 		fpath);
430 
431 	return(0);
432 }
433 
434 int
bristolMemoryImport(int dest,char * src,char * algo)435 bristolMemoryImport(int dest, char *src, char *algo)
436 {
437 	char dstpath[1024];
438 	char fpath[1024];
439 
440 	snprintf(dstpath, 1024, "%s/memory/%s/%s%i.mem",
441 		getBristolCache(algo), algo, algo, dest);
442 	bsmCopy(src, dstpath);
443 
444 	printf("Import %s to %s\n", src, dstpath);
445 
446 	snprintf(fpath, 1024, "%s.seq", src);
447 	snprintf(dstpath, 1024, "%s/memory/%s/%s%i.seq",
448 		getBristolCache(algo), algo, algo, dest);
449 	bsmCopy(fpath, dstpath);
450 
451 	snprintf(fpath, 1024, "%s.prof", src);
452 	brightonReadConfiguration(
453 		global.synths->win,
454 		global.synths->win->template,
455 		global.synths->midichannel,
456 		algo,
457 		fpath);
458 	//brightonReadConfiguration(synth->win, algo, synth->midichannel, fpath);
459 
460 	return(0);
461 }
462 
463 static int
checkSeqMem(arpeggiatorMemory * mem)464 checkSeqMem(arpeggiatorMemory *mem)
465 {
466 	if ((mem->s_max < 0)
467 		|| (mem->s_max > BRISTOL_SEQ_MAX)
468 		|| (mem->c_count < 0)
469 		|| (mem->c_count > BRISTOL_CHORD_MAX))
470 		return(-1);
471 
472 	return(0);
473 }
474 
475 /*
476  * Just to be aware if you reading this, the GUI does not sequence the engine
477  * or play chords. The calls below tell the engine to go into learning mode
478  * and then we tell it what keys it should store. The engine then sequences
479  * and chords.
480  */
481 int
fillSequencer(guiSynth * synth,arpeggiatorMemory * mem,int flags)482 fillSequencer(guiSynth *synth, arpeggiatorMemory *mem, int flags)
483 {
484 	int sid = synth->sid;
485 	int i;
486 
487 	if (flags & BRISTOL_NOCALLS)
488 		return(0);
489 
490 	if (checkSeqMem(mem) < 0)
491 	{
492 		printf("Sequencer sizing problem: %f %p\n", mem->s_max, mem->chord);
493 		return(-1);
494 	}
495 
496 	if (flags & BRISTOL_SID2)
497 		sid = synth->sid2;
498 
499 	if ((synth->flags & REQ_DEBUG_MASK) > REQ_MIDI_DEBUG2)
500 		printf("Sending Arpeggiation to engine: %i events\n", (int) mem->s_max);
501 
502 	printf("fill sequence %i\n", (int) mem->s_max);
503 
504 	if (mem->s_max > 0)
505 	{
506 		bristolMidiSendMsg(global.controlfd, sid,
507 			BRISTOL_ARPEGGIATOR, BRISTOL_SEQ_RESEQ, 1);
508 
509 		printf("send arpeggiation: %i\n", (int) mem->s_max);
510 
511 		for (i = 0; i < mem->s_max; i++)
512 		{
513 			printf("arpeggio step %i is %i\n", i, (int) mem->sequence[i]);
514 			bristolMidiSendMsg(global.controlfd, sid,
515 				BRISTOL_ARPEGGIATOR, BRISTOL_SEQ_KEY, (int) mem->sequence[i]);
516 		}
517 	}
518 
519 	bristolMidiSendMsg(global.controlfd, sid,
520 		BRISTOL_ARPEGGIATOR, BRISTOL_SEQ_RESEQ, 0);
521 
522 	if ((synth->flags & REQ_DEBUG_MASK) > REQ_MIDI_DEBUG2)
523 		printf("Sending Chord to engine: %i events\n", (int) mem->c_count);
524 
525 	if (mem->c_count > 0)
526 	{
527 		bristolMidiSendMsg(global.controlfd, sid,
528 			BRISTOL_ARPEGGIATOR, BRISTOL_CHORD_RESEQ, 1);
529 
530 		for (i = 0; i < mem->c_count; i++)
531 		{
532 			printf("chord %i is %i\n", i, (int) mem->chord[i]);
533 			bristolMidiSendMsg(global.controlfd, sid,
534 				BRISTOL_ARPEGGIATOR, BRISTOL_CHORD_KEY, (int) mem->chord[i]);
535 		}
536 	}
537 
538 	bristolMidiSendMsg(global.controlfd, sid,
539 		BRISTOL_ARPEGGIATOR, BRISTOL_CHORD_RESEQ, 0);
540 
541 	return(0);
542 }
543 
544 int
loadSequence(memory * seq,char * algo,int location,int flags)545 loadSequence(memory *seq, char *algo, int location, int flags)
546 {
547 	int fd;
548 	memory tmem;
549 
550 	if (seq->param == NULL) {
551 		seq->param = brightonmalloc(sizeof(arpeggiatorMemory));
552 		bzero(seq->param, sizeof(arpeggiatorMemory));
553 		seq->count = sizeof(arpeggiatorMemory) / sizeof(float);
554 		seq->active = seq->count;
555 		seq->vers = 0;
556 		sprintf(&seq->algo[0], "bristol sequencer");
557 	}
558 
559 	if ((fd = getMemoryLocation(algo, "seq", location, O_RDONLY)) < 0)
560 		return(-1);
561 
562 	if (read(fd, &tmem.algo[0], 32) < 0)
563 	{
564 		printf("read failed on params\n");
565 		close(fd);
566 		return(-1);
567 	}
568 	if (read(fd, &tmem.name[0], 32) < 0)
569 	{
570 		printf("read failed on name\n");
571 		close(fd);
572 		return(-1);
573 	}
574 	if (read(fd, &tmem.count, 4 * sizeof(short)) < 0)
575 	{
576 		printf("read failed opts\n");
577 		close(fd);
578 		return(-1);
579 	}
580 
581 	if (tmem.vers != 0)
582 	{
583 		/*
584 		 * Future revisions to the memory structures should put hooks in here
585 		 */
586 		printf("read failed: vers %i no supported\n", tmem.vers);
587 		close(fd);
588 		return(-1);
589 	}
590 
591 	if (strcmp(&tmem.algo[0], "bristol sequencer") != 0)
592 	{
593 		if (tmem.algo[0] == '\0')
594 			printf("Attempt to read (noname) into sequencer\n");
595 		else
596 			printf("Attempt to read %s into sequencer\n", &tmem.algo[0]);
597 
598 		if ((flags & BRISTOL_SEQFORCE) == 0)
599 		{
600 			close(fd);
601 			return(-1);
602 		}
603 		sprintf(&seq->algo[0], "%s", algo);
604 	} else {
605 		sprintf(&seq->algo[0], "%s", &tmem.algo[0]);
606 		sprintf(&seq->name[0], "%s", &tmem.name[0]);
607 	}
608 
609 	if (seq->count != tmem.count)
610 		printf("Sequence structure size mismatched %i vs %i\n",
611 			seq->count, tmem.count);
612 
613 	if (tmem.count > seq->count)
614 		tmem.count = seq->count;
615 
616 	seq->vers = tmem.vers;
617 
618 	if (read(fd, &seq->param[0], tmem.count * sizeof(float)) < 0)
619 		printf("read failed\n");
620 
621 	close(fd);
622 
623 printf("loaded sequence\n");
624 	return(0);
625 }
626 
627 int
loadMemory(guiSynth * synth,char * algo,char * name,int location,int active,int skip,int flags)628 loadMemory(guiSynth *synth, char *algo, char *name, int location,
629 int active, int skip, int flags)
630 {
631 	brightonEvent event;
632 	int i, fd, panel = 0, index = 0;
633 	memory tmem;
634 
635 	memset(&event, 0, sizeof(brightonEvent));
636 
637 /*printf("loadmemory %i: %s %x\n", location, synth->resources->name, flags); */
638 	if (active == 0)
639 		active = synth->mem.active;
640 
641 	synth->lmem = synth->cmem;
642 	synth->cmem = location;
643 
644 	if (flags & BRISTOL_SEQLOAD) {
645 		if (BRISTOL_SID2) {
646 			if (loadSequence(&synth->seq2, algo, location, flags) >= 0)
647 				/*
648 				 * These should now have given us a half valid arpeggioMemory
649 				 * structure, pass it off to some code to do a sanity check
650 				 * and then send the keys to the engine
651 				 */
652 				fillSequencer(synth, (arpeggiatorMemory *) synth->seq2.param,
653 					flags);
654 			else
655 				printf("sequencer memory not found\n");
656 		} else {
657 			if (loadSequence(&synth->seq1, algo, location, flags) >= 0)
658 				fillSequencer(synth, (arpeggiatorMemory *) synth->seq1.param,
659 					flags);
660 			else
661 				printf("sequencer memory not found\n");
662 		}
663 	}
664 
665 	location += synth->mbi;
666 
667 	if (location >= 0)
668 	{
669 		if ((fd = getMemoryLocation(algo, name, location, O_RDONLY)) < 0)
670 			return(-1);
671 
672 		if (flags & BRISTOL_STAT)
673 		{
674 			close(fd);
675 			return(0);
676 		}
677 
678 		if (read(fd, &tmem.algo[0], 32) < 0)
679 		{
680 			printf("read failed on params\n");
681 			close(fd);
682 			return(-1);
683 		}
684 		if (read(fd, &tmem.name[0], 32) < 0)
685 		{
686 			printf("read failed on name\n");
687 			close(fd);
688 			return(-1);
689 		}
690 		if (read(fd, &tmem.count, 4 * sizeof(short)) < 0)
691 		{
692 			printf("read failed opts\n");
693 			close(fd);
694 			return(-1);
695 		}
696 
697 		if (tmem.vers != 0)
698 		{
699 			/*
700 			 * Future revisions to the memory structures should put hooks in
701 			 * here
702 			 */
703 			printf("read failed: vers %i no supported\n", synth->mem.vers);
704 			close(fd);
705 			return(-1);
706 		}
707 
708 		if (strcmp(&tmem.algo[0], algo) != 0)
709 		{
710 			if ((flags & BRISTOL_FORCE) == 0)
711 			{
712 				if (tmem.algo[0] == '\0')
713 					printf("Attempt to read (noname) into %s algorithm\n",
714 						algo);
715 				else
716 					printf("Attempt to read %s into %s algo\n", &tmem.algo[0],
717 						algo);
718 
719 				close(fd);
720 				return(-1);
721 			}
722 			sprintf(&synth->mem.algo[0], "%s", algo);
723 		} else {
724 			sprintf(&synth->mem.algo[0], "%s", &tmem.algo[0]);
725 			sprintf(&synth->mem.name[0], "%s", &tmem.name[0]);
726 		}
727 		synth->mem.count = tmem.count;
728 		synth->mem.vers = tmem.vers;
729 
730 		if (((synth->flags & REQ_DEBUG_MASK) > REQ_MIDI_DEBUG2)
731 			&& (synth->mem.active != tmem.active))
732 			printf("Active count changed. Overriding\n");
733 /*	synth->mem.active = tmem.active; */
734 
735 		if (read(fd, &synth->mem.param[skip], active * sizeof(float)) < 0)
736 			printf("read failed\n");
737 
738 		close(fd);
739 
740 		if (flags & BRISTOL_NOCALLS)
741 			return(0);
742 	} else
743 		memset(synth->mem.param, 0, active * sizeof(float));
744 
745 	synth->flags |= MEM_LOADING;
746 	/*
747 	 * We now have to call the GUI to configure all these values. The GUI
748 	 * will then call us back with the parameters to send to the synth.
749 	 */
750 	for (i = 0; i < active; i++)
751 	{
752 		event.type = BRIGHTON_FLOAT;
753 		event.value = synth->mem.param[i];
754 		/*
755 		 * We need to find which panel hosts this memory index. If we only
756 		 * have one panel, this is easy, it has all the controls. If we have
757 		 * multiple then we need to go through them all.
758 		 */
759 		if (synth->resources->nresources == 1)
760 			brightonParamChange(synth->win, synth->panel, i, &event);
761 		else {
762 			index = i;
763 
764 			for (panel = 0; panel < synth->resources->nresources; panel++)
765 			{
766 				if ((index - synth->resources->resources[panel].ndevices) < 0)
767 				{
768 					/*
769 					 * If this is a text panel, skip it.
770 					 */
771 					if (synth->resources->resources[panel].devlocn[index].device
772 						== 3)
773 						continue;
774 					/*
775 					 * The next is odd, and could break a couple of the synth
776 					 * memories, but if the value that is in the newly loaded
777 					 * memory is outside of the configured range then we are
778 					 * not going to set the value.
779 					 */
780 					if ((synth->resources->resources[panel].devlocn[index].from
781 						< synth->resources->resources[panel].devlocn[index].to)
782 						&&
783 						((synth->resources->resources[panel].devlocn[index].from
784 							> event.value) ||
785 						(synth->resources->resources[panel].devlocn[index].to
786 							< event.value)))
787 						continue;
788 					brightonParamChange(synth->win, panel, index, &event);
789 					break;
790 				} else
791 					index -= synth->resources->resources[panel].ndevices;
792 			}
793 		}
794 	}
795 
796 	synth->flags &= ~MEM_LOADING;
797 
798 	return(0);
799 }
800 
801 int
saveSequence(guiSynth * synth,char * algo,int location,int flags)802 saveSequence(guiSynth *synth, char *algo, int location, int flags)
803 {
804 	memory *seq = &synth->seq1;
805 	int fd;
806 
807 	if (flags & BRISTOL_SID2)
808 		seq = &synth->seq2;
809 
810 	/*
811 	 * Try and save our sequencer information.
812 	 */
813 	if (seq->param != NULL)
814 	{
815 		if ((fd = getMemoryLocation(
816 			algo, "seq", location, O_WRONLY|O_CREAT|O_TRUNC)) < 0)
817 			return(-1);
818 
819 		if (checkSeqMem((arpeggiatorMemory *) seq->param) >= 0) {
820 printf("Saving %i steps\n", (int) ((arpeggiatorMemory *) seq->param)->s_max);
821 			if (write(fd, seq,
822 				sizeof(struct Memory) - sizeof(float *)) < 0)
823 				printf("seq write failed 1\n");
824 			if (write(fd, seq->param, sizeof(arpeggiatorMemory)) < 0)
825 				printf("seq write failed 2\n");
826 		} else {
827 			printf("problem saving sequencer memory\n");
828 			close(fd);
829 			return(-1);
830 		}
831 
832 		close(fd);
833 	}
834 	return(0);
835 }
836 
837 int
saveMemory(guiSynth * synth,char * algo,char * name,int location,int skip)838 saveMemory(guiSynth *synth, char *algo, char *name, int location, int skip)
839 {
840 	int fd;
841 
842 	if (location < 0)
843 		return(0);
844 
845 	location += synth->mbi;
846 
847 	if ((fd = getMemoryLocation(algo, name, location, O_WRONLY|O_CREAT|O_TRUNC))
848 		< 0)
849 		return(-1);
850 
851 	if (write(fd, &synth->mem, sizeof(struct Memory) - sizeof(float *)) < 0)
852 		printf("mem write failed 1\n");
853 	if (write(fd, &synth->mem.param[skip], synth->mem.active * sizeof(float))
854 		< 0)
855 		printf("mem write failed 2\n");
856 
857 	/*
858 	 * Save global profile with controller registrations. No filename is given
859 	 * so that the called code will take the cache copy.
860 	 */
861 	brightonWriteConfiguration(synth->win, algo, synth->midichannel, NULL);
862 
863 	close(fd);
864 
865 	return(0);
866 }
867 
868 static void
connectengine(guimain * global)869 connectengine(guimain *global)
870 {
871 	int flags;
872 
873 	flags = BRISTOL_CONN_TCP|BRISTOL_DUPLEX|BRISTOL_CONN_NBLOCK|
874 		(global->flags & BRISTOL_CONN_FORCE);
875 
876 	if ((global->controlfd = bristolMidiOpen(global->host,
877 		flags, global->port, -1, brightonMidiInput, global)) < 0)
878 	{
879 		printf("opening link to engine: %i\n", global->port);
880 		if ((global->controlfd = bristolMidiOpen(global->host,
881 			flags, global->port, -1, brightonMidiInput, global)) < 0)
882 			cleanupBristol();
883 	} else
884 		printf("%s already active (%i)\n", BRISTOL_ENGINE, global->controlfd);
885 }
886 
887 int
initConnection(guimain * global,guiSynth * synth)888 initConnection(guimain *global, guiSynth *synth)
889 {
890 	bristolMidiMsg msg;
891 	int sid = -1;
892 
893 	connectengine(global);
894 
895 	//printf("initConnection()\n");
896 	/*
897 	 * send a hello, with a voice count, then request starting of the
898 	 * synthtype. All of these will require an ACK, and we should wait here
899 	 * and read that ack before proceeding with each next step.
900 	 */
901 	bristolMidiSendMsg(global->controlfd, synth->midichannel,
902 /*		127, 0, BRISTOL_HELLO|BRISTOL_VOICES|synth->voices); */
903 		127, 0, BRISTOL_HELLO|synth->voices);
904 
905 	if (synth->sid > 0)
906 		synth->sid2 = global->controlfd + 1;
907 
908 	if (bristolMidiRead(global->controlfd, &msg) != BRISTOL_OK)
909 	{
910 		printf("unacknowledged request on %i\n", global->controlfd);
911 		bristolMidiPrint(&msg);
912 		sleep(1);
913 		global->flags |= REQ_EXIT;
914 		return(-1);
915 	}
916 
917 	/*
918 	 * The returned value is the connection ID that we need to use for all
919 	 * further system conversations.
920 	 */
921 	sid = (msg.params.bristol.valueMSB << 7) + msg.params.bristol.valueLSB;
922 
923 	if (synth->flags & REQ_MIDI_DEBUG2)
924 	{
925 		printf("sid is %i (%i, %i)\n", sid,
926 			msg.params.bristol.valueMSB, msg.params.bristol.valueLSB);
927 
928 		bristolMidiPrint(&msg);
929 	}
930 
931 	bristolMidiSendMsg(global->controlfd, sid,
932 		127, 0, BRISTOL_MIDICHANNEL|synth->midichannel);
933 
934 	if (bristolMidiRead(global->controlfd, &msg) != BRISTOL_OK)
935 	{
936 		bristolMidiSendMsg(global->controlfd, sid,
937 			127, 0, BRISTOL_MIDICHANNEL|synth->midichannel);
938 		if (bristolMidiRead(global->controlfd, &msg) != BRISTOL_OK)
939 		{
940 			printf("unacknowledged request on %i\n", sid);
941 			bristolMidiPrint(&msg);
942 			sleep(1);
943 			global->flags |= REQ_EXIT;
944 			return(-1);
945 		}
946 	}
947 
948 	bristolMidiSendMsg(global->controlfd, sid,
949 		127, 0, BRISTOL_REQSTART);
950 	if (bristolMidiRead(global->controlfd, &msg) != BRISTOL_OK)
951 	{
952 		printf("unacknowledged request on %i\n", sid);
953 		sleep(1);
954 		global->flags |= REQ_EXIT;
955 		return(-1);
956 	}
957 
958 /*printf("	initialising one connection of type %i\n", synth->synthtype); */
959 	bristolMidiSendMsg(global->controlfd, sid,
960 		127, 0, BRISTOL_INIT_ALGO|synth->synthtype);
961 	if (bristolMidiRead(global->controlfd, &msg) != BRISTOL_OK)
962 	{
963 		printf("unacknowledged request on %i\n", sid);
964 		sleep(1);
965 		global->flags |= REQ_EXIT;
966 		return(-1);
967 	}
968 
969 	return(sid);
970 }
971 
972