1 /*
2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2008 Masanao Izumo <iz@onicos.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdint.h>
24
25 #include "timidity.h"
26 #include "common.h"
27 #include "instrum.h"
28 #include "quantity.h"
29
30
31 namespace TimidityPlus
32 {
33
34 #define MAXWORDS 130
35 #define CHECKERRLIMIT \
36 if(++errcnt >= 10) { \
37 printMessage(CMSG_ERROR, VERB_NORMAL, \
38 "Too many errors... Give up read %s", name); \
39 reuse_mblock(&varbuf); \
40 tf_close(tf); return 1; }
41
42
43 typedef struct {
44 const char *name;
45 int mapid, isdrum;
46 } MapNameEntry;
47
mapnamecompare(const void * name,const void * entry)48 static int mapnamecompare(const void *name, const void *entry)
49 {
50 return strcmp((const char *)name, ((const MapNameEntry *)entry)->name);
51 }
52
mapname2id(char * name,int * isdrum)53 static int mapname2id(char *name, int *isdrum)
54 {
55 static const MapNameEntry data[] = {
56 /* sorted in alphabetical order */
57 { "gm2", GM2_TONE_MAP, 0 },
58 { "gm2drum", GM2_DRUM_MAP, 1 },
59 { "sc55", SC_55_TONE_MAP, 0 },
60 { "sc55drum", SC_55_DRUM_MAP, 1 },
61 { "sc88", SC_88_TONE_MAP, 0 },
62 { "sc8850", SC_8850_TONE_MAP, 0 },
63 { "sc8850drum", SC_8850_DRUM_MAP, 1 },
64 { "sc88drum", SC_88_DRUM_MAP, 1 },
65 { "sc88pro", SC_88PRO_TONE_MAP, 0 },
66 { "sc88prodrum", SC_88PRO_DRUM_MAP, 1 },
67 { "xg", XG_NORMAL_MAP, 0 },
68 { "xgdrum", XG_DRUM_MAP, 1 },
69 { "xgsfx126", XG_SFX126_MAP, 1 },
70 { "xgsfx64", XG_SFX64_MAP, 0 }
71 };
72 const MapNameEntry *found;
73
74 found = (MapNameEntry *)bsearch(name, data, sizeof data / sizeof data[0], sizeof data[0], mapnamecompare);
75 if (found != NULL)
76 {
77 *isdrum = found->isdrum;
78 return found->mapid;
79 }
80 return -1;
81 }
82
config_parse_tune(const char * cp,int * num)83 static float *config_parse_tune(const char *cp, int *num)
84 {
85 const char *p;
86 float *tune_list;
87 int i;
88
89 /* count num */
90 *num = 1, p = cp;
91 while ((p = strchr(p, ',')) != NULL)
92 (*num)++, p++;
93 /* alloc */
94 tune_list = (float *)safe_malloc((*num) * sizeof(float));
95 /* regist */
96 for (i = 0, p = cp; i < *num; i++, p++) {
97 tune_list[i] = atof(p);
98 if (!(p = strchr(p, ',')))
99 break;
100 }
101 return tune_list;
102 }
103
config_parse_int16(const char * cp,int * num)104 static int16_t *config_parse_int16(const char *cp, int *num)
105 {
106 const char *p;
107 int16_t *list;
108 int i;
109
110 /* count num */
111 *num = 1, p = cp;
112 while ((p = strchr(p, ',')) != NULL)
113 (*num)++, p++;
114 /* alloc */
115 list = (int16_t *)safe_malloc((*num) * sizeof(int16_t));
116 /* regist */
117 for (i = 0, p = cp; i < *num; i++, p++) {
118 list[i] = atoi(p);
119 if (!(p = strchr(p, ',')))
120 break;
121 }
122 return list;
123 }
124
config_parse_envelope(const char * cp,int * num)125 static int **config_parse_envelope(const char *cp, int *num)
126 {
127 const char *p, *px;
128 int **env_list;
129 int i, j;
130
131 /* count num */
132 *num = 1, p = cp;
133 while ((p = strchr(p, ',')) != NULL)
134 (*num)++, p++;
135 /* alloc */
136 env_list = (int **)safe_malloc((*num) * sizeof(int *));
137 for (i = 0; i < *num; i++)
138 env_list[i] = (int *)safe_malloc(6 * sizeof(int));
139 /* init */
140 for (i = 0; i < *num; i++)
141 for (j = 0; j < 6; j++)
142 env_list[i][j] = -1;
143 /* regist */
144 for (i = 0, p = cp; i < *num; i++, p++) {
145 px = strchr(p, ',');
146 for (j = 0; j < 6; j++, p++) {
147 if (*p == ':')
148 continue;
149 env_list[i][j] = atoi(p);
150 if (!(p = strchr(p, ':')))
151 break;
152 if (px && p > px)
153 break;
154 }
155 if (!(p = px))
156 break;
157 }
158 return env_list;
159 }
160
config_parse_modulation(const char * name,int line,const char * cp,int * num,int mod_type)161 static Quantity **config_parse_modulation(const char *name, int line, const char *cp, int *num, int mod_type)
162 {
163 const char *p, *px, *err;
164 char buf[128], *delim;
165 Quantity **mod_list;
166 int i, j;
167 static const char * qtypestr[] = { "tremolo", "vibrato" };
168 static const uint16_t qtypes[] = {
169 QUANTITY_UNIT_TYPE(TREMOLO_SWEEP), QUANTITY_UNIT_TYPE(TREMOLO_RATE), QUANTITY_UNIT_TYPE(DIRECT_INT),
170 QUANTITY_UNIT_TYPE(VIBRATO_SWEEP), QUANTITY_UNIT_TYPE(VIBRATO_RATE), QUANTITY_UNIT_TYPE(DIRECT_INT)
171 };
172
173 /* count num */
174 *num = 1, p = cp;
175 while ((p = strchr(p, ',')) != NULL)
176 (*num)++, p++;
177 /* alloc */
178 mod_list = (Quantity **)safe_malloc((*num) * sizeof(Quantity *));
179 for (i = 0; i < *num; i++)
180 mod_list[i] = (Quantity *)safe_malloc(3 * sizeof(Quantity));
181 /* init */
182 for (i = 0; i < *num; i++)
183 for (j = 0; j < 3; j++)
184 INIT_QUANTITY(mod_list[i][j]);
185 buf[sizeof buf - 1] = '\0';
186 /* regist */
187 for (i = 0, p = cp; i < *num; i++, p++) {
188 px = strchr(p, ',');
189 for (j = 0; j < 3; j++, p++) {
190 if (*p == ':')
191 continue;
192 if ((delim = strpbrk(strncpy(buf, p, sizeof buf - 1), ":,")) != NULL)
193 *delim = '\0';
194 if (*buf != '\0' && (err = string_to_quantity(buf, &mod_list[i][j], qtypes[mod_type * 3 + j])) != NULL) {
195 printMessage(CMSG_ERROR, VERB_NORMAL, "%s: line %d: %s: parameter %d of item %d: %s (%s)",
196 name, line, qtypestr[mod_type], j + 1, i + 1, err, buf);
197 free_ptr_list(mod_list, *num);
198 mod_list = NULL;
199 *num = 0;
200 return NULL;
201 }
202 if (!(p = strchr(p, ':')))
203 break;
204 if (px && p > px)
205 break;
206 }
207 if (!(p = px))
208 break;
209 }
210 return mod_list;
211 }
212
213
214 /*! copy bank and, if necessary, map appropriately */
copybank(ToneBank * to,ToneBank * from,int mapid,int bankmapfrom,int bankno)215 void Instruments::copybank(ToneBank *to, ToneBank *from, int mapid, int bankmapfrom, int bankno)
216 {
217 ToneBankElement *toelm, *fromelm;
218 int i;
219
220 if (from == NULL)
221 return;
222 for (i = 0; i < 128; i++)
223 {
224 toelm = &to->tone[i];
225 fromelm = &from->tone[i];
226 if (fromelm->name == NULL)
227 continue;
228 copy_tone_bank_element(toelm, fromelm);
229 toelm->instrument = NULL;
230 if (mapid != INST_NO_MAP)
231 set_instrument_map(mapid, bankmapfrom, i, bankno, i);
232 }
233 }
234
235 /*! copy the whole mapped bank. returns 0 if no error. */
copymap(int mapto,int mapfrom,int isdrum)236 int Instruments::copymap(int mapto, int mapfrom, int isdrum)
237 {
238 ToneBank **tb = isdrum ? drumset : tonebank;
239 int i, bankfrom, bankto;
240
241 for (i = 0; i < 128; i++)
242 {
243 bankfrom = find_instrument_map_bank(isdrum, mapfrom, i);
244 if (bankfrom <= 0) /* not mapped */
245 continue;
246 bankto = alloc_instrument_map_bank(isdrum, mapto, i);
247 if (bankto == -1) /* failed */
248 return 1;
249 copybank(tb[bankto], tb[bankfrom], mapto, i, bankto);
250 }
251 return 0;
252 }
253
set_gus_patchconf_opts(const char * name,int line,char * opts,ToneBankElement * tone)254 int Instruments::set_gus_patchconf_opts(const char *name, int line, char *opts, ToneBankElement *tone)
255 {
256 char *cp;
257 int k;
258
259 if (!(cp = strchr(opts, '='))) {
260 printMessage(CMSG_ERROR, VERB_NORMAL,
261 "%s: line %d: bad patch option %s", name, line, opts);
262 return 1;
263 }
264 *cp++ = 0;
265 if (!strcmp(opts, "amp")) {
266 k = atoi(cp);
267 if ((k < 0 || k > MAX_AMPLIFICATION) || (*cp < '0' || *cp > '9')) {
268 printMessage(CMSG_ERROR, VERB_NORMAL,
269 "%s: line %d: amplification must be between 0 and %d",
270 name, line, MAX_AMPLIFICATION);
271 return 1;
272 }
273 tone->amp = k;
274 }
275 else if (!strcmp(opts, "note")) {
276 k = atoi(cp);
277 if ((k < 0 || k > 127) || (*cp < '0' || *cp > '9')) {
278 printMessage(CMSG_ERROR, VERB_NORMAL,
279 "%s: line %d: note must be between 0 and 127",
280 name, line);
281 return 1;
282 }
283 tone->note = k;
284 tone->scltune = config_parse_int16("100", &tone->scltunenum);
285 }
286 else if (!strcmp(opts, "pan")) {
287 if (!strcmp(cp, "center"))
288 k = 64;
289 else if (!strcmp(cp, "left"))
290 k = 0;
291 else if (!strcmp(cp, "right"))
292 k = 127;
293 else {
294 k = ((atoi(cp) + 100) * 100) / 157;
295 if ((k < 0 || k > 127)
296 || (k == 0 && *cp != '-' && (*cp < '0' || *cp > '9'))) {
297 printMessage(CMSG_ERROR, VERB_NORMAL,
298 "%s: line %d: panning must be left, right, "
299 "center, or between -100 and 100",
300 name, line);
301 return 1;
302 }
303 }
304 tone->pan = k;
305 }
306 else if (!strcmp(opts, "tune"))
307 tone->tune = config_parse_tune(cp, &tone->tunenum);
308 else if (!strcmp(opts, "rate"))
309 tone->envrate = config_parse_envelope(cp, &tone->envratenum);
310 else if (!strcmp(opts, "offset"))
311 tone->envofs = config_parse_envelope(cp, &tone->envofsnum);
312 else if (!strcmp(opts, "keep")) {
313 if (!strcmp(cp, "env"))
314 tone->strip_envelope = 0;
315 else if (!strcmp(cp, "loop"))
316 tone->strip_loop = 0;
317 else {
318 printMessage(CMSG_ERROR, VERB_NORMAL,
319 "%s: line %d: keep must be env or loop", name, line);
320 return 1;
321 }
322 }
323 else if (!strcmp(opts, "strip")) {
324 if (!strcmp(cp, "env"))
325 tone->strip_envelope = 1;
326 else if (!strcmp(cp, "loop"))
327 tone->strip_loop = 1;
328 else if (!strcmp(cp, "tail"))
329 tone->strip_tail = 1;
330 else {
331 printMessage(CMSG_ERROR, VERB_NORMAL,
332 "%s: line %d: strip must be env, loop, or tail",
333 name, line);
334 return 1;
335 }
336 }
337 else if (!strcmp(opts, "tremolo")) {
338 if ((tone->trem = config_parse_modulation(name,
339 line, cp, &tone->tremnum, 0)) == NULL)
340 return 1;
341 }
342 else if (!strcmp(opts, "vibrato")) {
343 if ((tone->vib = config_parse_modulation(name,
344 line, cp, &tone->vibnum, 1)) == NULL)
345 return 1;
346 }
347 else if (!strcmp(opts, "sclnote"))
348 tone->sclnote = config_parse_int16(cp, &tone->sclnotenum);
349 else if (!strcmp(opts, "scltune"))
350 tone->scltune = config_parse_int16(cp, &tone->scltunenum);
351 else if (!strcmp(opts, "comm")) {
352 char *p;
353
354 if (tone->comment)
355 free(tone->comment);
356 p = tone->comment = safe_strdup(cp);
357 while (*p) {
358 if (*p == ',')
359 *p = ' ';
360 p++;
361 }
362 }
363 else if (!strcmp(opts, "modrate"))
364 tone->modenvrate = config_parse_envelope(cp, &tone->modenvratenum);
365 else if (!strcmp(opts, "modoffset"))
366 tone->modenvofs = config_parse_envelope(cp, &tone->modenvofsnum);
367 else if (!strcmp(opts, "envkeyf"))
368 tone->envkeyf = config_parse_envelope(cp, &tone->envkeyfnum);
369 else if (!strcmp(opts, "envvelf"))
370 tone->envvelf = config_parse_envelope(cp, &tone->envvelfnum);
371 else if (!strcmp(opts, "modkeyf"))
372 tone->modenvkeyf = config_parse_envelope(cp, &tone->modenvkeyfnum);
373 else if (!strcmp(opts, "modvelf"))
374 tone->modenvvelf = config_parse_envelope(cp, &tone->modenvvelfnum);
375 else if (!strcmp(opts, "trempitch"))
376 tone->trempitch = config_parse_int16(cp, &tone->trempitchnum);
377 else if (!strcmp(opts, "tremfc"))
378 tone->tremfc = config_parse_int16(cp, &tone->tremfcnum);
379 else if (!strcmp(opts, "modpitch"))
380 tone->modpitch = config_parse_int16(cp, &tone->modpitchnum);
381 else if (!strcmp(opts, "modfc"))
382 tone->modfc = config_parse_int16(cp, &tone->modfcnum);
383 else if (!strcmp(opts, "fc"))
384 tone->fc = config_parse_int16(cp, &tone->fcnum);
385 else if (!strcmp(opts, "q"))
386 tone->reso = config_parse_int16(cp, &tone->resonum);
387 else if (!strcmp(opts, "fckeyf")) /* filter key-follow */
388 tone->key_to_fc = atoi(cp);
389 else if (!strcmp(opts, "fcvelf")) /* filter velocity-follow */
390 tone->vel_to_fc = atoi(cp);
391 else if (!strcmp(opts, "qvelf")) /* resonance velocity-follow */
392 tone->vel_to_resonance = atoi(cp);
393 else {
394 printMessage(CMSG_ERROR, VERB_NORMAL,
395 "%s: line %d: bad patch option %s",
396 name, line, opts);
397 return 1;
398 }
399 return 0;
400 }
401
402
reinit_tone_bank_element(ToneBankElement * tone)403 void Instruments::reinit_tone_bank_element(ToneBankElement *tone)
404 {
405 free_tone_bank_element(tone);
406 tone->note = tone->pan = -1;
407 tone->strip_loop = tone->strip_envelope = tone->strip_tail = -1;
408 tone->amp = -1;
409 tone->rnddelay = 0;
410 tone->loop_timeout = 0;
411 tone->legato = tone->damper_mode = tone->key_to_fc = tone->vel_to_fc = 0;
412 tone->reverb_send = tone->chorus_send = tone->delay_send = -1;
413 tone->tva_level = -1;
414 tone->play_note = -1;
415 }
416
417
set_gus_patchconf(const char * name,int line,ToneBankElement * tone,char * pat,char ** opts)418 int Instruments::set_gus_patchconf(const char *name, int line, ToneBankElement *tone, char *pat, char **opts)
419 {
420 int j;
421 reinit_tone_bank_element(tone);
422
423 if (strcmp(pat, "%font") == 0) /* Font extention */
424 {
425 /* %font filename bank prog [note-to-use]
426 * %font filename 128 bank key
427 */
428
429 if (opts[0] == NULL || opts[1] == NULL || opts[2] == NULL ||
430 (atoi(opts[1]) == 128 && opts[3] == NULL))
431 {
432 printMessage(CMSG_ERROR, VERB_NORMAL,
433 "%s: line %d: Syntax error", name, line);
434 return 1;
435 }
436 tone->name = safe_strdup(opts[0]);
437 tone->instype = 1;
438 if (atoi(opts[1]) == 128) /* drum */
439 {
440 tone->font_bank = 128;
441 tone->font_preset = atoi(opts[2]);
442 tone->font_keynote = atoi(opts[3]);
443 opts += 4;
444 }
445 else
446 {
447 tone->font_bank = atoi(opts[1]);
448 tone->font_preset = atoi(opts[2]);
449
450 if (opts[3] && isdigit(opts[3][0]))
451 {
452 tone->font_keynote = atoi(opts[3]);
453 opts += 4;
454 }
455 else
456 {
457 tone->font_keynote = -1;
458 opts += 3;
459 }
460 }
461 }
462 else if (strcmp(pat, "%sample") == 0) /* Sample extention */
463 {
464 /* %sample filename */
465
466 if (opts[0] == NULL)
467 {
468 printMessage(CMSG_ERROR, VERB_NORMAL,
469 "%s: line %d: Syntax error", name, line);
470 return 1;
471 }
472 tone->name = safe_strdup(opts[0]);
473 tone->instype = 2;
474 opts++;
475 }
476 else
477 {
478 tone->instype = 0;
479 tone->name = safe_strdup(pat);
480 }
481
482 for (j = 0; opts[j] != NULL; j++)
483 {
484 int err;
485 if ((err = set_gus_patchconf_opts(name, line, opts[j], tone)) != 0)
486 return err;
487 }
488 if (tone->comment == NULL)
489 tone->comment = safe_strdup(tone->name);
490 return 0;
491 }
492
493
494
set_patchconf(const char * name,int line,ToneBank * bank,char * w[],int dr,int mapid,int bankmapfrom,int bankno)495 int Instruments::set_patchconf(const char *name, int line, ToneBank *bank, char *w[], int dr, int mapid, int bankmapfrom, int bankno)
496 {
497 int i;
498
499 i = atoi(w[0]);
500 if (!dr)
501 i -= progbase;
502 if (i < 0 || i > 127)
503 {
504 if (dr)
505 printMessage(CMSG_ERROR, VERB_NORMAL,
506 "%s: line %d: Drum number must be between "
507 "0 and 127",
508 name, line);
509 else
510 printMessage(CMSG_ERROR, VERB_NORMAL,
511 "%s: line %d: Program must be between "
512 "%d and %d",
513 name, line, progbase, 127 + progbase);
514 return 1;
515 }
516 if (!bank)
517 {
518 printMessage(CMSG_ERROR, VERB_NORMAL,
519 "%s: line %d: Must specify tone bank or drum set "
520 "before assignment", name, line);
521 return 1;
522 }
523
524 if (set_gus_patchconf(name, line, &bank->tone[i], w[1], w + 2))
525 return 1;
526 if (mapid != INST_NO_MAP)
527 set_instrument_map(mapid, bankmapfrom, i, bankno, i);
528 return 0;
529 }
530
531
532
533 /* string[0] should not be '#' */
strip_trailing_comment(char * string,int next_token_index)534 int Instruments::strip_trailing_comment(char *string, int next_token_index)
535 {
536 if (string[next_token_index - 1] == '#' /* strip \1 in /^\S+(#*[ \t].*)/ */
537 && (string[next_token_index] == ' ' || string[next_token_index] == '\t'))
538 {
539 string[next_token_index] = '\0'; /* new c-string terminator */
540 while (string[--next_token_index - 1] == '#')
541 ;
542 }
543 return next_token_index;
544 }
545
expand_variables(char * string,MBlockList * varbuf,const char * basedir)546 char *Instruments::expand_variables(char *string, MBlockList *varbuf, const char *basedir)
547 {
548 char *p, *expstr;
549 const char *copystr;
550 int limlen, copylen, explen, varlen, braced;
551
552 if ((p = strchr(string, '$')) == NULL)
553 return string;
554 varlen = (int)strlen(basedir);
555 explen = limlen = 0;
556 expstr = NULL;
557 copystr = string;
558 copylen = p - string;
559 string = p;
560 for (;;)
561 {
562 if (explen + copylen + 1 > limlen)
563 {
564 limlen += copylen + 128;
565 expstr = (char*)memcpy(new_segment(varbuf, limlen), expstr, explen);
566 }
567 memcpy(&expstr[explen], copystr, copylen);
568 explen += copylen;
569 if (*string == '\0')
570 break;
571 else if (*string == '$')
572 {
573 braced = *++string == '{';
574 if (braced)
575 {
576 if ((p = strchr(string + 1, '}')) == NULL)
577 p = string; /* no closing brace */
578 else
579 string++;
580 }
581 else
582 for (p = string; isalnum(*p) || *p == '_'; p++);
583 if (p == string) /* empty */
584 {
585 copystr = "${";
586 copylen = 1 + braced;
587 }
588 else
589 {
590 if (p - string == 7 && memcmp(string, "basedir", 7) == 0)
591 {
592 copystr = basedir;
593 copylen = varlen;
594 }
595 else /* undefined variable */
596 copylen = 0;
597 string = p + braced;
598 }
599 }
600 else /* search next */
601 {
602 p = strchr(string, '$');
603 if (p == NULL)
604 copylen = (int)strlen(string);
605 else
606 copylen = int(p - string);
607 copystr = string;
608 string += copylen;
609 }
610 }
611 expstr[explen] = '\0';
612 return expstr;
613 }
614
615
read_config_file(const char * name,int self,int allow_missing_file)616 int Instruments::read_config_file(const char *name, int self, int allow_missing_file)
617 {
618 timidity_file *tf;
619 char buf[1024], *tmp, *w[MAXWORDS + 1], *cp;
620 ToneBank *bank = NULL;
621 int i, j, k, line = 0, words, errcnt = 0;
622 static int rcf_count = 0;
623 int dr = 0, bankno = 0, mapid = INST_NO_MAP, origbankno = 0x7FFFFFFF;
624 int extension_flag, param_parse_err;
625 MBlockList varbuf;
626 const char *basedir;
627 char *sep;
628
629 if (rcf_count > 50)
630 {
631 printMessage(CMSG_ERROR, VERB_NORMAL,
632 "Probable source loop in configuration files");
633 return READ_CONFIG_RECURSION;
634 }
635
636 tf = open_file(name, sfreader);
637 if (tf == NULL)
638 return allow_missing_file ? READ_CONFIG_FILE_NOT_FOUND :
639 READ_CONFIG_ERROR;
640
641 init_mblock(&varbuf);
642 if (!self)
643 {
644 char *c = strdup_mblock(&varbuf, tf->filename.c_str());
645 basedir = c;
646 for (; *c; c++) if (*c == '\\') *c = '/';
647 sep = (char*)strrchr(basedir, '/');
648 }
649 else
650 sep = NULL;
651 if (sep == NULL)
652 {
653 basedir = ".";
654 }
655 else
656 {
657 if ((cp = (char*)strchr(sep, '#')) != NULL)
658 sep = cp + 1; /* inclusive of '#' */
659 *sep = '\0';
660 }
661
662 while (tf_gets(buf, sizeof(buf), tf))
663 {
664 line++;
665 if (strncmp(buf, "#extension", 10) == 0) {
666 extension_flag = 1;
667 i = 10;
668 }
669 else
670 {
671 extension_flag = 0;
672 i = 0;
673 }
674
675 while (isspace(buf[i])) /* skip /^\s*(?#)/ */
676 i++;
677 if (buf[i] == '#' || buf[i] == '\0') /* /^#|^$/ */
678 continue;
679 tmp = expand_variables(buf, &varbuf, basedir);
680 j = (int)strcspn(tmp + i, " \t\r\n\240");
681 if (j == 0)
682 j = (int)strlen(tmp + i);
683 j = strip_trailing_comment(tmp + i, j);
684 tmp[i + j] = '\0'; /* terminate the first token */
685 w[0] = tmp + i;
686 i += j + 1;
687 words = param_parse_err = 0;
688 while (words < MAXWORDS - 1) /* -1 : next arg */
689 {
690 char *terminator;
691
692 while (isspace(tmp[i])) /* skip /^\s*(?#)/ */
693 i++;
694 if (tmp[i] == '\0'
695 || tmp[i] == '#') /* /\s#/ */
696 break;
697 if ((tmp[i] == '"' || tmp[i] == '\'')
698 && (terminator = strchr(tmp + i + 1, tmp[i])) != NULL)
699 {
700 if (!isspace(terminator[1]) && terminator[1] != '\0')
701 {
702 printMessage(CMSG_ERROR, VERB_NORMAL,
703 "%s: line %d: there must be at least one whitespace between "
704 "string terminator (%c) and the next parameter", name, line, tmp[i]);
705 CHECKERRLIMIT;
706 param_parse_err = 1;
707 break;
708 }
709 w[++words] = tmp + i + 1;
710 i = terminator - tmp + 1;
711 *terminator = '\0';
712 }
713 else /* not terminated */
714 {
715 j = (int)strcspn(tmp + i, " \t\r\n\240");
716 if (j > 0)
717 j = strip_trailing_comment(tmp + i, j);
718 w[++words] = tmp + i;
719 i += j;
720 if (tmp[i] != '\0') /* unless at the end-of-string (i.e. EOF) */
721 tmp[i++] = '\0'; /* terminate the token */
722 }
723 }
724 if (param_parse_err)
725 continue;
726 w[++words] = NULL;
727
728 /*
729 * #extension [something...]
730 */
731
732 /* #extension timeout program sec */
733 if (strcmp(w[0], "timeout") == 0)
734 {
735 if (words != 3)
736 {
737 printMessage(CMSG_ERROR, VERB_NORMAL,
738 "%s: line %d: syntax error", name, line);
739 CHECKERRLIMIT;
740 continue;
741 }
742 if (!bank)
743 {
744 printMessage(CMSG_ERROR, VERB_NORMAL,
745 "%s: line %d: Must specify tone bank or drum set "
746 "before assignment", name, line);
747 CHECKERRLIMIT;
748 continue;
749 }
750 i = atoi(w[1]);
751 if (i < 0 || i > 127)
752 {
753 printMessage(CMSG_ERROR, VERB_NORMAL,
754 "%s: line %d: extension timeout "
755 "must be between 0 and 127", name, line);
756 CHECKERRLIMIT;
757 continue;
758 }
759 bank->tone[i].loop_timeout = atoi(w[2]);
760 }
761 /* #extension copydrumset drumset */
762 else if (strcmp(w[0], "copydrumset") == 0)
763 {
764 if (words < 2)
765 {
766 printMessage(CMSG_ERROR, VERB_NORMAL,
767 "%s: line %d: No copydrumset number given",
768 name, line);
769 CHECKERRLIMIT;
770 continue;
771 }
772 i = atoi(w[1]);
773 if (i < 0 || i > 127)
774 {
775 printMessage(CMSG_ERROR, VERB_NORMAL,
776 "%s: line %d: extension copydrumset "
777 "must be between 0 and 127", name, line);
778 CHECKERRLIMIT;
779 continue;
780 }
781 if (!bank)
782 {
783 printMessage(CMSG_ERROR, VERB_NORMAL,
784 "%s: line %d: Must specify tone bank or "
785 "drum set before assignment", name, line);
786 CHECKERRLIMIT;
787 continue;
788 }
789 copybank(bank, drumset[i], mapid, origbankno, bankno);
790 }
791 /* #extension copybank bank */
792 else if (strcmp(w[0], "copybank") == 0)
793 {
794 if (words < 2)
795 {
796 printMessage(CMSG_ERROR, VERB_NORMAL,
797 "%s: line %d: No copybank number given",
798 name, line);
799 CHECKERRLIMIT;
800 continue;
801 }
802 i = atoi(w[1]);
803 if (i < 0 || i > 127)
804 {
805 printMessage(CMSG_ERROR, VERB_NORMAL,
806 "%s: line %d: extension copybank "
807 "must be between 0 and 127", name, line);
808 CHECKERRLIMIT;
809 continue;
810 }
811 if (!bank)
812 {
813 printMessage(CMSG_ERROR, VERB_NORMAL,
814 "%s: line %d: Must specify tone bank or "
815 "drum set before assignment", name, line);
816 CHECKERRLIMIT;
817 continue;
818 }
819 copybank(bank, tonebank[i], mapid, origbankno, bankno);
820 }
821 /* #extension copymap tomapid frommapid */
822 else if (strcmp(w[0], "copymap") == 0)
823 {
824 int mapto, mapfrom;
825 int toisdrum, fromisdrum;
826
827 if (words != 3)
828 {
829 printMessage(CMSG_ERROR, VERB_NORMAL,
830 "%s: line %d: syntax error", name, line);
831 CHECKERRLIMIT;
832 continue;
833 }
834 if ((mapto = mapname2id(w[1], &toisdrum)) == -1)
835 {
836 printMessage(CMSG_ERROR, VERB_NORMAL,
837 "%s: line %d: Invalid map name: %s", name, line, w[1]);
838 CHECKERRLIMIT;
839 continue;
840 }
841 if ((mapfrom = mapname2id(w[2], &fromisdrum)) == -1)
842 {
843 printMessage(CMSG_ERROR, VERB_NORMAL,
844 "%s: line %d: Invalid map name: %s", name, line, w[2]);
845 CHECKERRLIMIT;
846 continue;
847 }
848 if (toisdrum != fromisdrum)
849 {
850 printMessage(CMSG_ERROR, VERB_NORMAL,
851 "%s: line %d: Map type should be matched", name, line);
852 CHECKERRLIMIT;
853 continue;
854 }
855 if (copymap(mapto, mapfrom, toisdrum))
856 {
857 printMessage(CMSG_ERROR, VERB_NORMAL,
858 "%s: line %d: No free %s available to map",
859 name, line, toisdrum ? "drum set" : "tone bank");
860 CHECKERRLIMIT;
861 continue;
862 }
863 }
864 /* #extension undef program */
865 else if (strcmp(w[0], "undef") == 0)
866 {
867 if (words < 2)
868 {
869 printMessage(CMSG_ERROR, VERB_NORMAL,
870 "%s: line %d: No undef number given",
871 name, line);
872 CHECKERRLIMIT;
873 continue;
874 }
875 i = atoi(w[1]);
876 if (i < 0 || i > 127)
877 {
878 printMessage(CMSG_ERROR, VERB_NORMAL,
879 "%s: line %d: extension undef "
880 "must be between 0 and 127", name, line);
881 CHECKERRLIMIT;
882 continue;
883 }
884 if (!bank)
885 {
886 printMessage(CMSG_ERROR, VERB_NORMAL,
887 "%s: line %d: Must specify tone bank or "
888 "drum set before assignment", name, line);
889 CHECKERRLIMIT;
890 continue;
891 }
892 free_tone_bank_element(&bank->tone[i]);
893 }
894 /* #extension altassign numbers... */
895 else if (strcmp(w[0], "altassign") == 0)
896 {
897 ToneBank *bk;
898
899 if (!bank)
900 {
901 printMessage(CMSG_ERROR, VERB_NORMAL,
902 "%s: line %d: Must specify tone bank or drum set "
903 "before altassign", name, line);
904 CHECKERRLIMIT;
905 continue;
906 }
907 if (words < 2)
908 {
909 printMessage(CMSG_ERROR, VERB_NORMAL,
910 "%s: line %d: No alternate assignment", name, line);
911 CHECKERRLIMIT;
912 continue;
913 }
914
915 if (!dr) {
916 printMessage(CMSG_WARNING, VERB_NORMAL,
917 "%s: line %d: Warning: Not a drumset altassign"
918 " (ignored)",
919 name, line);
920 continue;
921 }
922
923 bk = drumset[bankno];
924 bk->alt = add_altassign_string(bk->alt, w + 1, words - 1);
925 } /* #extension legato [program] [0 or 1] */
926 else if (strcmp(w[0], "legato") == 0)
927 {
928 if (words != 3)
929 {
930 printMessage(CMSG_ERROR, VERB_NORMAL,
931 "%s: line %d: syntax error", name, line);
932 CHECKERRLIMIT;
933 continue;
934 }
935 if (!bank)
936 {
937 printMessage(CMSG_ERROR, VERB_NORMAL,
938 "%s: line %d: Must specify tone bank or drum set "
939 "before assignment", name, line);
940 CHECKERRLIMIT;
941 continue;
942 }
943 i = atoi(w[1]);
944 if (i < 0 || i > 127)
945 {
946 printMessage(CMSG_ERROR, VERB_NORMAL,
947 "%s: line %d: extension legato "
948 "must be between 0 and 127", name, line);
949 CHECKERRLIMIT;
950 continue;
951 }
952 bank->tone[i].legato = atoi(w[2]);
953 } /* #extension damper [program] [0 or 1] */
954 else if (strcmp(w[0], "damper") == 0)
955 {
956 if (words != 3)
957 {
958 printMessage(CMSG_ERROR, VERB_NORMAL,
959 "%s: line %d: syntax error", name, line);
960 CHECKERRLIMIT;
961 continue;
962 }
963 if (!bank)
964 {
965 printMessage(CMSG_ERROR, VERB_NORMAL,
966 "%s: line %d: Must specify tone bank or drum set "
967 "before assignment", name, line);
968 CHECKERRLIMIT;
969 continue;
970 }
971 i = atoi(w[1]);
972 if (i < 0 || i > 127)
973 {
974 printMessage(CMSG_ERROR, VERB_NORMAL,
975 "%s: line %d: extension damper "
976 "must be between 0 and 127", name, line);
977 CHECKERRLIMIT;
978 continue;
979 }
980 bank->tone[i].damper_mode = atoi(w[2]);
981 } /* #extension rnddelay [program] [0 or 1] */
982 else if (strcmp(w[0], "rnddelay") == 0)
983 {
984 if (words != 3)
985 {
986 printMessage(CMSG_ERROR, VERB_NORMAL,
987 "%s: line %d: syntax error", name, line);
988 CHECKERRLIMIT;
989 continue;
990 }
991 if (!bank)
992 {
993 printMessage(CMSG_ERROR, VERB_NORMAL,
994 "%s: line %d: Must specify tone bank or drum set "
995 "before assignment", name, line);
996 CHECKERRLIMIT;
997 continue;
998 }
999 i = atoi(w[1]);
1000 if (i < 0 || i > 127)
1001 {
1002 printMessage(CMSG_ERROR, VERB_NORMAL,
1003 "%s: line %d: extension rnddelay "
1004 "must be between 0 and 127", name, line);
1005 CHECKERRLIMIT;
1006 continue;
1007 }
1008 bank->tone[i].rnddelay = atoi(w[2]);
1009 } /* #extension level program tva_level */
1010 else if (strcmp(w[0], "level") == 0)
1011 {
1012 if (words != 3)
1013 {
1014 printMessage(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line);
1015 CHECKERRLIMIT;
1016 continue;
1017 }
1018 if (!bank)
1019 {
1020 printMessage(CMSG_ERROR, VERB_NORMAL,
1021 "%s: line %d: Must specify tone bank or drum set "
1022 "before assignment", name, line);
1023 CHECKERRLIMIT;
1024 continue;
1025 }
1026 i = atoi(w[2]);
1027 if (i < 0 || i > 127)
1028 {
1029 printMessage(CMSG_ERROR, VERB_NORMAL,
1030 "%s: line %d: extension level "
1031 "must be between 0 and 127", name, line);
1032 CHECKERRLIMIT;
1033 continue;
1034 }
1035 cp = w[1];
1036 do {
1037 if (string_to_7bit_range(cp, &j, &k))
1038 {
1039 while (j <= k)
1040 bank->tone[j++].tva_level = i;
1041 }
1042 cp = strchr(cp, ',');
1043 } while (cp++ != NULL);
1044 } /* #extension reverbsend */
1045 else if (strcmp(w[0], "reverbsend") == 0)
1046 {
1047 if (words != 3)
1048 {
1049 printMessage(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line);
1050 CHECKERRLIMIT;
1051 continue;
1052 }
1053 if (!bank)
1054 {
1055 printMessage(CMSG_ERROR, VERB_NORMAL,
1056 "%s: line %d: Must specify tone bank or drum set "
1057 "before assignment", name, line);
1058 CHECKERRLIMIT;
1059 continue;
1060 }
1061 i = atoi(w[2]);
1062 if (i < 0 || i > 127)
1063 {
1064 printMessage(CMSG_ERROR, VERB_NORMAL,
1065 "%s: line %d: extension reverbsend "
1066 "must be between 0 and 127", name, line);
1067 CHECKERRLIMIT;
1068 continue;
1069 }
1070 cp = w[1];
1071 do {
1072 if (string_to_7bit_range(cp, &j, &k))
1073 {
1074 while (j <= k)
1075 bank->tone[j++].reverb_send = i;
1076 }
1077 cp = strchr(cp, ',');
1078 } while (cp++ != NULL);
1079 } /* #extension chorussend */
1080 else if (strcmp(w[0], "chorussend") == 0)
1081 {
1082 if (words != 3)
1083 {
1084 printMessage(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line);
1085 CHECKERRLIMIT;
1086 continue;
1087 }
1088 if (!bank)
1089 {
1090 printMessage(CMSG_ERROR, VERB_NORMAL,
1091 "%s: line %d: Must specify tone bank or drum set "
1092 "before assignment", name, line);
1093 CHECKERRLIMIT;
1094 continue;
1095 }
1096 i = atoi(w[2]);
1097 if (i < 0 || i > 127)
1098 {
1099 printMessage(CMSG_ERROR, VERB_NORMAL,
1100 "%s: line %d: extension chorussend "
1101 "must be between 0 and 127", name, line);
1102 CHECKERRLIMIT;
1103 continue;
1104 }
1105 cp = w[1];
1106 do {
1107 if (string_to_7bit_range(cp, &j, &k))
1108 {
1109 while (j <= k)
1110 bank->tone[j++].chorus_send = i;
1111 }
1112 cp = strchr(cp, ',');
1113 } while (cp++ != NULL);
1114 } /* #extension delaysend */
1115 else if (strcmp(w[0], "delaysend") == 0)
1116 {
1117 if (words != 3)
1118 {
1119 printMessage(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line);
1120 CHECKERRLIMIT;
1121 continue;
1122 }
1123 if (!bank)
1124 {
1125 printMessage(CMSG_ERROR, VERB_NORMAL,
1126 "%s: line %d: Must specify tone bank or drum set "
1127 "before assignment", name, line);
1128 CHECKERRLIMIT;
1129 continue;
1130 }
1131 i = atoi(w[2]);
1132 if (i < 0 || i > 127)
1133 {
1134 printMessage(CMSG_ERROR, VERB_NORMAL,
1135 "%s: line %d: extension delaysend "
1136 "must be between 0 and 127", name, line);
1137 CHECKERRLIMIT;
1138 continue;
1139 }
1140 cp = w[1];
1141 do {
1142 if (string_to_7bit_range(cp, &j, &k))
1143 {
1144 while (j <= k)
1145 bank->tone[j++].delay_send = i;
1146 }
1147 cp = strchr(cp, ',');
1148 } while (cp++ != NULL);
1149 } /* #extension playnote */
1150 else if (strcmp(w[0], "playnote") == 0)
1151 {
1152 if (words != 3)
1153 {
1154 printMessage(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line);
1155 CHECKERRLIMIT;
1156 continue;
1157 }
1158 if (!bank)
1159 {
1160 printMessage(CMSG_ERROR, VERB_NORMAL,
1161 "%s: line %d: Must specify tone bank or drum set "
1162 "before assignment", name, line);
1163 CHECKERRLIMIT;
1164 continue;
1165 }
1166 i = atoi(w[2]);
1167 if (i < 0 || i > 127)
1168 {
1169 printMessage(CMSG_ERROR, VERB_NORMAL,
1170 "%s: line %d: extension playnote"
1171 "must be between 0 and 127", name, line);
1172 CHECKERRLIMIT;
1173 continue;
1174 }
1175 cp = w[1];
1176 do {
1177 if (string_to_7bit_range(cp, &j, &k))
1178 {
1179 while (j <= k)
1180 bank->tone[j++].play_note = i;
1181 }
1182 cp = strchr(cp, ',');
1183 } while (cp++ != NULL);
1184 }
1185 else if (!strcmp(w[0], "soundfont"))
1186 {
1187 int order, cutoff, isremove, reso, amp;
1188 char *sf_file;
1189
1190 if (words < 2)
1191 {
1192 printMessage(CMSG_ERROR, VERB_NORMAL,
1193 "%s: line %d: No soundfont file given",
1194 name, line);
1195 CHECKERRLIMIT;
1196 continue;
1197 }
1198
1199 sf_file = w[1];
1200 order = cutoff = reso = amp = -1;
1201 isremove = 0;
1202 for (j = 2; j < words; j++)
1203 {
1204 if (strcmp(w[j], "remove") == 0)
1205 {
1206 isremove = 1;
1207 break;
1208 }
1209 if (!(cp = strchr(w[j], '=')))
1210 {
1211 printMessage(CMSG_ERROR, VERB_NORMAL,
1212 "%s: line %d: bad patch option %s",
1213 name, line, w[j]);
1214 CHECKERRLIMIT;
1215 break;
1216 }
1217 *cp++ = 0;
1218 k = atoi(cp);
1219 if (!strcmp(w[j], "order"))
1220 {
1221 if (k < 0 || (*cp < '0' || *cp > '9'))
1222 {
1223 printMessage(CMSG_ERROR, VERB_NORMAL,
1224 "%s: line %d: order must be a digit",
1225 name, line);
1226 CHECKERRLIMIT;
1227 break;
1228 }
1229 order = k;
1230 }
1231 else if (!strcmp(w[j], "cutoff"))
1232 {
1233 if (k < 0 || (*cp < '0' || *cp > '9'))
1234 {
1235 printMessage(CMSG_ERROR, VERB_NORMAL,
1236 "%s: line %d: cutoff must be a digit",
1237 name, line);
1238 CHECKERRLIMIT;
1239 break;
1240 }
1241 cutoff = k;
1242 }
1243 else if (!strcmp(w[j], "reso"))
1244 {
1245 if (k < 0 || (*cp < '0' || *cp > '9'))
1246 {
1247 printMessage(CMSG_ERROR, VERB_NORMAL,
1248 "%s: line %d: reso must be a digit",
1249 name, line);
1250 CHECKERRLIMIT;
1251 break;
1252 }
1253 reso = k;
1254 }
1255 else if (!strcmp(w[j], "amp"))
1256 {
1257 amp = k;
1258 }
1259 }
1260 if (isremove)
1261 remove_soundfont(sf_file);
1262 else
1263 add_soundfont(sf_file, order, cutoff, reso, amp);
1264 }
1265 else if (!strcmp(w[0], "font"))
1266 {
1267 int bank, preset, keynote;
1268 if (words < 2)
1269 {
1270 printMessage(CMSG_ERROR, VERB_NORMAL,
1271 "%s: line %d: no font command", name, line);
1272 CHECKERRLIMIT;
1273 continue;
1274 }
1275 if (!strcmp(w[1], "exclude"))
1276 {
1277 if (words < 3)
1278 {
1279 printMessage(CMSG_ERROR, VERB_NORMAL,
1280 "%s: line %d: No bank/preset/key is given",
1281 name, line);
1282 CHECKERRLIMIT;
1283 continue;
1284 }
1285 bank = atoi(w[2]);
1286 if (words >= 4)
1287 preset = atoi(w[3]) - progbase;
1288 else
1289 preset = -1;
1290 if (words >= 5)
1291 keynote = atoi(w[4]);
1292 else
1293 keynote = -1;
1294 if (exclude_soundfont(bank, preset, keynote))
1295 {
1296 printMessage(CMSG_ERROR, VERB_NORMAL,
1297 "%s: line %d: No soundfont is given",
1298 name, line);
1299 CHECKERRLIMIT;
1300 }
1301 }
1302 else if (!strcmp(w[1], "order"))
1303 {
1304 int order;
1305 if (words < 4)
1306 {
1307 printMessage(CMSG_ERROR, VERB_NORMAL,
1308 "%s: line %d: No order/bank is given",
1309 name, line);
1310 CHECKERRLIMIT;
1311 continue;
1312 }
1313 order = atoi(w[2]);
1314 bank = atoi(w[3]);
1315 if (words >= 5)
1316 preset = atoi(w[4]) - progbase;
1317 else
1318 preset = -1;
1319 if (words >= 6)
1320 keynote = atoi(w[5]);
1321 else
1322 keynote = -1;
1323 if (order_soundfont(bank, preset, keynote, order))
1324 {
1325 printMessage(CMSG_ERROR, VERB_NORMAL,
1326 "%s: line %d: No soundfont is given",
1327 name, line);
1328 CHECKERRLIMIT;
1329 }
1330 }
1331 }
1332 else if (!strcmp(w[0], "progbase"))
1333 {
1334 if (words < 2 || *w[1] < '0' || *w[1] > '9')
1335 {
1336 printMessage(CMSG_ERROR, VERB_NORMAL,
1337 "%s: line %d: syntax error", name, line);
1338 CHECKERRLIMIT;
1339 continue;
1340 }
1341 progbase = atoi(w[1]);
1342 }
1343 else if (!strcmp(w[0], "map")) /* map <name> set1 elem1 set2 elem2 */
1344 {
1345 int arg[5], isdrum;
1346
1347 if (words != 6)
1348 {
1349 printMessage(CMSG_ERROR, VERB_NORMAL,
1350 "%s: line %d: syntax error", name, line);
1351 CHECKERRLIMIT;
1352 continue;
1353 }
1354 if ((arg[0] = mapname2id(w[1], &isdrum)) == -1)
1355 {
1356 printMessage(CMSG_ERROR, VERB_NORMAL,
1357 "%s: line %d: Invalid map name: %s", name, line, w[1]);
1358 CHECKERRLIMIT;
1359 continue;
1360 }
1361 for (i = 2; i < 6; i++)
1362 arg[i - 1] = atoi(w[i]);
1363 if (isdrum)
1364 {
1365 arg[1] -= progbase;
1366 arg[3] -= progbase;
1367 }
1368 else
1369 {
1370 arg[2] -= progbase;
1371 arg[4] -= progbase;
1372 }
1373
1374 for (i = 1; i < 5; i++)
1375 if (arg[i] < 0 || arg[i] > 127)
1376 break;
1377 if (i != 5)
1378 {
1379 printMessage(CMSG_ERROR, VERB_NORMAL,
1380 "%s: line %d: Invalid parameter", name, line);
1381 CHECKERRLIMIT;
1382 continue;
1383 }
1384 set_instrument_map(arg[0], arg[1], arg[2], arg[3], arg[4]);
1385 }
1386
1387 /*
1388 * Standard configurations
1389 */
1390 else if (!strcmp(w[0], "dir"))
1391 {
1392 if (words < 2)
1393 {
1394 printMessage(CMSG_ERROR, VERB_NORMAL,
1395 "%s: line %d: No directory given", name, line);
1396 CHECKERRLIMIT;
1397 continue;
1398 }
1399 for (i = 1; i < words; i++)
1400 sfreader->add_search_path(w[i]);
1401 }
1402 else if (!strcmp(w[0], "source") || !strcmp(w[0], "trysource"))
1403 {
1404 if (words < 2)
1405 {
1406 printMessage(CMSG_ERROR, VERB_NORMAL,
1407 "%s: line %d: No file name given", name, line);
1408 CHECKERRLIMIT;
1409 continue;
1410 }
1411 for (i = 1; i < words; i++)
1412 {
1413 int status;
1414 rcf_count++;
1415 status = read_config_file(w[i], 0, !strcmp(w[0], "trysource"));
1416 rcf_count--;
1417 switch (status) {
1418 case READ_CONFIG_SUCCESS:
1419 break;
1420 case READ_CONFIG_ERROR:
1421 CHECKERRLIMIT;
1422 continue;
1423 case READ_CONFIG_RECURSION:
1424 reuse_mblock(&varbuf);
1425 tf_close(tf);
1426 return READ_CONFIG_RECURSION;
1427 case READ_CONFIG_FILE_NOT_FOUND:
1428 break;
1429 }
1430 }
1431 }
1432 else if (!strcmp(w[0], "default"))
1433 {
1434 if (words != 2)
1435 {
1436 printMessage(CMSG_ERROR, VERB_NORMAL,
1437 "%s: line %d: Must specify exactly one patch name",
1438 name, line);
1439 CHECKERRLIMIT;
1440 continue;
1441 }
1442 strncpy(def_instr_name, w[1], 255);
1443 def_instr_name[255] = '\0';
1444 default_instrument_name = def_instr_name;
1445 }
1446 /* drumset [mapid] num */
1447 else if (!strcmp(w[0], "drumset"))
1448 {
1449 int newmapid, isdrum, newbankno;
1450
1451 if (words < 2)
1452 {
1453 printMessage(CMSG_ERROR, VERB_NORMAL,
1454 "%s: line %d: No drum set number given", name, line);
1455 CHECKERRLIMIT;
1456 continue;
1457 }
1458 if (words != 2 && !isdigit(*w[1]))
1459 {
1460 if ((newmapid = mapname2id(w[1], &isdrum)) == -1 || !isdrum)
1461 {
1462 printMessage(CMSG_ERROR, VERB_NORMAL,
1463 "%s: line %d: Invalid drum set map name: %s", name, line, w[1]);
1464 CHECKERRLIMIT;
1465 continue;
1466 }
1467 words--;
1468 memmove(&w[1], &w[2], sizeof w[0] * words);
1469 }
1470 else
1471 newmapid = INST_NO_MAP;
1472 i = atoi(w[1]) - progbase;
1473 if (i < 0 || i > 127)
1474 {
1475 printMessage(CMSG_ERROR, VERB_NORMAL,
1476 "%s: line %d: Drum set must be between %d and %d",
1477 name, line,
1478 progbase, progbase + 127);
1479 CHECKERRLIMIT;
1480 continue;
1481 }
1482
1483 newbankno = i;
1484 i = alloc_instrument_map_bank(1, newmapid, i);
1485 if (i == -1)
1486 {
1487 printMessage(CMSG_ERROR, VERB_NORMAL,
1488 "%s: line %d: No free drum set available to map",
1489 name, line);
1490 CHECKERRLIMIT;
1491 continue;
1492 }
1493
1494 if (words == 2)
1495 {
1496 bank = drumset[i];
1497 bankno = i;
1498 mapid = newmapid;
1499 origbankno = newbankno;
1500 dr = 1;
1501 }
1502 else
1503 {
1504 if (words < 4 || *w[2] < '0' || *w[2] > '9')
1505 {
1506 printMessage(CMSG_ERROR, VERB_NORMAL,
1507 "%s: line %d: syntax error", name, line);
1508 CHECKERRLIMIT;
1509 continue;
1510 }
1511 if (set_patchconf(name, line, drumset[i], &w[2], 1, newmapid, newbankno, i))
1512 {
1513 CHECKERRLIMIT;
1514 continue;
1515 }
1516 }
1517 }
1518 /* bank [mapid] num */
1519 else if (!strcmp(w[0], "bank"))
1520 {
1521 int newmapid, isdrum, newbankno;
1522
1523 if (words < 2)
1524 {
1525 printMessage(CMSG_ERROR, VERB_NORMAL,
1526 "%s: line %d: No bank number given", name, line);
1527 CHECKERRLIMIT;
1528 continue;
1529 }
1530 if (words != 2 && !isdigit(*w[1]))
1531 {
1532 if ((newmapid = mapname2id(w[1], &isdrum)) == -1 || isdrum)
1533 {
1534 printMessage(CMSG_ERROR, VERB_NORMAL,
1535 "%s: line %d: Invalid bank map name: %s", name, line, w[1]);
1536 CHECKERRLIMIT;
1537 continue;
1538 }
1539 words--;
1540 memmove(&w[1], &w[2], sizeof w[0] * words);
1541 }
1542 else
1543 newmapid = INST_NO_MAP;
1544 i = atoi(w[1]);
1545 if (i < 0 || i > 127)
1546 {
1547 printMessage(CMSG_ERROR, VERB_NORMAL,
1548 "%s: line %d: Tone bank must be between 0 and 127",
1549 name, line);
1550 CHECKERRLIMIT;
1551 continue;
1552 }
1553
1554 newbankno = i;
1555 i = alloc_instrument_map_bank(0, newmapid, i);
1556 if (i == -1)
1557 {
1558 printMessage(CMSG_ERROR, VERB_NORMAL,
1559 "%s: line %d: No free tone bank available to map",
1560 name, line);
1561 CHECKERRLIMIT;
1562 continue;
1563 }
1564
1565 if (words == 2)
1566 {
1567 bank = tonebank[i];
1568 bankno = i;
1569 mapid = newmapid;
1570 origbankno = newbankno;
1571 dr = 0;
1572 }
1573 else
1574 {
1575 if (words < 4 || *w[2] < '0' || *w[2] > '9')
1576 {
1577 printMessage(CMSG_ERROR, VERB_NORMAL,
1578 "%s: line %d: syntax error", name, line);
1579 CHECKERRLIMIT;
1580 continue;
1581 }
1582 if (set_patchconf(name, line, tonebank[i], &w[2], 0, newmapid, newbankno, i))
1583 {
1584 CHECKERRLIMIT;
1585 continue;
1586 }
1587 }
1588 }
1589 else
1590 {
1591 if (words < 2 || *w[0] < '0' || *w[0] > '9')
1592 {
1593 if (extension_flag)
1594 continue;
1595 printMessage(CMSG_ERROR, VERB_NORMAL,
1596 "%s: line %d: syntax error", name, line);
1597 CHECKERRLIMIT;
1598 continue;
1599 }
1600 if (set_patchconf(name, line, bank, w, dr, mapid, origbankno, bankno))
1601 {
1602 CHECKERRLIMIT;
1603 continue;
1604 }
1605 }
1606 }
1607 reuse_mblock(&varbuf);
1608 tf_close(tf);
1609 return (errcnt == 0) ? READ_CONFIG_SUCCESS : READ_CONFIG_ERROR;
1610 }
1611
1612 }
1613