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