📄 timidity.c
字号:
opts += 4; } else { tone->font_keynote = -1; opts += 3; } } } else if(strcmp(pat, "%sample") == 0) /* Sample extention */ { /* %sample filename */ if(opts[0] == NULL) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: Syntax error", name, line); return 1; } tone->name = safe_strdup(opts[0]); tone->instype = 2; opts++; } else { tone->instype = 0; tone->name = safe_strdup(pat); } for(j = 0; opts[j] != NULL; j++) { int err; if((err = set_gus_patchconf_opts(name, line, opts[j], tone)) != 0) return err; }#ifdef SET_GUS_PATCHCONF_COMMENT if(tone->comment == NULL || (old_name != NULL && strcmp(old_name,tone->comment) == 0)) { if(tone->comment != NULL ) free(tone->comment); tone->comment = safe_strdup(tone->name); } if(old_name != NULL) free(old_name);#else if(tone->comment == NULL) tone->comment = safe_strdup(tone->name);#endif return 0;}static int set_patchconf(char *name, int line, ToneBank *bank, char *w[], int dr, int mapid, int bankmapfrom, int bankno){ int i; i = atoi(w[0]); if(!dr) i -= progbase; if(i < 0 || i > 127) { if(dr) ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: Drum number must be between " "0 and 127", name, line); else ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: Program must be between " "%d and %d", name, line, progbase, 127 + progbase); return 1; } if(!bank) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: Must specify tone bank or drum set " "before assignment", name, line); return 1; } if(set_gus_patchconf(name, line, &bank->tone[i], w[1], w + 2)) return 1; if (mapid != INST_NO_MAP) set_instrument_map(mapid, bankmapfrom, i, bankno, i); return 0;}typedef struct { const char *name; int mapid, isdrum;} MapNameEntry;static int mapnamecompare(const void *name, const void *entry){ return strcmp((const char *)name, ((const MapNameEntry *)entry)->name);}static int mapname2id(char *name, int *isdrum){ static const MapNameEntry data[] = { /* sorted in alphabetical order */ {"gm2", GM2_TONE_MAP, 0}, {"gm2drum", GM2_DRUM_MAP, 1}, {"sc55", SC_55_TONE_MAP, 0}, {"sc55drum", SC_55_DRUM_MAP, 1}, {"sc88", SC_88_TONE_MAP, 0}, {"sc8850", SC_8850_TONE_MAP, 0}, {"sc8850drum", SC_8850_DRUM_MAP, 1}, {"sc88drum", SC_88_DRUM_MAP, 1}, {"sc88pro", SC_88PRO_TONE_MAP, 0}, {"sc88prodrum", SC_88PRO_DRUM_MAP, 1}, {"xg", XG_NORMAL_MAP, 0}, {"xgdrum", XG_DRUM_MAP, 1}, {"xgsfx126", XG_SFX126_MAP, 1}, {"xgsfx64", XG_SFX64_MAP, 0} }; const MapNameEntry *found; found = (MapNameEntry *)bsearch(name, data, sizeof data / sizeof data[0], sizeof data[0], mapnamecompare); if (found != NULL) { *isdrum = found->isdrum; return found->mapid; } return -1;}/* string[0] should not be '#' */static int strip_trailing_comment(char *string, int next_token_index){ if (string[next_token_index - 1] == '#' /* strip \1 in /^\S+(#*[ \t].*)/ */ && (string[next_token_index] == ' ' || string[next_token_index] == '\t')) { string[next_token_index] = '\0'; /* new c-string terminator */ while(string[--next_token_index - 1] == '#') ; } return next_token_index;}static char *expand_variables(char *string, MBlockList *varbuf, const char *basedir){ char *p, *expstr; const char *copystr; int limlen, copylen, explen, varlen, braced; if ((p = strchr(string, '$')) == NULL) return string; varlen = strlen(basedir); explen = limlen = 0; expstr = NULL; copystr = string; copylen = p - string; string = p; for(;;) { if (explen + copylen + 1 > limlen) { limlen += copylen + 128; expstr = memcpy(new_segment(varbuf, limlen), expstr, explen); } memcpy(&expstr[explen], copystr, copylen); explen += copylen; if (*string == '\0') break; else if (*string == '$') { braced = *++string == '{'; if (braced) { if ((p = strchr(string + 1, '}')) == NULL) p = string; /* no closing brace */ else string++; } else for(p = string; isalnum(*p) || *p == '_'; p++) ; if (p == string) /* empty */ { copystr = "${"; copylen = 1 + braced; } else { if (p - string == 7 && memcmp(string, "basedir", 7) == 0) { copystr = basedir; copylen = varlen; } else /* undefined variable */ copylen = 0; string = p + braced; } } else /* search next */ { p = strchr(string, '$'); if (p == NULL) copylen = strlen(string); else copylen = p - string; copystr = string; string += copylen; } } expstr[explen] = '\0'; return expstr;}#define MAXWORDS 130#define CHECKERRLIMIT \ if(++errcnt >= 10) { \ ctl->cmsg(CMSG_ERROR, VERB_NORMAL, \ "Too many errors... Give up read %s", name); \ reuse_mblock(&varbuf); \ close_file(tf); return 1; }MAIN_INTERFACE int read_config_file(char *name, int self){ struct timidity_file *tf; char buf[1024], *tmp, *w[MAXWORDS + 1], *cp; ToneBank *bank = NULL; int i, j, k, line = 0, words, errcnt = 0; static int rcf_count = 0; int dr = 0, bankno = 0, mapid = INST_NO_MAP, origbankno = 0x7FFFFFFF; int extension_flag, param_parse_err; MBlockList varbuf; char *basedir, *sep; if(rcf_count > 50) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Probable source loop in configuration files"); return 2; } if(self) { tf = open_with_mem(name, (int32)strlen(name), OF_VERBOSE); name = "(configuration)"; } else tf = open_file(name, 1, OF_VERBOSE); if(tf == NULL) return 1; init_mblock(&varbuf); if (!self) { basedir = strdup_mblock(&varbuf, current_filename); if (is_url_prefix(basedir)) sep = strrchr(basedir, '/'); else sep = pathsep_strrchr(basedir); } else sep = NULL; if (sep == NULL) { #ifndef __MACOS__ basedir = "."; #else basedir = ""; #endif } else { if ((cp = strchr(sep, '#')) != NULL) sep = cp + 1; /* inclusive of '#' */ *sep = '\0'; } errno = 0; while(tf_gets(buf, sizeof(buf), tf)) { line++; if(strncmp(buf, "#extension", 10) == 0) { extension_flag = 1; i = 10; } else { extension_flag = 0; i = 0; } while(isspace(buf[i])) /* skip /^\s*(?#)/ */ i++; if (buf[i] == '#' || buf[i] == '\0') /* /^#|^$/ */ continue; tmp = expand_variables(buf, &varbuf, basedir); j = strcspn(tmp + i, " \t\r\n\240"); if (j == 0) j = strlen(tmp + i); j = strip_trailing_comment(tmp + i, j); tmp[i + j] = '\0'; /* terminate the first token */ w[0] = tmp + i; i += j + 1; words = param_parse_err = 0; while(words < MAXWORDS - 1) /* -1 : next arg */ { char *terminator; while(isspace(tmp[i])) /* skip /^\s*(?#)/ */ i++; if (tmp[i] == '\0' || tmp[i] == '#') /* /\s#/ */ break; if ((tmp[i] == '"' || tmp[i] == '\'') && (terminator = strchr(tmp + i + 1, tmp[i])) != NULL) { if (!isspace(terminator[1]) && terminator[1] != '\0') { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: there must be at least one whitespace between " "string terminator (%c) and the next parameter", name, line, tmp[i]); CHECKERRLIMIT; param_parse_err = 1; break; } w[++words] = tmp + i + 1; i = terminator - tmp + 1; *terminator = '\0'; } else /* not terminated */ { j = strcspn(tmp + i, " \t\r\n\240"); if (j > 0) j = strip_trailing_comment(tmp + i, j); w[++words] = tmp + i; i += j; if (tmp[i] != '\0') /* unless at the end-of-string (i.e. EOF) */ tmp[i++] = '\0'; /* terminate the token */ } } if (param_parse_err) continue; w[++words] = NULL; /* * #extension [something...] */ /* #extension comm program comment */ if(strcmp(w[0], "comm") == 0) { char *p; if(words != 3) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line); CHECKERRLIMIT; continue; } if(!bank) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: Must specify tone bank or drum " "set before assignment", name, line); CHECKERRLIMIT; continue; } i = atoi(w[1]); if(i < 0 || i > 127) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: extension comm must be " "between 0 and 127", name, line); CHECKERRLIMIT; continue; } if(bank->tone[i].comment) free(bank->tone[i].comment); p = bank->tone[i].comment = safe_strdup(w[2]); while(*p) { if(*p == ',') *p = ' '; p++; } } /* #extension timeout program sec */ else if(strcmp(w[0], "timeout") == 0) { if(words != 3) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line); CHECKERRLIMIT; continue; } if(!bank) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: Must specify tone bank or drum set " "before assignment", name, line); CHECKERRLIMIT; continue; } i = atoi(w[1]); if(i < 0 || i > 127) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: extension timeout " "must be between 0 and 127", name, line); CHECKERRLIMIT; continue; } bank->tone[i].loop_timeout = atoi(w[2]); } /* #extension copydrumset drumset */ else if(strcmp(w[0], "copydrumset") == 0) { if(words < 2) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: No copydrumset number given", name, line); CHECKERRLIMIT; continue; } i = atoi(w[1]); if(i < 0 || i > 127) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: extension copydrumset " "must be between 0 and 127", name, line); CHECKERRLIMIT; continue; } if(!bank) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: Must specify tone bank or " "drum set before assignment", name, line); CHECKERRLIMIT; continue; } copybank(bank, drumset[i], mapid, origbankno, bankno); } /* #extension copybank bank */ else if(strcmp(w[0], "copybank") == 0) { if(words < 2) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: No copybank number given", name, line); CHECKERRLIMIT; continue; } i = atoi(w[1]); if(i < 0 || i > 127) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: extension copybank " "must be between 0 and 127", name, line); CHECKERRLIMIT; continue; } if(!bank) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: Must specify tone bank or " "drum set before assignment", name, line); CHECKERRLIMIT; continue; } copybank(bank, tonebank[i], mapid, origbankno, bankno); } /* #extension copymap tomapid frommapid */ else if(strcmp(w[0], "copymap") == 0) { int mapto, mapfrom; int toisdrum, fromisdrum; if(words != 3) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line); CHECKERRLIMIT; continue; } if ((mapto = mapname2id(w[1], &toisdrum)) == -1) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -