1 
2 /*
3  *  Diverse Bristol midi 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 #define _GNU_SOURCE
23 #include <sys/socket.h>
24 #include <sys/select.h>
25 #include <sys/time.h>
26 #include <sys/stat.h>
27 #include <termios.h>
28 #include <stdlib.h>
29 #include <fcntl.h>
30 #include <ctype.h>
31 #include <stdio.h>
32 
33 #include <string.h>
34 
35 #include "brighton.h"
36 #include "brightoninternals.h"
37 #include "brightonMini.h"
38 
39 extern char *getBristolCache(char *);
40 extern void brightonChangeParam(guiSynth *, int, int, float);
41 extern void brightonKeyInput(brightonWindow *, int, int);
42 
43 static fd_set stdioset[32];
44 static struct timeval timeout;
45 
46 static float lp = -1;
47 
48 struct termios resetattr;
49 
50 #define B_TTY_ACT_COUNT	80
51 #define B_TTY_LINE_LEN	256
52 
53 #define B_TTY_RAW		0x00000001
54 #define B_TTY_RAW_P		0x00000002
55 #define B_TTY_RAW_P2	0x00000004
56 #define B_TTY_COOKED	0x00000008
57 #define B_TTY_RAW_ESC	0x00000010
58 #define B_TTY_RAW_ESC2	0x00000020
59 #define B_TTY_SEARCH	0x00000040
60 #define B_TTY_PLAY		0x00000080
61 #define B_TTY_MMASK		0x00000fff
62 
63 #define B_TTY_INIT		0x00001000
64 #define B_TTY_DEBUG		0x00002000
65 #define B_TTY_AWV		0x00004000
66 #define B_TTY_AUV		0x00008000
67 #define B_TTY_ALIASING	0x00010000
68 #define B_TTY_SAVE_HIST	0x00020000
69 #define B_TTY_PLAY_LINE	0x00040000
70 #define B_TTY_CLEAR_KEY	0x00080000
71 #define B_TTY_SEQ		0x00100000
72 
73 #define B_TTY_ARGC 32
74 
75 static char hist[51][B_TTY_LINE_LEN];
76 static char pbuf[B_TTY_LINE_LEN];
77 static char cbuf[B_TTY_LINE_LEN];
78 
79 #define B_SEQ_COUNT 16
80 
81 static struct {
82 	int count, rate, step[B_SEQ_COUNT];
83 } sequences[B_SEQ_COUNT] = {
84 	{8, 30, {52 + 0, 52 + 7, 52 + 3, 52 + 7, 52 + 0, 52 + 5, 52 + 9, 52 + 5}},
85 	{0, 0, {0}},
86 	{0, 0, {0}},
87 	{0, 0, {0}},
88 	{0, 0, {0}},
89 	{0, 0, {0}},
90 	{0, 0, {0}},
91 	{0, 0, {0}},
92 	{0, 0, {0}},
93 	{0, 0, {0}},
94 	{0, 0, {0}},
95 	{0, 0, {0}},
96 	{0, 0, {0}},
97 	{0, 0, {0}},
98 	{0, 0, {0}},
99 	{0, 0, {0}},
100 };
101 
102 static char *unknown = "unnamed parameter";
103 static char *b_blank = "                                                                            ";
104 
105 #define B_TTY_A_LEFT	0
106 #define B_TTY_A_RIGHT	1
107 #define B_TTY_A_INCMIN	2
108 #define B_TTY_A_INC		3
109 #define B_TTY_A_INCMAX	4
110 #define B_TTY_A_DECMIN	5
111 #define B_TTY_A_DEC		6
112 #define B_TTY_A_DECMAX	7
113 #define B_TTY_A_M_UP	8
114 #define B_TTY_A_M_DOWN	9
115 #define B_TTY_A_M_READ	10
116 #define B_TTY_A_M_WRITE	11
117 #define B_TTY_A_M_TOG	12
118 #define B_TTY_A_INSERT	13
119 #define B_TTY_A_INC1	14
120 #define B_TTY_A_INC4	15
121 #define B_TTY_A_DEC1	16
122 #define B_TTY_A_DEC4	17
123 #define B_TTY_A_UPDATE	18
124 #define B_TTY_A_FIND	19
125 #define B_TTY_A_NULL	-1
126 
127 #define RESOURCES global->synths->resources
128 #define SYNTHS global->synths
129 #define paramname(x) RESOURCES->resources[btty.p].devlocn[x].name
130 //#define DEVICE(x) RESOURCES->resources[btty.p].devlocn[x]
131 #define DEVICE(x) global->synths->win->app->resources[btty.p].devlocn[x]
132 #define PDEV(x) ((brightonDevice *) global->synths->win->app->resources[btty.p].devlocn[x].dev)
133 
134 #define unnamed(x) ((paramname(x)[0] == '\0') || (DEVICE(x).flags & BRIGHTON_WITHDRAWN))
135 
136 //	if (RESOURCES->resources[btty.p].devlocn[btty.i].to == 1.0f)
137 //	if (DEVICE(btty.i).to == 1.0f)
138 
139 brightonEvent event;
140 extern void printBrightonHelp(int);
141 
142 typedef int (*clicom)();
143 
144 static int bttyInterpret(guimain *, char *);
145 static int execHelp(guimain *, int, char **);
146 static int execMemory(guimain *, int, char **);
147 static int execLoad(guimain *, int, char **);
148 static int execDebug(guimain *, int, char **);
149 static int execImport(guimain *, int, char **);
150 static int execSet(guimain *, int, char **);
151 static int execBristol(guimain *, int, char **);
152 static int execBrighton(guimain *, int, char **);
153 static int execMidi(guimain *, int, char **);
154 static int execAlias(guimain *, int, char **);
155 static int execCLI(guimain *, int, char **);
156 static int execQuit(guimain *, int, char **);
157 static void bttyMemSave(guimain *);
158 
159 /* Error codes */
160 #define B_ERR_EXIT		-1
161 #define B_ERR_OK		0
162 #define B_ERR_NOT_FOUND	1
163 #define B_ERR_PARAM		2
164 #define B_ERR_VALUE		3
165 #define B_ERR_INV_ARG	4
166 #define B_ERR_EARLY		5
167 
168 /* global command codes */
169 #define B_COM_LAST		-1
170 #define B_COM_NOT_USED	0
171 #define B_COM_FREE		128
172 
173 /* 'set memory' commands */
174 #define B_COM_FIND		1
175 #define B_COM_READ		2
176 #define B_COM_WRITE		3
177 #define B_COM_IMPORT	4
178 #define B_COM_EXPORT	5
179 #define B_COM_FORCE		6
180 
181 typedef struct CommSet {
182 	char name[12];
183 	int map;
184 	char help[B_TTY_LINE_LEN];
185 	clicom exec;
186 	struct CommSet *subcom;
187 } comSet;
188 
189 comSet brightoncom[4] = {
190 	{"",		B_COM_NOT_USED, "", 0, 0},
191 	{"panel",	B_COM_FIND,
192 		"<n> Set the active emulator parameter panel",
193 		0, 0},
194 	{"device",	B_COM_FIND,
195 		"<panel> <dev> <value> send parameter change message",
196 		0, 0},
197 	{"", B_COM_LAST, "", 0, 0},
198 };
199 
200 comSet debugcomm[6] = {
201 	{"",		B_COM_NOT_USED, "", 0, 0},
202 	{"cli",	B_COM_FIND,
203 		"Command Line Debuging on/off",
204 		0, 0},
205 	{"midi",	B_COM_FIND,
206 		"debug level midi interface libraries 0..3",
207 		0, 0},
208 	{"frontend",	B_COM_FIND,
209 		"debug engine interface libraries on/off",
210 		0, 0},
211 	{"engine",	B_COM_FIND,
212 		"engine debuging level 0..15 (0 = off, >9 = verbose)",
213 		0, 0},
214 	{"", B_COM_LAST, "", 0, 0},
215 };
216 
217 comSet bristolcom[4] = {
218 	{"",		B_COM_NOT_USED, "", 0, 0},
219 	{"register",	B_COM_FIND,
220 		"send MIDI surface controller registration request",
221 		0, 0},
222 	{"control",	B_COM_FIND,
223 		"<op> <cont> <value> send parameter change message to engine",
224 		0, 0},
225 	{"", B_COM_LAST, "", 0, 0},
226 };
227 
228 comSet midicomm[24] = {
229 	{"",		B_COM_NOT_USED, "", 0, 0},
230 	{"channel",	B_COM_FIND,
231 		"configure engine midi channel 1..16",
232 		0, 0},
233 	{"sid",	B_COM_FIND,
234 		"select internal messaging id",
235 		0, 0},
236 	{"debug",	B_COM_FIND,
237 		"engine debuging level 0..16",
238 		0, 0},
239 	{"lowkey",	B_COM_FIND,
240 		"lower midi keyboard split point 0..127",
241 		0, 0},
242 	{"highkey",	B_COM_FIND,
243 		"higher midi keyboard split point 0..127",
244 		0, 0},
245 	{"chanpress",	B_COM_FIND,
246 		"send a channel pressure event value p=0..127",
247 		0, 0},
248 	{"polypress",	B_COM_FIND,
249 		"send a key pressure event k=0..127 p=0..127",
250 		0, 0},
251 	{"filter",	B_COM_FIND,
252 		"engine filters: lwf/nwf/wwf/hwf",
253 		0, 0},
254 	{"notepref",	B_COM_FIND,
255 		"monophonic note preference logic: hnp/lnp/nnp",
256 		0, 0},
257 	{"velocity",	B_COM_FIND,
258 		"midi velocity curve 0..1000",
259 		0, 0},
260 	{"detune",	B_COM_FIND,
261 		"engine 'temperature sensitivity' detuning",
262 		0, 0},
263 	{"glide",	B_COM_FIND,
264 		"maximum glide rate (5s)",
265 		0, 0},
266 	{"legato",	B_COM_FIND,
267 		"monophonic legato velocity logic on/off",
268 		0, 0},
269 	{"trigger",	B_COM_FIND,
270 		"monophonic trig/retrig logic on/off",
271 		0, 0},
272 	{"gain",	B_COM_FIND,
273 		"emulator global gain control",
274 		0, 0},
275 	{"pwd",	B_COM_FIND,
276 		"midi pitch wheel depth semitones",
277 		0, 0},
278 	{"nrp", B_COM_FIND,
279 		"enable user interface NRP response on/off",
280 		0, 0},
281 	{"enginenrp",	B_COM_FIND,
282 		"enable engine NRP response on/off",
283 		0, 0},
284 	{"forwarding",	B_COM_FIND,
285 		"enable engine midi message forwarding on/off",
286 		0, 0},
287 	{"tuning",	B_COM_FIND,
288 		"coarse/fine: global tuning 0..1.0",
289 		0, 0},
290 	{"controller",	B_COM_FIND,
291 		"send a value to a continuous controller value",
292 		0, 0},
293 	{"panic",	B_COM_FIND,
294 		"midi all-notes-off, etc",
295 		0, 0},
296 	{"", B_COM_LAST, "", 0, 0},
297 };
298 
299 comSet cliComm[4] = {
300 	{"",		B_COM_NOT_USED, "", 0, 0},
301 	{"cycle",	B_COM_FIND,
302 		"CLI cycle response time (ms)",
303 		0, 0},
304 	{"list",	B_COM_FIND,
305 		"list the CLI ESC command key templates",
306 		0, 0},
307 	{"", B_COM_LAST, "", 0, 0},
308 };
309 
310 comSet memcomm[8] = {
311 	/* Find/read/write/import/export should move to set memory */
312 	{"",		B_COM_NOT_USED, "", 0, 0},
313 	{"find",	B_COM_FIND,
314 		"'find', 'find free', 'find load' synth memory search",
315 		execLoad, 0},
316 	{"read",	B_COM_FIND,
317 		"[<n>|undo] load synth memory at the configured index",
318 		execLoad, 0},
319 	{"write",	B_COM_FIND,
320 		"[<n>] save current synth settings to memory",
321 		execLoad, 0},
322 	{"import",	B_COM_FIND,
323 		"[path [mem]] read a file and save to memory",
324 		execImport, 0},
325 	{"export",	B_COM_FIND,
326 		"[path [mem]] save memory to external file",
327 		execImport, 0},
328 	{"force",	B_COM_FIND,
329 		"force the loading of an otherwise erroneous memory, on/off",
330 		execLoad, 0},
331 	{"", B_COM_LAST, "", 0, 0},
332 };
333 
334 /*
335  * Need to build more structures to represent the parameters set of each
336  * command, this is needed for better help and command completion.
337 static struct {
338 	char name[12];
339 	int map;
340 	char help[B_TTY_LINE_LEN];
341 	clicom exec;
342 	comSet *subcom;
343 } tmp;
344  */
345 
346 /* 'set <comm> and top level interpretation */
347 #define B_COM_SET		1
348 #define B_COM_MEMORY	2
349 #define B_COM_MIDI		3
350 #define B_COM_DEBUG		4
351 #define B_COM_BRISTOL	5
352 #define B_COM_BRIGHTON	6
353 #define B_COM_CLI		7
354 #define B_COM_ALIAS		8
355 #define B_COM_SETALIAS	9
356 #define B_COM_HELP		10
357 #define B_COM_QUIT		11
358 #define B_COM_PLAY		12
359 
360 comSet setcomm[B_TTY_ACT_COUNT + 1] = {
361 	{"",		B_COM_NOT_USED, "", 0, 0},
362 	/* Find/read/write/import/export should move to set memory */
363 	{"memory",	B_COM_MEMORY,
364 		"'set memory [find|read|write|import|export]",
365 		execMemory, memcomm},
366 	{"midi",	B_COM_MIDI,
367 		"[channel|debug|help] midi control commands",
368 		execMidi, midicomm},
369 	{"debug",	B_COM_DEBUG,
370 		"[on|off|engine [0..15]] debug settings",
371 		execDebug, debugcomm},
372 	{"bristol",	B_COM_BRISTOL,
373 		"[cont/op/value|register] - operator commands",
374 		execBristol, bristolcom},
375 	{"brighton",B_COM_BRIGHTON,
376 		"[panel|p/d/v] - GUI management commands",
377 		execBrighton, brightoncom},
378 	{"cli",	    B_COM_CLI,
379 		"[list|<key> action|cycle] navigation key management",
380 		execCLI, cliComm},
381 	{"alias",	B_COM_SETALIAS,
382 		"command aliases, %/$ signs will be remapped parameters",
383 		execAlias, 0},
384 	{"play",	B_COM_PLAY,
385 		"set play mode|stop, set play sequence <id>, to test synth patches",
386 		execAlias, 0},
387 	{"noalias",	B_COM_SETALIAS,
388 		"noalias <name>: remove an alias called 'name'",
389 		execAlias, 0},
390 	{"line",	B_COM_NOT_USED,
391 		"command line length",
392 		0, 0},
393 	{"history",	B_COM_NOT_USED,
394 		"history table size (max 50)",
395 		0, 0},
396 	{"savehistory",	B_COM_NOT_USED,
397 		"autosave history and parameters on exit",
398 		0, 0},
399 	{"prompt",	B_COM_NOT_USED,
400 		"CLI Prompt",
401 		0, 0},
402 	{"accelerator",	B_COM_NOT_USED,
403 		"Default ESC mode Up/Down parameter change value",
404 		0, 0},
405 	{"awv",	B_COM_NOT_USED,
406 		"access withdrawn variables",
407 		0, 0},
408 	{"", B_COM_LAST, "", 0, 0},
409 };
410 
411 comSet commands[B_TTY_ACT_COUNT + 1] = {
412 	{"",		B_COM_NOT_USED, "", 0, 0},
413 	/* Find/read/write/import/export should move to set memory */
414 	{"set",		B_COM_SET,
415 		"[line|panel|awv|cli|noalias|hist|prompt]",
416 		execSet, setcomm},
417 	{"memory",	B_COM_MEMORY,
418 		"'set memory [find|read|write|import|export]",
419 		execMemory, memcomm},
420 	{"midi",	B_COM_MIDI,
421 		"[channel|debug|help] midi control commands",
422 		execMidi, midicomm},
423 	{"debug",	B_COM_DEBUG,
424 		"[on|off|engine [0..15]] debug settings",
425 		execDebug, debugcomm},
426 	{"bristol",	B_COM_BRISTOL,
427 		"[cont/op/value|register] - operator commands",
428 		execBristol, bristolcom},
429 	{"brighton",B_COM_BRIGHTON,
430 		"[panel|p/d/v] - GUI management commands",
431 		execBrighton, brightoncom},
432 	{"cli",	    B_COM_CLI,
433 		"[list|<key> action|cycle] navigation key management",
434 		execCLI, cliComm},
435 	{"alias",	B_COM_SETALIAS,
436 		"command aliases, %/$ signs will be remapped parameters",
437 		execAlias, 0},
438 	{"help",	B_COM_HELP,
439 		"'set <command> help', 'help <command>, this screen",
440 		execHelp, 0},
441 	{"quit",	B_COM_QUIT,
442 		"exit application, terminate the emulator",
443 		execQuit, NULL},
444 	{"", B_COM_LAST, "", 0, 0},
445 };
446 
447 #define B_TTY_A_PREDEF 20
448 
449 static struct {
450 	char opname[12];
451 	int imap;
452 } templates[B_TTY_ACT_COUNT + 1] = {
453 	{"left",	B_TTY_A_LEFT},
454 	{"right",	B_TTY_A_RIGHT},
455 	{"incmin",	B_TTY_A_INCMIN},
456 	{"inc",		B_TTY_A_INC},
457 	{"incmax",	B_TTY_A_INCMAX},
458 	{"decmin",	B_TTY_A_DECMIN},
459 	{"dec",		B_TTY_A_DEC},
460 	{"decmax",	B_TTY_A_DECMAX},
461 	{"memUp",	B_TTY_A_M_UP},
462 	{"memDown",	B_TTY_A_M_DOWN},
463 	{"read",	B_TTY_A_M_READ},
464 	{"write",	B_TTY_A_M_WRITE},
465 	{"toggle",	B_TTY_A_M_TOG},
466 	{"insert",	B_TTY_A_INSERT},
467 	{"fineup",	B_TTY_A_INC4},
468 	{"up",		B_TTY_A_INC1},
469 	{"finedown",B_TTY_A_DEC4},
470 	{"down",	B_TTY_A_DEC1},
471 	{"update",	B_TTY_A_UPDATE},
472 	{"search",	B_TTY_A_FIND},
473 	{"off",		B_TTY_A_NULL},
474 	{"", -1},
475 };
476 
477 static struct {
478 	char map;
479 	int imap;
480 } action[B_TTY_ACT_COUNT + 1] = {
481 	{'h', B_TTY_A_LEFT},
482 	{'l', B_TTY_A_RIGHT},
483 	{0x0b, B_TTY_A_INCMIN},
484 	{'k', B_TTY_A_INC},
485 	{'K', B_TTY_A_INCMAX},
486 	{0x0a, B_TTY_A_DECMIN},
487 	{'j', B_TTY_A_DEC},
488 	{'J', B_TTY_A_DECMAX},
489 	{'M', B_TTY_A_M_UP},
490 	{'m', B_TTY_A_M_DOWN},
491 	{'r', B_TTY_A_M_READ},
492 	{'w', B_TTY_A_M_WRITE},
493 	{'x', B_TTY_A_M_TOG},
494 	{'u', B_TTY_A_INC1},
495 	{'d', B_TTY_A_DEC1},
496 	{'f', B_TTY_A_UPDATE},
497 	{'U', B_TTY_A_INC4},
498 	{'D', B_TTY_A_DEC4},
499 	{':', B_TTY_A_INSERT},
500 	{'/', B_TTY_A_FIND},
501 	{'\0', -1},
502 };
503 
504 static struct {
505 	unsigned int flags;
506 	guimain *global;
507 	int cycle;
508 	int i;
509 	int p;
510 	char promptText[64];
511 	char prompt[64];
512 	char *hist[51];
513 	int hist_tmp;
514 	int hist_c;
515 	int edit_p;
516 	char b;
517 	char delim;
518 	int len;
519 	int fd[2];
520 	int lastmem;
521 	char ichan;
522 	char mdbg;
523 	char edbg;
524 	char lowkey;
525 	char highkey;
526 	char preference;
527 	float accel;
528 	int fl;
529 	int po;
530 	unsigned int key;
531 	int pcycle;
532 	int acycle;
533 	struct {
534 		int id;
535 		int step;
536 		int count;
537 		int transpose;
538 		unsigned int flags;
539 	} sequence;
540 } btty = {
541 	B_TTY_INIT|B_TTY_COOKED|B_TTY_PLAY_LINE,
542 	NULL,
543 	500,
544 	0,
545 	0,
546 	"%algo% (m %memory% ch %channel%): ",
547 	"%algo%: ",
548 	{hist[0], hist[1], hist[2], hist[3], hist[4],
549 	hist[5], hist[6], hist[7], hist[8], hist[9],
550 	hist[10], hist[11], hist[12], hist[13], hist[14],
551 	hist[15], hist[16], hist[17], hist[18], hist[19],
552 	hist[20], hist[21], hist[22], hist[23], hist[24],
553 	hist[25], hist[26], hist[27], hist[28], hist[29],
554 	hist[30], hist[31], hist[32], hist[33], hist[34],
555 	hist[35], hist[36], hist[37], hist[38], hist[39],
556 	hist[40], hist[41], hist[42], hist[43], hist[44],
557 	hist[45], hist[46], hist[47], hist[48], hist[49], hist[50]},
558 	0, 50, 0,
559 	'\0',
560 	':',
561 	80,
562 	{0, 0},
563 	0,
564 	/* These all default to zero, the MIDI options */
565 	0, 0, 0, 0, 127, 0,
566 	/* Default Cursor key accelerator */
567 	0.05f,
568 	0,
569 	0,
570 	/* Keystroke management */
571 	0, 500, 500
572 };
573 
574 static void
print(char * str)575 print(char *str)
576 {
577 	int i;
578 	char tbuf[B_TTY_LINE_LEN];
579 
580 	if (btty.flags & B_TTY_DEBUG)
581 	{
582 		snprintf(tbuf, btty.len, "d: %s\r\n", str);
583 		i = write(btty.fd[1], tbuf, strlen(tbuf));
584 	}
585 }
586 
587 static void
printChar(char ch)588 printChar(char ch)
589 {
590 	int i;
591 
592 	if (btty.flags & B_TTY_DEBUG)
593 	{
594 		snprintf(pbuf, btty.len, "char 0x%x\r\n", ch);
595 		i = write(btty.fd[1], pbuf, strlen(pbuf));
596 	}
597 }
598 
599 static void
seqStop(guimain * global)600 seqStop(guimain *global)
601 {
602 	print("seqStop");
603 
604 	if (btty.flags & B_TTY_SEQ)
605 	{
606 		bristolMidiSendMsg(global->controlfd, SYNTHS->midichannel,
607 			BRISTOL_EVENT_KEYOFF, 0,
608 			sequences[btty.sequence.id].step[btty.sequence.step]
609 			+ btty.sequence.transpose);
610 		bristolMidiSendMsg(global->controlfd, SYNTHS->sid, 127, 0,
611 			BRISTOL_ALL_NOTES_OFF);
612 	}
613 
614 	btty.flags &= ~B_TTY_SEQ;
615 	btty.sequence.step = 0;
616 }
617 
618 static void
bttyManageHistory(char * comm)619 bttyManageHistory(char *comm)
620 {
621 	if (btty.flags & B_TTY_ALIASING)
622 		return;
623 	if ((strcmp(comm, btty.hist[1]) != 0) && (comm[0] != '\0'))
624 	{
625 		int i;
626 		char *curr = btty.hist[50];
627 
628 		snprintf(btty.hist[0], btty.len, "%s", comm);
629 		/* different history, cycle them and clean current */
630 		for (i = 50; i > 0; i--)
631 			btty.hist[i] = btty.hist[i - 1];
632 		btty.hist[0] = curr;
633 		memset(btty.hist[0], 0, B_TTY_LINE_LEN);
634 	}
635 	btty.hist_tmp = 0;
636 }
637 
638 void
brightonCLIcleanup()639 brightonCLIcleanup()
640 {
641 	if (btty.flags & B_TTY_SAVE_HIST)
642 	{
643 		btty.SYNTHS->location = 9999;
644 		bttyMemSave(btty.global);
645 	}
646 	tcsetattr(btty.fd[0], TCSANOW, &resetattr);
647 }
648 
649 void
brightonGetCLIcodes(int fd)650 brightonGetCLIcodes(int fd)
651 {
652 	int i, n;
653 
654 	snprintf(pbuf, btty.len, "CLI: set history %i\n", btty.hist_c);
655 	n = write(fd, pbuf, strlen(pbuf));
656 
657 	snprintf(pbuf, btty.len, "CLI: set line %i\n", btty.len);
658 	n = write(fd, pbuf, strlen(pbuf));
659 
660 	snprintf(pbuf, btty.len, "CLI: set accel %f\n", btty.accel);
661 	n = write(fd, pbuf, strlen(pbuf));
662 
663 	snprintf(pbuf, btty.len, "CLI: set prompttext \"%s\"\n", btty.promptText);
664 	n = write(fd, pbuf, strlen(pbuf));
665 
666 	snprintf(pbuf, btty.len, "CLI: set cli cycle %i\n", btty.cycle);
667 	n = write(fd, pbuf, strlen(pbuf));
668 
669 	if (btty.flags & B_TTY_DEBUG)
670 	{
671 		snprintf(pbuf, btty.len, "CLI: debug on\n");
672 		n = write(fd, pbuf, strlen(pbuf));
673 	}
674 
675 	snprintf(pbuf, btty.len, "CLI: set panel %i\n", btty.p);
676 	n = write(fd, pbuf, strlen(pbuf));
677 
678 	for (i = 0; commands[i].map != -1; i++)
679 	{
680 		if (commands[i].map == B_COM_ALIAS)
681 		{
682 			snprintf(pbuf, btty.len, "CLI: set alias %s %s\n",
683 				commands[i].name, commands[i].help);
684 			n = write(fd, pbuf, strlen(pbuf));
685 		}
686 	}
687 
688 	for (i = 0; i < B_TTY_ACT_COUNT; i++)
689 	{
690 		if ((action[i].imap < 0) || (action[i].map == '\0'))
691 			continue;
692 
693 		if (action[i].map < 26)
694 		{
695 			snprintf(pbuf, btty.len,
696 				"CLI: set cli ^X %s\n", templates[action[i].imap].opname);
697 			pbuf[14] = action[i].map + 96;
698 		} else {
699 			snprintf(pbuf, btty.len,
700 				"CLI: set cli X %s\n", templates[action[i].imap].opname);
701 			pbuf[13] = action[i].map;
702 		}
703 
704 		n = write(fd, pbuf, strlen(pbuf));
705 	}
706 
707 	if (btty.flags & B_TTY_SAVE_HIST)
708 	{
709 		snprintf(pbuf, btty.len, "CLI: set savehistory on\n");
710 		n = write(fd, pbuf, strlen(pbuf));
711 
712 		for (i = 50; i >= 0; i--)
713 		{
714 			if (btty.hist[i][0] == '\0')
715 				continue;
716 			snprintf(pbuf, btty.len, "CLI: set history comm %s\n",
717 				btty.hist[i]);
718 			n = write(fd, pbuf, strlen(pbuf));
719 		}
720 	}
721 
722 }
723 
724 void
brightonSetCLIcode(char * input)725 brightonSetCLIcode(char *input)
726 {
727 	int map, i, stuff = 0;
728 	int act;
729 	char c = input[0];
730 	char *comm = &input[2];
731 
732 	if (btty.global == NULL)
733 		return;
734 
735 	print("SetCLIcode");
736 
737 	if ((input[strlen(input) -1] == '\n')
738 		|| (input[strlen(input) -1] == '\r'))
739 		input[strlen(input) -1] = '\0';
740 
741 	if (strncmp("set", input, 3) == 0)
742 	{
743 		snprintf(cbuf, btty.len, "%s", input);
744 		bttyInterpret(btty.global, cbuf);
745 		return;
746 	}
747 
748 	if (c == '^')
749 	{
750 		c = input[1] - 96;
751 		comm++;
752 	}
753 
754 	print(comm);
755 
756 	for (act = 0; act < B_TTY_ACT_COUNT; act++)
757 	{
758 		/* return if we cannot find the action */
759 		if (templates[act].imap == -1)
760 			break;
761 		if (templates[act].opname[0] == '\0')
762 			break;
763 		if (strcasecmp(comm, templates[act].opname) == 0)
764 		{
765 			stuff = act;
766 			break;
767 		}
768 	}
769 	if ((stuff) || (templates[act].imap == -1))
770 	{
771 		int i;
772 
773 		/*
774 		 * Search the ommmand table, add entry to templates
775 		 */
776 		for (i = 0 ;
777 			(commands[i].map != B_COM_LAST) && (i < B_TTY_ACT_COUNT);
778 			i++)
779 		{
780 			if (strcasecmp(comm, commands[i].name) == 0)
781 			{
782 				/*
783 				 * Found a command.
784 				 */
785 				if (templates[act].imap == -1)
786 				{
787 					templates[act + 1].imap = -1;
788 					templates[act + 1].opname[0] = '\0';
789 				}
790 				templates[act].imap = act;
791 				snprintf(templates[act].opname, 12, "%s", comm);
792 				break;
793 			}
794 		}
795 	}
796 
797 	print(templates[act].opname);
798 
799 	if (act >= B_TTY_ACT_COUNT)
800 		return;
801 
802 	act = templates[act].imap;
803 
804 	for (map = 0; map < B_TTY_ACT_COUNT; map++)
805 	{
806 		if (action[map].map == '\0')
807 			break;
808 		if (action[map].map == c)
809 			break;
810 	}
811 	if (map == B_TTY_ACT_COUNT)
812 		return;
813 
814 	if (action[map].map == '\0')
815 	{
816 		action[map + 1].map = '\0';
817 		action[map + 1].imap = B_COM_LAST;
818 	}
819 
820 	action[map].map = c;
821 	action[map].imap = act;
822 
823 	if (btty.flags & B_TTY_DEBUG)
824 	{
825 		if (input[0] == '^')
826 		{
827 			snprintf(pbuf, btty.len, "^X is %s\n\r", templates[act].opname);
828 			pbuf[1] = c + 96;
829 		} else {
830 			snprintf(pbuf, btty.len, "X is %s %i %i\n\r", templates[act].opname,
831 				map, action[map].imap);
832 			pbuf[0] = action[map].map;
833 		}
834 		i = write(btty.fd[1], pbuf, strlen(pbuf));
835 	}
836 }
837 
838 static int
execHelpCheck(int c,char ** v)839 execHelpCheck(int c, char **v)
840 {
841 	int i, j, n;
842 
843 	if ((c == 2) && (strncmp("help", v[1], strlen(v[1])) == 0))
844 	{
845 		for (i = 0; commands[i].map != B_COM_LAST; i++)
846 		{
847 			if (strncmp(commands[i].name, v[0], strlen(v[0])) == 0)
848 			{
849 				if (commands[i].subcom == 0)
850 				{
851 					snprintf(pbuf, B_TTY_LINE_LEN, "%12s: %s\n\r",
852 						commands[i].name, commands[i].help);
853 					n = write(btty.fd[1], pbuf, strlen(pbuf));
854 					return(1);
855 				} else {
856 					for (j = 0; commands[i].subcom[j].map != B_COM_LAST; j++)
857 					{
858 						if ((commands[i].subcom[j].name[0] == '\0')
859 							|| (commands[i].subcom[j].help[0] == '\0'))
860 							continue;
861 						snprintf(pbuf, B_TTY_LINE_LEN, "%13s: %s\n\r",
862 							commands[i].subcom[j].name,
863 							commands[i].subcom[j].help);
864 						n = write(btty.fd[1], pbuf, strlen(pbuf));
865 					}
866 					return(1);
867 				}
868 			}
869 		}
870 	}
871 
872 	return(0);
873 }
874 
875 static int
isparam(int set,int comm,char * name)876 isparam(int set, int comm, char *name)
877 {
878 	if (strncmp(commands[set].subcom[comm].name, name, strlen(name)) == 0)
879 		return(1);
880 	return(0);
881 }
882 
883 static void
bttyMemSave(guimain * global)884 bttyMemSave(guimain *global)
885 {
886 	int i;
887 
888 	SYNTHS->cmem = SYNTHS->lmem;
889 	if (SYNTHS->saveMemory != NULL)
890 		SYNTHS->saveMemory(SYNTHS,
891 			RESOURCES->name, 0,
892 			SYNTHS->location, 0);
893 	else
894 		saveMemory(SYNTHS, RESOURCES->name,
895 			0, SYNTHS->location, 0);
896 	if (btty.flags & B_TTY_DEBUG)
897 	{
898 		snprintf(pbuf, btty.len, "write: %i\n\r", SYNTHS->location);
899 		i = write(btty.fd[1], pbuf, strlen(pbuf));
900 	}
901 }
902 
903 static void
bttyMemLoad(guimain * global)904 bttyMemLoad(guimain *global)
905 {
906 	int i;
907 
908 	SYNTHS->lmem = SYNTHS->cmem;
909 	if (SYNTHS->loadMemory != NULL)
910 		SYNTHS->loadMemory(SYNTHS,
911 			RESOURCES->name,
912 			0, SYNTHS->location, SYNTHS->mem.active,
913 			0, btty.fl);
914 	else
915 		loadMemory(SYNTHS, RESOURCES->name,
916 			0, SYNTHS->location, SYNTHS->mem.active,
917 			0, btty.fl);
918 	SYNTHS->cmem = SYNTHS->location;
919 
920 	if (SYNTHS->location != 9999)
921 	{
922 		snprintf(pbuf, btty.len, "read: %i\r\n", SYNTHS->location);
923 		i = write(btty.fd[1], pbuf, strlen(pbuf));
924 	} else {
925 		snprintf(pbuf, btty.len, "read: unread\r\n");
926 		i = write(btty.fd[1], pbuf, strlen(pbuf));
927 	}
928 }
929 
930 static int
execMemory(guimain * global,int c,char ** argv)931 execMemory(guimain *global, int c, char **argv)
932 {
933 	int n;
934 
935 	if (c == 1)
936 		return(B_ERR_PARAM);
937 
938 	if (execHelpCheck(c, argv)) return(0);
939 
940 	if (c == 2)
941 	{
942 		/* <n> find, read, write */
943 		if (isparam(B_COM_MEMORY, B_COM_FIND, argv[1]))
944 		{
945 			int location = SYNTHS->location + 1;
946 			/* find mem */
947 			while (loadMemory(SYNTHS, RESOURCES->name, 0,
948 				location, SYNTHS->mem.active, 0, BRISTOL_STAT) != 0)
949 			{
950 				if (++location >= 1024)
951 					location = 0;
952 				if (location == SYNTHS->location)
953 					break;
954 			}
955 			if (location != SYNTHS->location)
956 			{
957 				SYNTHS->location = location;
958 				snprintf(pbuf, btty.len, "mem: %i\r\n", SYNTHS->location);
959 				n = write(btty.fd[1], pbuf, strlen(pbuf));
960 			} else {
961 				snprintf(pbuf, btty.len, "no memories\r\n");
962 				n = write(btty.fd[1], pbuf, strlen(pbuf));
963 			}
964 			return(B_ERR_OK);
965 		}
966 		if (isparam(B_COM_MEMORY, B_COM_READ, argv[1]))
967 		{
968 			bttyMemLoad(global);
969 			return(B_ERR_OK);
970 		}
971 		if (isparam(B_COM_MEMORY, B_COM_WRITE, argv[1]))
972 		{
973 			bttyMemSave(global);
974 			return(B_ERR_OK);
975 		}
976 		if (isdigit(argv[1][0]))
977 		{
978 			if ((n = atoi(argv[1])) < 0)
979 				return(B_ERR_VALUE);
980 			if (n > 1023)
981 				return(B_ERR_VALUE);
982 
983 			SYNTHS->location = n;
984 			return(B_ERR_OK);
985 		}
986 		return(B_ERR_PARAM);
987 	}
988 
989 	if (c == 3)
990 	{
991 		/* find free, find read, read undo, read n, write n */
992 		if (isparam(B_COM_MEMORY, B_COM_FIND, argv[1]))
993 		{
994 			if (strncmp("free", argv[2], strlen(argv[2])) == 0)
995 			{
996 				int location = SYNTHS->location + 1;
997 				/* find mem */
998 				while (loadMemory(SYNTHS, RESOURCES->name, 0,
999 					location, SYNTHS->mem.active, 0, BRISTOL_STAT) == 0)
1000 				{
1001 					if (++location >= 1024)
1002 						location = 0;
1003 					if (location == SYNTHS->location)
1004 						break;
1005 				}
1006 				if (location != SYNTHS->location)
1007 				{
1008 					SYNTHS->location = location;
1009 					snprintf(pbuf, btty.len, "mem: %i\r\n", SYNTHS->location);
1010 					n = write(btty.fd[1], pbuf, strlen(pbuf));
1011 				} else {
1012 					snprintf(pbuf, btty.len, "no memories\r\n");
1013 					n = write(btty.fd[1], pbuf, strlen(pbuf));
1014 					return(B_ERR_VALUE);
1015 				}
1016 				return(B_ERR_OK);
1017 			}
1018 			if ((strncmp("load", argv[2], strlen(argv[2])) == 0)
1019 				||(strncmp("read", argv[2], strlen(argv[2])) == 0))
1020 			{
1021 				int location = SYNTHS->location + 1;
1022 				/* find mem */
1023 				while (loadMemory(SYNTHS, RESOURCES->name, 0,
1024 					location, SYNTHS->mem.active, 0, BRISTOL_STAT) != 0)
1025 				{
1026 					if (++location >= 1024)
1027 						location = 0;
1028 					if (location == SYNTHS->location)
1029 						break;
1030 				}
1031 				if (location != SYNTHS->location)
1032 				{
1033 					SYNTHS->location = location;
1034 					bttyMemLoad(global);
1035 					return(B_ERR_OK);
1036 				} else {
1037 					snprintf(pbuf, btty.len, "no memories\r\n");
1038 					n = write(btty.fd[1], pbuf, strlen(pbuf));
1039 					return(B_ERR_VALUE);
1040 				}
1041 			}
1042 		} else if (isparam(B_COM_MEMORY, B_COM_READ, argv[1])) {
1043 			if (strncmp("undo", argv[2], strlen(argv[2])) == 0)
1044 			{
1045 				n = SYNTHS->location;
1046 				SYNTHS->location = 9999;
1047 				bttyMemLoad(global);
1048 				SYNTHS->location = n;
1049 				return(B_ERR_OK);
1050 			}
1051 
1052 			if ((n = atoi(argv[2])) < 0)
1053 				return(B_ERR_VALUE);
1054 			if (n > 1023)
1055 				return(B_ERR_VALUE);
1056 
1057 			SYNTHS->location = n;
1058 			bttyMemLoad(global);
1059 			return(B_ERR_OK);
1060 		} else if (isparam(B_COM_MEMORY, B_COM_FORCE, argv[1])) {
1061 			if (strcmp(argv[2], "on") == 0)
1062 			{
1063 				btty.fl = BRISTOL_FORCE;
1064 				return(B_ERR_OK);
1065 			} else if (strcmp(argv[2], "off") == 0) {
1066 				btty.fl = 0;
1067 				return(B_ERR_OK);
1068 			}
1069 			return(B_ERR_PARAM);
1070 		} else if (isparam(B_COM_MEMORY, B_COM_WRITE, argv[1])) {
1071 			if ((n = atoi(argv[2])) < 0)
1072 				return(B_ERR_VALUE);
1073 			if (n > 1023)
1074 				return(B_ERR_VALUE);
1075 
1076 			SYNTHS->location = n;
1077 			bttyMemSave(global);
1078 			return(B_ERR_OK);
1079 		}
1080 		return(B_ERR_PARAM);
1081 	}
1082 
1083 	if (c == 4)
1084 	{
1085 		int loc;
1086 
1087 		/* import, export */
1088 		if (isparam(B_COM_MEMORY, B_COM_IMPORT, argv[1]))
1089 		{
1090 			loc = atoi(argv[3]);
1091 			bristolMemoryImport(loc, argv[2], RESOURCES->name);
1092 			return(B_ERR_OK);
1093 		} else if (isparam(B_COM_MEMORY, B_COM_EXPORT, argv[1])) {
1094 			loc = atoi(argv[2]);
1095 			bristolMemoryExport(loc, argv[1], RESOURCES->name);
1096 			return(B_ERR_OK);
1097 		}
1098 		return(B_ERR_PARAM);
1099 	}
1100 
1101 	return(B_ERR_PARAM);
1102 }
1103 
1104 static int
execCLI(guimain * global,int c,char ** argv)1105 execCLI(guimain *global, int c, char **argv)
1106 {
1107 	int n;
1108 
1109 	if (c == 1)
1110 	{
1111 		int i;
1112 
1113 		snprintf(pbuf, btty.len, "cycle:                      %i\r\n", btty.cycle);
1114 		n = write(btty.fd[1], pbuf, strlen(pbuf));
1115 
1116 		snprintf(pbuf, btty.len, "CLI <ESC> mode navigation keys:\n\r");
1117 		n = write(btty.fd[1], pbuf, strlen(pbuf));
1118 
1119 		for (i = 0; action[i].imap != -1; i++)
1120 		{
1121 			snprintf(pbuf, btty.len, "%2i    : %s\n\r",
1122 				i,
1123 				templates[action[i].imap].opname);
1124 			if (action[i].map <= 27)
1125 			{
1126 				pbuf[3] = '^';
1127 				pbuf[4] = action[i].map + 96;
1128 			} else
1129 				pbuf[4] = action[i].map;
1130 			n = write(btty.fd[1], pbuf, strlen(pbuf));
1131 		}
1132 		return(0);
1133 	}
1134 
1135 	if (c == 2)
1136 	{
1137 		if (strncmp("cycle", argv[1], strlen(argv[1])) == 0) {
1138 			snprintf(pbuf, btty.len, "cycle:                      %i\r\n",
1139 				btty.cycle);
1140 			n = write(btty.fd[1], pbuf, strlen(pbuf));
1141 			return(0);
1142 		} else if (strncmp("listcommands", argv[1], strlen(argv[1])) == 0) {
1143 			int i;
1144 
1145 			for (i = 0; templates[i].imap != -1; i++)
1146 			{
1147 				snprintf(pbuf, btty.len, "    %s\n\r", templates[i].opname);
1148 				n = write(btty.fd[1], pbuf, strlen(pbuf));
1149 			}
1150 			return(0);
1151 		}
1152 	}
1153 
1154 	if (c == 3)
1155 	{
1156 		if (strncmp("cycle", argv[1], strlen(argv[1])) == 0) {
1157 			if ((btty.cycle = atoi(argv[2])) < 50)
1158 				btty.cycle = 50;
1159 			else if (btty.cycle > 1000)
1160 				btty.cycle = 1000;
1161 			snprintf(pbuf, btty.len, "cycle:                      %i\r\n",
1162 				btty.cycle);
1163 			n = write(btty.fd[1], pbuf, strlen(pbuf));
1164 		} else {
1165 			char comm[B_TTY_LINE_LEN];
1166 			snprintf(comm, B_TTY_LINE_LEN, "%s %s\n", argv[1], argv[2]);
1167 print(comm);
1168 			brightonSetCLIcode(comm);
1169 		}
1170 		return(0);
1171 	}
1172 	return(2);
1173 }
1174 
1175 static int
execAlias(guimain * global,int c,char ** argv)1176 execAlias(guimain *global, int c, char **argv)
1177 {
1178 	char *comm, alias[B_TTY_LINE_LEN];
1179 	int i;
1180 
1181 	print("execAlias");
1182 
1183 	if ((c == 1) && (strncmp(argv[0], "alias", strlen(argv[0])) == 0))
1184 	{
1185 		int n;
1186 		for (i = 0; commands[i].map != B_COM_LAST; i++)
1187 		{
1188 			if (commands[i].map == B_COM_ALIAS)
1189 			{
1190 				snprintf(pbuf, B_TTY_LINE_LEN, "%12s: %s\n\r",
1191 					commands[i].name, commands[i].help);
1192 				n = write(btty.fd[1], pbuf, strlen(pbuf));
1193 			}
1194 		}
1195 		return(0);
1196 	}
1197 
1198 	/*
1199 	 * Two calls, one with the actual 'alias' token, if not we should search
1200 	 * the alias list.
1201 	 */
1202 	if (strncmp("alias", argv[0], strlen(argv[0])) == 0)
1203 	{
1204 		if (c < 3)
1205 			return(2);
1206 		/*
1207 		 * the alias is in our cbuf, we just have to find it.
1208 		 */
1209 		if (cbuf[0] == 's')
1210 		{
1211 			if ((comm = index(cbuf, ' ')) == NULL)
1212 				return(3);
1213 			comm++;
1214 			if ((comm = index(comm, ' ')) == NULL)
1215 				return(3);
1216 			comm++;
1217 			if ((comm = index(comm, ' ')) == NULL)
1218 				return(3);
1219 			comm++;
1220 			if (comm[0] == '\0')
1221 				return(3);
1222 			snprintf(alias, btty.len, "%s", comm);
1223 		} else if (cbuf[0] == 'a') {
1224 			if ((comm = index(cbuf, ' ')) == NULL)
1225 				return(3);
1226 			comm++;
1227 			if ((comm = index(comm, ' ')) == NULL)
1228 				return(3);
1229 			comm++;
1230 			if (comm[0] == '\0')
1231 				return(3);
1232 			snprintf(alias, btty.len, "%s", comm);
1233 		} else
1234 			return(2);
1235 
1236 		comm = argv[1];
1237 		if (strncmp(comm, alias, strlen(comm)) == 0)
1238 		{
1239 			print("cannot apply alias: recursive");
1240 			return(2);
1241 		}
1242 
1243 		/* Find free command */
1244 		for (i = 0; commands[i].map != -1; i++)
1245 		{
1246 			if (i == (B_TTY_ACT_COUNT - 1))
1247 			{
1248 				snprintf(pbuf, btty.len, "command table full\r\n");
1249 				i = write(btty.fd[1], pbuf, strlen(pbuf));
1250 				return(4);
1251 			}
1252 
1253 			if (strcmp(commands[i].name, comm) == 0)
1254 			{
1255 				if (commands[i].map != B_COM_ALIAS)
1256 				{
1257 					print("cannot apply alias: name in use");
1258 					return(2);
1259 				}
1260 				print("remapping alias");
1261 				snprintf(commands[i].name, 11, "%s", comm);
1262 				snprintf(commands[i].help, B_TTY_LINE_LEN, "%s", alias);
1263 				commands[i].exec = execAlias;
1264 				return(0);
1265 			}
1266 			if (commands[i].map == B_COM_FREE)
1267 				break;
1268 		}
1269 
1270 		print(comm);
1271 		print(alias);
1272 
1273 		/* Flag next entry as last */
1274 		if (commands[i].map != B_COM_FREE)
1275 		{
1276 			commands[i + 1].name[0] = '\0';
1277 			commands[i + 1].map = B_COM_LAST;
1278 		}
1279 
1280 		snprintf(commands[i].name, 11, "%s", comm);
1281 		snprintf(commands[i].help, B_TTY_LINE_LEN, "%s", alias);
1282 		commands[i].map = B_COM_ALIAS;
1283 		commands[i].exec = execAlias;
1284 		return(0);
1285 	} else {
1286 		int j = 1, k = 0;
1287 
1288 		print("searchAlias");
1289 
1290 		/*
1291 		 * Build a new command line and exec it. Find the alias, take it's
1292 		 * help line, copy over byte by byte to cbuf, replace each % with
1293 		 * increasing argv (if we have enough)
1294 		 */
1295 		for (i = 0; commands[i].map != -1; i++)
1296 		{
1297 			if (strncmp(argv[0], commands[i].name, strlen(argv[0])) == 0)
1298 				break;
1299 		}
1300 		if (commands[i].map != B_COM_ALIAS)
1301 			return(B_ERR_PARAM);
1302 		comm = commands[i].help;
1303 
1304 		print(comm);
1305 
1306 		btty.flags |= B_TTY_ALIASING;
1307 		for (i = 0; comm[i] != '\0'; i++)
1308 		{
1309 			if  (comm[i] == '$')
1310 			{
1311 				int l, m;
1312 
1313 				i++;
1314 
1315 				if (((m = atoi(&comm[i])) < 1) || (m >= c))
1316 				{
1317 					print("alias failed: too few arguments");
1318 					btty.flags &= ~B_TTY_ALIASING;
1319 					return(B_ERR_INV_ARG);
1320 				}
1321 				for (l = 0; argv[m][l] != '\0'; l++)
1322 					alias[k++] = argv[m][l];
1323 			}
1324 			if (comm[i] == '%')
1325 			{
1326 				int l;
1327 
1328 				if (j == c)
1329 				{
1330 					print("alias failed: too few arguments");
1331 					btty.flags &= ~B_TTY_ALIASING;
1332 					return(B_ERR_INV_ARG);
1333 				}
1334 				for (l = 0; argv[j][l] != '\0'; l++)
1335 					alias[k++] = argv[j][l];
1336 				if (comm[i] == '%')
1337 					j++;
1338 				i++;
1339 			}
1340 			if (comm[i] == ';')
1341 			{
1342 				alias[k] = '\0';
1343 				print(alias);
1344 				bttyInterpret(global, alias);
1345 				memset(alias, 0, B_TTY_LINE_LEN);
1346 				k = 0;
1347 			} else
1348 				alias[k++] = comm[i];
1349 		}
1350 		alias[k++] = '\0';
1351 		print(alias);
1352 		bttyInterpret(global, alias);
1353 		btty.flags &= ~B_TTY_ALIASING;
1354 		return(0);
1355 	}
1356 	return(2);
1357 }
1358 
1359 /*
1360  * controller c o v - very expert usage.
1361  */
1362 static int
execBristol(guimain * global,int c,char ** argv)1363 execBristol(guimain *global, int c, char **argv)
1364 {
1365 	int o, p;
1366 	float v;
1367 
1368 	print("execBristol");
1369 
1370 	if (execHelpCheck(c, argv)) return(0);
1371 
1372 	if (c == 2)
1373 	{
1374 		if (strncmp(bristolcom[1].name, argv[1], strlen(argv[1])) == 0)
1375 		{
1376 			snprintf(pbuf, btty.len, "register request %i %p\n\r",
1377 				btty.i, DEVICE(btty.i).dev);
1378 			o = write(btty.fd[1], pbuf, strlen(pbuf));
1379 			brightonRegisterController((brightonDevice *)
1380 				DEVICE(btty.i).dev);
1381 			return(0);
1382 		}
1383 	}
1384 
1385 	if (c == 5)
1386 	{
1387 		if (strncmp(bristolcom[2].name, argv[1], strlen(argv[1])) == 0)
1388 		{
1389 			int sid;
1390 
1391 			if ((o = atoi(argv[2])) < 0) return(3); if (o > 127) return(3);
1392 			if ((p = atoi(argv[3])) < 0) return(3); if (p > 127) return(3);
1393 			if ((v = atof(argv[4])) < 0.0f) return(3); if (v > 1.0f) return(3);
1394 
1395 			if (btty.ichan == 0)
1396 				sid = SYNTHS->sid;
1397 			else
1398 				sid = SYNTHS->sid2;
1399 			bristolMidiSendMsg(global->controlfd, btty.ichan,
1400 				o, p, (int) (v * C_RANGE_MIN_1));
1401 			return(0);
1402 		}
1403 	}
1404 
1405 	return(B_ERR_PARAM);
1406 }
1407 
1408 extern int bristolPressureEvent(int, int, int, int);
1409 extern int bristolPolyPressureEvent(int, int, int, int, int);
1410 
1411 /*
1412  * This is probably going to become a large part of the interface, it can give
1413  * access to loads of stuff that many of the GUI may not use because there was
1414  * no other way to control them.
1415  *
1416  * midi channel 1..16
1417  * midi debug 0..3
1418  * midi lowkey|highkey 0..127
1419  * midi filters lwf|nwf|wwf|hwf
1420  * midi notepref hnp|lnp|nnp
1421  * midi velocity 1..1000
1422  * midi chanpressure 0..127
1423  * midi polypressure 0..127 0..127
1424  * midi detune 0..500
1425  * midi glide 0..30
1426  * midi legato on/off
1427  * midi trig on/off
1428  * midi gain 1..
1429  * midi pwd 0..
1430  * midi nrp on/off
1431  * midi forwarding on/off
1432  * midi tuning fine 0..1.0
1433  * midi tuning coarse 0..1.0
1434  * midi panic
1435  */
1436 static int
execMidi(guimain * global,int c,char ** v)1437 execMidi(guimain *global, int c, char **v)
1438 {
1439 	int i, n, k;
1440 
1441 	if (execHelpCheck(c, v)) return(0);
1442 	//if (midiHelpCheck(c, v)) return(0);
1443 
1444 	for (i = 0; i < c; i++)
1445 		print(v[i]);
1446 
1447 	if (c == 1)
1448 	{
1449 		snprintf(pbuf, btty.len, "MIDI channel:               %i\r\n",
1450 			SYNTHS->midichannel+1);
1451 		i = write(btty.fd[1], pbuf, strlen(pbuf));
1452 		snprintf(pbuf, btty.len, "SID channel:                %i\r\n",
1453 			btty.ichan);
1454 		i = write(btty.fd[1], pbuf, strlen(pbuf));
1455 		snprintf(pbuf, btty.len, "MIDI debug:                 %i\r\n",
1456 			btty.mdbg);
1457 		i = write(btty.fd[1], pbuf, strlen(pbuf));
1458 		snprintf(pbuf, btty.len, "MIDI lowkey                 %i\r\n",
1459 			btty.lowkey);
1460 		i = write(btty.fd[1], pbuf, strlen(pbuf));
1461 		snprintf(pbuf, btty.len, "MIDI highkey:               %i\r\n",
1462 			btty.highkey);
1463 		i = write(btty.fd[1], pbuf, strlen(pbuf));
1464 		return(B_ERR_OK);
1465 	}
1466 
1467 	if (c == 4)
1468 	{
1469 		if (strncmp("tuning", v[1], strlen(v[1])) == 0)
1470 		{
1471 			float tune = 0.5;
1472 			if (strncmp("fine", v[2], strlen(v[2])) == 0)
1473 			{
1474 				i = MIDI_RP_FINETUNE;
1475 
1476 				if ((tune = atof(v[3])) < 0.0f) return(3);
1477 				if (tune > 1.0f) return(3);
1478 			} else if (strncmp("coarse", v[2], strlen(v[3])) == 0) {
1479 				i = MIDI_RP_COARSETUNE;
1480 
1481 				if ((tune = atof(v[3])) < 0.0f) return(3);
1482 				if (tune > 1.0f) return(3);
1483 			}
1484 			tune *= C_RANGE_MIN_1;
1485 			bristolMidiSendNRP(global->controlfd, SYNTHS->midichannel, i, tune);
1486 			return(B_ERR_OK);
1487 		}
1488 		if (strncmp("polypressure", v[1], strlen(v[1])) == 0)
1489 		{
1490 			int k, p;
1491 
1492 			if ((k = atoi(v[2])) < 0) return(3); if (k > 127) return(3);
1493 			if ((p = atoi(v[3])) < 0) return(3); if (p > 127) return(3);
1494 
1495 			bristolPolyPressureEvent(global->controlfd, 0, SYNTHS->midichannel,
1496 				k, p);
1497 
1498 			return(B_ERR_OK);
1499 		}
1500 		if (strncmp("controller", v[1], strlen(v[1])) == 0)
1501 		{
1502 			int id, value;
1503 
1504 			if ((id = atoi(v[2])) < 0) return(B_ERR_VALUE);
1505 			if (id > 127) return(B_ERR_VALUE);
1506 			if ((value = atoi(v[3])) < 0) return(B_ERR_VALUE);
1507 			if (value > 127) return(B_ERR_VALUE);
1508 			bristolMidiSendControlMsg(global->controlfd,
1509 				SYNTHS->midichannel, id, value);
1510 			return(B_ERR_OK);
1511 		}
1512 		return(B_ERR_PARAM);
1513 	}
1514 
1515 	if (c == 2)
1516 	{
1517 		if (strncmp(v[1], "panic", strlen(v[1])) == 0) {
1518 			bristolMidiSendMsg(global->controlfd, SYNTHS->sid2, 127, 0,
1519 				BRISTOL_ALL_NOTES_OFF);
1520 			bristolMidiSendMsg(global->controlfd, SYNTHS->sid, 127, 0,
1521 				BRISTOL_ALL_NOTES_OFF);
1522 			return(B_ERR_OK);
1523 		} else if (strncmp(v[1], "sid", strlen(v[1])) == 0) {
1524 			snprintf(pbuf, btty.len, "SID channel :               %i\r\n",
1525 				btty.ichan);
1526 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1527 			return(B_ERR_OK);
1528 		} else if (strncmp(v[1], "channel", strlen(v[1])) == 0) {
1529 			snprintf(pbuf, btty.len, "MIDI channel:               %i\r\n",
1530 				SYNTHS->midichannel+1);
1531 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1532 			return(B_ERR_OK);
1533 		} else if (strncmp(v[1], "debug", strlen(v[1])) == 0) {
1534 			snprintf(pbuf, btty.len, "MIDI debug:                 %i\r\n",
1535 				btty.mdbg);
1536 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1537 			return(B_ERR_OK);
1538 		}
1539 		return(B_ERR_PARAM);
1540 	}
1541 
1542 	if (c == 3)
1543 	{
1544 		if (strncmp(v[1], "sid", strlen(v[1])) == 0) {
1545 			if ((n = atoi(v[2])) < 1)
1546 				n = 0;
1547 			else
1548 				n = 1;
1549 			btty.ichan = n;
1550 			snprintf(pbuf, btty.len, "SID channel:                %i\r\n", btty.ichan);
1551 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1552 			return(B_ERR_OK);
1553 		} else if (strncmp(v[1], "charpressure", strlen(v[1])) == 0) {
1554 			if ((n = atoi(v[2])) < 0) return(B_ERR_VALUE);
1555 			if (n > 127) return(B_ERR_VALUE);
1556 
1557 			bristolPressureEvent(global->controlfd, 0, SYNTHS->midichannel, n);
1558 			return(B_ERR_OK);
1559 		} else if (strncmp(v[1], "channel", strlen(v[1])) == 0) {
1560 			if ((n = atoi(v[2])) < 1)
1561 				return(3);
1562 			else if (n > 16)
1563 				return(3);
1564 			SYNTHS->midichannel = n - 1;
1565 			snprintf(pbuf, btty.len, "MIDI channel:               %i\r\n",
1566 				SYNTHS->midichannel+1);
1567 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1568 
1569 			SYNTHS->midichannel = SYNTHS->midichannel;
1570 			if (global->libtest == 0)
1571 				bristolMidiSendMsg(global->controlfd, SYNTHS->sid,
1572 		            127, 0, BRISTOL_MIDICHANNEL|SYNTHS->midichannel);
1573 			if ((k = atoi(v[2])) < 0) return(3); if (k > 127) return(3);
1574 
1575 			SYNTHS->highkey = btty.highkey = k;
1576 
1577 			bristolMidiSendMsg(global->controlfd, SYNTHS->sid, 127, 0,
1578 				BRISTOL_HIGHKEY|SYNTHS->highkey);
1579 			return(B_ERR_OK);
1580 		} else if (strncmp(v[1], "lowkey", strlen(v[1])) == 0) {
1581 			if ((k = atoi(v[2])) < 0) return(3); if (k > 127) return(3);
1582 
1583 			SYNTHS->lowkey = btty.lowkey = k;
1584 
1585 			bristolMidiSendMsg(global->controlfd, SYNTHS->sid, 127, 0,
1586 				BRISTOL_LOWKEY|SYNTHS->lowkey);
1587 			return(B_ERR_OK);
1588 		} else if (strncmp(v[1], "filter", strlen(v[1])) == 0) {
1589 			k = 0;
1590 			if (strcmp(v[2], "lwf") == 0) k = 1;
1591 			else if (strcmp(v[2], "nwf") == 0) k = 0;
1592 			else if (strcmp(v[2], "wwf") == 0) k = 2;
1593 			else if (strcmp(v[2], "hwf") == 0) k = 3;
1594 			else return(B_ERR_INV_ARG);
1595 			bristolMidiSendNRP(global->controlfd, SYNTHS->midichannel,
1596 				BRISTOL_NRP_LWF, k);
1597 			return(B_ERR_OK);
1598 		} else if (strncmp(v[1], "detune", strlen(v[1])) == 0) {
1599 			if ((k = atoi(v[2])) < 0) return(3); if (k > 16383) return(3);
1600 			bristolMidiSendNRP(global->controlfd, SYNTHS->midichannel,
1601 				BRISTOL_NRP_DETUNE, k);
1602 			return(B_ERR_OK);
1603 		} else if (strncmp(v[1], "velocity", strlen(v[1])) == 0) {
1604 			if ((k = atoi(v[2])) < 0) return(3); if (k > 16383) return(3);
1605 			bristolMidiSendNRP(global->controlfd, SYNTHS->midichannel,
1606 				BRISTOL_NRP_VELOCITY, k);
1607 			return(B_ERR_OK);
1608 		} else if (strncmp(v[1], "glide", strlen(v[1])) == 0) {
1609 			if ((k = atoi(v[2])) < 0) return(3); if (k > 16383) return(3);
1610 			bristolMidiSendNRP(global->controlfd, SYNTHS->midichannel,
1611 				BRISTOL_NRP_GLIDE, k);
1612 			return(B_ERR_OK);
1613 		} else if (strncmp(v[1], "pwd", strlen(v[1])) == 0) {
1614 			if ((k = atoi(v[2])) < 0) return(3); if (k > 16383) return(3);
1615 			bristolMidiSendNRP(global->controlfd, SYNTHS->midichannel,
1616 				MIDI_RP_PW, k);
1617 			return(B_ERR_OK);
1618 		} else if (strncmp(v[1], "gain", strlen(v[1])) == 0) {
1619 			if ((k = atoi(v[2])) < 0) return(3); if (k > 16383) return(3);
1620 			bristolMidiSendNRP(global->controlfd, SYNTHS->midichannel,
1621 				BRISTOL_NRP_GAIN, k);
1622 			return(B_ERR_OK);
1623 		} else if (strncmp(v[1], "forwarding", strlen(v[1])) == 0) {
1624 			k = 1;
1625 			if (strcmp(v[2], "on") == 0) k = 1;
1626 			if (strcmp(v[2], "off") == 0) k = 0;
1627 			bristolMidiSendNRP(global->controlfd, SYNTHS->midichannel,
1628 				BRISTOL_NRP_FORWARD, k);
1629 			return(B_ERR_OK);
1630 		} else if (strncmp(v[1], "nrp", strlen(v[1])) == 0) {
1631 			if (strcmp(v[2], "on") == 0)
1632 				SYNTHS->flags |= GUI_NRP;
1633 			else if (strcmp(v[2], "off") == 0)
1634 				SYNTHS->flags &= ~GUI_NRP;
1635 			return(B_ERR_OK);
1636 		} else if (strncmp(v[1], "enginenrp", strlen(v[1])) == 0) {
1637 			k = 0;
1638 			if (strcmp(v[2], "on") == 0) k = 1;
1639 			if (strcmp(v[2], "off") == 0) k = 0;
1640 			bristolMidiSendNRP(global->controlfd, SYNTHS->midichannel,
1641 				BRISTOL_NRP_ENABLE_NRP, k);
1642 			return(B_ERR_OK);
1643 		} else if (strncmp(v[1], "legato", strlen(v[1])) == 0) {
1644 			k = 1;
1645 			if (strcmp(v[2], "on") == 0) k = 1;
1646 			if (strcmp(v[2], "off") == 0) k = 0;
1647 			bristolMidiSendNRP(global->controlfd, SYNTHS->midichannel,
1648 				BRISTOL_NRP_MNL_VELOC, k);
1649 			return(B_ERR_OK);
1650 		} else if (strncmp(v[1], "trigger", strlen(v[1])) == 0) {
1651 			k = 1;
1652 			if (strcmp(v[2], "on") == 0) k = 1;
1653 			if (strcmp(v[2], "off") == 0) k = 0;
1654 			bristolMidiSendNRP(global->controlfd, SYNTHS->midichannel,
1655 				BRISTOL_NRP_MNL_TRIG, k);
1656 			return(B_ERR_OK);
1657 		} else if (strncmp(v[1], "precedence", strlen(v[1])) == 0) {
1658 			k = BRIGHTON_LNP;
1659 			if (strcmp(v[2], "hnp") == 0) k = BRIGHTON_HNP;
1660 			if (strcmp(v[2], "lnp") == 0) k = BRIGHTON_LNP;
1661 			if (strcmp(v[2], "nnp") == 0) k = BRIGHTON_POLYPHONIC;
1662 			bristolMidiSendNRP(global->controlfd, SYNTHS->midichannel,
1663 				BRISTOL_NRP_MNL_PREF, k);
1664 			return(B_ERR_OK);
1665 		} else if (strncmp(v[1], "debug", strlen(v[1])) == 0) {
1666 			n = atoi(v[2]);
1667 
1668 			switch (n) {
1669 				default:
1670 				case 0:
1671 					n = 0;
1672 					break;
1673 				case 1:
1674 					break;
1675 				case 2:
1676 					break;
1677 				case 3:
1678 					break;
1679 			}
1680 			btty.mdbg = n;
1681 			if (global->libtest == 0)
1682 				bristolMidiSendNRP(global->controlfd, SYNTHS->midichannel,
1683 		            BRISTOL_NRP_DEBUG, n);
1684 			snprintf(pbuf, btty.len, "MIDI debug:                   %i\r\n",
1685 				btty.mdbg);
1686 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1687 			return(B_ERR_OK);
1688 		}
1689 		return(B_ERR_PARAM);
1690 	}
1691 
1692 	return(B_ERR_PARAM);
1693 }
1694 
1695 /*
1696  * Set line width. Set debug on/off.
1697  */
1698 static int
execSet(guimain * global,int c,char ** v)1699 execSet(guimain *global, int c, char **v)
1700 {
1701 	int i, n;
1702 
1703 	if (execHelpCheck(c, v)) return(0);
1704 
1705 	for (i = 0; i < c; i++)
1706 		print(v[i]);
1707 
1708 	if (c > 1)
1709 	{
1710 		if (strncmp("memory", v[1], strlen(v[1])) == 0)
1711 			return(execMemory(global, c - 1, v += 1));
1712 		if (strncmp("midi", v[1], strlen(v[1])) == 0)
1713 			return(execMidi(global, c - 1, v += 1));
1714 		if (strncmp("debug", v[1], strlen(v[1])) == 0)
1715 			return(execDebug(global, c - 1, v += 1));
1716 		if (strncmp("bristol", v[1], strlen(v[1])) == 0)
1717 			return(execBristol(global, c - 1, v += 1));
1718 		if (strncmp("control", v[1], strlen(v[1])) == 0)
1719 			return(execBristol(global, c - 1, v += 1));
1720 		if (strncmp("brighton", v[1], strlen(v[1])) == 0)
1721 			return(execBrighton(global, c - 1, v += 1));
1722 		if (strncmp("alias", v[1], strlen(v[1])) == 0)
1723 			return(execAlias(global, c - 1, v += 1));
1724 		if (strncmp("cli", v[1], strlen(v[1])) == 0)
1725 			return(execCLI(global, c - 1, v += 1));
1726 	}
1727 
1728 
1729 	if (c == 1)
1730 	{
1731 		snprintf(pbuf, btty.len, "line width:                 %i\r\n",
1732 			btty.len);
1733 		i = write(btty.fd[1], pbuf, strlen(pbuf));
1734 		snprintf(pbuf, btty.len, "history:                    %i\r\n",
1735 			btty.hist_c);
1736 		i = write(btty.fd[1], pbuf, strlen(pbuf));
1737 		if (btty.flags & B_TTY_SAVE_HIST)
1738 			snprintf(pbuf, btty.len, "savehistory:                on\r\n");
1739 		else
1740 			snprintf(pbuf, btty.len, "savehistory:                off\r\n");
1741 		i = write(btty.fd[1], pbuf, strlen(pbuf));
1742 
1743 		snprintf(pbuf, btty.len, "prompt:                     %s\r\n",
1744 			btty.prompt);
1745 		i = write(btty.fd[1], pbuf, strlen(pbuf));
1746 
1747 		snprintf(pbuf, btty.len, "prompttext:                 %s\r\n",
1748 			btty.promptText);
1749 		i = write(btty.fd[1], pbuf, strlen(pbuf));
1750 
1751 		snprintf(pbuf, btty.len, "accelerator:                %0.3f\r\n",
1752 			btty.accel);
1753 		i = write(btty.fd[1], pbuf, strlen(pbuf));
1754 
1755 		snprintf(pbuf, btty.len, "active panel:               %i\r\n",
1756 			btty.p);
1757 		i = write(btty.fd[1], pbuf, strlen(pbuf));
1758 
1759 		if (btty.flags & B_TTY_DEBUG)
1760 			snprintf(pbuf, btty.len, "debug (cli):                on\r\n");
1761 		else
1762 			snprintf(pbuf, btty.len, "debug (cli):                off\r\n");
1763 		i = write(btty.fd[1], pbuf, strlen(pbuf));
1764 		if (btty.flags & B_TTY_AWV)
1765 			snprintf(pbuf, btty.len, "access withdrawn var        on\r\n");
1766 		else
1767 			snprintf(pbuf, btty.len, "access withdrawn var        off\r\n");
1768 		i = write(btty.fd[1], pbuf, strlen(pbuf));
1769 		if (btty.flags & B_TTY_AUV)
1770 			snprintf(pbuf, btty.len, "access unnamed var          on\r\n");
1771 		else
1772 			snprintf(pbuf, btty.len, "access unnamed var          off\r\n");
1773 		i = write(btty.fd[1], pbuf, strlen(pbuf));
1774 		return(B_ERR_OK);
1775 	}
1776 
1777 	if (c == 2)
1778 	{
1779 		if (strncmp(v[1], "line", strlen(v[1])) == 0)
1780 		{
1781 			snprintf(pbuf, btty.len, "line width:                 %i\r\n",
1782 				btty.len);
1783 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1784 			return(B_ERR_OK);
1785 		} else if (strncmp(v[1], "prompt", strlen(v[1])) == 0) {
1786 			snprintf(pbuf, btty.len, "prompt:                     %s\r\n",
1787 				btty.prompt);
1788 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1789 			return(B_ERR_OK);
1790 		} else if (strncmp(v[1], "prompttext", strlen(v[1])) == 0) {
1791 			snprintf(pbuf, btty.len, "prompttext:          %s\r\n",
1792 				btty.promptText);
1793 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1794 			return(B_ERR_OK);
1795 		} else if (strncmp(v[1], "panel", strlen(v[1])) == 0) {
1796 			snprintf(pbuf, btty.len, "active panel:               %i\r\n",
1797 				btty.p);
1798 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1799 			return(B_ERR_OK);
1800 		} else if (strncmp(v[1], "accelerator", strlen(v[1])) == 0) {
1801 			snprintf(pbuf, btty.len, "accelerator:                %0.3f\r\n",
1802 				btty.accel);
1803 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1804 			return(B_ERR_OK);
1805 		} else if (strncmp(v[1], "awv", strlen(v[1])) == 0) {
1806 			if (btty.flags & B_TTY_AWV)
1807 				snprintf(pbuf, btty.len, "access withdrawn var on\r\n");
1808 			else
1809 				snprintf(pbuf, btty.len, "access withdrawn var off\r\n");
1810 			return(B_ERR_OK);
1811 		} else if (strncmp(v[1], "prompt", strlen(v[1])) == 0) {
1812 			snprintf(pbuf, btty.len, "prompt:                     %s\r\n",
1813 				btty.prompt);
1814 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1815 			return(B_ERR_OK);
1816 		} else if (strncmp(v[1], "prompttext", strlen(v[1])) == 0) {
1817 			snprintf(pbuf, btty.len, "prompttext:          %s\r\n",
1818 				btty.promptText);
1819 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1820 			return(B_ERR_OK);
1821 		} else if (strncmp(v[1], "panel", strlen(v[1])) == 0) {
1822 			snprintf(pbuf, btty.len, "active panel:               %i\r\n",
1823 				btty.p);
1824 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1825 			return(B_ERR_OK);
1826 		} else if (strncmp(v[1], "accelerator", strlen(v[1])) == 0) {
1827 			snprintf(pbuf, btty.len, "accelerator:                %0.3f\r\n",
1828 				btty.accel);
1829 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1830 			return(B_ERR_OK);
1831 		} else if (strncmp(v[1], "awv", strlen(v[1])) == 0) {
1832 			if (btty.flags & B_TTY_AWV)
1833 				snprintf(pbuf, btty.len, "access withdrawn var on\r\n");
1834 			else
1835 				snprintf(pbuf, btty.len, "access withdrawn var off\r\n");
1836 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1837 			return(B_ERR_OK);
1838 		} else if (strncmp(v[1], "debug", strlen(v[1])) == 0) {
1839 			if (btty.flags & B_TTY_DEBUG)
1840 				snprintf(pbuf, btty.len, "debug (cli):                on\r\n");
1841 			else
1842 				snprintf(pbuf, btty.len, "debug (cli):                off\r\n");
1843 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1844 			return(B_ERR_OK);
1845 		} else if (strncmp(v[1], "save", strlen(v[1])) == 0) {
1846 			snprintf(pbuf, btty.len, "save set not implemented\r\n");
1847 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1848 			return(B_ERR_OK);
1849 		} else if (strncmp(v[1], "savehistory", strlen(v[1])) == 0) {
1850 			if (btty.flags & B_TTY_SAVE_HIST)
1851 				snprintf(pbuf, btty.len, "savehistory:                on\r\n");
1852 			else
1853 				snprintf(pbuf, btty.len, "savehistory:                off\r\n");
1854 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1855 			return(B_ERR_OK);
1856 		} else if (strncmp(v[1], "history", strlen(v[1])) == 0) {
1857 			for (i = btty.hist_c; i > 0; i--)
1858 			{
1859 				if (btty.hist[i][0] != '\0')
1860 				{
1861 					snprintf(pbuf, btty.len, "%i %s\r\n", i, btty.hist[i]);
1862 					n = write(btty.fd[1], pbuf, strlen(pbuf));
1863 				}
1864 			}
1865 			return(B_ERR_OK);
1866 		}
1867 		return(2);
1868 	}
1869 
1870 	if (c == 3)
1871 	{
1872 		if (strncmp(v[1], "line", strlen(v[1])) == 0)
1873 		{
1874 			if ((n = atoi(v[2])) < 0)
1875 				return(3);
1876 			else if (n > B_TTY_LINE_LEN)
1877 				return(3);
1878 			else
1879 				btty.len = n;
1880 			snprintf(pbuf, btty.len, "line width:                 %i\r\n",
1881 				btty.len);
1882 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1883 			return(B_ERR_OK);
1884 		} else if (strncmp(v[1], "prompttext", strlen(v[1])) == 0) {
1885 			snprintf(btty.promptText, 64, "%s", v[2]);
1886 			snprintf(pbuf, btty.len, "prompttext:                 %s\r\n",
1887 				btty.promptText);
1888 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1889 			return(B_ERR_OK);
1890 		} else if (strncmp(v[1], "play", strlen(v[1])) == 0) {
1891 			if (strncmp(v[2], "mode", strlen(v[2])) == 0) {
1892 				btty.flags &= ~B_TTY_MMASK;
1893 				btty.flags |= B_TTY_PLAY;
1894 				snprintf(pbuf, btty.len,
1895 					"Play mode: type ':' or <ESC> to exit\n\r");
1896 				i = write(btty.fd[1], pbuf, strlen(pbuf));
1897 				 return(B_ERR_EARLY);
1898 			}
1899 		} else if (strncmp(v[1], "accelerator", strlen(v[1])) == 0) {
1900 			btty.accel = atof(v[2]);
1901 			snprintf(pbuf, btty.len, "accelerator:                %0.3f\r\n",
1902 				btty.accel);
1903 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1904 			return(B_ERR_OK);
1905 		} else if (strncmp(v[1], "panel", strlen(v[1])) == 0) {
1906 			int x = -1;
1907 			if ((x = atoi(v[2])) < 0)
1908 				x = -1;
1909 			if (x >= SYNTHS->win->app->nresources)
1910 				x = -1;
1911 			if (SYNTHS->win->app->resources[x].ndevices == 0)
1912 				x = -1;
1913 			if (SYNTHS->win->app->resources[x].devlocn == NULL)
1914 				x = -1;
1915 			if (x >= 0)
1916 			{
1917 				btty.p = x;
1918 				if (btty.i >= SYNTHS->win->app->resources[x].ndevices)
1919 					btty.i = SYNTHS->win->app->resources[x].ndevices - 1;
1920 			}
1921 			else
1922 				return(3);
1923 			snprintf(pbuf, btty.len, "active panel:               %i\r\n",
1924 				btty.p);
1925 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1926 			return(B_ERR_OK);
1927 		} else if (strncmp(v[1], "auv", strlen(v[1])) == 0) {
1928 			btty.flags &= ~B_TTY_AUV;
1929 			if (strcmp("on", v[2]) == 0)
1930 				btty.flags |= B_TTY_AWV;
1931 			if (btty.flags & B_TTY_AWV)
1932 				snprintf(pbuf, btty.len, "access unnamed var          on\r\n");
1933 			else
1934 				snprintf(pbuf, btty.len, "access unnamed var          off\r\n");
1935 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1936 			return(B_ERR_OK);
1937 		} else if (strncmp(v[1], "awv", strlen(v[1])) == 0) {
1938 			btty.flags &= ~B_TTY_AWV;
1939 			if (strcmp("on", v[2]) == 0)
1940 				btty.flags |= B_TTY_AWV;
1941 			if (btty.flags & B_TTY_AWV)
1942 				snprintf(pbuf, btty.len, "access withdrawn var        on\r\n");
1943 			else
1944 				snprintf(pbuf, btty.len, "access withdrawn var        off\r\n");
1945 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1946 			return(B_ERR_OK);
1947 		} else if (strncmp(v[1], "savehistory", strlen(v[1])) == 0) {
1948 			if (strcmp(v[2], "on") == 0)
1949 				btty.flags |= B_TTY_SAVE_HIST;
1950 			else if (strcmp(v[2], "off") == 0)
1951 				btty.flags &= ~B_TTY_SAVE_HIST;
1952 			if (btty.flags & B_TTY_SAVE_HIST)
1953 				snprintf(pbuf, btty.len, "savehistory:                on\r\n");
1954 			else
1955 				snprintf(pbuf, btty.len, "savehistory:                off\r\n");
1956 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1957 			return(B_ERR_OK);
1958 		} else if (strncmp(v[1], "history", strlen(v[1])) == 0) {
1959 			if ((btty.hist_c = atoi(v[2])) <= 0)
1960 				btty.hist_c = 50;
1961 			else if (btty.hist_c > 50)
1962 				btty.hist_c = 50;
1963 			return(B_ERR_OK);
1964 		} else if (strncmp(v[1], "noalias", strlen(v[1])) == 0) {
1965 			for (i = 0; commands[i].map != -1; i++)
1966 			{
1967 				if (commands[i].map != B_COM_ALIAS)
1968 					continue;
1969 				if (strcmp(commands[i].name, v[2]) == 0)
1970 				{
1971 					commands[i].name[0] = '\0';
1972 					commands[i].help[0] = '\0';
1973 					commands[i].map = B_COM_FREE;
1974 					commands[i].exec = NULL;
1975 					break;
1976 				}
1977 			}
1978 			return(B_ERR_OK);
1979 		} else if (strncmp(v[1], "debug", strlen(v[1])) == 0) {
1980 			btty.flags &= ~B_TTY_DEBUG;
1981 			if (strcmp(v[2], "on") == 0)
1982 				btty.flags |= B_TTY_DEBUG;
1983 			if (btty.flags & B_TTY_DEBUG)
1984 				snprintf(pbuf, btty.len, "debug (cli):                on\r\n");
1985 			else
1986 				snprintf(pbuf, btty.len, "debug (cli):                off\r\n");
1987 			i = write(btty.fd[1], pbuf, strlen(pbuf));
1988 			return(B_ERR_OK);
1989 		}
1990 	}
1991 
1992 	if (c > 3)
1993 	{
1994 		if (strncmp(v[1], "play", strlen(v[1])) == 0) {
1995 			print("set play");
1996 			if (c != 4)
1997 				return(B_ERR_PARAM);
1998 			if (strncmp(v[2], "rate", strlen(v[2])) == 0)
1999 			{
2000 				int rate;
2001 
2002 				if ((rate = atoi(v[3])) < 0) return(B_ERR_VALUE);
2003 				sequences[btty.sequence.id].rate = rate;
2004 				return(B_ERR_OK);
2005 			}
2006 			if (strncmp(v[2], "transpose", strlen(v[2])) == 0)
2007 			{
2008 				int transpose;
2009 
2010 				transpose = atoi(v[3]);
2011 				btty.sequence.transpose = transpose;
2012 				return(B_ERR_OK);
2013 			}
2014 			if (strncmp(v[2], "sequence", strlen(v[2])) == 0)
2015 			{
2016 				int seq;
2017 
2018 				print("sequence");
2019 				if ((seq = atoi(v[3])) < 0) return(B_ERR_VALUE);
2020 				if (seq >= B_SEQ_COUNT) return(B_ERR_VALUE);
2021 				if (sequences[seq].count <= 0) return(B_ERR_VALUE);
2022 
2023 				btty.sequence.step = -1;
2024 				btty.sequence.count =
2025 					250 * 60 / sequences[btty.sequence.id].rate;
2026 
2027 				btty.flags &= ~B_TTY_MMASK;
2028 				btty.flags |= B_TTY_SEQ|B_TTY_RAW;
2029 
2030 				return(B_ERR_EARLY);
2031 			}
2032 		} else if ((strncmp(v[1], "history", strlen(v[1])) == 0)
2033 			&& (strncmp(v[2], "comm", strlen(v[2])) == 0))
2034 		{
2035 			char *comm;
2036 
2037 			/* rotate history, add this one */
2038 			if ((comm = strstr(cbuf, "comm")) == NULL)
2039 				return(2);
2040 			comm += 5;
2041 			snprintf(btty.hist[1], B_TTY_LINE_LEN, "%s", comm);
2042 			return(B_ERR_OK);
2043 		}
2044 	}
2045 
2046 	return(2);
2047 }
2048 
2049 static int
execImport(guimain * global,int c,char ** v)2050 execImport(guimain *global, int c, char **v)
2051 {
2052 	int loc;
2053 
2054 	if (execHelpCheck(c, v)) return(0);
2055 
2056 	loc = SYNTHS->location;
2057 
2058 	if (c == 1)
2059 		return(2);
2060 
2061 	if (c == 2) {
2062 		loc = SYNTHS->location;
2063 		if ((v[1] == NULL) || (v[1][0] == '\0'))
2064 			return(3);
2065 	}
2066 
2067 	print(v[1]);
2068 
2069 	if (strncmp("import", v[0], strlen(v[0])) == 0)
2070 	{
2071 		if (c == 3)
2072 			loc = atoi(v[2]);
2073 		bristolMemoryImport(loc, v[1], RESOURCES->name);
2074 		return(0);
2075 	} else if (strncmp("export", v[0], strlen(v[0])) == 0) {
2076 		if (c == 3)
2077 			loc = atoi(v[2]);
2078 		bristolMemoryExport(loc, v[1], RESOURCES->name);
2079 		return(0);
2080 	}
2081 
2082 	return(0);
2083 }
2084 
2085 static void
execParamChange(guimain * global,float v)2086 execParamChange(guimain *global, float v)
2087 {
2088 	int i;
2089 	char *name;
2090 
2091 	if ((paramname(btty.i) == NULL) || (paramname(btty.i)[0] == '\0'))
2092 		name = unknown;
2093 	else
2094 		name = paramname(btty.i);
2095 
2096 /*
2097 	if ((SYNTHS->win->app->resources[btty.p].devlocn[btty.i].type == 1)
2098 		|| (SYNTHS->win->app->resources[btty.p].devlocn[btty.i].type == 7))
2099 		brightonChangeParam(SYNTHS, btty.p, btty.i, v);
2100 	else
2101 		brightonChangeParam(SYNTHS, btty.p, btty.i,
2102 			v * RESOURCES->resources[btty.p].devlocn[btty.i].to);
2103 */
2104 	brightonChangeParam(SYNTHS, btty.p, btty.i, v * DEVICE(btty.i).to);
2105 
2106 	if (DEVICE(btty.i).to == 1.0f)
2107 	{
2108 		if (DEVICE(btty.i).type == 1)
2109 			snprintf(pbuf, btty.len, "%02i %-25s: %4.0f\r\n", btty.i,
2110 				name, (1.0 - PDEV(btty.i)->value) * 1000.0f);
2111 		else if (DEVICE(btty.i).type == 2)
2112 			snprintf(pbuf, btty.len, "%02i %-25s: %1.0f\r\n", btty.i,
2113 				name, PDEV(btty.i)->value);
2114 		else
2115 			snprintf(pbuf, btty.len, "%02i %-25s: %4.0f\r\n", btty.i,
2116 				name, PDEV(btty.i)->value * 1000.0f);
2117 	} else {
2118 		if (DEVICE(btty.i).type == 1)
2119 		{
2120 			if (DEVICE(btty.i).flags & BRIGHTON_REVERSE)
2121 				snprintf(pbuf, btty.len, "%02i %-25s: %4.0f\r\n", btty.i,
2122 					name, PDEV(btty.i)->value * DEVICE(btty.i).to);
2123 			else
2124 				snprintf(pbuf, btty.len, "%02i %-25s: %4.0f\r\n", btty.i,
2125 					name, (1.0 - PDEV(btty.i)->value)
2126 						* DEVICE(btty.i).to);
2127 		} else if (DEVICE(btty.i).type == 2) {
2128 			snprintf(pbuf, btty.len, "%02i %-25s: %4.0f\r\n", btty.i,
2129 				name, PDEV(btty.i)->value);
2130 		} else
2131 			snprintf(pbuf, btty.len, "%02i %-25s: %4.0f\r\n", btty.i,
2132 				name, PDEV(btty.i)->value * DEVICE(btty.i).to);
2133 		//	snprintf(pbuf, btty.len, "%02i %-25s: %3.0f\n\r", btty.i,
2134 		//		name, ((brightonDevice *) DEVICE(btty.i).dev)->value);
2135 	}
2136 
2137 	i = write(btty.fd[1], pbuf, strlen(pbuf));
2138 }
2139 
2140 static int
execBrighton(guimain * global,int c,char ** argv)2141 execBrighton(guimain *global, int c, char **argv)
2142 {
2143 	int p, d, tp, ti;
2144 	float v;
2145 
2146 	print("execBrighton");
2147 
2148 	if (execHelpCheck(c, argv)) return(0);
2149 
2150 	if (c == 2)
2151 	{
2152 		if (strncmp(brightoncom[1].name, argv[1], strlen(argv[1])) == 0)
2153 		{
2154 			snprintf(pbuf, btty.len, "active panel:        %i\r\n", btty.p);
2155 			p = write(btty.fd[1], pbuf, strlen(pbuf));
2156 			return(0);
2157 		}
2158 		return(1);
2159 	}
2160 
2161 	if (c == 3)
2162 	{
2163 		if (strncmp(brightoncom[1].name, argv[1], strlen(argv[1])) == 0)
2164 		{
2165 			int x;
2166 
2167 			if ((x = atoi(argv[2])) < 0)
2168 				return(3);
2169 			if (btty.p > SYNTHS->win->app->nresources)
2170 				return(3);
2171 			if (SYNTHS->win->app->resources[x].ndevices == 0)
2172 				return(3);
2173 			btty.p = x;
2174 			snprintf(pbuf, btty.len, "active panel:        %i\r\n", btty.p);
2175 			p = write(btty.fd[1], pbuf, strlen(pbuf));
2176 			return(0);
2177 		}
2178 		return(2);
2179 	}
2180 
2181 	if (c == 5)
2182 	{
2183 		if (strncmp(brightoncom[2].name, argv[1], strlen(argv[1])) == 0)
2184 		{
2185 			/* Device settings */
2186 			if ((p = atoi(argv[2])) < 0)
2187 				return(B_ERR_PARAM);
2188 			if (p >= SYNTHS->win->app->nresources)
2189 				return(B_ERR_PARAM);
2190 			if (SYNTHS->win->app->resources[p].ndevices <= 0)
2191 				return(B_ERR_PARAM);
2192 			if ((d = atoi(argv[3])) < 0)
2193 				return(B_ERR_PARAM);
2194 			if (d >= SYNTHS->win->app->resources[p].ndevices)
2195 				return(B_ERR_PARAM);
2196 
2197 			tp = btty.p;
2198 			ti = btty.i;
2199 
2200 			btty.p = p;
2201 			btty.i = d;
2202 
2203 			if (argv[4][1] == '=')
2204 			{
2205 				if (argv[4][0] == '+')
2206 					v = atof(&argv[4][2]) + PDEV(d)->value;
2207 				else if (argv[4][0] == '-')
2208 					v = PDEV(d)->value - atof(&argv[4][2]);
2209 				else
2210 					return(B_ERR_VALUE);
2211 			} else if ((v = atof(argv[4])) < 0.0f)
2212 				return(B_ERR_VALUE);
2213 
2214 			if (v < 0) v = 0.0f;
2215 
2216 			execParamChange(global, v);
2217 
2218 			btty.p = tp;
2219 			btty.i = ti;
2220 
2221 			return(B_ERR_OK);
2222 		}
2223 	}
2224 	return(B_ERR_PARAM);
2225 }
2226 
2227 static void
cliParamChange(guimain * global,float v)2228 cliParamChange(guimain *global, float v)
2229 {
2230 	int i;
2231 	char *name, crlf[4] = "\r\n", *c1 = crlf, *c2 = "";
2232 
2233 	if ((paramname(btty.i) == NULL) || (paramname(btty.i)[0] == '\0'))
2234 		name = unknown;
2235 	else
2236 		name = paramname(btty.i);
2237 
2238 	if (v != 0)
2239 	{
2240 		//if (RESOURCES->resources[btty.p].devlocn[btty.i].to != 1.0f)
2241 		if (DEVICE(btty.i).to != 1.0f)
2242 		{
2243 			if (DEVICE(btty.i).type == 1)
2244 			{
2245 				if (DEVICE(btty.i).flags & BRIGHTON_VERTICAL) {
2246 					if (v > 0)
2247 						brightonChangeParam(SYNTHS, btty.p, btty.i,
2248 							PDEV(btty.i)->value * DEVICE(btty.i).to + 1);
2249 					else
2250 						brightonChangeParam(SYNTHS, btty.p, btty.i,
2251 							PDEV(btty.i)->value * DEVICE(btty.i).to - 1);
2252 				} else if (DEVICE(btty.i).flags & BRIGHTON_REVERSE) {
2253 					if (v > 0)
2254 						brightonChangeParam(SYNTHS, btty.p, btty.i,
2255 							PDEV(btty.i)->value * DEVICE(btty.i).to - 1);
2256 					else
2257 						brightonChangeParam(SYNTHS, btty.p, btty.i,
2258 							PDEV(btty.i)->value * DEVICE(btty.i).to + 1);
2259 				} else {
2260 					if (v > 0)
2261 						brightonChangeParam(SYNTHS, btty.p, btty.i,
2262 							(1.0 - PDEV(btty.i)->value)
2263 							* DEVICE(btty.i).to + 1);
2264 					else
2265 						brightonChangeParam(SYNTHS, btty.p, btty.i,
2266 							(1.0 - PDEV(btty.i)->value)
2267 							* DEVICE(btty.i).to - 1);
2268 				}
2269 			} else if (DEVICE(btty.i).type == 7) {
2270 				if (v > 0)
2271 					brightonChangeParam(SYNTHS, btty.p, btty.i,
2272 						PDEV(btty.i)->value
2273 						* DEVICE(btty.i).to + 1);
2274 				else
2275 					brightonChangeParam(SYNTHS, btty.p, btty.i,
2276 						PDEV(btty.i)->value
2277 						* DEVICE(btty.i).to - 1);
2278 			} else if (DEVICE(btty.i).type == 2) {
2279 				if (v > 0)
2280 					brightonChangeParam(SYNTHS, btty.p, btty.i,
2281 						PDEV(btty.i)->value + 1);
2282 				else
2283 					brightonChangeParam(SYNTHS, btty.p, btty.i,
2284 						PDEV(btty.i)->value - 1);
2285 			} else {
2286 				if (v > 0)
2287 					brightonChangeParam(SYNTHS, btty.p, btty.i,
2288 						PDEV(btty.i)->value * DEVICE(btty.i).to + 1);
2289 				else
2290 					brightonChangeParam(SYNTHS, btty.p, btty.i,
2291 						PDEV(btty.i)->value * DEVICE(btty.i).to - 1);
2292 			}
2293 		} else {
2294 			if (DEVICE(btty.i).type == 1)
2295 			{
2296 				if (DEVICE(btty.i).flags & BRIGHTON_VERTICAL)
2297 					brightonChangeParam(SYNTHS, btty.p, btty.i,
2298 						PDEV(btty.i)->value + v);
2299 				else if (DEVICE(btty.i).flags & BRIGHTON_REVERSE)
2300 					brightonChangeParam(SYNTHS, btty.p, btty.i,
2301 						PDEV(btty.i)->value - v);
2302 				else
2303 					brightonChangeParam(SYNTHS, btty.p, btty.i,
2304 						(1.0 - PDEV(btty.i)->value) + v);
2305 			} else
2306 				brightonChangeParam(SYNTHS, btty.p, btty.i,
2307 					PDEV(btty.i)->value + v);
2308 		}
2309 	}
2310 
2311 	if (btty.flags & B_TTY_COOKED)
2312 	{
2313 		print("post return");
2314 		c1 = c2; c2 = crlf;
2315 	} else
2316 		print("pre return");
2317 
2318 	if (DEVICE(btty.i).to == 1.0f)
2319 	{
2320 		if (DEVICE(btty.i).type == 1)
2321 		{
2322 			if (DEVICE(btty.i).flags & BRIGHTON_VERTICAL)
2323 				snprintf(pbuf, btty.len, "%s%02i %-25s: %4.0f%s", c1, btty.i,
2324 					name, PDEV(btty.i)->value * 1000.0f, c2);
2325 			else
2326 				snprintf(pbuf, btty.len, "%s%02i %-25s: %4.0f%s", c1, btty.i,
2327 					name, (1.0 - PDEV(btty.i)->value) * 1000.0f, c2);
2328 		} else if (DEVICE(btty.i).type == 2)
2329 			snprintf(pbuf, btty.len, "%s%02i %-25s: %4.0f%s", c1, btty.i,
2330 				name, PDEV(btty.i)->value, c2);
2331 		else
2332 			snprintf(pbuf, btty.len, "%s%02i %-25s: %4.0f%s", c1, btty.i,
2333 				name, PDEV(btty.i)->value * 1000.0f, c2);
2334 	} else {
2335 		if (DEVICE(btty.i).type == 1)
2336 		{
2337 			if (DEVICE(btty.i).flags & BRIGHTON_REVERSE)
2338 				snprintf(pbuf, btty.len, "%s%02i %-25s: %4.0f%s", c1, btty.i,
2339 					name, PDEV(btty.i)->value * DEVICE(btty.i).to, c2);
2340 			else
2341 				snprintf(pbuf, btty.len, "%s%02i %-25s: %4.0f%s", c1, btty.i,
2342 					name, (1.0 - PDEV(btty.i)->value)
2343 						* DEVICE(btty.i).to, c2);
2344 		} else if (DEVICE(btty.i).type == 2) {
2345 			snprintf(pbuf, btty.len, "%s%02i %-25s: %4.0f%s", c1, btty.i,
2346 				name, PDEV(btty.i)->value, c2);
2347 		} else
2348 			snprintf(pbuf, btty.len, "%s%02i %-25s: %4.0f%s", c1, btty.i,
2349 				name, PDEV(btty.i)->value * DEVICE(btty.i).to, c2);
2350 		//	snprintf(pbuf, btty.len, "%02i %-25s: %3.0f\n\r", btty.i,
2351 		//		name, ((brightonDevice *) DEVICE(btty.i).dev)->value);
2352 	}
2353 
2354 	lp = PDEV(btty.i)->value;
2355 
2356 	i = write(btty.fd[1], pbuf, strlen(pbuf));
2357 }
2358 
2359 void
brightonCLIinit(guimain * global,int fd[])2360 brightonCLIinit(guimain *global, int fd[])
2361 {
2362 	btty.fd[0] = fd[0];
2363 	btty.fd[1] = fd[1];
2364 	btty.cycle = 500;
2365 
2366 	snprintf(btty.prompt, 64, "nicky");
2367 
2368 	btty.global = global;
2369 	btty.flags |= B_TTY_COOKED|B_TTY_INIT;
2370 }
2371 
2372 #define B_MATCHES 64
2373 
2374 /*
2375  * Take input line, extract word up to first space and attempt completion.
2376  * If we get a completion see if there are more words and complete them with
2377  * the new comset
2378  */
2379 int
bttyCookedCompletion(char * line,comSet * coms)2380 bttyCookedCompletion(char *line, comSet *coms)
2381 {
2382 	int i, v, count = 0, t, c, first = -1;
2383 	char src[B_TTY_LINE_LEN], dst[B_TTY_LINE_LEN];
2384 	char *matches[B_MATCHES];
2385 
2386 	print("Complete");
2387 
2388 	if (coms == NULL)
2389 		return(0);
2390 
2391 	print(line);
2392 
2393 	memset(matches, 0, sizeof(matches));
2394 	memset(src, 0, B_TTY_LINE_LEN);
2395 	memset(dst, 0, B_TTY_LINE_LEN);
2396 
2397 	for (i = 0; 1 ; i++)
2398 	{
2399 		if (((src[i] = line[i]) == ' ') || (src[i] == '\0'))
2400 		{
2401 			src[i] = '\0';
2402 			break;
2403 		}
2404 	}
2405 
2406 	for (v = 0; coms[v].map != B_COM_LAST; v++)
2407 	{
2408 		if (strncasecmp(coms[v].name, src, strlen(src)) == 0)
2409 		{
2410 			print(coms[v].name);
2411 
2412 			matches[count] = brightonmalloc(64);
2413 			snprintf(matches[count], 64, "%s", coms[v].name);
2414 
2415 			if (first < 0) first = v;
2416 			if (++count >= B_MATCHES)
2417 				break;
2418 		}
2419 	}
2420 
2421 	if (count == 1) {
2422 		/*
2423 		 * We now have one word filled out, see if we can continue
2424 		 */
2425 		snprintf(src, B_TTY_LINE_LEN, "%s", coms[first].name);
2426 
2427 		if (line[i] != '\0')
2428 		{
2429 			snprintf(dst, B_TTY_LINE_LEN, "%s", &line[i + 1]);
2430 			print("subsearch");
2431 			print(dst);
2432 			if (bttyCookedCompletion(dst, coms[first].subcom) >= 1)
2433 				snprintf(line, B_TTY_LINE_LEN, "%s %s", src, dst);
2434 			else
2435 				snprintf(line, B_TTY_LINE_LEN, "%s %s", src, &line[i + 1]);
2436 		} else
2437 			snprintf(line, B_TTY_LINE_LEN, "%s ", src);
2438 		//btty.edit_p = strlen(src);
2439 	} else if (count != 0) {
2440 		int y, x, ch, cont = 1;
2441 
2442 		/* Many hits - see how we can match them, display the result */
2443 		for (x = 0; cont; x++)
2444 		{
2445 			ch = matches[0][x];
2446 			for (y = 1; y < count; y++)
2447 			{
2448 				if (matches[y][x] == '\0')
2449 					cont = 0;
2450 				if (matches[y][x] != ch)
2451 					cont = 0;
2452 			}
2453 		}
2454 		if (x > 0)
2455 		{
2456 			c = 0;
2457 			ch = ' ';
2458 			/* Show the list of commands we have matched */
2459 			for (y = 0; y < count; y++)
2460 			{
2461 				t = write(btty.fd[1], matches[y], strlen(matches[y]));
2462 				t = write(btty.fd[1], &ch, 1);
2463 				if ((c += strlen(matches[y]) + 1) > btty.len - 16)
2464 				{
2465 					snprintf(pbuf, 4, "\n\r");
2466 					t = write(btty.fd[1], pbuf, 2);
2467 					c = 0;
2468 				}
2469 			}
2470 			/* And an extra return if we need it */
2471 			if (c != 0)
2472 			{
2473 				snprintf(pbuf, 4, "\n\r");
2474 				t = write(btty.fd[1], pbuf, 2);
2475 			}
2476 			/* Then see if we can move the display forward */
2477 			if (x > strlen(line))
2478 			{
2479 				snprintf(line, x, "%s", matches[0]);
2480 				btty.edit_p = strlen(line);
2481 			}
2482 //			snprintf(pbuf, B_TTY_LINE_LEN, "%i %s\r\n", x, line);
2483 //			t = write(btty.fd[1], pbuf, strlen(pbuf));
2484 		}
2485 	}
2486 
2487 	btty.edit_p = strlen(line);
2488 
2489 	for (i = 0; matches[i] != NULL; i++)
2490 		brightonfree(matches[i]);
2491 
2492 	return(count);
2493 }
2494 
2495 /*
2496  * Search only through the CLI command set
2497  */
2498 static int
bttyComplete(guimain * global)2499 bttyComplete(guimain *global)
2500 {
2501 	int v, first = -1, count = 0, c, t;//, mi = 0;
2502 	char *matches[B_MATCHES];
2503 
2504 	memset(matches, 0, sizeof(matches));
2505 
2506 	if (btty.flags & B_TTY_DEBUG)
2507 	{
2508 		snprintf(pbuf, btty.len, "\n\rcomplete %s\r", cbuf);
2509 		t = write(btty.fd[1], pbuf, strlen(pbuf));
2510 	}
2511 
2512 	if (btty.flags & B_TTY_COOKED) {
2513 		/* Complete then edit */
2514 		if (isdigit(cbuf[0]))
2515 		{
2516 			switch (strlen(cbuf)) {
2517 				case 1:
2518 				case 2:
2519 					v = atoi(cbuf);
2520 					if (btty.hist[v][0] == '\0')
2521 						break;
2522 					snprintf(cbuf, btty.len, "%s", btty.hist[v]);
2523 					btty.edit_p = strlen(cbuf);
2524 					return(1);
2525 				default:
2526 					break;
2527 			}
2528 		}
2529 
2530 		/* Complete then edit */
2531 		if ((cbuf[0] == '!') && (isdigit(cbuf[1])))
2532 		{
2533 			switch (strlen(&cbuf[1])) {
2534 				case 1:
2535 				case 2:
2536 					v = atoi(&cbuf[1]);
2537 					if (btty.hist[v][0] == '\0')
2538 						break;
2539 					snprintf(cbuf, btty.len, "%s", btty.hist[v]);
2540 					btty.edit_p = strlen(cbuf);
2541 					return(1);
2542 				default:
2543 					break;
2544 			}
2545 		}
2546 
2547 		count = bttyCookedCompletion(cbuf, commands);
2548 		btty.edit_p = strlen(cbuf);
2549 	}
2550 
2551 	for (v = 0; ((matches[v] != NULL) && (v < B_MATCHES)); v++)
2552 		brightonfree(matches[v]);
2553 	memset(matches, 0, sizeof(matches));
2554 
2555 	if (count != 0)
2556 		return(0);
2557 
2558 	c = SYNTHS->win->app->resources[btty.p].ndevices;
2559 
2560 	for (v = 0; v != c; v++)
2561 	{
2562 		if (cbuf[0] == '^') {
2563 			if (strncasecmp(paramname(v), &cbuf[1], strlen(cbuf) - 1) == 0)
2564 			{
2565 				if (first < 0) first = v;
2566 				matches[count] = brightonmalloc(64);
2567 				snprintf(matches[count], 64, "%s", paramname(v));
2568 				if (++count >= B_MATCHES)
2569 					break;
2570 			}
2571 		} else if (strcasestr(paramname(v), cbuf) != NULL) {
2572 			if (first < 0) first = v;
2573 			matches[count] = brightonmalloc(64);
2574 			snprintf(matches[count], 64, "%s", paramname(v));
2575 			if (++count >= B_MATCHES)
2576 				break;
2577 		}
2578 	}
2579 	if (count == 1) {
2580 		snprintf(cbuf, btty.len, "%s", paramname(first));
2581 		btty.i = first;
2582 		btty.edit_p = strlen(cbuf);
2583 	} else if (count != 0) {
2584 		int y, x, ch, cont = 1;
2585 
2586 		/* Many hits - see how far we can match them, display the result */
2587 		for (x = 0; cont; x++)
2588 		{
2589 			ch = matches[0][x];
2590 			for (y = 1; y < count; y++)
2591 				{
2592 				if (matches[y][x] == '\0')
2593 					cont = 0;
2594 				if (matches[y][x] != ch)
2595 					cont = 0;
2596 			}
2597 		}
2598 		if (x > 0)
2599 		{
2600 			c = 0;
2601 			ch = ' ';
2602 			for (y = 0; y < count; y++)
2603 			{
2604 				t = write(btty.fd[1], matches[y], strlen(matches[y]));
2605 				t = write(btty.fd[1], &ch, 1);
2606 				if ((c += strlen(matches[y]) + 1) > btty.len - 16)
2607 				{
2608 					snprintf(pbuf, 4, "\n\r");
2609 					t = write(btty.fd[1], pbuf, 2);
2610 					c = 0;
2611 				}
2612 			}
2613 			if (c != 0)
2614 			{
2615 				snprintf(pbuf, 4, "\n\r");
2616 				t = write(btty.fd[1], pbuf, 2);
2617 			}
2618 			if (x > strlen(cbuf))
2619 			{
2620 				snprintf(cbuf, x, "%s", matches[0]);
2621 				btty.edit_p = strlen(cbuf);
2622 			}
2623 		}
2624 	}
2625 
2626 	for (v = 0; ((matches[v] != NULL) && (v < B_MATCHES)); v++)
2627 		brightonfree(matches[v]);
2628 
2629 	return(count);
2630 }
2631 
2632 /*
2633  * Search only through the synth parameters.
2634  */
2635 static int
bttySearch(guimain * global)2636 bttySearch(guimain *global)
2637 {
2638 	int v, first = -1, count = 0;
2639 
2640 //	snprintf(pbuf, btty.len, "bttySearch\n\r");
2641 //	t = write(btty.fd[1], pbuf, strlen(pbuf));
2642 
2643 	if (cbuf[0] == '\0')
2644 		return(1);
2645 
2646 	if (btty.flags & B_TTY_DEBUG)
2647 	{
2648 		snprintf(pbuf, btty.len, "\n\rsearch %s\r", cbuf);
2649 		v = write(btty.fd[1], pbuf, strlen(pbuf));
2650 	}
2651 
2652 	/*
2653 	 * Search through the internal commands and the synth parameters. If only
2654 	 * one match then commplete it, otherwise list them.
2655 	 */
2656 	if (btty.i >= SYNTHS->win->app->resources[btty.p].ndevices)
2657 	{
2658 		btty.i = SYNTHS->win->app->resources[btty.p].ndevices - 1;
2659 		v = 0;
2660 	} else
2661 		v = btty.i + 1;
2662 
2663 	for (; v != btty.i; v++)
2664 	{
2665 		if (v >= SYNTHS->win->app->resources[btty.p].ndevices)
2666 			v = -1;
2667 //snprintf(pbuf, btty.len, "%s %s %i %i\n\r", paramname(v), cbuf, btty.i, v);
2668 //t = write(btty.fd[1], pbuf, strlen(pbuf));
2669 		if (paramname(v) == NULL)
2670 			continue;
2671 		if (unnamed(v))
2672 			continue;
2673 		if (cbuf[0] == '^') {
2674 			if (strncasecmp(paramname(v), &cbuf[1], strlen(cbuf) - 1) == 0)
2675 			{
2676 				if (first == -1)
2677 					first = v;
2678 				count++;
2679 				break;
2680 			}
2681 		} else if (strcasestr(paramname(v), cbuf) != NULL) {
2682 			if (first == -1)
2683 				first = v;
2684 			count++;
2685 			break;
2686 		}
2687 	}
2688 
2689 	if (first >= 0)
2690 		btty.i = first;
2691 
2692 	cliParamChange(global, 0.0f);
2693 
2694 	btty.flags &= ~B_TTY_MMASK;
2695 	btty.flags |= B_TTY_RAW;
2696 
2697 	btty.edit_p = 0;
2698 	btty.hist_tmp = 0;
2699 	memset(cbuf, 0, B_TTY_LINE_LEN);
2700 
2701 	return(count);
2702 }
2703 
2704 static int
execDebug(guimain * global,int c,char ** v)2705 execDebug(guimain *global, int c, char **v)
2706 {
2707 	int i;
2708 
2709 	if (execHelpCheck(c, v)) return(0);
2710 
2711 	if (c == 2) {
2712 		if (strncmp("off", v[1], strlen(v[1])) == 0)
2713 			btty.flags &= ~B_TTY_DEBUG;
2714 		else if (strncmp("on", v[1], strlen(v[1])) == 0)
2715 			btty.flags |= B_TTY_DEBUG;
2716 		else
2717 			btty.flags &= ~B_TTY_DEBUG;
2718 		return(0);
2719 	}
2720 
2721 	if (c == 3)
2722 	{
2723 		if (strncmp("cli", v[1], strlen(v[1])) == 0)
2724 		{
2725 			if (strncmp("off", v[2], strlen(v[2])) == 0)
2726 				btty.flags &= ~B_TTY_DEBUG;
2727 			else if (strncmp("on", v[2], strlen(v[2])) == 0)
2728 				btty.flags |= B_TTY_DEBUG;
2729 			else
2730 				btty.flags &= ~B_TTY_DEBUG;
2731 			return(0);
2732 		}
2733 		if (strncmp(debugcomm[2].name, v[1], strlen(v[1])) == 0)
2734 		{
2735 			if (strncmp("off", v[2], strlen(v[2])) == 0)
2736 			{
2737 				SYNTHS->flags &= ~REQ_DEBUG_MASK;
2738 				SYNTHS->win->flags &= ~BRIGHTON_DEBUG;
2739 			} else if (strncmp("on", v[2], strlen(v[2])) == 0) {
2740 				SYNTHS->flags |= REQ_DEBUG_MASK;
2741 				SYNTHS->win->flags |= BRIGHTON_DEBUG;
2742 			}
2743 		}
2744 		if (strncmp("engine", v[1], strlen(v[1])) == 0)
2745 		{
2746 			if ((btty.edbg = atoi(v[2])) <= 0)
2747 				btty.edbg = 0;
2748 			if (btty.edbg > 15)
2749 				btty.edbg = 15;
2750 
2751 			bristolMidiSendMsg(global->controlfd, SYNTHS->sid,
2752 				BRISTOL_SYSTEM, 0, BRISTOL_REQ_DEBUG|btty.edbg);
2753 
2754 			snprintf(pbuf, btty.len, "debug (engine):             %i\r\n",
2755 				btty.edbg);
2756 			i = write(btty.fd[1], pbuf, strlen(pbuf));
2757 
2758 			return(0);
2759 		} if (strncmp("midi", v[1], strlen(v[1])) == 0) {
2760 			int n = atoi(v[2]);
2761 			switch (n) {
2762 				default:
2763 				case 0:
2764 					n = 0;
2765 					break;
2766 				case 1:
2767 					break;
2768 				case 2:
2769 					break;
2770 				case 3:
2771 					break;
2772 			}
2773 			btty.mdbg = n;
2774 			if (global->libtest == 0)
2775 				bristolMidiSendNRP(global->controlfd, SYNTHS->midichannel,
2776 		            BRISTOL_NRP_DEBUG, n);
2777 			snprintf(pbuf, btty.len, "MIDI debug:                   %i\r\n",
2778 				btty.mdbg);
2779 			i = write(btty.fd[1], pbuf, strlen(pbuf));
2780 			return(B_ERR_OK);
2781 		}
2782 	}
2783 
2784 	if (c == 1)
2785 	{
2786 		if (btty.flags & B_TTY_DEBUG)
2787 			snprintf(pbuf, btty.len, "debug (cli):                on\r\n");
2788 		else
2789 			snprintf(pbuf, btty.len, "debug (cli):                off\r\n");
2790 		i = write(btty.fd[1], pbuf, strlen(pbuf));
2791 
2792 		snprintf(pbuf, btty.len, "debug (engine):             %i\r\n", btty.edbg);
2793 		i = write(btty.fd[1], pbuf, strlen(pbuf));
2794 
2795 		return(0);
2796 	}
2797 
2798 	return(0);
2799 }
2800 
2801 static int
execLoad(guimain * global,int c,char ** v)2802 execLoad(guimain *global, int c, char **v)
2803 {
2804 	int n = 0, undo = 0;
2805 
2806 	if (execHelpCheck(c, v)) return(0);
2807 
2808 	print(v[0]);
2809 
2810 	if (c >= 2)
2811 	{
2812 		if (strncmp("undo", v[1], strlen(v[1])) == 0)
2813 			undo = 1;
2814 		else if ((n = atoi(v[1])) < 0)
2815 			return(0);
2816 	}
2817 
2818 	if ((strncmp(v[0], "load", strlen(v[0])) == 0)
2819 		|| (strncmp(v[0], "read", strlen(v[0])) == 0))
2820 	{
2821 		if (undo) {
2822 			SYNTHS->location = 9999;
2823 			bttyMemLoad(global);
2824 			SYNTHS->location = btty.lastmem;
2825 		} else if (c == 1) {
2826 			/* load current mem */
2827 			btty.lastmem = SYNTHS->location;
2828 			bttyMemLoad(global);
2829 			SYNTHS->location = btty.lastmem;
2830 			return(0);
2831 		} else {
2832 			/* load named memory */
2833 			btty.lastmem = SYNTHS->location;
2834 			SYNTHS->location = n;
2835 			bttyMemLoad(global);
2836 		}
2837 	}
2838 
2839 	if ((strncmp(v[0], "save", strlen(v[0])) == 0)
2840 		|| (strncmp(v[0], "write", strlen(v[0])) == 0))
2841 	{
2842 		if (c == 1)
2843 		{
2844 			/* save current mem */
2845 			bttyMemSave(global);
2846 			return(0);
2847 		} else {
2848 			SYNTHS->location = n;
2849 			bttyMemSave(global);
2850 		}
2851 	}
2852 
2853 	if (strncmp(v[0], "find", strlen(v[0])) == 0)
2854 	{
2855 		int location = SYNTHS->location + 1;
2856 
2857 		if (location > 1023)
2858 			location = 0;
2859 
2860 		if ((c == 2) && (strncmp(v[1], "free", strlen(v[1])) == 0))
2861 		{
2862 			/* find free mem */
2863 			while (loadMemory(SYNTHS, RESOURCES->name, 0,
2864 				location, SYNTHS->mem.active, 0, BRISTOL_STAT) == 0)
2865 			{
2866 				if (++location > 1024)
2867 					location = 0;
2868 				if (location == SYNTHS->location)
2869 					break;
2870 			}
2871 			if (location != SYNTHS->location)
2872 			{
2873 				SYNTHS->location = location;
2874 				snprintf(pbuf, btty.len, "free: %i\r\n", SYNTHS->location);
2875 				n = write(btty.fd[1], pbuf, strlen(pbuf));
2876 			} else {
2877 				snprintf(pbuf, btty.len, "no free memories\r\n");
2878 				n = write(btty.fd[1], pbuf, strlen(pbuf));
2879 			}
2880 		}
2881 
2882 		if ((c == 2) && ((strncmp(v[1], "load", strlen(v[1])) == 0)
2883 			|| (strncmp(v[1], "read", strlen(v[1])) == 0)))
2884 		{
2885 			/* find mem */
2886 			while (loadMemory(SYNTHS, RESOURCES->name, 0,
2887 				location, SYNTHS->mem.active, 0, BRISTOL_STAT) != 0)
2888 			{
2889 				if (++location > 1024)
2890 					location = 0;
2891 				if (location == SYNTHS->location)
2892 					break;
2893 			}
2894 
2895 			SYNTHS->location = location;
2896 			bttyMemLoad(global);
2897 		}
2898 
2899 		if (c == 1)
2900 		{
2901 			/* find mem */
2902 			while (loadMemory(SYNTHS, RESOURCES->name, 0,
2903 				location, SYNTHS->mem.active, 0, BRISTOL_STAT) != 0)
2904 			{
2905 				if (++location > 1024)
2906 					location = 0;
2907 				if (location == SYNTHS->location)
2908 					break;
2909 			}
2910 			if (location != SYNTHS->location)
2911 			{
2912 				SYNTHS->location = location;
2913 				snprintf(pbuf, btty.len, "mem: %i\r\n", SYNTHS->location);
2914 				n = write(btty.fd[1], pbuf, strlen(pbuf));
2915 			} else {
2916 				snprintf(pbuf, btty.len, "no memories\r\n");
2917 				n = write(btty.fd[1], pbuf, strlen(pbuf));
2918 			}
2919 
2920 			return(0);
2921 		}
2922 	}
2923 
2924 	return(0);
2925 }
2926 
2927 static int
execHelp(guimain * global,int c,char ** v)2928 execHelp(guimain *global, int c, char **v)
2929 {
2930 	int i, n;
2931 
2932 	if (execHelpCheck(c, v)) return(0);
2933 
2934 	print(v[0]);
2935 
2936 	if (c == 1)
2937 	{
2938 		snprintf(pbuf, B_TTY_LINE_LEN, "CLI ':insert' mode command list:\r\n");
2939 		n = write(btty.fd[1], pbuf, strlen(pbuf));
2940 
2941 		for (i = 0; commands[i].map != -1; i++)
2942 		{
2943 			if (commands[i].map == B_COM_NOT_USED)
2944 				continue;
2945 			snprintf(pbuf, B_TTY_LINE_LEN, "%12s (:) %s\n\r",
2946 				commands[i].name, commands[i].help);
2947 			if (commands[i].map == B_COM_ALIAS)
2948 				pbuf[14] = 'a';
2949 			else
2950 				pbuf[14] = 'c';
2951 			n = write(btty.fd[1], pbuf, strlen(pbuf));
2952 		}
2953 		return(0);
2954 	}
2955 
2956 	for (i = 0; commands[i].map != B_COM_LAST; i++)
2957 	{
2958 		if (commands[i].map == B_COM_NOT_USED)
2959 			continue;
2960 		if (strncmp(commands[i].name, v[1], strlen(v[1])) == 0)
2961 		{
2962 			snprintf(pbuf, B_TTY_LINE_LEN, "%12s: %s\n\r",
2963 				commands[i].name, commands[i].help);
2964 			n = write(btty.fd[1], pbuf, strlen(pbuf));
2965 			break;
2966 		}
2967 	}
2968 
2969 	if (commands[i].map == B_COM_LAST)
2970 	{
2971 		snprintf(pbuf, btty.len, "help '%s' not found\n\r", v[1]);
2972 		n = write(btty.fd[1], pbuf, strlen(pbuf));
2973 	}
2974 
2975 	return(0);
2976 }
2977 static int
execQuit(guimain * global,int c,char ** v)2978 execQuit(guimain *global, int c, char **v)
2979 {
2980 	if ((c == 1) && (strlen(v[0]) == 4) && (strcmp(v[0], "quit") == 0))
2981 		return(B_ERR_EXIT);
2982 	return(B_ERR_PARAM);
2983 }
2984 
2985 static int
bttyExecute(guimain * global,int c,char ** v)2986 bttyExecute(guimain *global, int c, char **v)
2987 {
2988 	int i, j, k, n;
2989 	char var[B_TTY_LINE_LEN];
2990 	float value = 0.0f;
2991 
2992 	if (btty.flags & B_TTY_DEBUG)
2993 	{
2994 		for (i = 0; i < c; i++)
2995 		{
2996 			snprintf(pbuf, btty.len, "%i: %i: %s\n\r", i, (int) strlen(v[i]), v[i]);
2997 			n = write(btty.fd[1], pbuf, strlen(pbuf));
2998 		}
2999 	}
3000 
3001 	for (i = 0; commands[i].map != B_COM_LAST; i++)
3002 	{
3003 		if (commands[i].map == B_COM_NOT_USED)
3004 			continue;
3005 		if (commands[i].map == B_COM_FREE)
3006 			continue;
3007 		if ((strncmp(v[0], commands[i].name, strlen(v[0])) == 0)
3008 			&& (commands[i].exec != NULL))
3009 		{
3010 			n = commands[i].exec(global, c, v);
3011 			if (btty.flags & B_TTY_ALIASING)
3012 				return(n);
3013 			memset(pbuf, 0, B_TTY_LINE_LEN);
3014 			return(n);
3015 		}
3016 	}
3017 
3018 	/*
3019 	 * Search for the command in the synth parameters.
3020 	 */
3021 	for (i = 0, j = 0, k = 0, n = -1; j < c; i++)
3022 	{
3023 		switch (v[j][i]) {
3024 			case '\0':
3025 				i = -1;
3026 				if (++j < c)
3027 					var[k++] = ' ';
3028 				else
3029 					var[k++] = '\0';
3030 				break;
3031 			case '=':
3032 				var[k] = '\0';
3033 				print(var);
3034 				value = atof(&v[j][++i]);
3035 				n = 1;
3036 				break;
3037 			case '+':
3038 				if (v[j][i+1] == '+') {
3039 					n = 3;
3040 				} else if (v[j][i+1] == '=') {
3041 					n = 4;
3042 					++i;
3043 					value = atof(&v[j][++i]);
3044 				} else {
3045 					n = 2;
3046 				}
3047 				var[k] = '\0';
3048 				print("found");
3049 				break;
3050 			case '-':
3051 				if (v[j][i+1] == '-') {
3052 					n = 6;
3053 				} else if (v[j][i+1] == '=') {
3054 					n = 7;
3055 					++i;
3056 					value = atof(&v[j][++i]);
3057 				} else {
3058 					n = 5;
3059 				}
3060 				var[k] = '\0';
3061 				print("found");
3062 				break;
3063 			default:
3064 				var[k++] = v[j][i];
3065 				break;
3066 		}
3067 		if (n != -1) break;
3068 	}
3069 
3070 	for (i = 0; i < SYNTHS->win->app->resources[btty.p].ndevices; i++)
3071 	{
3072 		if ((paramname(i) == NULL) || (paramname(i)[0] == '\0'))
3073 			continue;
3074 		if (strcmp(var, paramname(i)) == 0)
3075 		{
3076 			print(paramname(i));
3077 			btty.i = i;
3078 
3079 			switch (n) {
3080 				case 1: /* Value was set explicity */
3081 					break;
3082 				case 2: /* + */
3083 					value = PDEV(btty.i)->value + 0.01;
3084 					break;
3085 				case 3: /* ++ */
3086 					value = PDEV(btty.i)->value + btty.accel;
3087 					break;
3088 				case 4: /* += */
3089 					value += PDEV(btty.i)->value;
3090 					break;
3091 				case 5: /* - */
3092 					if ((value = PDEV(btty.i)->value - 0.01) < 0.0f)
3093 						value = 0.0f;
3094 					break;
3095 				case 6: /* -- */
3096 					if ((value = PDEV(btty.i)->value - btty.accel) < 0.0f)
3097 						value = 0.0f;
3098 					break;
3099 				case 7: /* -= */
3100 					if ((value = PDEV(btty.i)->value - value) < 0.0f)
3101 						value = 0.0f;
3102 					break;
3103 			}
3104 
3105 			if (n > 0)
3106 				execParamChange(global, value);
3107 			else
3108 				cliParamChange(global, 0.0f);
3109 			n = 0;
3110 			return(0);
3111 		}
3112 	}
3113 
3114 	memset(pbuf, 0, B_TTY_LINE_LEN);
3115 
3116 	return(1);
3117 }
3118 
3119 static char resvar[64];
3120 
3121 char *
getprintvar(guimain * global,char * var)3122 getprintvar(guimain *global, char *var)
3123 {
3124 	int i;
3125 
3126 	if (strcmp(var, "panelid") == 0)
3127 	{
3128 		snprintf(resvar, 64, "%s", RESOURCES->resources[btty.p].name);
3129 		return(resvar);
3130 	}
3131 	if (strcmp(var, "algo") == 0)
3132 	{
3133 		snprintf(resvar, 64, "%s", RESOURCES->name);
3134 		return(resvar);
3135 	}
3136 	if (strcmp(var, "channel") == 0)
3137 	{
3138 		snprintf(resvar, 64, "%i", SYNTHS->midichannel + 1);
3139 		return(resvar);
3140 	}
3141 	if (strcmp(var, "memory") == 0)
3142 	{
3143 		snprintf(resvar, 64, "%i", SYNTHS->location);
3144 		return(resvar);
3145 	}
3146 
3147 	for (i = 0 ; i < SYNTHS->win->app->resources[btty.p].ndevices; i++)
3148 	{
3149 		if (strcasecmp(paramname(i), var) == 0)
3150 			break;
3151 	}
3152 
3153 	if (i >= SYNTHS->win->app->resources[btty.p].ndevices)
3154 	{
3155 		snprintf(resvar, 64, "%s", var);
3156 		return(resvar);
3157 	}
3158 
3159 	/*
3160 	 * Found var, take value.
3161 	 */
3162 	if (DEVICE(i).to == 1.0f)
3163 	{
3164 		if (DEVICE(i).type == 2)
3165 			snprintf(resvar, 64, "%1.0f", PDEV(i)->value);
3166 		else
3167 			snprintf(resvar, 64, "%-3.0f", PDEV(i)->value*1000.0f);
3168 	} else
3169 		snprintf(resvar, 64, "%1.0f", PDEV(btty.i)->value);
3170 
3171 	return(resvar);
3172 }
3173 
3174 /*
3175  * So how much work to accept a single string:
3176  * promt='mem %memory% chan %channel%'
3177  */
3178 char *
printprompt(guimain * global)3179 printprompt(guimain *global)
3180 {
3181 	int i = 0, j = 0, aliasing = 0;;
3182 	char var[64], *s = btty.promptText, *d = btty.prompt, *alias;
3183 
3184 	/*
3185 	 * Format is "text", or "text <variable>" where var is searched in the
3186 	 * synth table.
3187 	 *
3188 	 * We are looking for 'mem %something% chan %something%: '
3189 	 */
3190 	for (i = 0; i < 64; i++)
3191 	{
3192 		if (*s == '\0')
3193 		{
3194 			*d = '\0';
3195 			break;
3196 		}
3197 		if (*s == '%')
3198 		{
3199 			if (aliasing)
3200 			{
3201 				var[j] = '\0';
3202 				alias = getprintvar(global, var);
3203 				for (; *alias != 0;)
3204 					*d++ = *alias++;
3205 				aliasing = 0;
3206 			} else {
3207 				aliasing = 1;
3208 				memset(var, 0, 64);
3209 				j = 0;
3210 			}
3211 			s++;
3212 		} else if (aliasing)
3213 			var[j++] = *s++;
3214 		else
3215 			*d++ = *s++;
3216 	}
3217 
3218 	if (btty.prompt[0] == '\0')
3219 	{
3220 		btty.prompt[0] = ':';
3221 		btty.prompt[1] = '\0';
3222 	}
3223 
3224 	return(btty.prompt);
3225 }
3226 
3227 static int
bttyInterpret(guimain * global,char * tbuf)3228 bttyInterpret(guimain *global, char *tbuf)
3229 {
3230 	int v, i = 0, j = 0, k, quoted = 0;
3231 	char *comm = tbuf, **vargs, zbuf[B_TTY_LINE_LEN];
3232 
3233 	while (isspace(*comm))
3234 		comm++;
3235 
3236 	/*
3237 	 * This is to 'overlook' cooked commands that start with a colon, they
3238 	 * typicaly come from retyping ':' due to a damaged output stream from
3239 	 * debuging output.
3240 	 */
3241 	if ((*comm == ':') && (btty.flags & B_TTY_COOKED))
3242 		comm++;
3243 
3244 	if (comm[0] == '!')
3245 	{
3246 		if (((i = atoi(&comm[1])) < 0) || (i >= 49))
3247 		{
3248 			btty.hist_tmp = 0;
3249 			btty.edit_p = 0;
3250 			memset(tbuf, 0, B_TTY_LINE_LEN);
3251 			return(0);
3252 		}
3253 		memset(zbuf, 0, B_TTY_LINE_LEN);
3254 		snprintf(zbuf, B_TTY_LINE_LEN, "%s", btty.hist[i]);
3255 		comm = zbuf;
3256 	}
3257 
3258 	if ((comm[0] == '\0') || (isalpha(comm[0]) == 0))
3259 	{
3260 		v = write(btty.fd[1], btty.hist[0], strlen(btty.hist[0]));
3261 		snprintf(pbuf, btty.len, "\r:");
3262 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3263 
3264 		btty.edit_p = 0;
3265 		memset(cbuf, 0, B_TTY_LINE_LEN);
3266 		memset(btty.hist[0], 0, B_TTY_LINE_LEN);
3267 		return(1);
3268 	}
3269 
3270 	if (strncmp("history", comm, strlen(comm)) == 0)
3271 	{
3272 		for (i = btty.hist_c; i > 0; i--)
3273 		{
3274 			if (btty.hist[i][0] == '\0')
3275 				continue;
3276 			snprintf(pbuf, B_TTY_LINE_LEN, "%i %s\n\r", i, btty.hist[i]);
3277 			v = write(btty.fd[1], pbuf, strlen(pbuf));
3278 		}
3279 		snprintf(pbuf, B_TTY_LINE_LEN, ":");
3280 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3281 		btty.edit_p = 0;
3282 		memset(cbuf, 0, B_TTY_LINE_LEN);
3283 		return(0);
3284 	}
3285 
3286 	if (((strncmp("quit", comm, 4) == 0) || (strncmp("exit", comm, 4) == 0))
3287 		&& (strlen(comm) == 4))
3288 	{
3289 		memset(pbuf, 0, B_TTY_LINE_LEN);
3290 		snprintf(pbuf, btty.len, "quiting\n\r");
3291 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3292 		brightonCLIcleanup();
3293 		return(-1);
3294 	}
3295 
3296 	if (strlen(comm) == 0)
3297 	{
3298 		snprintf(pbuf, B_TTY_LINE_LEN, "\r%s", btty.prompt);
3299 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3300 		btty.edit_p = 0;
3301 		memset(cbuf, 0, B_TTY_LINE_LEN);
3302 		return(1);
3303 	}
3304 
3305 	if (~btty.flags & B_TTY_RAW)
3306 		bttyManageHistory(comm);
3307 
3308 	vargs = brightonmalloc(sizeof(size_t) * B_TTY_ARGC);
3309 	memset(vargs, 0, sizeof(size_t) * B_TTY_ARGC);
3310 
3311 	for (k = 0, i = 0, j = 0; k < btty.len; k++)
3312 	{
3313 		/* Get an arg pointer */
3314 		if (vargs[i] == NULL)
3315 		{
3316 			vargs[i] = brightonmalloc(B_TTY_LINE_LEN);
3317 			memset(vargs[i], 0, B_TTY_LINE_LEN);
3318 		}
3319 		/* See if it is the end of the line */
3320 		if (comm[k] == '\0')
3321 		{
3322 			if ((quoted) & (j != 0))
3323 				vargs[i][j - 1] = '"';
3324 			vargs[i][j] = '\0';
3325 			if (j != 0)
3326 				i++;
3327 			break;
3328 		}
3329 		if ((comm[k] == '\'') || (comm[k] == '"'))
3330 		{
3331 			//vargs[i][j++] = comm[k];
3332 			if (quoted)
3333 			{
3334 				quoted = 0;
3335 				vargs[i][j] = '\0';
3336 				if (j == 0)
3337 					break;
3338 				if (++i >= B_TTY_ARGC)
3339 					break;
3340 				j = 0;
3341 			} else
3342 				quoted = 1;
3343 		} else if ((comm[k] == ' ') & (quoted == 0)) {
3344 			vargs[i][j] = '\0';
3345 			if (j == 0)
3346 				break;
3347 			if (++i >= B_TTY_ARGC)
3348 				break;
3349 			j = 0;
3350 		} else
3351 			vargs[i][j++] = comm[k];
3352 	}
3353 
3354 	k = bttyExecute(global, i, vargs);
3355 
3356 	switch (k) {
3357 		case 0:
3358 			if (btty.flags & B_TTY_DEBUG)
3359 			{
3360 				snprintf(pbuf, btty.len, "success: command executed\n\r");
3361 				v = write(btty.fd[1], pbuf, strlen(pbuf));
3362 			}
3363 			break;
3364 		case B_ERR_NOT_FOUND:
3365 			snprintf(pbuf, btty.len, "failed: command not found\n\r");
3366 			v = write(btty.fd[1], pbuf, strlen(pbuf));
3367 			break;
3368 		case B_ERR_PARAM:
3369 			snprintf(pbuf, btty.len, "failed: parameter error\n\r");
3370 			v = write(btty.fd[1], pbuf, strlen(pbuf));
3371 			break;
3372 		case B_ERR_VALUE:
3373 			snprintf(pbuf, btty.len, "failed: parameter out of range\n\r");
3374 			v = write(btty.fd[1], pbuf, strlen(pbuf));
3375 			break;
3376 		case B_ERR_INV_ARG:
3377 			snprintf(pbuf, btty.len, "failed: invalid argument\n\r");
3378 			v = write(btty.fd[1], pbuf, strlen(pbuf));
3379 			break;
3380 		case B_ERR_EXIT:
3381 			snprintf(pbuf, btty.len, "requested to exit\n\r");
3382 			v = write(btty.fd[1], pbuf, strlen(pbuf));
3383 			break;
3384 		case B_ERR_EARLY:
3385 			break;
3386 		default:
3387 			snprintf(pbuf, btty.len, "failed: unknown error\n\r");
3388 			v = write(btty.fd[1], pbuf, strlen(pbuf));
3389 			break;
3390 	}
3391 
3392 	for (i = 0; vargs[i] != NULL; i++)
3393 		brightonfree(vargs[i]);
3394 	brightonfree(vargs);
3395 
3396 	snprintf(btty.hist[0], btty.len, "%s", b_blank);
3397 	if (~btty.flags & B_TTY_RAW)
3398 	{
3399 		snprintf(pbuf, btty.len, "\r%s\r", b_blank);
3400 		//snprintf(pbuf, btty.len, "\r:");
3401 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3402 	}
3403 
3404 	btty.edit_p = 0;
3405 	memset(cbuf, 0, B_TTY_LINE_LEN);
3406 	memset(btty.hist[0], 0, B_TTY_LINE_LEN);
3407 
3408 	return(k);
3409 }
3410 
3411 static int
bttyPlayMode(guimain * global,char ch)3412 bttyPlayMode(guimain *global, char ch)
3413 {
3414 	int v;
3415 
3416 	if (btty.flags & B_TTY_DEBUG)
3417 	{
3418 		snprintf(pbuf, btty.len, "%x\r\n", ch);
3419 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3420 	}
3421 
3422 	btty.acycle = btty.pcycle;
3423 
3424 	if (ch == 0x1b)
3425 	{
3426 		btty.flags &= ~B_TTY_MMASK;
3427 		btty.flags |= B_TTY_RAW;
3428 		brightonKeyInput(SYNTHS->win, btty.key, 0);
3429 		cliParamChange(global, 0.0f);
3430 		btty.acycle = btty.cycle;
3431 		return(B_ERR_OK);
3432 	} else if (ch == ':') {
3433 		btty.flags &= ~B_TTY_MMASK;
3434 		btty.flags |= B_TTY_COOKED;
3435 		brightonKeyInput(SYNTHS->win, btty.key, 0);
3436 		snprintf(pbuf, btty.len, "%s", btty.prompt);
3437 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3438 		btty.acycle = btty.cycle;
3439 		return(B_ERR_OK);
3440 	}
3441 
3442 	/* They were the two escape codes, now we have to play keys */
3443 	if (ch != btty.key)
3444 	{
3445 		brightonKeyInput(SYNTHS->win, btty.key, 0);
3446 		brightonKeyInput(SYNTHS->win, ch, 1);
3447 		btty.key = ch;
3448 		btty.flags &= ~B_TTY_CLEAR_KEY;
3449 	}
3450 
3451 	return(B_ERR_OK);
3452 }
3453 
3454 static int
bttyCookedMode(guimain * global,char ch)3455 bttyCookedMode(guimain *global, char ch)
3456 {
3457 	int v, i;
3458 
3459 	snprintf(pbuf, btty.len, "\r%s", b_blank);
3460 	v = write(btty.fd[1], pbuf, strlen(pbuf));
3461 	snprintf(pbuf, btty.len, "\r");
3462 	v = write(btty.fd[1], pbuf, strlen(pbuf));
3463 
3464 	btty.acycle = btty.cycle;
3465 
3466 	/*
3467 	 * Start with escape, this will later become interpretted as it could
3468 	 * also by arrows for history functions.
3469 	 */
3470 	if (btty.flags & B_TTY_RAW_P2) {
3471 		btty.flags &= ~B_TTY_MMASK;
3472 		btty.flags |= B_TTY_COOKED;
3473 		/*
3474 		 * If we get back here with P2 then we have an arrow escape. Start with
3475 		 * up and down arrow for history, then command line editing later.
3476 		 */
3477 		switch (ch) {
3478 			case 0x43: /* Right */
3479 			{
3480 				if (cbuf[btty.edit_p] != '\0')
3481 					btty.edit_p++;
3482 				break;
3483 			}
3484 			case 0x44: /* Left */
3485 			{
3486 				if (--btty.edit_p < 0)
3487 					btty.edit_p = 0;
3488 				//snprintf(tbuf, btty.edit_p, "\r%s", btty.hist[btty.hist_tmp]);
3489 				//v = write(btty.fd[1], tbuf, strlen(tbuf));
3490 				break;
3491 			}
3492 			case 0x41: /* Up */
3493 				if ((btty.hist_tmp < 50)
3494 					&& (btty.hist[btty.hist_tmp + 1] != NULL)
3495 					&& (btty.hist[btty.hist_tmp + 1][0] != '\0'))
3496 				{
3497 					btty.hist_tmp++;
3498 					//memset(cbuf, 0, B_TTY_LINE_LEN);
3499 					//memset(btty.hist[btty.hist_tmp], 0, B_TTY_LINE_LEN);
3500 					snprintf(cbuf, btty.len, "%s", btty.hist[btty.hist_tmp]);
3501 					snprintf(pbuf, btty.len, "%s%s", btty.prompt, cbuf);
3502 					v = write(btty.fd[1], pbuf, strlen(pbuf));
3503 				} else
3504 					snprintf(cbuf, btty.len, "%s", btty.hist[btty.hist_tmp]);
3505 				btty.edit_p = strlen(cbuf);;
3506 				break;
3507 			case 0x42: /* Down */
3508 				if (btty.hist_tmp > 0)
3509 					btty.hist_tmp--;
3510 				snprintf(cbuf, btty.len, "%s", btty.hist[btty.hist_tmp]);
3511 				snprintf(pbuf, btty.len, "\r%s%s", btty.prompt, cbuf);
3512 				btty.edit_p = strlen(cbuf);;
3513 				v = write(btty.fd[1], pbuf, strlen(pbuf));
3514 				break;
3515 		}
3516 	} else if (ch == 0x03) {
3517 		/* ^C kill line
3518 		btty.edit_p = 0;
3519 		btty.hist_tmp = 0;
3520 		btty.flags &= ~B_TTY_MMASK;
3521 		btty.flags |= B_TTY_RAW_P;
3522 		snprintf(pbuf, btty.len, "\r%s%s", btty.prompt, cbuf);
3523 		memset(cbuf, 0, B_TTY_LINE_LEN);
3524 		btty.edit_p = 0;
3525 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3526 		cliParamChange(global, 0.0f);
3527 		return(0);
3528 		*/
3529 		snprintf(pbuf, btty.len, "\r%s%s\n\r", btty.prompt, cbuf);
3530 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3531 		memset(cbuf, 0, B_TTY_LINE_LEN);
3532 		btty.edit_p = 0;
3533 		snprintf(pbuf, btty.len, "\r%s%s", printprompt(global), cbuf);
3534 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3535 	} else if ((ch == 0x08) || (ch == 0x7f)) {
3536 		int c;
3537 		/* BS/DEL */
3538 		if (btty.edit_p == 0)
3539 		{
3540 			if (btty.flags & B_TTY_SEARCH)
3541 			{
3542 				btty.flags &= ~B_TTY_MMASK;
3543 				btty.flags |= B_TTY_RAW;
3544 				snprintf(pbuf, btty.len, "\r/");
3545 				v = write(btty.fd[1], pbuf, strlen(pbuf));
3546 				cliParamChange(global, 0.0f);
3547 				return(1);
3548 			}
3549 			//snprintf(pbuf, btty.len, "\r:");
3550 			snprintf(pbuf, btty.len, "\r%s%s", btty.prompt, cbuf);
3551 			//pbuf[1] = btty.delim;
3552 			v = write(btty.fd[1], pbuf, strlen(pbuf));
3553 			return(0);
3554 		}
3555 
3556 		btty.edit_p--;
3557 
3558 		for (c = btty.edit_p; c < strlen(cbuf); c++)
3559 			cbuf[c] = cbuf[c + 1];
3560 
3561 		if (btty.flags & B_TTY_COOKED)
3562 			snprintf(pbuf, btty.len, "\r%s%s", btty.prompt, cbuf);
3563 		else if (btty.flags & B_TTY_SEARCH)
3564 			snprintf(pbuf, btty.len, "\r/%s", cbuf);
3565 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3566 		if (strlen(cbuf) == btty.len)
3567 		{
3568 			cbuf[strlen(cbuf) - 1] = '\0';
3569 			btty.edit_p = strlen(cbuf);;
3570 		}
3571 	} else if ((ch == 0x0c) || (ch == 0x12)) {
3572 		/* ^L ^R - redraw */
3573 		snprintf(pbuf, btty.len, "\r%s%s", btty.prompt, cbuf);
3574 		pbuf[1] = btty.delim;
3575 	} else if (ch == 0x09) {
3576 		/* tab */
3577 		bttyComplete(global);
3578 	} else if (ch == 0x01) {
3579 		/* ^A start of line */
3580 		snprintf(pbuf, btty.len, "\r%s%s", btty.prompt, cbuf);
3581 		btty.edit_p = 0;
3582 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3583 	} else if (ch == 0x05) {
3584 		/* ^E end of line */
3585 		snprintf(pbuf, btty.len, "\r%s%s", btty.prompt, cbuf);
3586 		btty.edit_p = strlen(cbuf);
3587 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3588 	} else if (ch == 0x0e) {
3589 		/* Down hist ^n */
3590 		if (btty.hist_tmp > 0)
3591 			btty.hist_tmp--;
3592 		snprintf(cbuf, btty.len, "%s", btty.hist[btty.hist_tmp]);
3593 		snprintf(pbuf, btty.len, "\r%s%s", btty.prompt, cbuf);
3594 		btty.edit_p = strlen(cbuf);;
3595 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3596 	} else if (ch == 0x10) {
3597 		/* Up hist ^p */
3598 		if ((btty.hist_tmp < 50)
3599 			&& (btty.hist[btty.hist_tmp + 1] != NULL)
3600 			&& (btty.hist[btty.hist_tmp + 1][0] != '\0'))
3601 		{
3602 			btty.hist_tmp++;
3603 			//memset(cbuf, 0, B_TTY_LINE_LEN);
3604 			//memset(btty.hist[btty.hist_tmp], 0, B_TTY_LINE_LEN);
3605 			snprintf(cbuf, btty.len, "%s", btty.hist[btty.hist_tmp]);
3606 			snprintf(pbuf, btty.len, "\r%s%s", btty.prompt, cbuf);
3607 			v = write(btty.fd[1], pbuf, strlen(pbuf));
3608 		} else
3609 			snprintf(cbuf, btty.len, "%s", btty.hist[btty.hist_tmp]);
3610 		btty.edit_p = strlen(cbuf);;
3611 	} else if (ch == 0x15) {
3612 		/* ^U kill  line */
3613 		memset(cbuf, 0, B_TTY_LINE_LEN);
3614 		memset(btty.hist[0], 0, B_TTY_LINE_LEN);
3615 		btty.edit_p = 0;
3616 		btty.hist_tmp = 0;
3617 	} else if (ch == 0x17) {
3618 		int t = btty.edit_p - 1;
3619 		int o = btty.edit_p;
3620 		/* ^W kill word - current edit point to start of previous word */
3621 		snprintf(btty.hist[0], btty.len, "%s", cbuf);
3622 		while (cbuf[t] == ' ')
3623 		{
3624 			if (--t == 0)
3625 				break;
3626 		}
3627 		if (strlen(cbuf) != '\0')
3628 		{
3629 			while (t != 0)
3630 			{
3631 				if (cbuf[t] == ' ')
3632 					break;
3633 				t--;
3634 			}
3635 			if (t != 0)
3636 				btty.edit_p = ++t;
3637 			else
3638 				btty.edit_p = 0;
3639 			while ((cbuf[t++] = cbuf[o++]) != '\0')
3640 				;
3641 
3642 			if (btty.flags & B_TTY_COOKED)
3643 				snprintf(pbuf, btty.len, "\r%s%s", btty.prompt, cbuf);
3644 			else
3645 				snprintf(pbuf, btty.len, "\r/%s", cbuf);
3646 			v = write(btty.fd[1], pbuf, strlen(pbuf));
3647 		}
3648 	} else if (ch == 0x1b) {
3649 		/* Esc - we should not actually get this */
3650 		btty.flags &= ~B_TTY_MMASK;
3651 		btty.flags |= B_TTY_RAW_P;
3652 		cliParamChange(global, 0.0f);
3653 		return(1);
3654 	} else if ((ch == 0x0a) || (ch == 0x0d)) {
3655 		/*
3656 		 * Enter
3657 		if (cbuf[0] == '\0')
3658 		{
3659 			snprintf(pbuf, btty.len, ":\r");
3660 			pbuf[0] = btty.delim;
3661 			v = write(btty.fd[1], pbuf, strlen(pbuf));
3662 			btty.flags &= ~B_TTY_MMASK;
3663 			btty.flags |= B_TTY_RAW_P;
3664 			cliParamChange(global, 0.0f);
3665 			return(1);
3666 		}
3667 		 */
3668 		if (btty.flags & B_TTY_COOKED)
3669 		{
3670 			int i;
3671 			snprintf(pbuf, btty.len, "\r%s%s\n\r", btty.prompt, cbuf);
3672 			v = write(btty.fd[1], pbuf, strlen(pbuf));
3673 			if ((i = bttyInterpret(global, cbuf)) < 0)
3674 			{
3675 				brightonCLIcleanup();
3676 				return(i);
3677 			}
3678 			if (i != B_ERR_EARLY)
3679 			{
3680 				snprintf(pbuf, btty.len, "\r%s%s", printprompt(global), cbuf);
3681 				v = write(btty.fd[1], pbuf, strlen(pbuf));
3682 			}
3683 			return(i);
3684 		}
3685 		if (btty.flags & B_TTY_SEARCH)
3686 		{
3687 			if (cbuf[0] == '\0')
3688 			{
3689 				btty.flags &= ~B_TTY_MMASK;
3690 				btty.flags |= B_TTY_RAW;
3691 				snprintf(pbuf, btty.len, "\r/");
3692 				v = write(btty.fd[1], pbuf, strlen(pbuf));
3693 				cliParamChange(global, 0.0f);
3694 				return(1);
3695 			}
3696 			snprintf(pbuf, btty.len, "/%s", cbuf);
3697 			v = write(btty.fd[1], pbuf, strlen(pbuf));
3698 			return(bttySearch(global));
3699 		}
3700 	} else {
3701 		/* Insert char at edit point */
3702 		for (i = strlen(cbuf) + 1; i >= btty.edit_p; i--)
3703 			cbuf[i] = cbuf[i - 1];
3704 		cbuf[btty.edit_p++] = ch;
3705 	}
3706 
3707 	if (btty.flags & B_TTY_SEARCH)
3708 	{
3709 		snprintf(pbuf, btty.len, "\r/%s", cbuf);
3710 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3711 	} else if (btty.flags & B_TTY_COOKED) {
3712 		if (strlen(cbuf) >= 79)
3713 			return(bttyInterpret(global, cbuf));
3714 		snprintf(pbuf, btty.len, "\r%s%s", btty.prompt, cbuf);
3715 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3716 	}
3717 
3718 	/* Cursor positioning for command line editing */
3719 	*pbuf = 0x08;
3720 	for (i = strlen(cbuf); i > btty.edit_p; i--)
3721 		v = write(btty.fd[1], pbuf, 1);
3722 
3723 	return(1);
3724 }
3725 
3726 int
brightonCLIcheck(guimain * global)3727 brightonCLIcheck(guimain *global)
3728 {
3729 	char ch = 0, chmap = B_TTY_A_NULL;
3730 	int i = 0, v = 0, r = 0, s;
3731 
3732 	if (btty.flags & B_TTY_INIT)
3733 	{
3734 		struct termios attr;
3735 
3736 		sleep(1);
3737 
3738 		memset(&attr, 0, sizeof(struct termios));
3739 
3740 		tcgetattr(btty.fd[0], &resetattr);
3741 		tcgetattr(btty.fd[0], &attr);
3742 		cfmakeraw(&attr);
3743 		tcsetattr(btty.fd[0], TCSANOW, &attr);
3744 
3745 		btty.flags &= ~B_TTY_MMASK;
3746 
3747 		if (SYNTHS->flags & REQ_DEBUG_1)
3748 		{
3749 			btty.p = RESOURCES->emulate.panel;
3750 			snprintf(pbuf, btty.len, "panel: %i\r\n", btty.p);
3751 			v = write(btty.fd[1], pbuf, strlen(pbuf));
3752 		}
3753 
3754 		btty.flags &= ~B_TTY_INIT;
3755 		btty.flags |= B_TTY_RAW;
3756 		snprintf(pbuf, btty.len, "\n\rHi %s!\n\r", getenv("USER"));
3757 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3758 		snprintf(pbuf, btty.len, "Bristol Command Line Interface.\r\n");
3759 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3760 		snprintf(pbuf, btty.len, "Cursor motion keys will access parameters.\r\n");
3761 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3762 		snprintf(pbuf, btty.len, "Try ':help' and ':set cli' for information");
3763 		v = write(btty.fd[1], pbuf, strlen(pbuf));
3764 		btty.i = 0;
3765 	}
3766 
3767 	FD_ZERO(stdioset);
3768 	FD_SET(btty.fd[0], stdioset);
3769 	timeout.tv_sec = 0;
3770 
3771 	if ((timeout.tv_usec = btty.acycle * 1000 - 1) < 0)
3772 		timeout.tv_usec = 100000;
3773 
3774 	/*
3775 	 * We have three modes here:
3776 	 *	raw: default vi type control
3777 	 *	insert mode: readline style entry
3778 	 *	raw_p pending: seen escape but might be arrow keys, needs second state
3779 	 */
3780 	while ((s = select(2, stdioset, NULL, NULL, &timeout)) != 0)
3781 	{
3782 		r = read(btty.fd[0], &ch, 1);
3783 
3784 //		pbuf[0] = ch + 96;
3785 //		pbuf[1] = '\0';
3786 //		print(pbuf);
3787 		printChar(ch);
3788 
3789 		if (ch == 0x04)
3790 		{
3791 			brightonCLIcleanup();
3792 			return(-1);
3793 		}
3794 
3795 		switch (btty.flags & B_TTY_MMASK) {
3796 			default:
3797 			case B_TTY_RAW:
3798 				if (ch == 0x1b)
3799 				{
3800 					/* Esc */
3801 					btty.flags &= ~B_TTY_MMASK;
3802 					btty.flags |= B_TTY_RAW_ESC;
3803 					return(1);
3804 				}
3805 				if (ch == 0x0c)
3806 				{
3807 					if ((unnamed(btty.i)) && (~btty.flags & B_TTY_AWV))
3808 						break;
3809 
3810 					cliParamChange(global, 0.0f);
3811 					return(0);
3812 				}
3813 				break;
3814 				if (ch == 0x0d)
3815 				{
3816 					if (btty.i >= SYNTHS->win->app->resources[btty.p].ndevices)
3817 						btty.i = SYNTHS->win->app->resources[btty.p].ndevices-1;
3818 
3819 					if ((unnamed(btty.i)) && (~btty.flags & B_TTY_AWV))
3820 						break;
3821 
3822 					cliParamChange(global, 0.0f);
3823 					return(0);
3824 				}
3825 				break;
3826 			case B_TTY_RAW_ESC:
3827 				if (ch == '[')
3828 				{
3829 					btty.flags &= ~B_TTY_MMASK;
3830 					btty.flags |= B_TTY_RAW_ESC2;
3831 					return(1);
3832 				}
3833 				break;
3834 			case B_TTY_RAW_P:
3835 				/* If we get 'O' go to P2 else RAW */
3836 				btty.flags &= ~B_TTY_MMASK;
3837 				if (ch == '[') {
3838 					btty.flags |= B_TTY_RAW_P2;
3839 					return(1);
3840 				}
3841 				btty.flags |= B_TTY_RAW;
3842 				break;
3843 			case B_TTY_RAW_P2:
3844 				if ((ch == 0x41) || (ch == 0x42)
3845 					|| (ch == 0x43) || (ch == 0x44))
3846 					return(bttyCookedMode(global, ch));
3847 				btty.flags &= ~B_TTY_MMASK;
3848 				btty.flags |= B_TTY_RAW;
3849 				break;
3850 			case B_TTY_COOKED:
3851 				if (ch == 0x1b)
3852 				{
3853 					btty.flags &= ~B_TTY_MMASK;
3854 					btty.flags |= B_TTY_RAW_P;
3855 					return(1);
3856 				}
3857 			case B_TTY_SEARCH:
3858 				return(bttyCookedMode(global, ch));
3859 			case B_TTY_PLAY:
3860 				return(bttyPlayMode(global, ch));
3861 		}
3862 
3863 		if (btty.flags & B_TTY_RAW_ESC2)
3864 		{
3865 			btty.flags &= ~B_TTY_MMASK;
3866 			btty.flags |= B_TTY_RAW;
3867 			switch (ch) {
3868 				case 0x41:
3869 					ch = 'k';
3870 					break;
3871 				case 0x42:
3872 					ch = 'j';
3873 					break;
3874 				case 0x43:
3875 					ch = 'l';
3876 					break;
3877 				case 0x44:
3878 					ch = 'h';
3879 					break;
3880 				case 0x0d:
3881 				case 0x0a:
3882 					ch = 'l';
3883 					break;
3884 			}
3885 		}
3886 		if (btty.flags & B_TTY_RAW_ESC2)
3887 		{
3888 			switch (ch) {
3889 				case 0x5b:
3890 				case 0x1b:
3891 					btty.flags &= ~B_TTY_MMASK;
3892 					btty.flags |= B_TTY_RAW_P;
3893 					return(i);
3894 			}
3895 		}
3896 /*
3897 		switch (ch) {
3898 			case 0x0d:
3899 				if (++btty.i >= SYNTHS->mem.active)
3900 					btty.i = SYNTHS->mem.active -1;
3901 
3902 				if (DEVICE(bbty.i).flags & BRIGHTON_WITHDRAWN)
3903 					break;
3904 
3905 				cliParamChange(global, 0.0f);
3906 				return(0);
3907 		};
3908 */
3909 
3910 		for (i = 0; i < B_TTY_ACT_COUNT; i++)
3911 		{
3912 			if (action[i].map == '\0')
3913 				break;
3914 			if (action[i].map == ch)
3915 			{
3916 				chmap = action[i].imap;
3917 				/*
3918 				 * We need to exec the template here, it is not predefined so
3919 				 * is probably an aliased command for accelerated access
3920 				 */
3921 				if (chmap >= B_TTY_A_PREDEF)
3922 				{
3923 					i = chmap;
3924 					print(templates[i].opname);
3925 					snprintf(cbuf, B_TTY_LINE_LEN, "%s", templates[i].opname);
3926 					return(bttyInterpret(global, cbuf));
3927 				}
3928 				break;
3929 			}
3930 		}
3931 
3932 		if ((chmap == B_TTY_A_NULL) || (i == B_TTY_ACT_COUNT))
3933 			return(1);
3934 
3935 		switch (chmap) {
3936 			case B_TTY_A_M_TOG:
3937 			{
3938 				int cmem;
3939 
3940 				if ((SYNTHS->flags & REQ_DEBUG_MASK) > REQ_DEBUG_2)
3941 					snprintf(pbuf, btty.len,
3942 						"excepted Control switch memory: %s\r\n",
3943 						RESOURCES->name);
3944 				v = write(btty.fd[1], pbuf, strlen(pbuf));
3945 
3946 				cmem = SYNTHS->cmem;
3947 
3948 				if (SYNTHS->loadMemory != NULL)
3949 					SYNTHS->loadMemory(SYNTHS,
3950 						RESOURCES->name, 0,
3951 						SYNTHS->lmem, SYNTHS->mem.active, 0, btty.fl);
3952 				else
3953 					loadMemory(SYNTHS, RESOURCES->name,
3954 						0, SYNTHS->lmem, SYNTHS->mem.active,
3955 						0, btty.fl);
3956 				SYNTHS->lmem = cmem;
3957 				break;
3958 			}
3959 			case B_TTY_A_M_WRITE:
3960 				/* Save */
3961 				SYNTHS->cmem = SYNTHS->lmem;
3962 				if (SYNTHS->saveMemory != NULL)
3963 					SYNTHS->saveMemory(SYNTHS,
3964 						RESOURCES->name, 0,
3965 						SYNTHS->location, 0);
3966 				else
3967 					saveMemory(SYNTHS, RESOURCES->name,
3968 						0, SYNTHS->location, 0);
3969 				snprintf(pbuf, btty.len, "\r\nwrite: %i", SYNTHS->location);
3970 				v = write(btty.fd[1], pbuf, strlen(pbuf));
3971 				break;
3972 			case B_TTY_A_M_READ:
3973 				/* Open */
3974 				SYNTHS->lmem = SYNTHS->cmem;
3975 				if (SYNTHS->loadMemory != NULL)
3976 					SYNTHS->loadMemory(SYNTHS,
3977 						RESOURCES->name,
3978 						0, SYNTHS->location, SYNTHS->mem.active,
3979 						0, btty.fl);
3980 				else
3981 					loadMemory(SYNTHS, RESOURCES->name,
3982 						0, SYNTHS->location, SYNTHS->mem.active,
3983 						0, btty.fl);
3984 				SYNTHS->cmem = SYNTHS->location;
3985 				snprintf(pbuf, btty.len, "read: %i\r\n", SYNTHS->location);
3986 				v = write(btty.fd[1], pbuf, strlen(pbuf));
3987 				break;
3988 			case B_TTY_A_M_DOWN:
3989 				/* Mem down */
3990 				if (--SYNTHS->location < 0)
3991 					SYNTHS->location = 99;
3992 				if (loadMemory(SYNTHS, RESOURCES->name,
3993 						0, SYNTHS->location, SYNTHS->mem.active,
3994 						0, BRISTOL_STAT) < 0)
3995 					snprintf(pbuf, btty.len, "free mem: %i\r\n",
3996 						SYNTHS->location);
3997 				else
3998 					snprintf(pbuf, btty.len, "mem: %i\r\n", SYNTHS->location);
3999 					v = write(btty.fd[1], pbuf, strlen(pbuf));
4000 				break;
4001 			case B_TTY_A_M_UP:
4002 				/* Mem up */
4003 				if (++SYNTHS->location > 99)
4004 					SYNTHS->location = 0;
4005 				if (loadMemory(SYNTHS, RESOURCES->name,
4006 						0, SYNTHS->location, SYNTHS->mem.active,
4007 						0, BRISTOL_STAT) < 0)
4008 					snprintf(pbuf, btty.len, "free mem: %i\r\n",
4009 						SYNTHS->location);
4010 				else
4011 					snprintf(pbuf, btty.len, "mem: %i\r\n", SYNTHS->location);
4012 					v = write(btty.fd[1], pbuf, strlen(pbuf));
4013 				break;
4014 			case B_TTY_A_LEFT:
4015 				if (--btty.i < 0)
4016 				{
4017 					btty.i = 0;
4018 					break;
4019 				}
4020 
4021 				if ((paramname(btty.i)[0] == '\0') && (~btty.flags & B_TTY_AWV))
4022 				{
4023 					while (paramname(btty.i)[0] == '\0')
4024 					{
4025 						btty.i--;
4026 						if (btty.i < 0)
4027 						{
4028 							btty.i = 0;
4029 							return(1);
4030 						}
4031 					}
4032 				}
4033 
4034 				cliParamChange(global, 0.0f);
4035 				break;
4036 			case B_TTY_A_RIGHT:
4037 				btty.i++;
4038 
4039 				if (btty.i >= SYNTHS->win->app->resources[btty.p].ndevices)
4040 				{
4041 					btty.i = SYNTHS->win->app->resources[btty.p].ndevices - 1;
4042 					break;
4043 				}
4044 
4045 				//if ((DEVICE(btty.i).flags & BRIGHTON_WITHDRAWN)
4046 				if ((unnamed(btty.i)) && (~btty.flags & B_TTY_AWV))
4047 				{
4048 					int h = btty.i - 1;
4049 					//while (DEVICE(btty.i).flags & BRIGHTON_WITHDRAWN)
4050 					while (paramname(btty.i)[0] == '\0')
4051 					{
4052 						if (++btty.i
4053 							>= SYNTHS->win->app->resources[btty.p].ndevices)
4054 						{
4055 							if ((btty.i = h) < 0)
4056 								btty.i = 0;
4057 							return(1);
4058 						}
4059 					}
4060 				}
4061 
4062 				cliParamChange(global, 0.0f);
4063 				break;
4064 			case B_TTY_A_UPDATE:
4065 				/* refresh */
4066 				cliParamChange(global, 0.0f);
4067 				break;
4068 			case B_TTY_A_DECMAX:
4069 				/* Param down */
4070 				cliParamChange(global, -0.1f);
4071 				break;
4072 			case B_TTY_A_DEC:
4073 				/* Param down */
4074 				cliParamChange(global, -btty.accel);
4075 				break;
4076 				/*
4077 				 * Param down
4078 				 */
4079 			case B_TTY_A_DEC1:
4080 				cliParamChange(global, -1.0f/16383);
4081 				break;
4082 			case B_TTY_A_DEC4:
4083 				cliParamChange(global, -4.0f/16383);
4084 				break;
4085 			case B_TTY_A_DECMIN:
4086 				cliParamChange(global, -0.001f);
4087 				break;
4088 			case B_TTY_A_INCMAX:
4089 				/* Param up */
4090 				cliParamChange(global, 0.1f);
4091 				break;
4092 			case B_TTY_A_INC:
4093 				/* Param up */
4094 				cliParamChange(global, btty.accel);
4095 				break;
4096 				/*
4097 				 * Param up
4098 				 */
4099 			case B_TTY_A_INCMIN:
4100 				cliParamChange(global, 0.001f);
4101 				break;
4102 			case B_TTY_A_INC1:
4103 				cliParamChange(global, 1.0f/16383.001f);
4104 				break;
4105 			case B_TTY_A_INC4:
4106 				cliParamChange(global, 4.0f/16383.001f);
4107 				break;
4108 			case B_TTY_A_INSERT:
4109 				seqStop(global);
4110 				btty.flags &= ~(B_TTY_MMASK|B_TTY_SEQ);
4111 				btty.flags |= B_TTY_COOKED;
4112 				btty.edit_p = 0;
4113 				memset(cbuf, 0, B_TTY_LINE_LEN);
4114 				snprintf(pbuf, btty.len, "\n\r%s", printprompt(global));
4115 				btty.delim = ':';
4116 				v = write(btty.fd[1], pbuf, strlen(pbuf));
4117 				break;
4118 			case B_TTY_A_FIND:
4119 				btty.flags &= ~B_TTY_MMASK;
4120 				btty.flags |= B_TTY_SEARCH;
4121 				btty.edit_p = 0;
4122 				memset(cbuf, 0, B_TTY_LINE_LEN);
4123 				snprintf(pbuf, btty.len, "\n\r/");
4124 				btty.delim = '/';
4125 				v = write(btty.fd[1], pbuf, strlen(pbuf));
4126 				break;
4127 			default:
4128 			case B_TTY_A_NULL:
4129 				snprintf(pbuf, btty.len, "unimplemented char 0x%x\r\n", ch);
4130 				if (SYNTHS->flags & REQ_DEBUG_1)
4131 					v = write(btty.fd[1], pbuf, strlen(pbuf));
4132 				break;
4133 		}
4134 		lp = PDEV(btty.i)->value;
4135 	}
4136 
4137 	/* if the GUI has changed the value we show here, CLI to match */
4138 	if ((btty.flags & B_TTY_PLAY) && (btty.flags & B_TTY_PLAY_LINE))
4139 	{
4140 		if (btty.flags & B_TTY_CLEAR_KEY)
4141 		{
4142 			brightonKeyInput(SYNTHS->win, btty.key, 0);
4143 			btty.key = 255;
4144 		}
4145 
4146 		btty.flags |= B_TTY_CLEAR_KEY;
4147 	}
4148 
4149 	if (btty.flags & B_TTY_SEQ)
4150 	{
4151 		if (sequences[btty.sequence.id].count > 0)
4152 		{
4153 			if ((btty.sequence.count -= btty.acycle) <= 0)
4154 			{
4155 				/* Send note off/on */
4156 				print("note off");
4157 				if (btty.sequence.step < 0)
4158 					btty.sequence.step = sequences[btty.sequence.id].count;
4159 				else if (sequences[btty.sequence.id].step[btty.sequence.step]
4160 					> 0)
4161 					bristolMidiSendMsg(global->controlfd, SYNTHS->midichannel,
4162 						BRISTOL_EVENT_KEYOFF, 0,
4163 						sequences[btty.sequence.id].step[btty.sequence.step]
4164 						+ btty.sequence.transpose);
4165 
4166 				if (++btty.sequence.step
4167 					>= sequences[btty.sequence.id].count)
4168 					btty.sequence.step = 0;
4169 
4170 				print("note on");
4171 				if (sequences[btty.sequence.id].step[btty.sequence.step] > 0)
4172 					bristolMidiSendMsg(global->controlfd, SYNTHS->midichannel,
4173 						BRISTOL_EVENT_KEYON, 0,
4174 						sequences[btty.sequence.id].step[btty.sequence.step]
4175 						+ btty.sequence.transpose);
4176 
4177 				btty.sequence.count =
4178 					250 * 60 / sequences[btty.sequence.id].rate;
4179 
4180 				snprintf(pbuf, btty.len, "rate %i, count %i(%i), step %i\n\r",
4181 					sequences[0].rate, btty.sequence.count, btty.acycle,
4182 					btty.sequence.step);
4183 				v = write(btty.fd[1], pbuf, strlen(pbuf));
4184 			}
4185 		} else {
4186 			btty.flags &= ~B_TTY_SEQ;
4187 			seqStop(global);
4188 		}
4189 	}
4190 
4191 	if ((btty.flags & B_TTY_RAW)
4192 		&& (s == 0) && (r == 0)
4193 		&& (lp != PDEV(btty.i)->value))
4194 	{
4195 		lp = PDEV(btty.i)->value;
4196 		cliParamChange(global, 0.0f);
4197 	}
4198 
4199 	if ((r == 0) && (btty.flags & B_TTY_RAW_P))
4200 	{
4201 		btty.flags &= ~B_TTY_MMASK;
4202 		btty.flags |= B_TTY_RAW;
4203 		cliParamChange(global, 0.0f);
4204 	}
4205 
4206 	return(r);
4207 }
4208 
4209