1 /*
2     TiMidity++ -- MIDI to WAVE converter and player
3     Copyright (C) 1999-2018 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 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif /* HAVE_CONFIG_H */
24 #ifdef __POCC__
25 #include <sys/types.h>
26 #endif //for off_t
27 #include <stdio.h>
28 #ifdef STDC_HEADERS
29 #include <stdlib.h>
30 #include <ctype.h>
31 #include <stddef.h>
32 #endif
33 #ifndef NO_STRING_H
34 #include <string.h>
35 #else
36 #include <strings.h>
37 #endif
38 #ifdef __W32__
39 #include <windows.h>
40 #include <io.h>
41 #include <shlobj.h>
42 #endif
43 #ifdef HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif /* HAVE_UNISTD_H */
46 #if TIME_WITH_SYS_TIME
47 # include <sys/time.h>
48 # include <time.h>
49 #else
50 # if HAVE_SYS_TIME_H
51 #  include <sys/time.h>
52 # else
53 #  include <time.h>
54 # endif
55 #endif  /* TIME_WITH_SYS_TIME */
56 #include <fcntl.h> /* for open */
57 
58 #ifdef BORLANDC_EXCEPTION
59 #include <excpt.h>
60 #endif /* BORLANDC_EXCEPTION */
61 #include <signal.h>
62 
63 #if defined(__FreeBSD__) && !defined(__alpha__)
64 #include <floatingpoint.h> /* For FP exceptions */
65 #endif
66 #if defined(__NetBSD__) || defined(__OpenBSD__)
67 #include <ieeefp.h> /* For FP exceptions */
68 #endif
69 
70 #include "interface.h"
71 #include "timidity.h"
72 #include "tmdy_getopt.h"
73 #include "common.h"
74 #include "instrum.h"
75 #include "playmidi.h"
76 #include "readmidi.h"
77 #include "output.h"
78 #include "controls.h"
79 #include "tables.h"
80 #include "miditrace.h"
81 #include "reverb.h"
82 #ifdef SUPPORT_SOUNDSPEC
83 #include "soundspec.h"
84 #endif /* SUPPORT_SOUNDSPEC */
85 #include "resample.h"
86 #include "recache.h"
87 #include "arc.h"
88 #include "strtab.h"
89 #include "wrd.h"
90 #define DEFINE_GLOBALS
91 #include "mid.defs"
92 #include "aq.h"
93 #include "mix.h"
94 #include "unimod.h"
95 #include "quantity.h"
96 #include "rtsyn.h"
97 
98 #ifdef __BORLANDC__
99 #undef inline
100 #define inline
101 #endif
102 
103 #ifdef IA_W32GUI
104 #include "w32g.h"
105 #include "w32g_utl.h"
106 #endif
107 
108 #ifdef WINDRV
109 /* supress std outputs */
110 #define fputs(a, b)
111 #endif
112 
113 #ifndef __GNUC__
114 #define __attribute__(x) /* ignore */
115 #endif
116 
117 /* option enums */
118 enum {
119 	TIM_OPT_FIRST = 256,
120 	/* first entry */
121 	TIM_OPT_VOLUME = TIM_OPT_FIRST,
122 	TIM_OPT_DRUM_POWER,
123 	TIM_OPT_VOLUME_COMP,
124 	TIM_OPT_ANTI_ALIAS,
125 	TIM_OPT_BUFFER_FRAGS,
126 	TIM_OPT_CONTROL_RATIO,
127 	TIM_OPT_CONFIG_FILE,
128 	TIM_OPT_DRUM_CHANNEL,
129 	TIM_OPT_IFACE_PATH,
130 	TIM_OPT_EXT,
131 	TIM_OPT_MOD_WHEEL,
132 	TIM_OPT_PORTAMENTO,
133 	TIM_OPT_VIBRATO,
134 	TIM_OPT_CH_PRESS,
135 	TIM_OPT_MOD_ENV,
136 	TIM_OPT_TRACE_TEXT,
137 	TIM_OPT_OVERLAP,
138 	TIM_OPT_TEMPER_CTRL,
139 	TIM_OPT_DEFAULT_MID,
140 	TIM_OPT_SYSTEM_MID,
141 	TIM_OPT_DEFAULT_BANK,
142 	TIM_OPT_FORCE_BANK,
143 	TIM_OPT_DEFAULT_PGM,
144 	TIM_OPT_FORCE_PGM,
145 	TIM_OPT_DELAY,
146 	TIM_OPT_CHORUS,
147 	TIM_OPT_REVERB,
148 	TIM_OPT_VOICE_LPF,
149 	TIM_OPT_NS,
150 	TIM_OPT_RESAMPLE,
151 	TIM_OPT_EVIL,
152 	TIM_OPT_FAST_PAN,
153 	TIM_OPT_FAST_DECAY,
154 	TIM_OPT_SEGMENT,
155 	TIM_OPT_SPECTROGRAM,
156 	TIM_OPT_KEYSIG,
157 	TIM_OPT_HELP,
158 	TIM_OPT_INTERFACE,
159 	TIM_OPT_VERBOSE,
160 	TIM_OPT_QUIET,
161 	TIM_OPT_TRACE,
162 	TIM_OPT_LOOP,
163 	TIM_OPT_RANDOM,
164 	TIM_OPT_SORT,
165 	TIM_OPT_BACKGROUND,
166 	TIM_OPT_RT_PRIO,
167 	TIM_OPT_SEQ_PORTS,
168 	TIM_OPT_RTSYN_LATENCY,
169 	TIM_OPT_REALTIME_LOAD,
170 	TIM_OPT_ADJUST_KEY,
171 	TIM_OPT_VOICE_QUEUE,
172 	TIM_OPT_PATCH_PATH,
173 	TIM_OPT_PCM_FILE,
174 	TIM_OPT_DECAY_TIME,
175 	TIM_OPT_INTERPOLATION,
176 	TIM_OPT_OUTPUT_MODE,
177 	TIM_OPT_OUTPUT_STEREO,
178 	TIM_OPT_OUTPUT_SIGNED,
179 	TIM_OPT_OUTPUT_BITWIDTH,
180 	TIM_OPT_OUTPUT_FORMAT,
181 	TIM_OPT_OUTPUT_SWAB,
182 	TIM_OPT_FLAC_VERIFY,
183 	TIM_OPT_FLAC_PADDING,
184 	TIM_OPT_FLAC_COMPLEVEL,
185 	TIM_OPT_FLAC_OGGFLAC,
186 	TIM_OPT_SPEEX_QUALITY,
187 	TIM_OPT_SPEEX_VBR,
188 	TIM_OPT_SPEEX_ABR,
189 	TIM_OPT_SPEEX_VAD,
190 	TIM_OPT_SPEEX_DTX,
191 	TIM_OPT_SPEEX_COMPLEXITY,
192 	TIM_OPT_SPEEX_NFRAMES,
193 	TIM_OPT_OUTPUT_FILE,
194 	TIM_OPT_PATCH_FILE,
195 	TIM_OPT_POLYPHONY,
196 	TIM_OPT_POLY_REDUCE,
197 	TIM_OPT_MUTE,
198 	TIM_OPT_TEMPER_MUTE,
199 	TIM_OPT_PRESERVE_SILENCE,
200 	TIM_OPT_AUDIO_BUFFER,
201 	TIM_OPT_CACHE_SIZE,
202 	TIM_OPT_SAMPLE_FREQ,
203 	TIM_OPT_ADJUST_TEMPO,
204 	TIM_OPT_CHARSET,
205 	TIM_OPT_UNLOAD_INST,
206 	TIM_OPT_VOLUME_CURVE,
207 	TIM_OPT_VERSION,
208 	TIM_OPT_WRD,
209 	TIM_OPT_RCPCV_DLL,
210 	TIM_OPT_CONFIG_STR,
211 	TIM_OPT_FREQ_TABLE,
212 	TIM_OPT_PURE_INT,
213 	TIM_OPT_MODULE,
214 	/* last entry */
215 	TIM_OPT_LAST = TIM_OPT_MODULE
216 };
217 
218 #ifdef IA_WINSYN
219 const char *optcommands =
220 #else
221 static const char *optcommands =
222 #endif
223 		"4A:aB:b:C:c:D:d:E:eFfG:g:H:hI:i:jK:k:L:M:m:N:"
224 		"O:o:P:p:Q:q:R:S:s:T:t:UV:vW:"
225 #ifdef __W32__
226 		"w:"
227 #endif
228 		"x:Z:";		/* Only JlnruXYyz are remain... */
229 #ifdef IA_WINSYN
230 const struct option longopts[] = {
231 #else
232 static const struct option longopts[] = {
233 #endif
234 	{ "volume",                 required_argument, NULL, TIM_OPT_VOLUME },
235 	{ "drum-power",             required_argument, NULL, TIM_OPT_DRUM_POWER },
236 	{ "no-volume-compensation", no_argument,       NULL, TIM_OPT_DRUM_POWER },
237 	{ "volume-compensation",    optional_argument, NULL, TIM_OPT_VOLUME_COMP },
238 	{ "no-anti-alias",          no_argument,       NULL, TIM_OPT_ANTI_ALIAS },
239 	{ "anti-alias",             optional_argument, NULL, TIM_OPT_ANTI_ALIAS },
240 	{ "buffer-fragments",       required_argument, NULL, TIM_OPT_BUFFER_FRAGS },
241 	{ "control-ratio",          required_argument, NULL, TIM_OPT_CONTROL_RATIO },
242 	{ "config-file",            required_argument, NULL, TIM_OPT_CONFIG_FILE },
243 	{ "drum-channel",           required_argument, NULL, TIM_OPT_DRUM_CHANNEL },
244 	{ "interface-path",         required_argument, NULL, TIM_OPT_IFACE_PATH },
245 	{ "ext",                    required_argument, NULL, TIM_OPT_EXT },
246 	{ "no-mod-wheel",           no_argument,       NULL, TIM_OPT_MOD_WHEEL },
247 	{ "mod-wheel",              optional_argument, NULL, TIM_OPT_MOD_WHEEL },
248 	{ "no-portamento",          no_argument,       NULL, TIM_OPT_PORTAMENTO },
249 	{ "portamento",             optional_argument, NULL, TIM_OPT_PORTAMENTO },
250 	{ "no-vibrato",             no_argument,       NULL, TIM_OPT_VIBRATO },
251 	{ "vibrato",                optional_argument, NULL, TIM_OPT_VIBRATO },
252 	{ "no-ch-pressure",         no_argument,       NULL, TIM_OPT_CH_PRESS },
253 	{ "ch-pressure",            optional_argument, NULL, TIM_OPT_CH_PRESS },
254 	{ "no-mod-envelope",        no_argument,       NULL, TIM_OPT_MOD_ENV },
255 	{ "mod-envelope",           optional_argument, NULL, TIM_OPT_MOD_ENV },
256 	{ "no-trace-text-meta",     no_argument,       NULL, TIM_OPT_TRACE_TEXT },
257 	{ "trace-text-meta",        optional_argument, NULL, TIM_OPT_TRACE_TEXT },
258 	{ "no-overlap-voice",       no_argument,       NULL, TIM_OPT_OVERLAP },
259 	{ "overlap-voice",          optional_argument, NULL, TIM_OPT_OVERLAP },
260 	{ "no-temper-control",      no_argument,       NULL, TIM_OPT_TEMPER_CTRL },
261 	{ "temper-control",         optional_argument, NULL, TIM_OPT_TEMPER_CTRL },
262 	{ "default-mid",            required_argument, NULL, TIM_OPT_DEFAULT_MID },
263 	{ "system-mid",             required_argument, NULL, TIM_OPT_SYSTEM_MID },
264 	{ "default-bank",           required_argument, NULL, TIM_OPT_DEFAULT_BANK },
265 	{ "force-bank",             required_argument, NULL, TIM_OPT_FORCE_BANK },
266 	{ "default-program",        required_argument, NULL, TIM_OPT_DEFAULT_PGM },
267 	{ "force-program",          required_argument, NULL, TIM_OPT_FORCE_PGM },
268 	{ "delay",                  required_argument, NULL, TIM_OPT_DELAY },
269 	{ "chorus",                 required_argument, NULL, TIM_OPT_CHORUS },
270 	{ "reverb",                 required_argument, NULL, TIM_OPT_REVERB },
271 	{ "voice-lpf",              required_argument, NULL, TIM_OPT_VOICE_LPF },
272 	{ "noise-shaping",          required_argument, NULL, TIM_OPT_NS },
273 #ifndef FIXED_RESAMPLATION
274 	{ "resample",               required_argument, NULL, TIM_OPT_RESAMPLE },
275 #endif
276 	{ "evil",                   required_argument, NULL, TIM_OPT_EVIL },
277 	{ "no-fast-panning",        no_argument,       NULL, TIM_OPT_FAST_PAN },
278 	{ "fast-panning",           optional_argument, NULL, TIM_OPT_FAST_PAN },
279 	{ "no-fast-decay",          no_argument,       NULL, TIM_OPT_FAST_DECAY },
280 	{ "fast-decay",             optional_argument, NULL, TIM_OPT_FAST_DECAY },
281 	{ "segment",                required_argument, NULL, TIM_OPT_SEGMENT },
282 	{ "spectrogram",            required_argument, NULL, TIM_OPT_SPECTROGRAM },
283 	{ "force-keysig",           required_argument, NULL, TIM_OPT_KEYSIG },
284 	{ "help",                   optional_argument, NULL, TIM_OPT_HELP },
285 	{ "interface",              required_argument, NULL, TIM_OPT_INTERFACE },
286 	{ "verbose",                optional_argument, NULL, TIM_OPT_VERBOSE },
287 	{ "quiet",                  optional_argument, NULL, TIM_OPT_QUIET },
288 	{ "no-trace",               no_argument,       NULL, TIM_OPT_TRACE },
289 	{ "trace",                  optional_argument, NULL, TIM_OPT_TRACE },
290 	{ "no-loop",                no_argument,       NULL, TIM_OPT_LOOP },
291 	{ "loop",                   optional_argument, NULL, TIM_OPT_LOOP },
292 	{ "no-random",              no_argument,       NULL, TIM_OPT_RANDOM },
293 	{ "random",                 optional_argument, NULL, TIM_OPT_RANDOM },
294 	{ "no-sort",                no_argument,       NULL, TIM_OPT_SORT },
295 	{ "sort",                   optional_argument, NULL, TIM_OPT_SORT },
296 #ifdef IA_ALSASEQ
297 	{ "no-background",          no_argument,       NULL, TIM_OPT_BACKGROUND },
298 	{ "background",             optional_argument, NULL, TIM_OPT_BACKGROUND },
299 	{ "realtime-priority",      required_argument, NULL, TIM_OPT_RT_PRIO },
300 	{ "sequencer-ports",        required_argument, NULL, TIM_OPT_SEQ_PORTS },
301 #endif
302 #if defined(IA_WINSYN) || defined(IA_PORTMIDISYN) || defined(IA_NPSYN) || defined(IA_W32G_SYN) || defined(IA_W32GUI)
303 	{ "rtsyn-latency",          required_argument, NULL, TIM_OPT_RTSYN_LATENCY },
304 #endif
305 	{ "no-realtime-load",       no_argument,       NULL, TIM_OPT_REALTIME_LOAD },
306 	{ "realtime-load",          optional_argument, NULL, TIM_OPT_REALTIME_LOAD },
307 	{ "adjust-key",             required_argument, NULL, TIM_OPT_ADJUST_KEY },
308 	{ "voice-queue",            required_argument, NULL, TIM_OPT_VOICE_QUEUE },
309 	{ "patch-path",             required_argument, NULL, TIM_OPT_PATCH_PATH },
310 	{ "pcm-file",               required_argument, NULL, TIM_OPT_PCM_FILE },
311 	{ "decay-time",             required_argument, NULL, TIM_OPT_DECAY_TIME },
312 	{ "interpolation",          required_argument, NULL, TIM_OPT_INTERPOLATION },
313 	{ "output-mode",            required_argument, NULL, TIM_OPT_OUTPUT_MODE },
314 	{ "output-stereo",          no_argument,       NULL, TIM_OPT_OUTPUT_STEREO },
315 	{ "output-mono",            no_argument,       NULL, TIM_OPT_OUTPUT_STEREO },
316 	{ "output-signed",          no_argument,       NULL, TIM_OPT_OUTPUT_SIGNED },
317 	{ "output-unsigned",        no_argument,       NULL, TIM_OPT_OUTPUT_SIGNED },
318 	{ "output-16bit",           no_argument,       NULL, TIM_OPT_OUTPUT_BITWIDTH },
319 	{ "output-24bit",           no_argument,       NULL, TIM_OPT_OUTPUT_BITWIDTH },
320 	{ "output-8bit",            no_argument,       NULL, TIM_OPT_OUTPUT_BITWIDTH },
321 	{ "output-linear",          no_argument,       NULL, TIM_OPT_OUTPUT_FORMAT },
322 	{ "output-ulaw",            no_argument,       NULL, TIM_OPT_OUTPUT_FORMAT },
323 	{ "output-alaw",            no_argument,       NULL, TIM_OPT_OUTPUT_FORMAT },
324 	{ "no-output-swab",         no_argument,       NULL, TIM_OPT_OUTPUT_SWAB },
325 	{ "output-swab",            optional_argument, NULL, TIM_OPT_OUTPUT_SWAB },
326 #ifdef AU_FLAC
327 	{ "flac-verify",            no_argument,       NULL, TIM_OPT_FLAC_VERIFY },
328 	{ "flac-padding",           required_argument, NULL, TIM_OPT_FLAC_PADDING },
329 	{ "flac-complevel",         required_argument, NULL, TIM_OPT_FLAC_COMPLEVEL },
330 #ifdef AU_OGGFLAC
331 	{ "oggflac",                no_argument,       NULL, TIM_OPT_FLAC_OGGFLAC },
332 #endif /* AU_OGGFLAC */
333 #endif /* AU_FLAC */
334 #ifdef AU_SPEEX
335 	{ "speex-quality",          required_argument, NULL, TIM_OPT_SPEEX_QUALITY },
336 	{ "speex-vbr",              no_argument,       NULL, TIM_OPT_SPEEX_VBR },
337 	{ "speex-abr",              required_argument, NULL, TIM_OPT_SPEEX_ABR },
338 	{ "speex-vad",              no_argument,       NULL, TIM_OPT_SPEEX_VAD },
339 	{ "speex-dtx",              no_argument,       NULL, TIM_OPT_SPEEX_DTX },
340 	{ "speex-complexity",       required_argument, NULL, TIM_OPT_SPEEX_COMPLEXITY },
341 	{ "speex-nframes",          required_argument, NULL, TIM_OPT_SPEEX_NFRAMES },
342 #endif /* AU_SPEEX */
343 	{ "output-file",            required_argument, NULL, TIM_OPT_OUTPUT_FILE },
344 	{ "patch-file",             required_argument, NULL, TIM_OPT_PATCH_FILE },
345 	{ "polyphony",              required_argument, NULL, TIM_OPT_POLYPHONY },
346 	{ "no-polyphony-reduction", no_argument,       NULL, TIM_OPT_POLY_REDUCE },
347 	{ "polyphony-reduction",    optional_argument, NULL, TIM_OPT_POLY_REDUCE },
348 	{ "mute",                   required_argument, NULL, TIM_OPT_MUTE },
349 	{ "temper-mute",            required_argument, NULL, TIM_OPT_TEMPER_MUTE },
350 	{ "preserve-silence",       no_argument,       NULL, TIM_OPT_PRESERVE_SILENCE },
351 	{ "audio-buffer",           required_argument, NULL, TIM_OPT_AUDIO_BUFFER },
352 	{ "cache-size",             required_argument, NULL, TIM_OPT_CACHE_SIZE },
353 	{ "sampling-freq",          required_argument, NULL, TIM_OPT_SAMPLE_FREQ },
354 	{ "adjust-tempo",           required_argument, NULL, TIM_OPT_ADJUST_TEMPO },
355 	{ "output-charset",         required_argument, NULL, TIM_OPT_CHARSET },
356 	{ "no-unload-instruments",  no_argument,       NULL, TIM_OPT_UNLOAD_INST },
357 	{ "unload-instruments",     optional_argument, NULL, TIM_OPT_UNLOAD_INST },
358 	{ "volume-curve",           required_argument, NULL, TIM_OPT_VOLUME_CURVE },
359 	{ "version",                no_argument,       NULL, TIM_OPT_VERSION },
360 	{ "wrd",                    required_argument, NULL, TIM_OPT_WRD },
361 #ifdef __W32__
362 	{ "rcpcv-dll",              required_argument, NULL, TIM_OPT_RCPCV_DLL },
363 #endif
364 	{ "config-string",          required_argument, NULL, TIM_OPT_CONFIG_STR },
365 	{ "freq-table",             required_argument, NULL, TIM_OPT_FREQ_TABLE },
366 	{ "pure-intonation",        optional_argument, NULL, TIM_OPT_PURE_INT },
367 	{ "module",                 required_argument, NULL, TIM_OPT_MODULE },
368 	{ NULL,                     no_argument,       NULL, '\0'     }
369 };
370 #define INTERACTIVE_INTERFACE_IDS "kmqagrwAWNP"
371 
372 /* main interfaces (To be used another main) */
373 #if defined(main) || defined(ANOTHER_MAIN) || defined ( IA_W32GUI ) || defined ( IA_W32G_SYN )
374 #define MAIN_INTERFACE
375 #else
376 #define MAIN_INTERFACE static
377 #endif /* main */
378 
379 MAIN_INTERFACE void timidity_start_initialize(void);
380 MAIN_INTERFACE int timidity_pre_load_configuration(void);
381 MAIN_INTERFACE int timidity_post_load_configuration(void);
382 MAIN_INTERFACE void timidity_init_player(void);
383 MAIN_INTERFACE int timidity_play_main(int nfiles, char **files);
384 MAIN_INTERFACE int got_a_configuration;
385 char *wrdt_open_opts = NULL;
386 char *opt_aq_max_buff = NULL,
387      *opt_aq_fill_buff = NULL;
388 int opt_aq_fill_buff_free_needed = 1;
389 void timidity_init_aq_buff(void);
390 int opt_control_ratio = 0; /* Save -C option */
391 #ifdef AU_PORTAUDIO
392 extern int opt_pa_device_id;
393 #endif
394 #ifdef AU_W32
395 extern int opt_wmme_device_id;
396 #endif
397 
398 int set_extension_modes(char *);
399 int set_ctl(char *);
400 int set_play_mode(char *);
401 int set_wrd(char *);
402 MAIN_INTERFACE int set_tim_opt_short(int, char *);
403 MAIN_INTERFACE int set_tim_opt_long(int, char *, int);
404 static inline int parse_opt_A(const char *);
405 static inline int parse_opt_drum_power(const char *);
406 static inline int parse_opt_volume_comp(const char *);
407 static inline int parse_opt_a(const char *);
408 static inline int parse_opt_B(const char *);
409 static inline int parse_opt_C(const char *);
410 static inline int parse_opt_c(char *);
411 static inline int parse_opt_D(const char *);
412 static inline int parse_opt_d(const char *);
413 static inline int parse_opt_E(char *);
414 static inline int parse_opt_mod_wheel(const char *);
415 static inline int parse_opt_portamento(const char *);
416 static inline int parse_opt_vibrato(const char *);
417 static inline int parse_opt_ch_pressure(const char *);
418 static inline int parse_opt_mod_env(const char *);
419 static inline int parse_opt_trace_text(const char *);
420 static inline int parse_opt_overlap_voice(const char *);
421 static inline int parse_opt_temper_control(const char *);
422 static inline int parse_opt_default_mid(char *);
423 static inline int parse_opt_system_mid(char *);
424 static inline int parse_opt_default_bank(const char *);
425 static inline int parse_opt_force_bank(const char *);
426 static inline int parse_opt_default_program(const char *);
427 static inline int parse_opt_force_program(const char *);
428 static inline int set_default_program(int);
429 static inline int parse_opt_delay(const char *);
430 static inline int parse_opt_chorus(const char *);
431 static inline int parse_opt_reverb(const char *);
432 static int parse_opt_reverb_freeverb(const char *arg, char type);
433 static inline int parse_opt_voice_lpf(const char *);
434 static inline int parse_opt_noise_shaping(const char *);
435 static inline int parse_opt_resample(const char *);
436 static inline int parse_opt_e(const char *);
437 static inline int parse_opt_F(const char *);
438 static inline int parse_opt_f(const char *);
439 static inline int parse_opt_G(const char *);
440 static inline int parse_opt_G1(const char *);
441 static int parse_segment(TimeSegment *, const char *);
442 static int parse_segment2(TimeSegment *, const char *);
443 static int parse_time(FLOAT_T *, const char *);
444 static int parse_time2(Measure *, const char *);
445 static inline int parse_opt_g(const char *);
446 static inline int parse_opt_H(const char *);
447 __attribute__((noreturn))
448 static inline int parse_opt_h(const char *);
449 #ifdef IA_DYNAMIC
450 static inline void list_dyna_interface(FILE *, char *, char *);
451 ControlMode *dynamic_interface_module(int);
452 #endif
453 static inline int parse_opt_i(const char *);
454 static inline int parse_opt_verbose(const char *);
455 static inline int parse_opt_quiet(const char *);
456 static inline int parse_opt_trace(const char *);
457 static inline int parse_opt_loop(const char *);
458 static inline int parse_opt_random(const char *);
459 static inline int parse_opt_sort(const char *);
460 #ifdef IA_ALSASEQ
461 static inline int parse_opt_background(const char *);
462 static inline int parse_opt_rt_prio(const char *);
463 static inline int parse_opt_seq_ports(const char *);
464 #endif
465 #if defined(IA_WINSYN) || defined(IA_PORTMIDISYN) || defined(IA_NPSYN) || defined(IA_W32G_SYN) || defined(IA_W32GUI)
466 static inline int parse_opt_rtsyn_latency(const char *);
467 #endif
468 static inline int parse_opt_j(const char *);
469 static inline int parse_opt_K(const char *);
470 static inline int parse_opt_k(const char *);
471 static inline int parse_opt_L(char *);
472 static inline int parse_opt_M(const char *);
473 static inline int parse_opt_m(const char *);
474 static inline int parse_opt_N(const char *);
475 static inline int parse_opt_O(const char *);
476 static inline int parse_opt_output_stereo(const char *);
477 static inline int parse_opt_output_signed(const char *);
478 static inline int parse_opt_output_bitwidth(const char *);
479 static inline int parse_opt_output_format(const char *);
480 static inline int parse_opt_output_swab(const char *);
481 #if defined(AU_PORTAUDIO) || defined(AU_W32)
482 static inline int parse_opt_output_device(const char *);
483 #endif
484 #ifdef AU_FLAC
485 static inline int parse_opt_flac_verify(const char *);
486 static inline int parse_opt_flac_padding(const char *);
487 static inline int parse_opt_flac_complevel(const char *);
488 #ifdef AU_OGGFLAC
489 static inline int parse_opt_flac_oggflac(const char *);
490 #endif /* AU_OGGFLAC */
491 #endif /* AU_FLAC */
492 #ifdef AU_SPEEX
493 static inline int parse_opt_speex_quality(const char *);
494 static inline int parse_opt_speex_vbr(const char *);
495 static inline int parse_opt_speex_abr(const char *);
496 static inline int parse_opt_speex_vad(const char *);
497 static inline int parse_opt_speex_dtx(const char *);
498 static inline int parse_opt_speex_complexity(const char *);
499 static inline int parse_opt_speex_nframes(const char *);
500 #endif /* AU_SPEEX */
501 static inline int parse_opt_o(char *);
502 static inline int parse_opt_P(const char *);
503 static inline int parse_opt_p(const char *);
504 static inline int parse_opt_p1(const char *);
505 static inline int parse_opt_Q(const char *);
506 static inline int parse_opt_Q1(const char *);
507 static inline int parse_opt_preserve_silence(const char *);
508 static inline int parse_opt_q(const char *);
509 static inline int parse_opt_R(const char *);
510 static inline int parse_opt_S(const char *);
511 static inline int parse_opt_s(const char *);
512 static inline int parse_opt_T(const char *);
513 static inline int parse_opt_t(const char *);
514 static inline int parse_opt_U(const char *);
515 static inline int parse_opt_volume_curve(char *);
516 __attribute__((noreturn))
517 static inline int parse_opt_v(const char *);
518 static inline int parse_opt_W(char *);
519 #ifdef __W32__
520 static inline int parse_opt_w(const char *);
521 #endif
522 static inline int parse_opt_x(char *);
523 static inline void expand_escape_string(char *);
524 static inline int parse_opt_Z(char *);
525 static inline int parse_opt_Z1(const char *);
526 static inline int parse_opt_default_module(const char *);
527 __attribute__((noreturn))
528 static inline int parse_opt_fail(const char *);
529 static inline int set_value(int *, int, int, int, char *);
530 static inline int set_val_i32(int32 *, int32, int32, int32, char *);
531 static int parse_val_float_t(FLOAT_T *, const char *, FLOAT_T, FLOAT_T,
532 		const char *, int);
533 static inline int set_val_float_t(FLOAT_T *, FLOAT_T, FLOAT_T, FLOAT_T,
534 		const char *, int);
535 static inline int set_channel_flag(ChannelBitMask *, int32, char *);
536 static inline int y_or_n_p(const char *);
537 static inline int set_flag(int32 *, int32, const char *);
538 static inline FILE *open_pager(void);
539 static inline void close_pager(FILE *);
540 static void interesting_message(void);
541 
542 extern StringTable wrd_read_opts;
543 
544 extern int SecondMode;
545 
546 extern struct URL_module URL_module_file;
547 #ifndef __MACOS__
548 extern struct URL_module URL_module_dir;
549 #endif /* __MACOS__ */
550 #ifdef SUPPORT_SOCKET
551 extern struct URL_module URL_module_http;
552 extern struct URL_module URL_module_ftp;
553 extern struct URL_module URL_module_news;
554 extern struct URL_module URL_module_newsgroup;
555 #endif /* SUPPORT_SOCKET */
556 #ifdef HAVE_POPEN
557 extern struct URL_module URL_module_pipe;
558 #endif /* HAVE_POPEN */
559 
560 MAIN_INTERFACE struct URL_module *url_module_list[] =
561 {
562     &URL_module_file,
563 #ifndef __MACOS__
564     &URL_module_dir,
565 #endif /* __MACOS__ */
566 #ifdef SUPPORT_SOCKET
567     &URL_module_http,
568     &URL_module_ftp,
569     &URL_module_news,
570     &URL_module_newsgroup,
571 #endif /* SUPPORT_SOCKET */
572 #if !defined(__MACOS__) && defined(HAVE_POPEN)
573     &URL_module_pipe,
574 #endif
575 #if defined(main) || defined(ANOTHER_MAIN)
576     /* You can put some other modules */
577     NULL,
578     NULL,
579     NULL,
580     NULL,
581     NULL,
582     NULL,
583     NULL,
584     NULL,
585 #endif /* main */
586     NULL
587 };
588 
589 #ifdef IA_DYNAMIC
590 #include "dlutils.h"
591 #ifndef SHARED_LIB_PATH
592 #define SHARED_LIB_PATH PKGLIBDIR
593 #endif /* SHARED_LIB_PATH */
594 static char *dynamic_lib_root = NULL;
595 #endif /* IA_DYNAMIC */
596 
597 #ifndef MAXPATHLEN
598 #define MAXPATHLEN 1024
599 #endif /* MAXPATHLEN */
600 
601 int free_instruments_afterwards=0;
602 int def_prog = -1;
603 char def_instr_name[256]="";
604 VOLATILE int intr = 0;
605 
606 #ifdef __W32__
607 CRITICAL_SECTION critSect;
608 
609 #pragma argsused
handler(DWORD dw)610 static BOOL WINAPI handler(DWORD dw)
611 {
612 #if defined(IA_WINSYN) || defined(IA_PORTMIDISYN)
613 	if (ctl->id_character == 'W' || ctl->id_character == 'P')
614 		rtsyn_midiports_close();
615 #endif
616 #if 0
617 #if defined(IA_NPSYN)
618 	if (ctl->id_character == 'N')
619 		return FALSE;	/* why FALSE need?  It must close by intr++; */
620 #endif
621 #endif
622 	printf ("***BREAK" NLS);
623 	fflush(stdout);
624 	intr++;
625 	return TRUE;
626 }
627 #endif
628 
629 int effect_lr_mode = -1;
630 /* 0: left delay
631  * 1: right delay
632  * 2: rotate
633  * -1: not use
634  */
635 int effect_lr_delay_msec = 25;
636 
637 extern char* pcm_alternate_file;
638 /* NULL, "none": disabled (default)
639  * "auto":       automatically selected
640  * filename:     use the one.
641  */
642 
643 #ifndef atof
644 extern double atof(const char *);
645 #endif
646 
647 /*! copy bank and, if necessary, map appropriately */
copybank(ToneBank * to,ToneBank * from,int mapid,int bankmapfrom,int bankno)648 static void copybank(ToneBank *to, ToneBank *from, int mapid, int bankmapfrom, int bankno)
649 {
650 	ToneBankElement *toelm, *fromelm;
651 	int i;
652 
653 	if (from == NULL)
654 		return;
655 	for(i = 0; i < 128; i++)
656 	{
657 		toelm = &to->tone[i];
658 		fromelm = &from->tone[i];
659 		if (fromelm->name == NULL)
660 		    continue;
661 		copy_tone_bank_element(toelm, fromelm);
662 		toelm->instrument = NULL;
663 		if (mapid != INST_NO_MAP)
664 		    set_instrument_map(mapid, bankmapfrom, i, bankno, i);
665 	}
666 }
667 
668 /*! copy the whole mapped bank. returns 0 if no error. */
copymap(int mapto,int mapfrom,int isdrum)669 static int copymap(int mapto, int mapfrom, int isdrum)
670 {
671 	ToneBank **tb = isdrum ? drumset : tonebank;
672 	int i, bankfrom, bankto;
673 
674 	for(i = 0; i < 128; i++)
675 	{
676 		bankfrom = find_instrument_map_bank(isdrum, mapfrom, i);
677 		if (bankfrom <= 0) /* not mapped */
678 			continue;
679 		bankto = alloc_instrument_map_bank(isdrum, mapto, i);
680 		if (bankto == -1) /* failed */
681 			return 1;
682 		copybank(tb[bankto], tb[bankfrom], mapto, i, bankto);
683 	}
684 	return 0;
685 }
686 
config_parse_tune(const char * cp,int * num)687 static float *config_parse_tune(const char *cp, int *num)
688 {
689 	const char *p;
690 	float *tune_list;
691 	int i;
692 
693 	/* count num */
694 	*num = 1, p = cp;
695 	while ((p = strchr(p, ',')) != NULL)
696 		(*num)++, p++;
697 	/* alloc */
698 	tune_list = (float *) safe_malloc((*num) * sizeof(float));
699 	/* regist */
700 	for (i = 0, p = cp; i < *num; i++, p++) {
701 		tune_list[i] = atof(p);
702 		if (! (p = strchr(p, ',')))
703 			break;
704 	}
705 	return tune_list;
706 }
707 
config_parse_int16(const char * cp,int * num)708 static int16 *config_parse_int16(const char *cp, int *num)
709 {
710 	const char *p;
711 	int16 *list;
712 	int i;
713 
714 	/* count num */
715 	*num = 1, p = cp;
716 	while ((p = strchr(p, ',')) != NULL)
717 		(*num)++, p++;
718 	/* alloc */
719 	list = (int16 *) safe_malloc((*num) * sizeof(int16));
720 	/* regist */
721 	for (i = 0, p = cp; i < *num; i++, p++) {
722 		list[i] = atoi(p);
723 		if (! (p = strchr(p, ',')))
724 			break;
725 	}
726 	return list;
727 }
728 
config_parse_envelope(const char * cp,int * num)729 static int **config_parse_envelope(const char *cp, int *num)
730 {
731 	const char *p, *px;
732 	int **env_list;
733 	int i, j;
734 
735 	/* count num */
736 	*num = 1, p = cp;
737 	while ((p = strchr(p, ',')) != NULL)
738 		(*num)++, p++;
739 	/* alloc */
740 	env_list = (int **) safe_malloc((*num) * sizeof(int *));
741 	for (i = 0; i < *num; i++)
742 		env_list[i] = (int *) safe_malloc(6 * sizeof(int));
743 	/* init */
744 	for (i = 0; i < *num; i++)
745 		for (j = 0; j < 6; j++)
746 			env_list[i][j] = -1;
747 	/* regist */
748 	for (i = 0, p = cp; i < *num; i++, p++) {
749 		px = strchr(p, ',');
750 		for (j = 0; j < 6; j++, p++) {
751 			if (*p == ':')
752 				continue;
753 			env_list[i][j] = atoi(p);
754 			if (! (p = strchr(p, ':')))
755 				break;
756 			if (px && p > px)
757 				break;
758 		}
759 		if (! (p = px))
760 			break;
761 	}
762 	return env_list;
763 }
764 
config_parse_modulation(const char * name,int line,const char * cp,int * num,int mod_type)765 static Quantity **config_parse_modulation(const char *name, int line, const char *cp, int *num, int mod_type)
766 {
767 	const char *p, *px, *err;
768 	char buf[128], *delim;
769 	Quantity **mod_list;
770 	int i, j;
771 	static const char * qtypestr[] = {"tremolo", "vibrato"};
772 	static const uint16 qtypes[] = {
773 		QUANTITY_UNIT_TYPE(TREMOLO_SWEEP), QUANTITY_UNIT_TYPE(TREMOLO_RATE), QUANTITY_UNIT_TYPE(DIRECT_INT),
774 		QUANTITY_UNIT_TYPE(VIBRATO_SWEEP), QUANTITY_UNIT_TYPE(VIBRATO_RATE), QUANTITY_UNIT_TYPE(DIRECT_INT)
775 	};
776 
777 	/* count num */
778 	*num = 1, p = cp;
779 	while ((p = strchr(p, ',')) != NULL)
780 		(*num)++, p++;
781 	/* alloc */
782 	mod_list = (Quantity **) safe_malloc((*num) * sizeof(Quantity *));
783 	for (i = 0; i < *num; i++)
784 		mod_list[i] = (Quantity *) safe_malloc(3 * sizeof(Quantity));
785 	/* init */
786 	for (i = 0; i < *num; i++)
787 		for (j = 0; j < 3; j++)
788 			INIT_QUANTITY(mod_list[i][j]);
789 	buf[sizeof buf - 1] = '\0';
790 	/* regist */
791 	for (i = 0, p = cp; i < *num; i++, p++) {
792 		px = strchr(p, ',');
793 		for (j = 0; j < 3; j++, p++) {
794 			if (*p == ':')
795 				continue;
796 			if ((delim = strpbrk(strncpy(buf, p, sizeof buf - 1), ":,")) != NULL)
797 				*delim = '\0';
798 			if (*buf != '\0' && (err = string_to_quantity(buf, &mod_list[i][j], qtypes[mod_type * 3 + j])) != NULL) {
799 				ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: %s: parameter %d of item %d: %s (%s)",
800 						name, line, qtypestr[mod_type], j+1, i+1, err, buf);
801 				free_ptr_list(mod_list, *num);
802 				mod_list = NULL;
803 				*num = 0;
804 				return NULL;
805 			}
806 			if (! (p = strchr(p, ':')))
807 				break;
808 			if (px && p > px)
809 				break;
810 		}
811 		if (! (p = px))
812 			break;
813 	}
814 	return mod_list;
815 }
816 
set_gus_patchconf_opts(char * name,int line,char * opts,ToneBankElement * tone)817 static int set_gus_patchconf_opts(char *name,
818 		int line, char *opts, ToneBankElement *tone)
819 {
820 	char *cp;
821 	int k;
822 
823 	if (! (cp = strchr(opts, '='))) {
824 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
825 				"%s: line %d: bad patch option %s", name, line, opts);
826 		return 1;
827 	}
828 	*cp++ = 0;
829 	if (! strcmp(opts, "amp")) {
830 		k = atoi(cp);
831 		if ((k < 0 || k > MAX_AMPLIFICATION) || (*cp < '0' || *cp > '9')) {
832 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
833 					"%s: line %d: amplification must be between 0 and %d",
834 					name, line, MAX_AMPLIFICATION);
835 			return 1;
836 		}
837 		tone->amp = k;
838 	} else if (! strcmp(opts, "note")) {
839 		k = atoi(cp);
840 		if ((k < 0 || k > 127) || (*cp < '0' || *cp > '9')) {
841 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
842 					"%s: line %d: note must be between 0 and 127",
843 					name, line);
844 			return 1;
845 		}
846 		tone->note = k;
847 		tone->scltune = config_parse_int16("100", &tone->scltunenum);
848 	} else if (! strcmp(opts, "pan")) {
849 		if (! strcmp(cp, "center"))
850 			k = 64;
851 		else if (! strcmp(cp, "left"))
852 			k = 0;
853 		else if (! strcmp(cp, "right"))
854 			k = 127;
855 		else {
856 			k = ((atoi(cp) + 100) * 100) / 157;
857 			if ((k < 0 || k > 127)
858 					|| (k == 0 && *cp != '-' && (*cp < '0' || *cp > '9'))) {
859 				ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
860 						"%s: line %d: panning must be left, right, "
861 						"center, or between -100 and 100",
862 						name, line);
863 				return 1;
864 			}
865 		}
866 		tone->pan = k;
867 	} else if (! strcmp(opts, "tune"))
868 		tone->tune = config_parse_tune(cp, &tone->tunenum);
869 	else if (! strcmp(opts, "rate"))
870 		tone->envrate = config_parse_envelope(cp, &tone->envratenum);
871 	else if (! strcmp(opts, "offset"))
872 		tone->envofs = config_parse_envelope(cp, &tone->envofsnum);
873 	else if (! strcmp(opts, "keep")) {
874 		if (! strcmp(cp, "env"))
875 			tone->strip_envelope = 0;
876 		else if (! strcmp(cp, "loop"))
877 			tone->strip_loop = 0;
878 		else {
879 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
880 					"%s: line %d: keep must be env or loop", name, line);
881 			return 1;
882 		}
883 	} else if (! strcmp(opts, "strip")) {
884 		if (! strcmp(cp, "env"))
885 			tone->strip_envelope = 1;
886 		else if (! strcmp(cp, "loop"))
887 			tone->strip_loop = 1;
888 		else if (! strcmp(cp, "tail"))
889 			tone->strip_tail = 1;
890 		else {
891 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
892 					"%s: line %d: strip must be env, loop, or tail",
893 					name, line);
894 			return 1;
895 		}
896 	} else if (! strcmp(opts, "tremolo")) {
897 		if ((tone->trem = config_parse_modulation(name,
898 				line, cp, &tone->tremnum, 0)) == NULL)
899 			return 1;
900 	} else if (! strcmp(opts, "vibrato")) {
901 		if ((tone->vib = config_parse_modulation(name,
902 				line, cp, &tone->vibnum, 1)) == NULL)
903 			return 1;
904 	} else if (! strcmp(opts, "sclnote"))
905 		tone->sclnote = config_parse_int16(cp, &tone->sclnotenum);
906 	else if (! strcmp(opts, "scltune"))
907 		tone->scltune = config_parse_int16(cp, &tone->scltunenum);
908 	else if (! strcmp(opts, "comm")) {
909 		char *p;
910 
911 		if (tone->comment)
912 			free(tone->comment);
913 		p = tone->comment = safe_strdup(cp);
914 		while (*p) {
915 			if (*p == ',')
916 				*p = ' ';
917 			p++;
918 		}
919 	} else if (! strcmp(opts, "modrate"))
920 		tone->modenvrate = config_parse_envelope(cp, &tone->modenvratenum);
921 	else if (! strcmp(opts, "modoffset"))
922 		tone->modenvofs = config_parse_envelope(cp, &tone->modenvofsnum);
923 	else if (! strcmp(opts, "envkeyf"))
924 		tone->envkeyf = config_parse_envelope(cp, &tone->envkeyfnum);
925 	else if (! strcmp(opts, "envvelf"))
926 		tone->envvelf = config_parse_envelope(cp, &tone->envvelfnum);
927 	else if (! strcmp(opts, "modkeyf"))
928 		tone->modenvkeyf = config_parse_envelope(cp, &tone->modenvkeyfnum);
929 	else if (! strcmp(opts, "modvelf"))
930 		tone->modenvvelf = config_parse_envelope(cp, &tone->modenvvelfnum);
931 	else if (! strcmp(opts, "trempitch"))
932 		tone->trempitch = config_parse_int16(cp, &tone->trempitchnum);
933 	else if (! strcmp(opts, "tremfc"))
934 		tone->tremfc = config_parse_int16(cp, &tone->tremfcnum);
935 	else if (! strcmp(opts, "modpitch"))
936 		tone->modpitch = config_parse_int16(cp, &tone->modpitchnum);
937 	else if (! strcmp(opts, "modfc"))
938 		tone->modfc = config_parse_int16(cp, &tone->modfcnum);
939 	else if (! strcmp(opts, "fc"))
940 		tone->fc = config_parse_int16(cp, &tone->fcnum);
941 	else if (! strcmp(opts, "q"))
942 		tone->reso = config_parse_int16(cp, &tone->resonum);
943 	else if (! strcmp(opts, "fckeyf"))		/* filter key-follow */
944 		tone->key_to_fc = atoi(cp);
945 	else if (! strcmp(opts, "fcvelf"))		/* filter velocity-follow */
946 		tone->vel_to_fc = atoi(cp);
947 	else if (! strcmp(opts, "qvelf"))		/* resonance velocity-follow */
948 		tone->vel_to_resonance = atoi(cp);
949 	else {
950 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
951 				"%s: line %d: bad patch option %s",
952 				name, line, opts);
953 		return 1;
954 	}
955 	return 0;
956 }
957 
reinit_tone_bank_element(ToneBankElement * tone)958 static void reinit_tone_bank_element(ToneBankElement *tone)
959 {
960 	free_tone_bank_element(tone);
961 	tone->note = tone->pan = -1;
962 	tone->strip_loop = tone->strip_envelope = tone->strip_tail = -1;
963 	tone->amp = -1;
964 	tone->rnddelay = 0;
965 	tone->loop_timeout = 0;
966 	tone->legato = tone->damper_mode = tone->key_to_fc = tone->vel_to_fc = 0;
967 	tone->reverb_send = tone->chorus_send = tone->delay_send = -1;
968 	tone->tva_level = -1;
969 	tone->play_note = -1;
970 }
971 
972 #define SET_GUS_PATCHCONF_COMMENT
set_gus_patchconf(char * name,int line,ToneBankElement * tone,char * pat,char ** opts)973 static int set_gus_patchconf(char *name, int line,
974 			     ToneBankElement *tone, char *pat, char **opts)
975 {
976     int j;
977 #ifdef SET_GUS_PATCHCONF_COMMENT
978 		char *old_name = NULL;
979 
980 		if(tone != NULL && tone->name != NULL)
981 			old_name = safe_strdup(tone->name);
982 #endif
983     reinit_tone_bank_element(tone);
984 
985     if(strcmp(pat, "%font") == 0) /* Font extention */
986     {
987 	/* %font filename bank prog [note-to-use]
988 	 * %font filename 128 bank key
989 	 */
990 
991 	if(opts[0] == NULL || opts[1] == NULL || opts[2] == NULL ||
992 	   (atoi(opts[1]) == 128 && opts[3] == NULL))
993 	{
994 	    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
995 		      "%s: line %d: Syntax error", name, line);
996 #ifdef SET_GUS_PATCHCONF_COMMENT
997         if(old_name != NULL)
998             free(old_name);
999 #endif
1000 	    return 1;
1001 	}
1002 	tone->name = safe_strdup(opts[0]);
1003 	tone->instype = 1;
1004 	if(atoi(opts[1]) == 128) /* drum */
1005 	{
1006 	    tone->font_bank = 128;
1007 	    tone->font_preset = atoi(opts[2]);
1008 	    tone->font_keynote = atoi(opts[3]);
1009 	    opts += 4;
1010 	}
1011 	else
1012 	{
1013 	    tone->font_bank = atoi(opts[1]);
1014 	    tone->font_preset = atoi(opts[2]);
1015 
1016 	    if(opts[3] && isdigit(opts[3][0]))
1017 	    {
1018 		tone->font_keynote = atoi(opts[3]);
1019 		opts += 4;
1020 	    }
1021 	    else
1022 	    {
1023 		tone->font_keynote = -1;
1024 		opts += 3;
1025 	    }
1026 	}
1027     }
1028     else if(strcmp(pat, "%sample") == 0) /* Sample extention */
1029     {
1030 	/* %sample filename */
1031 
1032 	if(opts[0] == NULL)
1033 	{
1034 	    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1035 		      "%s: line %d: Syntax error", name, line);
1036 	    return 1;
1037 	}
1038 	tone->name = safe_strdup(opts[0]);
1039 	tone->instype = 2;
1040 	opts++;
1041     }
1042     else
1043     {
1044 	tone->instype = 0;
1045 	tone->name = safe_strdup(pat);
1046     }
1047 
1048     for(j = 0; opts[j] != NULL; j++)
1049     {
1050 	int err;
1051 	if((err = set_gus_patchconf_opts(name, line, opts[j], tone)) != 0)
1052     {
1053 #ifdef SET_GUS_PATCHCONF_COMMENT
1054         if(old_name != NULL)
1055             free(old_name);
1056 #endif
1057             return err;
1058     }
1059 	    return err;
1060     }
1061 #ifdef SET_GUS_PATCHCONF_COMMENT
1062 		if(tone->comment == NULL ||
1063 			(old_name != NULL && strcmp(old_name,tone->comment) == 0))
1064 		{
1065 			if(tone->comment != NULL )
1066 				free(tone->comment);
1067 			tone->comment = safe_strdup(tone->name);
1068 		}
1069 		if(old_name != NULL)
1070 			free(old_name);
1071 #else
1072     if(tone->comment == NULL)
1073 	tone->comment = safe_strdup(tone->name);
1074 #endif
1075     return 0;
1076 }
1077 
set_patchconf(char * name,int line,ToneBank * bank,char * w[],int dr,int mapid,int bankmapfrom,int bankno)1078 static int set_patchconf(char *name, int line, ToneBank *bank, char *w[], int dr, int mapid, int bankmapfrom, int bankno)
1079 {
1080     int i;
1081 
1082     i = atoi(w[0]);
1083     if(!dr)
1084 	i -= progbase;
1085     if(i < 0 || i > 127)
1086     {
1087 	if(dr)
1088 	    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1089 		      "%s: line %d: Drum number must be between "
1090 		      "0 and 127",
1091 		      name, line);
1092 	else
1093 	    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1094 		      "%s: line %d: Program must be between "
1095 		      "%d and %d",
1096 		      name, line, progbase, 127 + progbase);
1097 	return 1;
1098     }
1099     if(!bank)
1100     {
1101 	ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1102 		  "%s: line %d: Must specify tone bank or drum set "
1103 		  "before assignment", name, line);
1104 	return 1;
1105     }
1106 
1107     if(set_gus_patchconf(name, line, &bank->tone[i], w[1], w + 2))
1108 	return 1;
1109     if (mapid != INST_NO_MAP)
1110 	set_instrument_map(mapid, bankmapfrom, i, bankno, i);
1111     return 0;
1112 }
1113 
1114 typedef struct {
1115 	const char *name;
1116 	int mapid, isdrum;
1117 } MapNameEntry;
1118 
mapnamecompare(const void * name,const void * entry)1119 static int mapnamecompare(const void *name, const void *entry)
1120 {
1121 	return strcmp((const char *)name, ((const MapNameEntry *)entry)->name);
1122 }
1123 
mapname2id(char * name,int * isdrum)1124 static int mapname2id(char *name, int *isdrum)
1125 {
1126 	static const MapNameEntry data[] = {
1127 		/* sorted in alphabetical order */
1128 		{"gm2",         GM2_TONE_MAP, 0},
1129 		{"gm2drum",     GM2_DRUM_MAP, 1},
1130 		{"sc55",        SC_55_TONE_MAP, 0},
1131 		{"sc55drum",    SC_55_DRUM_MAP, 1},
1132 		{"sc88",        SC_88_TONE_MAP, 0},
1133 		{"sc8850",      SC_8850_TONE_MAP, 0},
1134 		{"sc8850drum",  SC_8850_DRUM_MAP, 1},
1135 		{"sc88drum",    SC_88_DRUM_MAP, 1},
1136 		{"sc88pro",     SC_88PRO_TONE_MAP, 0},
1137 		{"sc88prodrum", SC_88PRO_DRUM_MAP, 1},
1138 		{"xg",          XG_NORMAL_MAP, 0},
1139 		{"xgdrum",      XG_DRUM_MAP, 1},
1140 		{"xgsfx126",    XG_SFX126_MAP, 1},
1141 		{"xgsfx64",     XG_SFX64_MAP, 0}
1142 	};
1143 	const MapNameEntry *found;
1144 
1145 	found = (MapNameEntry *)bsearch(name, data, sizeof data / sizeof data[0], sizeof data[0], mapnamecompare);
1146 	if (found != NULL)
1147 	{
1148 		*isdrum = found->isdrum;
1149 		return found->mapid;
1150 	}
1151 	return -1;
1152 }
1153 
1154 /* string[0] should not be '#' */
strip_trailing_comment(char * string,int next_token_index)1155 static int strip_trailing_comment(char *string, int next_token_index)
1156 {
1157     if (string[next_token_index - 1] == '#'	/* strip \1 in /^\S+(#*[ \t].*)/ */
1158 	&& (string[next_token_index] == ' ' || string[next_token_index] == '\t'))
1159     {
1160 	string[next_token_index] = '\0';	/* new c-string terminator */
1161 	while(string[--next_token_index - 1] == '#')
1162 	    ;
1163     }
1164     return next_token_index;
1165 }
1166 
expand_variables(char * string,MBlockList * varbuf,const char * basedir)1167 static char *expand_variables(char *string, MBlockList *varbuf, const char *basedir)
1168 {
1169 	char *p, *expstr;
1170 	const char *copystr;
1171 	int limlen, copylen, explen, varlen, braced;
1172 
1173 	if ((p = strchr(string, '$')) == NULL)
1174 		return string;
1175 	varlen = strlen(basedir);
1176 	explen = limlen = 0;
1177 	expstr = NULL;
1178 	copystr = string;
1179 	copylen = p - string;
1180 	string = p;
1181 	for(;;)
1182 	{
1183 		if (explen + copylen + 1 > limlen)
1184 		{
1185 			limlen += copylen + 128;
1186 			expstr = memcpy(new_segment(varbuf, limlen), expstr, explen);
1187 		}
1188 		memcpy(&expstr[explen], copystr, copylen);
1189 		explen += copylen;
1190 		if (*string == '\0')
1191 			break;
1192 		else if (*string == '$')
1193 		{
1194 			braced = *++string == '{';
1195 			if (braced)
1196 			{
1197 				if ((p = strchr(string + 1, '}')) == NULL)
1198 					p = string;	/* no closing brace */
1199 				else
1200 					string++;
1201 			}
1202 			else
1203 				for(p = string; isalnum(*p) || *p == '_'; p++) ;
1204 			if (p == string)	/* empty */
1205 			{
1206 				copystr = "${";
1207 				copylen = 1 + braced;
1208 			}
1209 			else
1210 			{
1211 				if (p - string == 7 && memcmp(string, "basedir", 7) == 0)
1212 				{
1213 					copystr = basedir;
1214 					copylen = varlen;
1215 				}
1216 				else	/* undefined variable */
1217 					copylen = 0;
1218 				string = p + braced;
1219 			}
1220 		}
1221 		else	/* search next */
1222 		{
1223 			p = strchr(string, '$');
1224 			if (p == NULL)
1225 				copylen = strlen(string);
1226 			else
1227 				copylen = p - string;
1228 			copystr = string;
1229 			string += copylen;
1230 		}
1231 	}
1232 	expstr[explen] = '\0';
1233 	return expstr;
1234 }
1235 
1236 #define MAXWORDS 130
1237 #define CHECKERRLIMIT \
1238   if(++errcnt >= 10) { \
1239     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, \
1240       "Too many errors... Give up read %s", name); \
1241     reuse_mblock(&varbuf); \
1242     close_file(tf); return 1; }
1243 
1244 #define READ_CONFIG_SUCCESS        0
1245 #define READ_CONFIG_ERROR          1
1246 #define READ_CONFIG_RECURSION      2 /* Too much recursion */
1247 #define READ_CONFIG_FILE_NOT_FOUND 3 /* Returned only w. allow_missing_file */
read_config_file(char * name,int self,int allow_missing_file)1248 MAIN_INTERFACE int read_config_file(char *name, int self, int allow_missing_file)
1249 {
1250     struct timidity_file *tf;
1251     char buf[1024], *tmp, *w[MAXWORDS + 1], *cp;
1252     ToneBank *bank = NULL;
1253     int i, j, k, line = 0, words, errcnt = 0;
1254     static int rcf_count = 0;
1255     int dr = 0, bankno = 0, mapid = INST_NO_MAP, origbankno = 0x7FFFFFFF;
1256     int extension_flag, param_parse_err;
1257     MBlockList varbuf;
1258     char *basedir, *sep;
1259 
1260     if(rcf_count > 50)
1261     {
1262 	ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1263 		  "Probable source loop in configuration files");
1264 	return READ_CONFIG_RECURSION;
1265     }
1266 
1267     if(self)
1268     {
1269 	tf = open_with_mem(name, (int32)strlen(name), OF_VERBOSE);
1270 	name = "(configuration)";
1271     }
1272     else
1273 	tf = open_file(name, 1, allow_missing_file ? OF_NORMAL : OF_VERBOSE);
1274     if(tf == NULL)
1275 	return allow_missing_file ? READ_CONFIG_FILE_NOT_FOUND :
1276 	                            READ_CONFIG_ERROR;
1277 
1278 	init_mblock(&varbuf);
1279 	if (!self)
1280 	{
1281 		basedir = strdup_mblock(&varbuf, current_filename);
1282 		if (is_url_prefix(basedir))
1283 			sep = strrchr(basedir, '/');
1284 		else
1285 			sep = pathsep_strrchr(basedir);
1286 	}
1287 	else
1288 		sep = NULL;
1289 	if (sep == NULL)
1290 	{
1291 		#ifndef __MACOS__
1292 		basedir = ".";
1293 		#else
1294 		basedir = "";
1295 		#endif
1296 	}
1297 	else
1298 	{
1299 		if ((cp = strchr(sep, '#')) != NULL)
1300 			sep = cp + 1;	/* inclusive of '#' */
1301 		*sep = '\0';
1302 	}
1303 
1304     errno = 0;
1305     while(tf_gets(buf, sizeof(buf), tf))
1306     {
1307 	line++;
1308 	if(strncmp(buf, "#extension", 10) == 0) {
1309 	    extension_flag = 1;
1310 	    i = 10;
1311 	}
1312 	else
1313 	{
1314 	    extension_flag = 0;
1315 	    i = 0;
1316 	}
1317 
1318 	while(isspace(buf[i]))			/* skip /^\s*(?#)/ */
1319 	    i++;
1320 	if (buf[i] == '#' || buf[i] == '\0')	/* /^#|^$/ */
1321 	    continue;
1322 	tmp = expand_variables(buf, &varbuf, basedir);
1323 	j = strcspn(tmp + i, " \t\r\n\240");
1324 	if (j == 0)
1325 		j = strlen(tmp + i);
1326 	j = strip_trailing_comment(tmp + i, j);
1327 	tmp[i + j] = '\0';			/* terminate the first token */
1328 	w[0] = tmp + i;
1329 	i += j + 1;
1330 	words = param_parse_err = 0;
1331 	while(words < MAXWORDS - 1)		/* -1 : next arg */
1332 	{
1333 	    char *terminator;
1334 
1335 	    while(isspace(tmp[i]))		/* skip /^\s*(?#)/ */
1336 		i++;
1337 	    if (tmp[i] == '\0'
1338 		    || tmp[i] == '#')		/* /\s#/ */
1339 		break;
1340 	    if ((tmp[i] == '"' || tmp[i] == '\'')
1341 		    && (terminator = strchr(tmp + i + 1, tmp[i])) != NULL)
1342 	    {
1343 		if (!isspace(terminator[1]) && terminator[1] != '\0')
1344 		{
1345 		    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1346 			"%s: line %d: there must be at least one whitespace between "
1347 			"string terminator (%c) and the next parameter", name, line, tmp[i]);
1348 		    CHECKERRLIMIT;
1349 		    param_parse_err = 1;
1350 		    break;
1351 		}
1352 		w[++words] = tmp + i + 1;
1353 		i = terminator - tmp + 1;
1354 		*terminator = '\0';
1355 	    }
1356 	    else	/* not terminated */
1357 	    {
1358 		j = strcspn(tmp + i, " \t\r\n\240");
1359 		if (j > 0)
1360 		    j = strip_trailing_comment(tmp + i, j);
1361 		w[++words] = tmp + i;
1362 		i += j;
1363 		if (tmp[i] != '\0')		/* unless at the end-of-string (i.e. EOF) */
1364 		    tmp[i++] = '\0';		/* terminate the token */
1365 	    }
1366 	}
1367 	if (param_parse_err)
1368 	    continue;
1369 	w[++words] = NULL;
1370 
1371 	/*
1372 	 * #extension [something...]
1373 	 */
1374 
1375 	/* #extension comm program comment */
1376 	if(strcmp(w[0], "comm") == 0)
1377 	{
1378 	    char *p;
1379 
1380 	    if(words != 3)
1381 	    {
1382 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1383 			  "%s: line %d: syntax error", name, line);
1384 		CHECKERRLIMIT;
1385 		continue;
1386 	    }
1387 	    if(!bank)
1388 	    {
1389 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1390 			  "%s: line %d: Must specify tone bank or drum "
1391 			  "set before assignment", name, line);
1392 		CHECKERRLIMIT;
1393 		continue;
1394 	    }
1395 	    i = atoi(w[1]);
1396 	    if(i < 0 || i > 127)
1397 	    {
1398 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1399 			  "%s: line %d: extension comm must be "
1400 			  "between 0 and 127", name, line);
1401 		CHECKERRLIMIT;
1402 		continue;
1403 	    }
1404 	    if(bank->tone[i].comment)
1405 		free(bank->tone[i].comment);
1406 	    p = bank->tone[i].comment = safe_strdup(w[2]);
1407 	    while(*p)
1408 	    {
1409 		if(*p == ',') *p = ' ';
1410 		p++;
1411 	    }
1412 	}
1413 	/* #extension timeout program sec */
1414 	else if(strcmp(w[0], "timeout") == 0)
1415 	{
1416 	    if(words != 3)
1417 	    {
1418 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1419 			  "%s: line %d: syntax error", name, line);
1420 		CHECKERRLIMIT;
1421 		continue;
1422 	    }
1423 	    if(!bank)
1424 	    {
1425 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1426 			  "%s: line %d: Must specify tone bank or drum set "
1427 			  "before assignment", name, line);
1428 		CHECKERRLIMIT;
1429 		continue;
1430 	    }
1431 	    i = atoi(w[1]);
1432 	    if(i < 0 || i > 127)
1433 	    {
1434 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1435 			  "%s: line %d: extension timeout "
1436 			  "must be between 0 and 127", name, line);
1437 		CHECKERRLIMIT;
1438 		continue;
1439 	    }
1440 	    bank->tone[i].loop_timeout = atoi(w[2]);
1441 	}
1442 	/* #extension copydrumset drumset */
1443 	else if(strcmp(w[0], "copydrumset") == 0)
1444 	{
1445 	    if(words < 2)
1446 	    {
1447 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1448 			  "%s: line %d: No copydrumset number given",
1449 			  name, line);
1450 		CHECKERRLIMIT;
1451 		continue;
1452 	    }
1453 	    i = atoi(w[1]);
1454 	    if(i < 0 || i > 127)
1455 	    {
1456 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1457 			  "%s: line %d: extension copydrumset "
1458 			  "must be between 0 and 127", name, line);
1459 		CHECKERRLIMIT;
1460 		continue;
1461 	    }
1462 	    if(!bank)
1463 	    {
1464 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1465 			  "%s: line %d: Must specify tone bank or "
1466 			  "drum set before assignment", name, line);
1467 		CHECKERRLIMIT;
1468 		continue;
1469 	    }
1470 	    copybank(bank, drumset[i], mapid, origbankno, bankno);
1471 	}
1472 	/* #extension copybank bank */
1473 	else if(strcmp(w[0], "copybank") == 0)
1474 	{
1475 	    if(words < 2)
1476 	    {
1477 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1478 			  "%s: line %d: No copybank number given",
1479 			  name, line);
1480 		CHECKERRLIMIT;
1481 		continue;
1482 	    }
1483 	    i = atoi(w[1]);
1484 	    if(i < 0 || i > 127)
1485 	    {
1486 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1487 			  "%s: line %d: extension copybank "
1488 			  "must be between 0 and 127", name, line);
1489 		CHECKERRLIMIT;
1490 		continue;
1491 	    }
1492 	    if(!bank)
1493 	    {
1494 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1495 			  "%s: line %d: Must specify tone bank or "
1496 			  "drum set before assignment", name, line);
1497 		CHECKERRLIMIT;
1498 		continue;
1499 	    }
1500 	    copybank(bank, tonebank[i], mapid, origbankno, bankno);
1501 	}
1502 	/* #extension copymap tomapid frommapid */
1503 	else if(strcmp(w[0], "copymap") == 0)
1504 	{
1505 	    int mapto, mapfrom;
1506 	    int toisdrum, fromisdrum;
1507 
1508 	    if(words != 3)
1509 	    {
1510 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1511 			  "%s: line %d: syntax error", name, line);
1512 		CHECKERRLIMIT;
1513 		continue;
1514 	    }
1515 	    if ((mapto = mapname2id(w[1], &toisdrum)) == -1)
1516 	    {
1517 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1518 			  "%s: line %d: Invalid map name: %s", name, line, w[1]);
1519 		CHECKERRLIMIT;
1520 		continue;
1521 	    }
1522 	    if ((mapfrom = mapname2id(w[2], &fromisdrum)) == -1)
1523 	    {
1524 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1525 			  "%s: line %d: Invalid map name: %s", name, line, w[2]);
1526 		CHECKERRLIMIT;
1527 		continue;
1528 	    }
1529 	    if (toisdrum != fromisdrum)
1530 	    {
1531 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1532 			  "%s: line %d: Map type should be matched", name, line);
1533 		CHECKERRLIMIT;
1534 		continue;
1535 	    }
1536 	    if (copymap(mapto, mapfrom, toisdrum))
1537 	    {
1538 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1539 			  "%s: line %d: No free %s available to map",
1540 			  name, line, toisdrum ? "drum set" : "tone bank");
1541 		CHECKERRLIMIT;
1542 		continue;
1543 	    }
1544 	}
1545 	/* #extension HTTPproxy hostname:port */
1546 	else if(strcmp(w[0], "HTTPproxy") == 0)
1547 	{
1548             char r_bracket, l_bracket;
1549 
1550 	    if(words < 2)
1551 	    {
1552 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1553 			  "%s: line %d: No proxy name given",
1554 			  name, line);
1555 		CHECKERRLIMIT;
1556 		continue;
1557 	    }
1558 	    /* If network is not supported, this extension is ignored. */
1559 #ifdef SUPPORT_SOCKET
1560 	    url_http_proxy_host = safe_strdup(w[1]);
1561 	    if((cp = strrchr(url_http_proxy_host, ':')) == NULL)
1562 	    {
1563 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1564 			  "%s: line %d: Syntax error", name, line);
1565 		CHECKERRLIMIT;
1566 		continue;
1567 	    }
1568 	    *cp++ = '\0';
1569 	    if((url_http_proxy_port = atoi(cp)) <= 0)
1570 	    {
1571 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1572 			  "%s: line %d: Port number must be "
1573 			  "positive number", name, line);
1574 		CHECKERRLIMIT;
1575 		continue;
1576 	    }
1577 
1578             l_bracket = url_http_proxy_host[0];
1579             r_bracket = url_http_proxy_host[strlen(url_http_proxy_host) - 1];
1580 
1581             if (l_bracket == '[' || r_bracket == ']')
1582             {
1583                 if (l_bracket != '[' || r_bracket != ']')
1584                 {
1585                     ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1586                               "%s: line %d: Malformed IPv6 address",
1587                               name, line);
1588                     CHECKERRLIMIT;
1589                     continue;
1590                 }
1591                 url_http_proxy_host++;
1592                 url_http_proxy_host[strlen(url_http_proxy_host) - 1] = '\0';
1593             }
1594 #endif
1595 	}
1596 	/* #extension FTPproxy hostname:port */
1597 	else if(strcmp(w[0], "FTPproxy") == 0)
1598 	{
1599             char l_bracket, r_bracket;
1600 
1601 	    if(words < 2)
1602 	    {
1603 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1604 			  "%s: line %d: No proxy name given",
1605 			  name, line);
1606 		CHECKERRLIMIT;
1607 		continue;
1608 	    }
1609 	    /* If network is not supported, this extension is ignored. */
1610 #ifdef SUPPORT_SOCKET
1611 	    url_ftp_proxy_host = safe_strdup(w[1]);
1612 	    if((cp = strrchr(url_ftp_proxy_host, ':')) == NULL)
1613 	    {
1614 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1615 			  "%s: line %d: Syntax error", name, line);
1616 		CHECKERRLIMIT;
1617 		continue;
1618 	    }
1619 	    *cp++ = '\0';
1620 	    if((url_ftp_proxy_port = atoi(cp)) <= 0)
1621 	    {
1622 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1623 			  "%s: line %d: Port number "
1624 			  "must be positive number", name, line);
1625 		CHECKERRLIMIT;
1626 		continue;
1627 	    }
1628 
1629             l_bracket = url_ftp_proxy_host[0];
1630             r_bracket = url_ftp_proxy_host[strlen(url_ftp_proxy_host) - 1];
1631 
1632             if (l_bracket == '[' || r_bracket == ']')
1633             {
1634                 if (l_bracket != '[' || r_bracket != ']')
1635                 {
1636                     ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1637                               "%s: line %d: Malformed IPv6 address",
1638                               name, line);
1639                     CHECKERRLIMIT;
1640                     continue;
1641                 }
1642                 url_ftp_proxy_host++;
1643                 url_ftp_proxy_host[strlen(url_ftp_proxy_host) - 1] = '\0';
1644             }
1645 #endif
1646 	}
1647 	/* #extension mailaddr somebody@someware.domain.com */
1648 	else if(strcmp(w[0], "mailaddr") == 0)
1649 	{
1650 	    if(words < 2)
1651 	    {
1652 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1653 			  "%s: line %d: No mail address given",
1654 			  name, line);
1655 		CHECKERRLIMIT;
1656 		continue;
1657 	    }
1658 	    if(strchr(w[1], '@') == NULL) {
1659 		ctl->cmsg(CMSG_WARNING, VERB_NOISY,
1660 			  "%s: line %d: Warning: Mail address %s is not valid",
1661 			  name, line);
1662 	    }
1663 
1664 	    /* If network is not supported, this extension is ignored. */
1665 #ifdef SUPPORT_SOCKET
1666 	    user_mailaddr = safe_strdup(w[1]);
1667 #endif /* SUPPORT_SOCKET */
1668 	}
1669 	/* #extension opt [-]{option}[optarg] */
1670 	else if (strcmp(w[0], "opt") == 0) {
1671 		int c, longind, err;
1672 		char *p, *cmd, *arg;
1673 
1674 		if (words != 2 && words != 3) {
1675 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1676 					"%s: line %d: Syntax error", name, line);
1677 			CHECKERRLIMIT;
1678 			continue;
1679 		}
1680 		if (*w[1] == '-') {
1681 			int optind_save = optind;
1682 			optind = 0;
1683 #if defined(__CYGWIN__)
1684 			optreset = 1;
1685 #endif
1686 			c = getopt_long(words, w, optcommands, longopts, &longind);
1687 			err = set_tim_opt_long(c, optarg, longind);
1688 			optind = optind_save;
1689 		} else {
1690 			/* backward compatibility */
1691 			if ((p = strchr(optcommands, c = *(cmd = w[1]))) == NULL)
1692 				err = 1;
1693 			else {
1694 				if (*(p + 1) == ':')
1695 					arg = (words == 2) ? cmd + 1 : w[2];
1696 				else
1697 					arg = "";
1698 				err = set_tim_opt_short(c, arg);
1699 			}
1700 		}
1701 		if (err) {
1702 			/* error */
1703 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1704 					"%s: line %d: Invalid command line option",
1705 					name, line);
1706 			errcnt += err - 1;
1707 			CHECKERRLIMIT;
1708 			continue;
1709 		}
1710 	}
1711 	/* #extension undef program */
1712 	else if(strcmp(w[0], "undef") == 0)
1713 	{
1714 	    if(words < 2)
1715 	    {
1716 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1717 			  "%s: line %d: No undef number given",
1718 			  name, line);
1719 		CHECKERRLIMIT;
1720 		continue;
1721 	    }
1722 	    i = atoi(w[1]);
1723 	    if(i < 0 || i > 127)
1724 	    {
1725 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1726 			  "%s: line %d: extension undef "
1727 			  "must be between 0 and 127", name, line);
1728 		CHECKERRLIMIT;
1729 		continue;
1730 	    }
1731 	    if(!bank)
1732 	    {
1733 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1734 			  "%s: line %d: Must specify tone bank or "
1735 			  "drum set before assignment", name, line);
1736 		CHECKERRLIMIT;
1737 		continue;
1738 	    }
1739 	    free_tone_bank_element(&bank->tone[i]);
1740 	}
1741 	/* #extension altassign numbers... */
1742 	else if(strcmp(w[0], "altassign") == 0)
1743 	{
1744 	    ToneBank *bk;
1745 
1746 	    if(!bank)
1747 	    {
1748 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1749 			  "%s: line %d: Must specify tone bank or drum set "
1750 			  "before altassign", name, line);
1751 		CHECKERRLIMIT;
1752 		continue;
1753 	    }
1754 	    if(words < 2)
1755 	    {
1756 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1757 			  "%s: line %d: No alternate assignment", name, line);
1758 		CHECKERRLIMIT;
1759 		continue;
1760 	    }
1761 
1762 	    if(!dr) {
1763 		ctl->cmsg(CMSG_WARNING, VERB_NORMAL,
1764 			  "%s: line %d: Warning: Not a drumset altassign"
1765 			  " (ignored)",
1766 			  name, line);
1767 		continue;
1768 	    }
1769 
1770 	    bk = drumset[bankno];
1771 	    bk->alt = add_altassign_string(bk->alt, w + 1, words - 1);
1772 	}	/* #extension legato [program] [0 or 1] */
1773 	else if(strcmp(w[0], "legato") == 0)
1774 	{
1775 	    if(words != 3)
1776 	    {
1777 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1778 			  "%s: line %d: syntax error", name, line);
1779 		CHECKERRLIMIT;
1780 		continue;
1781 	    }
1782 	    if(!bank)
1783 	    {
1784 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1785 			  "%s: line %d: Must specify tone bank or drum set "
1786 			  "before assignment", name, line);
1787 		CHECKERRLIMIT;
1788 		continue;
1789 	    }
1790 	    i = atoi(w[1]);
1791 	    if(i < 0 || i > 127)
1792 	    {
1793 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1794 			  "%s: line %d: extension legato "
1795 			  "must be between 0 and 127", name, line);
1796 		CHECKERRLIMIT;
1797 		continue;
1798 	    }
1799 	    bank->tone[i].legato = atoi(w[2]);
1800 	}	/* #extension damper [program] [0 or 1] */
1801 	else if(strcmp(w[0], "damper") == 0)
1802 	{
1803 	    if(words != 3)
1804 	    {
1805 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1806 			  "%s: line %d: syntax error", name, line);
1807 		CHECKERRLIMIT;
1808 		continue;
1809 	    }
1810 	    if(!bank)
1811 	    {
1812 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1813 			  "%s: line %d: Must specify tone bank or drum set "
1814 			  "before assignment", name, line);
1815 		CHECKERRLIMIT;
1816 		continue;
1817 	    }
1818 	    i = atoi(w[1]);
1819 	    if(i < 0 || i > 127)
1820 	    {
1821 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1822 			  "%s: line %d: extension damper "
1823 			  "must be between 0 and 127", name, line);
1824 		CHECKERRLIMIT;
1825 		continue;
1826 	    }
1827 	    bank->tone[i].damper_mode = atoi(w[2]);
1828 	}	/* #extension rnddelay [program] [0 or 1] */
1829 	else if(strcmp(w[0], "rnddelay") == 0)
1830 	{
1831 	    if(words != 3)
1832 	    {
1833 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1834 			  "%s: line %d: syntax error", name, line);
1835 		CHECKERRLIMIT;
1836 		continue;
1837 	    }
1838 	    if(!bank)
1839 	    {
1840 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1841 			  "%s: line %d: Must specify tone bank or drum set "
1842 			  "before assignment", name, line);
1843 		CHECKERRLIMIT;
1844 		continue;
1845 	    }
1846 	    i = atoi(w[1]);
1847 	    if(i < 0 || i > 127)
1848 	    {
1849 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1850 			  "%s: line %d: extension rnddelay "
1851 			  "must be between 0 and 127", name, line);
1852 		CHECKERRLIMIT;
1853 		continue;
1854 	    }
1855 	    bank->tone[i].rnddelay = atoi(w[2]);
1856 	}	/* #extension level program tva_level */
1857 	else if(strcmp(w[0], "level") == 0)
1858 	{
1859 	    if(words != 3)
1860 	    {
1861 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line);
1862 		CHECKERRLIMIT;
1863 		continue;
1864 	    }
1865 	    if(!bank)
1866 	    {
1867 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1868 			  "%s: line %d: Must specify tone bank or drum set "
1869 			  "before assignment", name, line);
1870 		CHECKERRLIMIT;
1871 		continue;
1872 	    }
1873 		i = atoi(w[2]);
1874 		if(i < 0 || i > 127)
1875 		{
1876 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1877 			  "%s: line %d: extension level "
1878 			  "must be between 0 and 127", name, line);
1879 		CHECKERRLIMIT;
1880 		continue;
1881 		}
1882 		cp = w[1];
1883 		do {
1884 			if (string_to_7bit_range(cp, &j, &k))
1885 			{
1886 				while (j <= k)
1887 					bank->tone[j++].tva_level = i;
1888 			}
1889 			cp = strchr(cp, ',');
1890 		} while(cp++ != NULL);
1891 	}	/* #extension reverbsend */
1892 	else if(strcmp(w[0], "reverbsend") == 0)
1893 	{
1894 	    if(words != 3)
1895 	    {
1896 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line);
1897 		CHECKERRLIMIT;
1898 		continue;
1899 	    }
1900 	    if(!bank)
1901 	    {
1902 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1903 			  "%s: line %d: Must specify tone bank or drum set "
1904 			  "before assignment", name, line);
1905 		CHECKERRLIMIT;
1906 		continue;
1907 	    }
1908 		i = atoi(w[2]);
1909 		if(i < 0 || i > 127)
1910 		{
1911 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1912 			  "%s: line %d: extension reverbsend "
1913 			  "must be between 0 and 127", name, line);
1914 		CHECKERRLIMIT;
1915 		continue;
1916 		}
1917 		cp = w[1];
1918 		do {
1919 			if (string_to_7bit_range(cp, &j, &k))
1920 			{
1921 				while (j <= k)
1922 					bank->tone[j++].reverb_send = i;
1923 			}
1924 			cp = strchr(cp, ',');
1925 		} while(cp++ != NULL);
1926 	}	/* #extension chorussend */
1927 	else if(strcmp(w[0], "chorussend") == 0)
1928 	{
1929 	    if(words != 3)
1930 	    {
1931 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line);
1932 		CHECKERRLIMIT;
1933 		continue;
1934 	    }
1935 	    if(!bank)
1936 	    {
1937 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1938 			  "%s: line %d: Must specify tone bank or drum set "
1939 			  "before assignment", name, line);
1940 		CHECKERRLIMIT;
1941 		continue;
1942 	    }
1943 		i = atoi(w[2]);
1944 		if(i < 0 || i > 127)
1945 		{
1946 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1947 			  "%s: line %d: extension chorussend "
1948 			  "must be between 0 and 127", name, line);
1949 		CHECKERRLIMIT;
1950 		continue;
1951 		}
1952 		cp = w[1];
1953 		do {
1954 			if (string_to_7bit_range(cp, &j, &k))
1955 			{
1956 				while (j <= k)
1957 					bank->tone[j++].chorus_send = i;
1958 			}
1959 			cp = strchr(cp, ',');
1960 		} while(cp++ != NULL);
1961 	}	/* #extension delaysend */
1962 	else if(strcmp(w[0], "delaysend") == 0)
1963 	{
1964 	    if(words != 3)
1965 	    {
1966 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line);
1967 		CHECKERRLIMIT;
1968 		continue;
1969 	    }
1970 	    if(!bank)
1971 	    {
1972 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1973 			  "%s: line %d: Must specify tone bank or drum set "
1974 			  "before assignment", name, line);
1975 		CHECKERRLIMIT;
1976 		continue;
1977 	    }
1978 		i = atoi(w[2]);
1979 		if(i < 0 || i > 127)
1980 		{
1981 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1982 			  "%s: line %d: extension delaysend "
1983 			  "must be between 0 and 127", name, line);
1984 		CHECKERRLIMIT;
1985 		continue;
1986 		}
1987 		cp = w[1];
1988 		do {
1989 			if (string_to_7bit_range(cp, &j, &k))
1990 			{
1991 				while (j <= k)
1992 					bank->tone[j++].delay_send = i;
1993 			}
1994 			cp = strchr(cp, ',');
1995 		} while(cp++ != NULL);
1996 	}	/* #extension playnote */
1997 	else if(strcmp(w[0], "playnote") == 0)
1998 	{
1999 	    if(words != 3)
2000 	    {
2001 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line);
2002 		CHECKERRLIMIT;
2003 		continue;
2004 	    }
2005 	    if(!bank)
2006 	    {
2007 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2008 			  "%s: line %d: Must specify tone bank or drum set "
2009 			  "before assignment", name, line);
2010 		CHECKERRLIMIT;
2011 		continue;
2012 	    }
2013 		i = atoi(w[2]);
2014 		if(i < 0 || i > 127)
2015 		{
2016 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2017 			  "%s: line %d: extension playnote"
2018 			  "must be between 0 and 127", name, line);
2019 		CHECKERRLIMIT;
2020 		continue;
2021 		}
2022 		cp = w[1];
2023 		do {
2024 			if (string_to_7bit_range(cp, &j, &k))
2025 			{
2026 				while (j <= k)
2027 					bank->tone[j++].play_note = i;
2028 			}
2029 			cp = strchr(cp, ',');
2030 		} while(cp++ != NULL);
2031 	}
2032 	else if(!strcmp(w[0], "soundfont"))
2033 	{
2034 	    int order, cutoff, isremove, reso, amp;
2035 	    char *sf_file;
2036 
2037 	    if(words < 2)
2038 	    {
2039 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2040 			  "%s: line %d: No soundfont file given",
2041 			  name, line);
2042 		CHECKERRLIMIT;
2043 		continue;
2044 	    }
2045 
2046 	    sf_file = w[1];
2047 	    order = cutoff = reso = amp = -1;
2048 	    isremove = 0;
2049 	    for(j = 2; j < words; j++)
2050 	    {
2051 		if(strcmp(w[j], "remove") == 0)
2052 		{
2053 		    isremove = 1;
2054 		    break;
2055 		}
2056 		if(!(cp = strchr(w[j], '=')))
2057 		{
2058 		    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2059 			      "%s: line %d: bad patch option %s",
2060 			      name, line, w[j]);
2061 		    CHECKERRLIMIT;
2062 		    break;
2063 		}
2064 		*cp++=0;
2065 		k = atoi(cp);
2066 		if(!strcmp(w[j], "order"))
2067 		{
2068 		    if(k < 0 || (*cp < '0' || *cp > '9'))
2069 		    {
2070 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2071 				  "%s: line %d: order must be a digit",
2072 				  name, line);
2073 			CHECKERRLIMIT;
2074 			break;
2075 		    }
2076 		    order = k;
2077 		}
2078 		else if(!strcmp(w[j], "cutoff"))
2079 		{
2080 		    if(k < 0 || (*cp < '0' || *cp > '9'))
2081 		    {
2082 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2083 				  "%s: line %d: cutoff must be a digit",
2084 				  name, line);
2085 			CHECKERRLIMIT;
2086 			break;
2087 		    }
2088 		    cutoff = k;
2089 		}
2090 		else if(!strcmp(w[j], "reso"))
2091 		{
2092 		    if(k < 0 || (*cp < '0' || *cp > '9'))
2093 		    {
2094 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2095 				  "%s: line %d: reso must be a digit",
2096 				  name, line);
2097 			CHECKERRLIMIT;
2098 			break;
2099 		    }
2100 		    reso = k;
2101 		}
2102 		else if(!strcmp(w[j], "amp"))
2103 		{
2104 		    amp = k;
2105 		}
2106 	    }
2107 	    if(isremove)
2108 		remove_soundfont(sf_file);
2109 	    else
2110 		add_soundfont(sf_file, order, cutoff, reso, amp);
2111 	}
2112 	else if(!strcmp(w[0], "font"))
2113 	{
2114 	    int bank, preset, keynote;
2115 	    if(words < 2)
2116 	    {
2117 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2118 			  "%s: line %d: no font command", name, line);
2119 		CHECKERRLIMIT;
2120 		continue;
2121 	    }
2122 	    if(!strcmp(w[1], "exclude"))
2123 	    {
2124 		if(words < 3)
2125 		{
2126 		    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2127 			      "%s: line %d: No bank/preset/key is given",
2128 			      name, line);
2129 		    CHECKERRLIMIT;
2130 		    continue;
2131 		}
2132 		bank = atoi(w[2]);
2133 		if(words >= 4)
2134 		    preset = atoi(w[3]) - progbase;
2135 		else
2136 		    preset = -1;
2137 		if(words >= 5)
2138 		    keynote = atoi(w[4]);
2139 		else
2140 		    keynote = -1;
2141 		if(exclude_soundfont(bank, preset, keynote))
2142 		{
2143 		    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2144 			      "%s: line %d: No soundfont is given",
2145 			      name, line);
2146 		    CHECKERRLIMIT;
2147 		}
2148 	    }
2149 	    else if(!strcmp(w[1], "order"))
2150 	    {
2151 		int order;
2152 		if(words < 4)
2153 		{
2154 		    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2155 			      "%s: line %d: No order/bank is given",
2156 			      name, line);
2157 		    CHECKERRLIMIT;
2158 		    continue;
2159 		}
2160 		order = atoi(w[2]);
2161 		bank = atoi(w[3]);
2162 		if(words >= 5)
2163 		    preset = atoi(w[4]) - progbase;
2164 		else
2165 		    preset = -1;
2166 		if(words >= 6)
2167 		    keynote = atoi(w[5]);
2168 		else
2169 		    keynote = -1;
2170 		if(order_soundfont(bank, preset, keynote, order))
2171 		{
2172 		    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2173 			      "%s: line %d: No soundfont is given",
2174 			      name, line);
2175 		    CHECKERRLIMIT;
2176 		}
2177 	    }
2178 	}
2179 	else if(!strcmp(w[0], "progbase"))
2180 	{
2181 	    if(words < 2 || *w[1] < '0' || *w[1] > '9')
2182 	    {
2183 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2184 			  "%s: line %d: syntax error", name, line);
2185 		CHECKERRLIMIT;
2186 		continue;
2187 	    }
2188 	    progbase = atoi(w[1]);
2189 	}
2190 	else if(!strcmp(w[0], "map")) /* map <name> set1 elem1 set2 elem2 */
2191 	{
2192 	    int arg[5], isdrum;
2193 
2194 	    if(words != 6)
2195 	    {
2196 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2197 			  "%s: line %d: syntax error", name, line);
2198 		CHECKERRLIMIT;
2199 		continue;
2200 	    }
2201 	    if((arg[0] = mapname2id(w[1], &isdrum)) == -1)
2202 	    {
2203 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2204 			  "%s: line %d: Invalid map name: %s", name, line, w[1]);
2205 		CHECKERRLIMIT;
2206 		continue;
2207 	    }
2208 	    for(i = 2; i < 6; i++)
2209 		arg[i - 1] = atoi(w[i]);
2210 	    if(isdrum)
2211 	    {
2212 		arg[1] -= progbase;
2213 		arg[3] -= progbase;
2214 	    }
2215 	    else
2216 	    {
2217 		arg[2] -= progbase;
2218 		arg[4] -= progbase;
2219 	    }
2220 
2221 	    for(i = 1; i < 5; i++)
2222 		if(arg[i] < 0 || arg[i] > 127)
2223 		    break;
2224 	    if(i != 5)
2225 	    {
2226 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2227 			  "%s: line %d: Invalid parameter", name, line);
2228 		CHECKERRLIMIT;
2229 		continue;
2230 	    }
2231 	    set_instrument_map(arg[0], arg[1], arg[2], arg[3], arg[4]);
2232 	}
2233 
2234 	/*
2235 	 * Standard configurations
2236 	 */
2237 	else if(!strcmp(w[0], "dir"))
2238 	{
2239 	    if(words < 2)
2240 	    {
2241 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2242 			  "%s: line %d: No directory given", name, line);
2243 		CHECKERRLIMIT;
2244 		continue;
2245 	    }
2246 	    for(i = 1; i < words; i++)
2247 		add_to_pathlist(w[i]);
2248 	}
2249 	else if(!strcmp(w[0], "source") || !strcmp(w[0], "trysource"))
2250 	{
2251 	    if(words < 2)
2252 	    {
2253 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2254 			  "%s: line %d: No file name given", name, line);
2255 		CHECKERRLIMIT;
2256 		continue;
2257 	    }
2258 	    for(i = 1; i < words; i++)
2259 	    {
2260 		int status;
2261 		rcf_count++;
2262 		status = read_config_file(w[i], 0, !strcmp(w[0], "trysource"));
2263 		rcf_count--;
2264 		switch (status) {
2265 		case READ_CONFIG_SUCCESS:
2266 		    break;
2267 		case READ_CONFIG_ERROR:
2268 		    CHECKERRLIMIT;
2269 		    continue;
2270 		case READ_CONFIG_RECURSION:
2271 		    reuse_mblock(&varbuf);
2272 		    close_file(tf);
2273 		    return READ_CONFIG_RECURSION;
2274 		case READ_CONFIG_FILE_NOT_FOUND:
2275 		    break;
2276 		}
2277 	    }
2278 	}
2279 	else if(!strcmp(w[0], "default"))
2280 	{
2281 	    if(words != 2)
2282 	    {
2283 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2284 			  "%s: line %d: Must specify exactly one patch name",
2285 			  name, line);
2286 		CHECKERRLIMIT;
2287 		continue;
2288 	    }
2289 	    strncpy(def_instr_name, w[1], 255);
2290 	    def_instr_name[255] = '\0';
2291 	    default_instrument_name = def_instr_name;
2292 	}
2293 	/* drumset [mapid] num */
2294 	else if(!strcmp(w[0], "drumset"))
2295 	{
2296 	    int newmapid, isdrum, newbankno;
2297 
2298 	    if(words < 2)
2299 	    {
2300 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2301 			  "%s: line %d: No drum set number given", name, line);
2302 		CHECKERRLIMIT;
2303 		continue;
2304 	    }
2305 	    if (words != 2 && !isdigit(*w[1]))
2306 	    {
2307 		if ((newmapid = mapname2id(w[1], &isdrum)) == -1 || !isdrum)
2308 		{
2309 		    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2310 			  "%s: line %d: Invalid drum set map name: %s", name, line, w[1]);
2311 		    CHECKERRLIMIT;
2312 		    continue;
2313 		}
2314 		words--;
2315 		memmove(&w[1], &w[2], sizeof w[0] * words);
2316 	    }
2317 	    else
2318 		newmapid = INST_NO_MAP;
2319 	    i = atoi(w[1]) - progbase;
2320 	    if(i < 0 || i > 127)
2321 	    {
2322 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2323 			  "%s: line %d: Drum set must be between %d and %d",
2324 			  name, line,
2325 			  progbase, progbase + 127);
2326 		CHECKERRLIMIT;
2327 		continue;
2328 	    }
2329 
2330 	    newbankno = i;
2331 	    i = alloc_instrument_map_bank(1, newmapid, i);
2332 	    if (i == -1)
2333 	    {
2334 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2335 			  "%s: line %d: No free drum set available to map",
2336 			  name, line);
2337 		CHECKERRLIMIT;
2338 		continue;
2339 	    }
2340 
2341 	    if(words == 2)
2342 	    {
2343 		bank = drumset[i];
2344 		bankno = i;
2345 		mapid = newmapid;
2346 		origbankno = newbankno;
2347 		dr = 1;
2348 	    }
2349 	    else
2350 	    {
2351 		if(words < 4 || *w[2] < '0' || *w[2] > '9')
2352 		{
2353 		    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2354 			      "%s: line %d: syntax error", name, line);
2355 		    CHECKERRLIMIT;
2356 		    continue;
2357 		}
2358 		if (set_patchconf(name, line, drumset[i], &w[2], 1, newmapid, newbankno, i))
2359 		{
2360 		    CHECKERRLIMIT;
2361 		    continue;
2362 		}
2363 	    }
2364 	}
2365 	/* bank [mapid] num */
2366 	else if(!strcmp(w[0], "bank"))
2367 	{
2368 	    int newmapid, isdrum, newbankno;
2369 
2370 	    if(words < 2)
2371 	    {
2372 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2373 			  "%s: line %d: No bank number given", name, line);
2374 		CHECKERRLIMIT;
2375 		continue;
2376 	    }
2377 	    if (words != 2 && !isdigit(*w[1]))
2378 	    {
2379 		if ((newmapid = mapname2id(w[1], &isdrum)) == -1 || isdrum)
2380 		{
2381 		    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2382 			  "%s: line %d: Invalid bank map name: %s", name, line, w[1]);
2383 		    CHECKERRLIMIT;
2384 		    continue;
2385 		}
2386 		words--;
2387 		memmove(&w[1], &w[2], sizeof w[0] * words);
2388 	    }
2389 	    else
2390 		newmapid = INST_NO_MAP;
2391 	    i = atoi(w[1]);
2392 	    if(i < 0 || i > 127)
2393 	    {
2394 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2395 			  "%s: line %d: Tone bank must be between 0 and 127",
2396 			  name, line);
2397 		CHECKERRLIMIT;
2398 		continue;
2399 	    }
2400 
2401 	    newbankno = i;
2402 	    i = alloc_instrument_map_bank(0, newmapid, i);
2403 	    if (i == -1)
2404 	    {
2405 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2406 			  "%s: line %d: No free tone bank available to map",
2407 			  name, line);
2408 		CHECKERRLIMIT;
2409 		continue;
2410 	    }
2411 
2412 	    if(words == 2)
2413 	    {
2414 		bank = tonebank[i];
2415 		bankno = i;
2416 		mapid = newmapid;
2417 		origbankno = newbankno;
2418 		dr = 0;
2419 	    }
2420 	    else
2421 	    {
2422 		if(words < 4 || *w[2] < '0' || *w[2] > '9')
2423 		{
2424 		    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2425 			      "%s: line %d: syntax error", name, line);
2426 		    CHECKERRLIMIT;
2427 		    continue;
2428 		}
2429 		if (set_patchconf(name, line, tonebank[i], &w[2], 0, newmapid, newbankno, i))
2430 		{
2431 		    CHECKERRLIMIT;
2432 		    continue;
2433 		}
2434 	    }
2435 	}
2436 	else
2437 	{
2438 	    if(words < 2 || *w[0] < '0' || *w[0] > '9')
2439 	    {
2440 		if(extension_flag)
2441 		    continue;
2442 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2443 			  "%s: line %d: syntax error", name, line);
2444 		CHECKERRLIMIT;
2445 		continue;
2446 	    }
2447 	    if (set_patchconf(name, line, bank, w, dr, mapid, origbankno, bankno))
2448 	    {
2449 		CHECKERRLIMIT;
2450 		continue;
2451 	    }
2452 	}
2453     }
2454     if(errno)
2455     {
2456 	ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2457 		  "Can't read %s: %s", name, strerror(errno));
2458 	errcnt++;
2459     }
2460     reuse_mblock(&varbuf);
2461     close_file(tf);
2462     return (errcnt == 0) ? READ_CONFIG_SUCCESS : READ_CONFIG_ERROR;
2463 }
2464 
2465 #ifdef SUPPORT_SOCKET
2466 
2467 #if defined(__W32__) && !defined(MAIL_NAME)
2468 #define MAIL_NAME "anonymous"
2469 #endif /* __W32__ */
2470 
2471 #ifdef MAIL_NAME
2472 #define get_username() MAIL_NAME
2473 #else /* MAIL_NAME */
2474 #include <pwd.h>
get_username(void)2475 static char *get_username(void)
2476 {
2477     char *p;
2478     struct passwd *pass;
2479 
2480     /* USER
2481      * LOGIN
2482      * LOGNAME
2483      * getpwnam()
2484      */
2485 
2486     if((p = getenv("USER")) != NULL)
2487         return p;
2488     if((p = getenv("LOGIN")) != NULL)
2489         return p;
2490     if((p = getenv("LOGNAME")) != NULL)
2491         return p;
2492 
2493     pass = getpwuid(getuid());
2494     if(pass == NULL)
2495         return "nobody";
2496     return pass->pw_name;
2497 }
2498 #endif /* MAIL_NAME */
2499 
init_mail_addr(void)2500 static void init_mail_addr(void)
2501 {
2502     char addr[BUFSIZ];
2503 
2504     sprintf(addr, "%s%s", get_username(), MAIL_DOMAIN);
2505     user_mailaddr = safe_strdup(addr);
2506 }
2507 #endif /* SUPPORT_SOCKET */
2508 
read_user_config_file(void)2509 static int read_user_config_file(void)
2510 {
2511     char *home;
2512     char path[BUFSIZ];
2513     int status;
2514 
2515     home = getenv("HOME");
2516 #ifdef __W32__
2517 /* HOME or home */
2518     if(home == NULL)
2519 	home = getenv("home");
2520 #endif
2521     if(home == NULL)
2522     {
2523 	ctl->cmsg(CMSG_INFO, VERB_NOISY,
2524 		  "Warning: HOME environment is not defined.");
2525 	return 0;
2526     }
2527 
2528 #ifdef __W32__
2529 /* timidity.cfg or _timidity.cfg or .timidity.cfg*/
2530     sprintf(path, "%s" PATH_STRING "timidity.cfg", home);
2531     status = read_config_file(path, 0, 1);
2532     if (status != READ_CONFIG_FILE_NOT_FOUND)
2533         return status;
2534 
2535     sprintf(path, "%s" PATH_STRING "_timidity.cfg", home);
2536     status = read_config_file(path, 0, 1);
2537     if (status != READ_CONFIG_FILE_NOT_FOUND)
2538         return status;
2539 #endif
2540 
2541     sprintf(path, "%s" PATH_STRING ".timidity.cfg", home);
2542     status = read_config_file(path, 0, 1);
2543     if (status != READ_CONFIG_FILE_NOT_FOUND)
2544         return status;
2545 
2546     return 0;
2547 }
2548 
tmdy_free_config(void)2549 MAIN_INTERFACE void tmdy_free_config(void)
2550 {
2551 	free_tone_bank();
2552 	free_instrument_map();
2553 	clean_up_pathlist();
2554 }
2555 
set_extension_modes(char * flag)2556 int set_extension_modes(char *flag)
2557 {
2558 	return parse_opt_E(flag);
2559 }
2560 
set_ctl(char * cp)2561 int set_ctl(char *cp)
2562 {
2563 	return parse_opt_i(cp);
2564 }
2565 
set_play_mode(char * cp)2566 int set_play_mode(char *cp)
2567 {
2568 	return parse_opt_O(cp);
2569 }
2570 
set_wrd(char * w)2571 int set_wrd(char *w)
2572 {
2573 	return parse_opt_W(w);
2574 }
2575 
2576 #ifdef __W32__
2577 int opt_evil_mode = 0;
2578 #ifdef SMFCONV
2579 int opt_rcpcv_dll = 0;
2580 #endif	/* SMFCONV */
2581 #endif	/* __W32__ */
2582 static int   try_config_again = 0;
2583 int32 opt_output_rate = 0;
2584 static char *opt_output_name = NULL;
2585 static StringTable opt_config_string;
2586 #ifdef SUPPORT_SOUNDSPEC
2587 static double spectrogram_update_sec = 0.0;
2588 #endif /* SUPPORT_SOUNDSPEC */
2589 int opt_buffer_fragments = -1;
2590 
set_tim_opt_short(int c,char * optarg)2591 MAIN_INTERFACE int set_tim_opt_short(int c, char *optarg)
2592 {
2593 	int err = 0;
2594 
2595 	switch (c) {
2596 	case '4':
2597 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2598 				"-4 option is obsoleted.  Please use -N");
2599 		return 1;
2600 	case 'A':
2601 		if (*optarg != ',' && *optarg != 'a')
2602 			err += parse_opt_A(optarg);
2603 		if (strchr(optarg, ','))
2604 			err += parse_opt_drum_power(strchr(optarg, ',') + 1);
2605 		if (strchr(optarg, 'a'))
2606 			opt_amp_compensation = 1;
2607 		return err;
2608 	case 'a':
2609 		antialiasing_allowed = 1;
2610 		break;
2611 	case 'B':
2612 		return parse_opt_B(optarg);
2613 	case 'C':
2614 		return parse_opt_C(optarg);
2615 	case 'c':
2616 		return parse_opt_c(optarg);
2617 	case 'D':
2618 		return parse_opt_D(optarg);
2619 	case 'd':
2620 		return parse_opt_d(optarg);
2621 	case 'E':
2622 		return parse_opt_E(optarg);
2623 	case 'e':
2624 		return parse_opt_e(optarg);
2625 	case 'F':
2626 		adjust_panning_immediately = (adjust_panning_immediately) ? 0 : 1;
2627 		break;
2628 	case 'f':
2629 		fast_decay = (fast_decay) ? 0 : 1;
2630 		break;
2631 	case 'G':
2632 		return parse_opt_G(optarg);
2633 	case 'g':
2634 		return parse_opt_g(optarg);
2635 	case 'H':
2636 		return parse_opt_H(optarg);
2637 	case 'h':
2638 		return parse_opt_h(optarg);
2639 	case 'I':
2640 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
2641 				"-I option is obsoleted.  Please use -Ei");
2642 		return 1;
2643 	case 'i':
2644 		return parse_opt_i(optarg);
2645 	case 'j':
2646 		opt_realtime_playing = (opt_realtime_playing) ? 0 : 1;
2647 		break;
2648 	case 'K':
2649 		return parse_opt_K(optarg);
2650 	case 'k':
2651 		return parse_opt_k(optarg);
2652 	case 'L':
2653 		return parse_opt_L(optarg);
2654 	case 'M':
2655 		return parse_opt_M(optarg);
2656 	case 'm':
2657 		return parse_opt_m(optarg);
2658 	case 'N':
2659 		return parse_opt_N(optarg);
2660 	case 'O':
2661 		return parse_opt_O(optarg);
2662 	case 'o':
2663 		return parse_opt_o(optarg);
2664 	case 'P':
2665 		return parse_opt_P(optarg);
2666 	case 'p':
2667 		if (*optarg != 'a')
2668 			err += parse_opt_p(optarg);
2669 		if (strchr(optarg, 'a'))
2670 			auto_reduce_polyphony = (auto_reduce_polyphony) ? 0 : 1;
2671 		return err;
2672 	case 'Q':
2673 		return parse_opt_Q(optarg);
2674 	case 'q':
2675 		return parse_opt_q(optarg);
2676 	case 'R':
2677 		return parse_opt_R(optarg);
2678 	case 'S':
2679 		return parse_opt_S(optarg);
2680 	case 's':
2681 		return parse_opt_s(optarg);
2682 	case 'T':
2683 		return parse_opt_T(optarg);
2684 	case 't':
2685 		return parse_opt_t(optarg);
2686 	case 'U':
2687 		free_instruments_afterwards = 1;
2688 		break;
2689 	case 'V':
2690 		return parse_opt_volume_curve(optarg);
2691 	case 'v':
2692 		return parse_opt_v(optarg);
2693 	case 'W':
2694 		return parse_opt_W(optarg);
2695 #ifdef __W32__
2696 	case 'w':
2697 		return parse_opt_w(optarg);
2698 #endif
2699 	case 'x':
2700 		return parse_opt_x(optarg);
2701 	case 'Z':
2702 		if (strncmp(optarg, "pure", 4))
2703 			return parse_opt_Z(optarg);
2704 		else
2705 			return parse_opt_Z1(optarg + 4);
2706 	default:
2707 		return 1;
2708 	}
2709 	return 0;
2710 }
2711 
2712 #ifdef __W32__
set_tim_opt_short_cfg(int c,char * optarg)2713 MAIN_INTERFACE int set_tim_opt_short_cfg(int c, char *optarg)
2714 {
2715 	switch (c) {
2716 	case 'c':
2717 		return parse_opt_c(optarg);
2718 	}
2719 	return 0;
2720 }
2721 #endif
2722 
2723 /* -------- getopt_long -------- */
set_tim_opt_long(int c,char * optarg,int index)2724 MAIN_INTERFACE int set_tim_opt_long(int c, char *optarg, int index)
2725 {
2726 	const struct option *the_option = &(longopts[index]);
2727 	char *arg;
2728 
2729 	if (c == '?')	/* getopt_long failed parsing */
2730 		parse_opt_fail(optarg);
2731 	else if (c < TIM_OPT_FIRST)
2732 		return set_tim_opt_short(c, optarg);
2733 	if (! strncmp(the_option->name, "no-", 3))
2734 		arg = "no";		/* `reverse' switch */
2735 	else
2736 		arg = optarg;
2737 	switch (c) {
2738 	case TIM_OPT_VOLUME:
2739 		return parse_opt_A(arg);
2740 	case TIM_OPT_DRUM_POWER:
2741 		return parse_opt_drum_power(arg);
2742 	case TIM_OPT_VOLUME_COMP:
2743 		return parse_opt_volume_comp(arg);
2744 	case TIM_OPT_ANTI_ALIAS:
2745 		return parse_opt_a(arg);
2746 	case TIM_OPT_BUFFER_FRAGS:
2747 		return parse_opt_B(arg);
2748 	case TIM_OPT_CONTROL_RATIO:
2749 		return parse_opt_C(arg);
2750 	case TIM_OPT_CONFIG_FILE:
2751 		return parse_opt_c(arg);
2752 	case TIM_OPT_DRUM_CHANNEL:
2753 		return parse_opt_D(arg);
2754 	case TIM_OPT_IFACE_PATH:
2755 		return parse_opt_d(arg);
2756 	case TIM_OPT_EXT:
2757 		return parse_opt_E(arg);
2758 	case TIM_OPT_MOD_WHEEL:
2759 		return parse_opt_mod_wheel(arg);
2760 	case TIM_OPT_PORTAMENTO:
2761 		return parse_opt_portamento(arg);
2762 	case TIM_OPT_VIBRATO:
2763 		return parse_opt_vibrato(arg);
2764 	case TIM_OPT_CH_PRESS:
2765 		return parse_opt_ch_pressure(arg);
2766 	case TIM_OPT_MOD_ENV:
2767 		return parse_opt_mod_env(arg);
2768 	case TIM_OPT_TRACE_TEXT:
2769 		return parse_opt_trace_text(arg);
2770 	case TIM_OPT_OVERLAP:
2771 		return parse_opt_overlap_voice(arg);
2772 	case TIM_OPT_TEMPER_CTRL:
2773 		return parse_opt_temper_control(arg);
2774 	case TIM_OPT_DEFAULT_MID:
2775 		return parse_opt_default_mid(arg);
2776 	case TIM_OPT_SYSTEM_MID:
2777 		return parse_opt_system_mid(arg);
2778 	case TIM_OPT_DEFAULT_BANK:
2779 		return parse_opt_default_bank(arg);
2780 	case TIM_OPT_FORCE_BANK:
2781 		return parse_opt_force_bank(arg);
2782 	case TIM_OPT_DEFAULT_PGM:
2783 		return parse_opt_default_program(arg);
2784 	case TIM_OPT_FORCE_PGM:
2785 		return parse_opt_force_program(arg);
2786 	case TIM_OPT_DELAY:
2787 		return parse_opt_delay(arg);
2788 	case TIM_OPT_CHORUS:
2789 		return parse_opt_chorus(arg);
2790 	case TIM_OPT_REVERB:
2791 		return parse_opt_reverb(arg);
2792 	case TIM_OPT_VOICE_LPF:
2793 		return parse_opt_voice_lpf(arg);
2794 	case TIM_OPT_NS:
2795 		return parse_opt_noise_shaping(arg);
2796 #ifndef FIXED_RESAMPLATION
2797 	case TIM_OPT_RESAMPLE:
2798 		return parse_opt_resample(arg);
2799 #endif
2800 	case TIM_OPT_EVIL:
2801 		return parse_opt_e(arg);
2802 	case TIM_OPT_FAST_PAN:
2803 		return parse_opt_F(arg);
2804 	case TIM_OPT_FAST_DECAY:
2805 		return parse_opt_f(arg);
2806 	case TIM_OPT_SEGMENT:
2807 		return parse_opt_G(arg);
2808 	case TIM_OPT_SPECTROGRAM:
2809 		return parse_opt_g(arg);
2810 	case TIM_OPT_KEYSIG:
2811 		return parse_opt_H(arg);
2812 	case TIM_OPT_HELP:
2813 		return parse_opt_h(arg);
2814 	case TIM_OPT_INTERFACE:
2815 		return parse_opt_i(arg);
2816 	case TIM_OPT_VERBOSE:
2817 		return parse_opt_verbose(arg);
2818 	case TIM_OPT_QUIET:
2819 		return parse_opt_quiet(arg);
2820 	case TIM_OPT_TRACE:
2821 		return parse_opt_trace(arg);
2822 	case TIM_OPT_LOOP:
2823 		return parse_opt_loop(arg);
2824 	case TIM_OPT_RANDOM:
2825 		return parse_opt_random(arg);
2826 	case TIM_OPT_SORT:
2827 		return parse_opt_sort(arg);
2828 #ifdef IA_ALSASEQ
2829 	case TIM_OPT_BACKGROUND:
2830 		return parse_opt_background(arg);
2831 	case TIM_OPT_RT_PRIO:
2832 		return parse_opt_rt_prio(arg);
2833 	case TIM_OPT_SEQ_PORTS:
2834 		return parse_opt_seq_ports(arg);
2835 #endif
2836 #if defined(IA_WINSYN) || defined(IA_PORTMIDISYN) || defined(IA_NPSYN) || defined(IA_W32G_SYN) || defined(IA_W32GUI)
2837 	case TIM_OPT_RTSYN_LATENCY:
2838 		return parse_opt_rtsyn_latency(arg);
2839 #endif
2840 	case TIM_OPT_REALTIME_LOAD:
2841 		return parse_opt_j(arg);
2842 	case TIM_OPT_ADJUST_KEY:
2843 		return parse_opt_K(arg);
2844 	case TIM_OPT_VOICE_QUEUE:
2845 		return parse_opt_k(arg);
2846 	case TIM_OPT_PATCH_PATH:
2847 		return parse_opt_L(arg);
2848 	case TIM_OPT_PCM_FILE:
2849 		return parse_opt_M(arg);
2850 	case TIM_OPT_DECAY_TIME:
2851 		return parse_opt_m(arg);
2852 	case TIM_OPT_INTERPOLATION:
2853 		return parse_opt_N(arg);
2854 	case TIM_OPT_OUTPUT_MODE:
2855 		return parse_opt_O(arg);
2856 	case TIM_OPT_OUTPUT_STEREO:
2857 		if (! strcmp(the_option->name, "output-mono"))
2858 			/* --output-mono == --output-stereo=no */
2859 			arg = "no";
2860 		return parse_opt_output_stereo(arg);
2861 	case TIM_OPT_OUTPUT_SIGNED:
2862 		if (! strcmp(the_option->name, "output-unsigned"))
2863 			/* --output-unsigned == --output-signed=no */
2864 			arg = "no";
2865 		return parse_opt_output_signed(arg);
2866 	case TIM_OPT_OUTPUT_BITWIDTH:
2867 		if (! strcmp(the_option->name, "output-16bit"))
2868 			arg = "16bit";
2869 		else if (! strcmp(the_option->name, "output-24bit"))
2870 			arg = "24bit";
2871 		else if (! strcmp(the_option->name, "output-8bit"))
2872 			arg = "8bit";
2873 		return parse_opt_output_bitwidth(arg);
2874 	case TIM_OPT_OUTPUT_FORMAT:
2875 		if (! strcmp(the_option->name, "output-linear"))
2876 			arg = "linear";
2877 		else if (! strcmp(the_option->name, "output-ulaw"))
2878 			arg = "ulaw";
2879 		else if (! strcmp(the_option->name, "output-alaw"))
2880 			arg = "alaw";
2881 		return parse_opt_output_format(arg);
2882 	case TIM_OPT_OUTPUT_SWAB:
2883 		return parse_opt_output_swab(arg);
2884 #ifdef AU_FLAC
2885 	case TIM_OPT_FLAC_VERIFY:
2886 		return parse_opt_flac_verify(arg);
2887 	case TIM_OPT_FLAC_PADDING:
2888 		return parse_opt_flac_padding(arg);
2889 	case TIM_OPT_FLAC_COMPLEVEL:
2890 		return parse_opt_flac_complevel(arg);
2891 #ifdef AU_OGGFLAC
2892 	case TIM_OPT_FLAC_OGGFLAC:
2893 		return parse_opt_flac_oggflac(arg);
2894 #endif /* AU_OGGFLAC */
2895 #endif /* AU_FLAC */
2896 #ifdef AU_SPEEX
2897 	case TIM_OPT_SPEEX_QUALITY:
2898 		return parse_opt_speex_quality(arg);
2899 	case TIM_OPT_SPEEX_VBR:
2900 		return parse_opt_speex_vbr(arg);
2901 	case TIM_OPT_SPEEX_ABR:
2902 		return parse_opt_speex_abr(arg);
2903 	case TIM_OPT_SPEEX_VAD:
2904 		return parse_opt_speex_vad(arg);
2905 	case TIM_OPT_SPEEX_DTX:
2906 		return parse_opt_speex_dtx(arg);
2907 	case TIM_OPT_SPEEX_COMPLEXITY:
2908 		return parse_opt_speex_complexity(arg);
2909 	case TIM_OPT_SPEEX_NFRAMES:
2910 		return parse_opt_speex_nframes(arg);
2911 #endif /* AU_SPEEX */
2912 	case TIM_OPT_OUTPUT_FILE:
2913 		return parse_opt_o(arg);
2914 	case TIM_OPT_PATCH_FILE:
2915 		return parse_opt_P(arg);
2916 	case TIM_OPT_POLYPHONY:
2917 		return parse_opt_p(arg);
2918 	case TIM_OPT_POLY_REDUCE:
2919 		return parse_opt_p1(arg);
2920 	case TIM_OPT_MUTE:
2921 		return parse_opt_Q(arg);
2922 	case TIM_OPT_TEMPER_MUTE:
2923 		return parse_opt_Q1(arg);
2924 	case TIM_OPT_PRESERVE_SILENCE:
2925 		return parse_opt_preserve_silence(arg);
2926 	case TIM_OPT_AUDIO_BUFFER:
2927 		return parse_opt_q(arg);
2928 	case TIM_OPT_CACHE_SIZE:
2929 		return parse_opt_S(arg);
2930 	case TIM_OPT_SAMPLE_FREQ:
2931 		return parse_opt_s(arg);
2932 	case TIM_OPT_ADJUST_TEMPO:
2933 		return parse_opt_T(arg);
2934 	case TIM_OPT_CHARSET:
2935 		return parse_opt_t(arg);
2936 	case TIM_OPT_UNLOAD_INST:
2937 		return parse_opt_U(arg);
2938 	case TIM_OPT_VOLUME_CURVE:
2939 		return parse_opt_volume_curve(arg);
2940 	case TIM_OPT_VERSION:
2941 		return parse_opt_v(arg);
2942 	case TIM_OPT_WRD:
2943 		return parse_opt_W(arg);
2944 #ifdef __W32__
2945 	case TIM_OPT_RCPCV_DLL:
2946 		return parse_opt_w(arg);
2947 #endif
2948 	case TIM_OPT_CONFIG_STR:
2949 		return parse_opt_x(arg);
2950 	case TIM_OPT_FREQ_TABLE:
2951 		return parse_opt_Z(arg);
2952 	case TIM_OPT_PURE_INT:
2953 		return parse_opt_Z1(arg);
2954 	case TIM_OPT_MODULE:
2955 		return parse_opt_default_module(arg);
2956 	default:
2957 		ctl->cmsg(CMSG_FATAL, VERB_NORMAL,
2958 				"[BUG] Inconceivable case branch %d", c);
2959 		abort();
2960 	}
2961 }
2962 
2963 #ifdef __W32__
set_tim_opt_long_cfg(int c,char * optarg,int index)2964 MAIN_INTERFACE int set_tim_opt_long_cfg(int c, char *optarg, int index)
2965 {
2966 	const struct option *the_option = &(longopts[index]);
2967 	char *arg;
2968 
2969 	if (c == '?')	/* getopt_long failed parsing */
2970 		parse_opt_fail(optarg);
2971 	else if (c < TIM_OPT_FIRST)
2972 		return set_tim_opt_short_cfg(c, optarg);
2973 	if (! strncmp(the_option->name, "no-", 3))
2974 		arg = "no";		/* `reverse' switch */
2975 	else
2976 		arg = optarg;
2977 	switch (c) {
2978 	case TIM_OPT_CONFIG_FILE:
2979 		return parse_opt_c(arg);
2980 	}
2981 	return 1;
2982 }
2983 #endif
2984 
parse_opt_A(const char * arg)2985 static inline int parse_opt_A(const char *arg)
2986 {
2987 	/* amplify volume by n percent */
2988 	return set_val_i32(&amplification, atoi(arg), 0, MAX_AMPLIFICATION,
2989 			"Amplification");
2990 }
2991 
parse_opt_drum_power(const char * arg)2992 static inline int parse_opt_drum_power(const char *arg)
2993 {
2994 	/* --drum-power */
2995 	return set_val_i32(&opt_drum_power, atoi(arg), 0, MAX_AMPLIFICATION,
2996 			"Drum power");
2997 }
2998 
parse_opt_volume_comp(const char * arg)2999 static inline int parse_opt_volume_comp(const char *arg)
3000 {
3001 	/* --[no-]volume-compensation */
3002 	opt_amp_compensation = y_or_n_p(arg);
3003 	return 0;
3004 }
3005 
parse_opt_a(const char * arg)3006 static inline int parse_opt_a(const char *arg)
3007 {
3008 	antialiasing_allowed = y_or_n_p(arg);
3009 	return 0;
3010 }
3011 
parse_opt_B(const char * arg)3012 static inline int parse_opt_B(const char *arg)
3013 {
3014 	/* --buffer-fragments */
3015 	const char *p;
3016 
3017 	/* num */
3018 	if (*arg != ',') {
3019 		if (set_value(&opt_buffer_fragments, atoi(arg), 0, 1000,
3020 				"Buffer Fragments (num)"))
3021 			return 1;
3022 	}
3023 	/* bits */
3024 	if ((p = strchr(arg, ',')) != NULL) {
3025 		if (set_value(&audio_buffer_bits, atoi(++p), 1, AUDIO_BUFFER_BITS,
3026 				"Buffer Fragments (bit)"))
3027 			return 1;
3028 	}
3029 	return 0;
3030 }
3031 
parse_opt_C(const char * arg)3032 static inline int parse_opt_C(const char *arg)
3033 {
3034 	if (set_val_i32(&control_ratio, atoi(arg), 0, MAX_CONTROL_RATIO,
3035 			"Control ratio"))
3036 		return 1;
3037 	opt_control_ratio = control_ratio;
3038 	return 0;
3039 }
3040 
parse_opt_c(char * arg)3041 static inline int parse_opt_c(char *arg)
3042 {
3043 #ifdef __W32__
3044 	if (got_a_configuration == 1)
3045 		return 0;
3046 #endif
3047 	if (read_config_file(arg, 0, 0))
3048 		return 1;
3049 	got_a_configuration = 1;
3050 	return 0;
3051 }
3052 
parse_opt_D(const char * arg)3053 static inline int parse_opt_D(const char *arg)
3054 {
3055 	return set_channel_flag(&default_drumchannels, atoi(arg), "Drum channel");
3056 }
3057 
parse_opt_d(const char * arg)3058 static inline int parse_opt_d(const char *arg)
3059 {
3060 	/* dynamic lib root */
3061 #ifdef IA_DYNAMIC
3062 	if (dynamic_lib_root)
3063 		free(dynamic_lib_root);
3064 	dynamic_lib_root = safe_strdup(arg);
3065 	return 0;
3066 #else
3067 	ctl->cmsg(CMSG_WARNING, VERB_NOISY, "-d option is not supported");
3068 	return 1;
3069 #endif	/* IA_DYNAMIC */
3070 }
3071 
parse_opt_E(char * arg)3072 static inline int parse_opt_E(char *arg)
3073 {
3074 	/* undocumented option --ext */
3075 	int err = 0;
3076 
3077 	while (*arg) {
3078 		switch (*arg) {
3079 		case 'w':
3080 			opt_modulation_wheel = 1;
3081 			break;
3082 		case 'W':
3083 			opt_modulation_wheel = 0;
3084 			break;
3085 		case 'p':
3086 			opt_portamento = 1;
3087 			break;
3088 		case 'P':
3089 			opt_portamento = 0;
3090 			break;
3091 		case 'v':
3092 			opt_nrpn_vibrato = 1;
3093 			break;
3094 		case 'V':
3095 			opt_nrpn_vibrato = 0;
3096 			break;
3097 		case 's':
3098 			opt_channel_pressure = 1;
3099 			break;
3100 		case 'S':
3101 			opt_channel_pressure = 0;
3102 			break;
3103 		case 'e':
3104 			opt_modulation_envelope = 1;
3105 			break;
3106 		case 'E':
3107 			opt_modulation_envelope = 0;
3108 			break;
3109 		case 't':
3110 			opt_trace_text_meta_event = 1;
3111 			break;
3112 		case 'T':
3113 			opt_trace_text_meta_event = 0;
3114 			break;
3115 		case 'o':
3116 			opt_overlap_voice_allow = 1;
3117 			break;
3118 		case 'O':
3119 			opt_overlap_voice_allow = 0;
3120 			break;
3121 		case 'z':
3122 			opt_temper_control = 1;
3123 			break;
3124 		case 'Z':
3125 			opt_temper_control = 0;
3126 			break;
3127 		case 'm':
3128 			if (parse_opt_default_mid(arg + 1))
3129 				err++;
3130 			arg += 2;
3131 			break;
3132 		case 'M':
3133 			if (parse_opt_system_mid(arg + 1))
3134 				err++;
3135 			arg += 2;
3136 			break;
3137 		case 'b':
3138 			if (parse_opt_default_bank(arg + 1))
3139 				err++;
3140 			while (isdigit(*(arg + 1)))
3141 				arg++;
3142 			break;
3143 		case 'B':
3144 			if (parse_opt_force_bank(arg + 1))
3145 				err++;
3146 			while (isdigit(*(arg + 1)))
3147 				arg++;
3148 			break;
3149 		case 'i':
3150 			if (parse_opt_default_program(arg + 1))
3151 				err++;
3152 			while (isdigit(*(arg + 1)) || *(arg + 1) == '/')
3153 				arg++;
3154 			break;
3155 		case 'I':
3156 			if (parse_opt_force_program(arg + 1))
3157 				err++;
3158 			while (isdigit(*(arg + 1)) || *(arg + 1) == '/')
3159 				arg++;
3160 			break;
3161 		case 'F':
3162 			if (strncmp(arg + 1, "delay=", 6) == 0) {
3163 				if (parse_opt_delay(arg + 7))
3164 					err++;
3165 			} else if (strncmp(arg + 1, "chorus=", 7) == 0) {
3166 				if (parse_opt_chorus(arg + 8))
3167 					err++;
3168 			} else if (strncmp(arg + 1, "reverb=", 7) == 0) {
3169 				if (parse_opt_reverb(arg + 8))
3170 					err++;
3171 			} else if (strncmp(arg + 1, "ns=", 3) == 0) {
3172 				if (parse_opt_noise_shaping(arg + 4))
3173 					err++;
3174 #ifndef FIXED_RESAMPLATION
3175 			} else if (strncmp(arg + 1, "resamp=", 7) == 0) {
3176 				if (parse_opt_resample(arg + 8))
3177 					err++;
3178 #endif
3179 			}
3180 			if (err) {
3181 				ctl->cmsg(CMSG_ERROR,
3182 						VERB_NORMAL, "-E%s: unsupported effect", arg);
3183 				return err;
3184 			}
3185 			return err;
3186 		default:
3187 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
3188 					"-E: Illegal mode `%c'", *arg);
3189 			err++;
3190 			break;
3191 		}
3192 		arg++;
3193 	}
3194 	return err;
3195 }
3196 
parse_opt_mod_wheel(const char * arg)3197 static inline int parse_opt_mod_wheel(const char *arg)
3198 {
3199 	/* --[no-]mod-wheel */
3200 	opt_modulation_wheel = y_or_n_p(arg);
3201 	return 0;
3202 }
3203 
parse_opt_portamento(const char * arg)3204 static inline int parse_opt_portamento(const char *arg)
3205 {
3206 	/* --[no-]portamento */
3207 	opt_portamento = y_or_n_p(arg);
3208 	return 0;
3209 }
3210 
parse_opt_vibrato(const char * arg)3211 static inline int parse_opt_vibrato(const char *arg)
3212 {
3213 	/* --[no-]vibrato */
3214 	opt_nrpn_vibrato = y_or_n_p(arg);
3215 	return 0;
3216 }
3217 
parse_opt_ch_pressure(const char * arg)3218 static inline int parse_opt_ch_pressure(const char *arg)
3219 {
3220 	/* --[no-]ch-pressure */
3221 	opt_channel_pressure = y_or_n_p(arg);
3222 	return 0;
3223 }
3224 
parse_opt_mod_env(const char * arg)3225 static inline int parse_opt_mod_env(const char *arg)
3226 {
3227 	/* --[no-]mod-envelope */
3228 	opt_modulation_envelope = y_or_n_p(arg);
3229 	return 0;
3230 }
3231 
parse_opt_trace_text(const char * arg)3232 static inline int parse_opt_trace_text(const char *arg)
3233 {
3234 	/* --[no-]trace-text-meta */
3235 	opt_trace_text_meta_event = y_or_n_p(arg);
3236 	return 0;
3237 }
3238 
parse_opt_overlap_voice(const char * arg)3239 static inline int parse_opt_overlap_voice(const char *arg)
3240 {
3241 	/* --[no-]overlap-voice */
3242 	opt_overlap_voice_allow = y_or_n_p(arg);
3243 	return 0;
3244 }
3245 
parse_opt_temper_control(const char * arg)3246 static inline int parse_opt_temper_control(const char *arg)
3247 {
3248 	/* --[no-]temper-control */
3249 	opt_temper_control = y_or_n_p(arg);
3250 	return 0;
3251 }
3252 
parse_opt_default_mid(char * arg)3253 static inline int parse_opt_default_mid(char *arg)
3254 {
3255 	/* --default-mid */
3256 	int val = str2mID(arg);
3257 
3258 	if (! val) {
3259 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Manufacture ID: Illegal value");
3260 		return 1;
3261 	}
3262 	opt_default_mid = val;
3263 	return 0;
3264 }
3265 
parse_opt_system_mid(char * arg)3266 static inline int parse_opt_system_mid(char *arg)
3267 {
3268 	/* --system-mid */
3269 	int val = str2mID(arg);
3270 
3271 	if (! val) {
3272 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Manufacture ID: Illegal value");
3273 		return 1;
3274 	}
3275 	opt_system_mid = val;
3276 	return 0;
3277 }
3278 
parse_opt_default_bank(const char * arg)3279 static inline int parse_opt_default_bank(const char *arg)
3280 {
3281 	/* --default-bank */
3282 	if (set_value(&default_tonebank, atoi(arg), 0, 0x7f, "Bank number"))
3283 		return 1;
3284 	special_tonebank = -1;
3285 	return 0;
3286 }
3287 
parse_opt_force_bank(const char * arg)3288 static inline int parse_opt_force_bank(const char *arg)
3289 {
3290 	/* --force-bank */
3291 	if (set_value(&special_tonebank, atoi(arg), 0, 0x7f, "Bank number"))
3292 		return 1;
3293 	return 0;
3294 }
3295 
parse_opt_default_program(const char * arg)3296 static inline int parse_opt_default_program(const char *arg)
3297 {
3298 	/* --default-program */
3299 	int prog, i;
3300 	const char *p;
3301 
3302 	if (set_value(&prog, atoi(arg), 0, 0x7f, "Program number"))
3303 		return 1;
3304 	if ((p = strchr(arg, '/')) != NULL) {
3305 		if (set_value(&i, atoi(++p), 1, MAX_CHANNELS, "Program channel"))
3306 			return 1;
3307 		default_program[i - 1] = prog;
3308 	} else
3309 		for (i = 0; i < MAX_CHANNELS; i++)
3310 			default_program[i] = prog;
3311 	return 0;
3312 }
3313 
parse_opt_force_program(const char * arg)3314 static inline int parse_opt_force_program(const char *arg)
3315 {
3316 	/* --force-program */
3317 	const char *p;
3318 	int i;
3319 
3320 	if (set_value(&def_prog, atoi(arg), 0, 0x7f, "Program number"))
3321 		return 1;
3322 	if (ctl->opened)
3323 		set_default_program(def_prog);
3324 	if ((p = strchr(arg, '/')) != NULL) {
3325 		if (set_value(&i, atoi(++p), 1, MAX_CHANNELS, "Program channel"))
3326 			return 1;
3327 		default_program[i - 1] = SPECIAL_PROGRAM;
3328 	} else
3329 		for (i = 0; i < MAX_CHANNELS; i++)
3330 			default_program[i] = SPECIAL_PROGRAM;
3331 	return 0;
3332 }
3333 
set_default_program(int prog)3334 static inline int set_default_program(int prog)
3335 {
3336 	int bank;
3337 	Instrument *ip;
3338 
3339 	bank = (special_tonebank >= 0) ? special_tonebank : default_tonebank;
3340 	if ((ip = play_midi_load_instrument(0, bank, prog)) == NULL)
3341 		return 1;
3342 	default_instrument = ip;
3343 	return 0;
3344 }
3345 
parse_opt_delay(const char * arg)3346 static inline int parse_opt_delay(const char *arg)
3347 {
3348 	/* --delay */
3349 	const char *p;
3350 
3351 	switch (*arg) {
3352 	case '0':
3353 	case 'd':	/* disable */
3354 		effect_lr_mode = -1;
3355 		return 0;
3356 	case 'l':	/* left */
3357 		effect_lr_mode = 0;
3358 		break;
3359 	case 'r':	/* right */
3360 		effect_lr_mode = 1;
3361 		break;
3362 	case 'b':	/* both */
3363 		effect_lr_mode = 2;
3364 		break;
3365 	}
3366 	if ((p = strchr(arg, ',')) != NULL)
3367 		if ((effect_lr_delay_msec = atoi(++p)) < 0) {
3368 			effect_lr_delay_msec = 0;
3369 			effect_lr_mode = -1;
3370 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Invalid delay parameter.");
3371 			return 1;
3372 		}
3373 	return 0;
3374 }
3375 
parse_opt_chorus(const char * arg)3376 static inline int parse_opt_chorus(const char *arg)
3377 {
3378 	/* --chorus */
3379 	const char *p;
3380 
3381 	switch (*arg) {
3382 	case '0':
3383 	case 'd':	/* disable */
3384 		opt_chorus_control = 0;
3385 		opt_surround_chorus = 0;
3386 		break;
3387 	case '1':
3388 	case 'n':	/* normal */
3389 	case '2':
3390 	case 's':	/* surround */
3391 		opt_surround_chorus = (*arg == '2' || *arg == 's') ? 1 : 0;
3392 		if ((p = strchr(arg, ',')) != NULL) {
3393 			if (set_value(&opt_chorus_control, atoi(++p), 0, 0x7f,
3394 					"Chorus level"))
3395 				return 1;
3396 			opt_chorus_control = -opt_chorus_control;
3397 		} else
3398 			opt_chorus_control = 1;
3399 		break;
3400 	default:
3401 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Invalid chorus parameter.");
3402 		return 1;
3403 	}
3404 	return 0;
3405 }
3406 
parse_opt_reverb(const char * arg)3407 static inline int parse_opt_reverb(const char *arg)
3408 {
3409 	/* --reverb */
3410 	const char *p;
3411 
3412 	/* option       action                  opt_reverb_control
3413 	 * reverb=0     no reverb                 0
3414 	 * reverb=1     old reverb                1
3415 	 * reverb=1,n   set reverb level to n   (-1 to -127)
3416 	 * reverb=2     "global" old reverb       2
3417 	 * reverb=2,n   set reverb level to n   (-1 to -127) - 128
3418 	 * reverb=3     new reverb                3
3419 	 * reverb=3,n   set reverb level to n   (-1 to -127) - 256
3420 	 * reverb=4     "global" new reverb       4
3421 	 * reverb=4,n   set reverb level to n   (-1 to -127) - 384
3422 	 *
3423 	 * I think "global" was meant to apply a single global reverb,
3424 	 * without applying any reverb to the channels.  The do_effects()
3425 	 * function in effects.c looks like a good way to do this.
3426 	 *
3427 	 * This is NOT the "correct" way to implement global reverb, we should
3428 	 * really make a new variable just for that.  But if opt_reverb_control
3429 	 * is already used in a similar fashion, rather than creating a new
3430 	 * variable for setting the channel reverb levels, then I guess
3431 	 * maybe this isn't so bad....  It would be nice to create new
3432 	 * variables for both global reverb and channel reverb level settings
3433 	 * in the future, but this will do for now.
3434 	 */
3435 
3436 	switch (*arg) {
3437 	case '0':
3438 	case 'd':	/* disable */
3439 		opt_reverb_control = 0;
3440 		break;
3441 	case '1':
3442 	case 'n':	/* normal */
3443 		if ((p = strchr(arg, ',')) != NULL) {
3444 			if (set_value(&opt_reverb_control, atoi(++p), 1, 0x7f,
3445 					"Reverb level"))
3446 				return 1;
3447 			opt_reverb_control = -opt_reverb_control;
3448 		} else
3449 			opt_reverb_control = 1;
3450 		break;
3451 	case '2':
3452 	case 'g':	/* global */
3453 		if ((p = strchr(arg, ',')) != NULL) {
3454 			if (set_value(&opt_reverb_control, atoi(++p), 1, 0x7f,
3455 					"Reverb level"))
3456 				return 1;
3457 			opt_reverb_control = -opt_reverb_control - 128;
3458 		} else
3459 			opt_reverb_control = 2;
3460 		break;
3461 	case '3':
3462 	case 'f':	/* freeverb */
3463 		return parse_opt_reverb_freeverb(arg, 'f');
3464 	case '4':
3465 	case 'G':	/* global freeverb */
3466 		return parse_opt_reverb_freeverb(arg, 'G');
3467 	default:
3468 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Invalid reverb parameter.");
3469 		return 1;
3470 	}
3471 	return 0;
3472 }
3473 
parse_opt_reverb_freeverb(const char * arg,char type)3474 static int parse_opt_reverb_freeverb(const char *arg, char type)
3475 {
3476 	const char *p;
3477 
3478 	if ((p = strchr(arg, ',')) != NULL)
3479 		p++;
3480 	else
3481 		p = "";
3482 	/* reverb level */
3483 	if (*p && *p != ',') {
3484 		if (set_value(&opt_reverb_control, atoi(p), 1, 0x7f,
3485 				"Reverb level"))
3486 			return 1;
3487 		if (type == 'f')
3488 			opt_reverb_control = -opt_reverb_control - 256;
3489 		else
3490 			opt_reverb_control = -opt_reverb_control - 384;
3491 	} else
3492 		opt_reverb_control = (type == 'f') ? 3 : 4;
3493 	if ((p = strchr(p, ',')) == NULL)
3494 		return 0;
3495 	p++;
3496 	/* ranges 0..10 below determined just to reject an extreme value */
3497 	/* scaleroom */
3498 	if (*p && *p != ',') {
3499 		if (parse_val_float_t(&freeverb_scaleroom, p, 0, 10,
3500 				"Freeverb scaleroom", 1))
3501 			return 1;
3502 	}
3503 	if ((p = strchr(p, ',')) == NULL)
3504 		return 0;
3505 	p++;
3506 	/* offsetroom */
3507 	if (*p && *p != ',') {
3508 		if (parse_val_float_t(&freeverb_offsetroom, p, 0, 10,
3509 				"Freeverb offsetroom", 1))
3510 			return 1;
3511 	}
3512 	if ((p = strchr(p, ',')) == NULL)
3513 		return 0;
3514 	p++;
3515 	/* predelay factor */
3516 	if (*p && *p != ',') {
3517 		int value;
3518 
3519 		if (set_val_i32(&value, atoi(p), 0, 1000,
3520 				"Freeverb predelay factor"))
3521 			return 1;
3522 		reverb_predelay_factor = value / 100.0;
3523 	}
3524 	return 0;
3525 }
3526 
parse_opt_voice_lpf(const char * arg)3527 static inline int parse_opt_voice_lpf(const char *arg)
3528 {
3529 	/* --voice-lpf */
3530 	switch (*arg) {
3531 	case '0':
3532 	case 'd':	/* disable */
3533 		opt_lpf_def = 0;
3534 		break;
3535 	case '1':
3536 	case 'c':	/* chamberlin */
3537 		opt_lpf_def = 1;
3538 		break;
3539 	case '2':
3540 	case 'm':	/* moog */
3541 		opt_lpf_def = 2;
3542 		break;
3543 	default:
3544 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Invalid voice LPF type %s", arg);
3545 		return 1;
3546 	}
3547 	return 0;
3548 }
3549 
3550 /* Noise Shaping filter from
3551  * Kunihiko IMAI <imai@leo.ec.t.kanazawa-u.ac.jp>
3552  */
parse_opt_noise_shaping(const char * arg)3553 static inline int parse_opt_noise_shaping(const char *arg)
3554 {
3555 	/* --noise-shaping */
3556 	if (set_value(&noise_sharp_type, atoi(arg), 0, 4, "Noise shaping type"))
3557 		return 1;
3558 	return 0;
3559 }
3560 
parse_opt_resample(const char * arg)3561 static inline int parse_opt_resample(const char *arg)
3562 {
3563 	/* --resample */
3564 	switch (*arg) {
3565 	case '0':
3566 	case 'd':	/* disable */
3567 		set_current_resampler(RESAMPLE_NONE);
3568 		break;
3569 	case '1':
3570 	case 'l':	/* linear */
3571 		set_current_resampler(RESAMPLE_LINEAR);
3572 		break;
3573 	case '2':
3574 	case 'c':	/* cspline */
3575 		set_current_resampler(RESAMPLE_CSPLINE);
3576 		break;
3577 	case '3':
3578 	case 'L':	/* lagrange */
3579 		set_current_resampler(RESAMPLE_LAGRANGE);
3580 		break;
3581 	case '4':
3582 	case 'n':	/* newton */
3583 		set_current_resampler(RESAMPLE_NEWTON);
3584 		break;
3585 	case '5':
3586 	case 'g':	/* guass */
3587 		set_current_resampler(RESAMPLE_GAUSS);
3588 		break;
3589 	default:
3590 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Invalid resample type %s", arg);
3591 		return 1;
3592 	}
3593 	return 0;
3594 }
3595 
parse_opt_e(const char * arg)3596 static inline int parse_opt_e(const char *arg)
3597 {
3598 	/* evil */
3599 #ifdef __W32__
3600 	opt_evil_mode = 1;
3601 	return 0;
3602 #else
3603 	ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "-e option is not supported");
3604 	return 1;
3605 #endif /* __W32__ */
3606 }
3607 
parse_opt_F(const char * arg)3608 static inline int parse_opt_F(const char *arg)
3609 {
3610 	adjust_panning_immediately = y_or_n_p(arg);
3611 	return 0;
3612 }
3613 
parse_opt_f(const char * arg)3614 static inline int parse_opt_f(const char *arg)
3615 {
3616 	fast_decay = y_or_n_p(arg);
3617 	return 0;
3618 }
3619 
parse_opt_G(const char * arg)3620 static inline int parse_opt_G(const char *arg)
3621 {
3622 	/* play just sub-segment(s) (seconds) */
3623 	TimeSegment *sp;
3624 	const char *p = arg;
3625 	int prev_end;
3626 
3627 	if (strchr(arg, 'm'))
3628 		return parse_opt_G1(arg);
3629 	if (time_segments == NULL) {
3630 		time_segments = (TimeSegment *) safe_malloc(sizeof(TimeSegment));
3631 		time_segments->type = 0;
3632 		if (parse_segment(time_segments, p)) {
3633 			free_time_segments();
3634 			return 1;
3635 		}
3636 		time_segments->prev = time_segments->next = NULL, sp = time_segments;
3637 	} else {
3638 		for (sp = time_segments; sp->next != NULL; sp = sp->next)
3639 			;
3640 		sp->next = (TimeSegment *) safe_malloc(sizeof(TimeSegment));
3641 		sp->next->type = 0;
3642 		if (parse_segment(sp->next, p)) {
3643 			free_time_segments();
3644 			return 1;
3645 		}
3646 		sp->next->prev = sp, sp->next->next = NULL, sp = sp->next;
3647 	}
3648 	while ((p = strchr(p, ',')) != NULL) {
3649 		sp->next = (TimeSegment *) safe_malloc(sizeof(TimeSegment));
3650 		sp->next->type = 0;
3651 		if (parse_segment(sp->next, ++p)) {
3652 			free_time_segments();
3653 			return 1;
3654 		}
3655 		sp->next->prev = sp, sp->next->next = NULL, sp = sp->next;
3656 	}
3657 	prev_end = -1;
3658 	for (sp = time_segments; sp != NULL; sp = sp->next) {
3659 		if (sp->type != 0)
3660 			continue;
3661 		if (sp->begin.s <= prev_end) {
3662 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Segments must be ordered");
3663 			free_time_segments();
3664 			return 1;
3665 		} else if (sp->end.s != -1 && sp->begin.s >= sp->end.s) {
3666 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Segment time must be ordered");
3667 			free_time_segments();
3668 			return 1;
3669 		}
3670 		prev_end = sp->end.s;
3671 	}
3672 	return 0;
3673 }
3674 
parse_opt_G1(const char * arg)3675 static inline int parse_opt_G1(const char *arg)
3676 {
3677 	/* play just sub-segment(s) (measure) */
3678 	TimeSegment *sp;
3679 	const char *p = arg;
3680 	int prev_end_meas, prev_end_beat;
3681 
3682 	if (time_segments == NULL) {
3683 		time_segments = (TimeSegment *) safe_malloc(sizeof(TimeSegment));
3684 		time_segments->type = 1;
3685 		if (parse_segment2(time_segments, p)) {
3686 			free_time_segments();
3687 			return 1;
3688 		}
3689 		time_segments->prev = time_segments->next = NULL, sp = time_segments;
3690 	} else {
3691 		for (sp = time_segments; sp->next != NULL; sp = sp->next)
3692 			;
3693 		sp->next = (TimeSegment *) safe_malloc(sizeof(TimeSegment));
3694 		sp->next->type = 1;
3695 		if (parse_segment2(sp->next, p)) {
3696 			free_time_segments();
3697 			return 1;
3698 		}
3699 		sp->next->prev = sp, sp->next->next = NULL, sp = sp->next;
3700 	}
3701 	while ((p = strchr(p, ',')) != NULL) {
3702 		sp->next = (TimeSegment *) safe_malloc(sizeof(TimeSegment));
3703 		sp->next->type = 1;
3704 		if (parse_segment2(sp->next, ++p)) {
3705 			free_time_segments();
3706 			return 1;
3707 		}
3708 		sp->next->prev = sp, sp->next->next = NULL, sp = sp->next;
3709 	}
3710 	prev_end_meas = prev_end_beat = -1;
3711 	for (sp = time_segments; sp != NULL; sp = sp->next) {
3712 		if (sp->type != 1)
3713 			continue;
3714 		if (sp->begin.m.meas * 16 + sp->begin.m.beat
3715 				<= prev_end_meas * 16 + prev_end_beat) {
3716 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Segments must be ordered");
3717 			free_time_segments();
3718 			return 1;
3719 		} else if (sp->end.m.meas != -1 && sp->end.m.beat != -1
3720 				&& sp->begin.m.meas * 16 + sp->begin.m.beat
3721 				>= sp->end.m.meas * 16 + sp->end.m.beat) {
3722 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Segment time must be ordered");
3723 			free_time_segments();
3724 			return 1;
3725 		}
3726 		prev_end_meas = sp->end.m.meas, prev_end_beat = sp->end.m.beat;
3727 	}
3728 	return 0;
3729 }
3730 
parse_segment(TimeSegment * seg,const char * p)3731 static int parse_segment(TimeSegment *seg, const char *p)
3732 {
3733 	const char *q;
3734 
3735 	if (*p == '-')
3736 		seg->begin.s = 0;
3737 	else if (parse_time(&seg->begin.s, p))
3738 		return 1;
3739 	p = ((q = strchr(p, '-')) == NULL) ? p + strlen(p) : q + 1;
3740 	if (*p == ',' || *p == '\0')
3741 		seg->end.s = -1;
3742 	else if (parse_time(&seg->end.s, p))
3743 		return 1;
3744 	return 0;
3745 }
3746 
parse_segment2(TimeSegment * seg,const char * p)3747 static int parse_segment2(TimeSegment *seg, const char *p)
3748 {
3749 	const char *q;
3750 
3751 	if (*p == '-')
3752 		seg->begin.m.meas = seg->begin.m.beat = 1;
3753 	else if (parse_time2(&seg->begin.m, p))
3754 		return 1;
3755 	p = ((q = strchr(p, '-')) == NULL) ? p + strlen(p) : q + 1;
3756 	if (*p == ',' || *p == 'm')
3757 		seg->end.m.meas = seg->end.m.beat = -1;
3758 	else if (parse_time2(&seg->end.m, p))
3759 		return 1;
3760 	return 0;
3761 }
3762 
parse_time(FLOAT_T * param,const char * p)3763 static int parse_time(FLOAT_T *param, const char *p)
3764 {
3765 	const char *p1, *p2, *p3;
3766 	int min;
3767 	FLOAT_T sec;
3768 
3769 	p1 = ((p1 = strchr(p, ':')) == NULL) ? p + strlen(p) : p1;
3770 	p2 = ((p2 = strchr(p, '-')) == NULL) ? p + strlen(p) : p2;
3771 	p3 = ((p3 = strchr(p, ',')) == NULL) ? p + strlen(p) : p3;
3772 	if ((p1 < p2 && p2 <= p3) || (p1 < p3 && p3 <= p2)) {
3773 		if (set_value(&min, atoi(p), 0, 59, "Segment time (min part)"))
3774 			return 1;
3775 		if (parse_val_float_t(&sec, p1 + 1, 0, 59.999,
3776 				"Segment time (sec+frac part)", 3))
3777 			return 1;
3778 		*param = min * 60 + sec;
3779 	} else if (parse_val_float_t(param, p, 0, 3599.999, "Segment time", 3))
3780 		return 1;
3781 	return 0;
3782 }
3783 
parse_time2(Measure * param,const char * p)3784 static int parse_time2(Measure *param, const char *p)
3785 {
3786 	const char *p1, *p2, *p3;
3787 
3788 	if (set_value(&param->meas, atoi(p), 0, 999, "Segment time (measure)"))
3789 		return 1;
3790 	p1 = ((p1 = strchr(p, '.')) == NULL) ? p + strlen(p) : p1;
3791 	p2 = ((p2 = strchr(p, '-')) == NULL) ? p + strlen(p) : p2;
3792 	p3 = ((p3 = strchr(p, ',')) == NULL) ? p + strlen(p) : p3;
3793 	if ((p1 < p2 && p2 <= p3) || (p1 < p3 && p3 <= p2)) {
3794 		if (set_value(&param->beat, atoi(p1 + 1), 1, 15,
3795 				"Segment time (beat)"))
3796 			return 1;
3797 	} else
3798 		param->beat = 1;
3799 	return 0;
3800 }
3801 
parse_opt_g(const char * arg)3802 static inline int parse_opt_g(const char *arg)
3803 {
3804 #ifdef SUPPORT_SOUNDSPEC
3805 	spectrogram_update_sec = atof(arg);
3806 	if (spectrogram_update_sec <= 0) {
3807 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
3808 				"Invalid -g argument: `%s'", arg);
3809 		return 1;
3810 	}
3811 	view_soundspec_flag = 1;
3812 	return 0;
3813 #else
3814 	ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "-g option is not supported");
3815 	return 1;
3816 #endif	/* SUPPORT_SOUNDSPEC */
3817 }
3818 
parse_opt_H(const char * arg)3819 static inline int parse_opt_H(const char *arg)
3820 {
3821 	/* force keysig (number of sharp/flat) */
3822 	int keysig;
3823 
3824 	if (set_value(&keysig, atoi(arg), -7, 7,
3825 			"Force keysig (number of sHarp(+)/flat(-))"))
3826 		return 1;
3827 	opt_force_keysig = keysig;
3828 	return 0;
3829 }
3830 
3831 __attribute__((noreturn))
3832 #ifndef __BORLANDC__
parse_opt_h(const char * arg)3833 static inline int parse_opt_h(const char *arg)
3834 #else
3835 static int parse_opt_h(const char *arg)
3836 #endif
3837 {
3838 	static char *help_list[] = {
3839 "TiMidity++ %s (C) 1999-2018 Masanao Izumo <iz@onicos.co.jp>",
3840 "The original version (C) 1995 Tuukka Toivonen <tt@cgs.fi>",
3841 "TiMidity is free software and comes with ABSOLUTELY NO WARRANTY.",
3842 "",
3843 #ifdef __W32__
3844 "Win32 version by Davide Moretti <dave@rimini.com>",
3845 "              and Daisuke Aoki <dai@y7.net>",
3846 "",
3847 #endif /* __W32__ */
3848 "Usage:",
3849 "  %s [options] filename [...]",
3850 "",
3851 #ifndef __W32__		/*does not work in Windows */
3852 "  Use \"-\" as filename to read a MIDI file from stdin",
3853 "",
3854 #endif
3855 "Options:",
3856 "  -A n,m     --volume=n, --drum-power=m",
3857 "               Amplify volume by n percent (may cause clipping),",
3858 "                 and amplify drum power by m percent",
3859 "     (a)     --[no-]volume-compensation",
3860 "               Toggle amplify compensation (disabled by default)",
3861 "  -a         --[no-]anti-alias",
3862 "               Enable the anti-aliasing filter",
3863 "  -B n,m     --buffer-fragments=n,m",
3864 "               Set number of buffer fragments(n), and buffer size(2^m)",
3865 "  -C n       --control-ratio=n",
3866 "               Set ratio of sampling and control frequencies",
3867 "  -c file    --config-file=file",
3868 "               Read extra configuration file",
3869 "  -D n       --drum-channel=n",
3870 "               Play drums on channel n",
3871 #ifdef IA_DYNAMIC
3872 "  -d path    --interface-path=path",
3873 "               Set dynamic interface module directory",
3874 #endif /* IA_DYNAMIC */
3875 "  -E mode    --ext=mode",
3876 "               TiMidity sequencer extensional modes:",
3877 "                 mode = w/W : Enable/Disable Modulation wheel",
3878 "                        p/P : Enable/Disable Portamento",
3879 "                        v/V : Enable/Disable NRPN Vibrato",
3880 "                        s/S : Enable/Disable Channel pressure",
3881 "                        e/E : Enable/Disable Modulation Envelope",
3882 "                        t/T : Enable/Disable Trace Text Meta Event at playing",
3883 "                        o/O : Enable/Disable Overlapped voice",
3884 "                        z/Z : Enable/Disable Temperament control",
3885 "                        m<HH>: Define default Manufacture ID <HH> in two hex",
3886 "                        M<HH>: Define system Manufacture ID <HH> in two hex",
3887 "                        b<n>: Use tone bank <n> as the default",
3888 "                        B<n>: Always use tone bank <n>",
3889 "                        i<n/m>: Use program <n> on channel <m> as the default",
3890 "                        I<n/m>: Always use program <n> on channel <m>",
3891 "                        F<args>: For effect.  See below for effect options",
3892 "                   default: -E "
3893 #ifdef MODULATION_WHEEL_ALLOW
3894 "w"
3895 #else
3896 "W"
3897 #endif /* MODULATION_WHEEL_ALLOW */
3898 #ifdef PORTAMENTO_ALLOW
3899 "p"
3900 #else
3901 "P"
3902 #endif /* PORTAMENTO_ALLOW */
3903 #ifdef NRPN_VIBRATO_ALLOW
3904 "v"
3905 #else
3906 "V"
3907 #endif /* NRPN_VIBRATO_ALLOW */
3908 #ifdef GM_CHANNEL_PRESSURE_ALLOW
3909 "s"
3910 #else
3911 "S"
3912 #endif /* GM_CHANNEL_PRESSURE_ALLOW */
3913 #ifdef MODULATION_ENVELOPE_ALLOW
3914 "e"
3915 #else
3916 "E"
3917 #endif /* MODULATION_ENVELOPE_ALLOW */
3918 #ifdef ALWAYS_TRACE_TEXT_META_EVENT
3919 "t"
3920 #else
3921 "T"
3922 #endif /* ALWAYS_TRACE_TEXT_META_EVENT */
3923 #ifdef OVERLAP_VOICE_ALLOW
3924 "o"
3925 #else
3926 "O"
3927 #endif /* OVERLAP_VOICE_ALLOW */
3928 #ifdef TEMPER_CONTROL_ALLOW
3929 "z"
3930 #else
3931 "Z"
3932 #endif /* TEMPER_CONTROL_ALLOW */
3933 ,
3934 #ifdef __W32__
3935 "  -e         --evil",
3936 "               Increase thread priority (evil) - be careful!",
3937 #endif
3938 "  -F         --[no-]fast-panning",
3939 "               Disable/Enable fast panning (toggle on/off, default is on)",
3940 "  -f         --[no-]fast-decay",
3941 "               "
3942 #ifdef FAST_DECAY
3943 "Disable "
3944 #else
3945 "Enable "
3946 #endif
3947 "fast decay mode (toggle)",
3948 "  -G <begin>-<end>[,<begin2>-<end2>,...](m)",
3949 "  --segment=<begin>-<end>[,<begin2>-<end2>,...](m)",
3950 "               Play just sub-segment(s), comma separated segments",
3951 "                 Each segment is dash separated of two time values of:",
3952 "                 <begin>-<end> - defaulted to 0-infinity",
3953 "                 Playing from <begin> to <end>",
3954 "                 Time format: [<minutes>:]<seconds>[.<milliseconds>]",
3955 "                 'm' stands for using measure and beat instead of secs",
3956 "                 Time format: <measure>[.<beat>] (one-origin)",
3957 #ifdef SUPPORT_SOUNDSPEC
3958 "  -g sec     --spectrogram=sec",
3959 "               Open Sound-Spectrogram Window",
3960 #endif /* SUPPORT_SOUNDSPEC */
3961 "  -H n       --force-keysig=n",
3962 "               Force keysig number of sHarp(+)/flat(-) (-7..7)",
3963 "  -h         --help",
3964 "               Display this help message",
3965 "  -i mode    --interface=mode",
3966 "               Select user interface (see below for list)",
3967 #ifdef IA_ALSASEQ
3968 "             --realtime-priority=n (for alsaseq only)",
3969 "               Set the realtime priority (0-100)",
3970 "             --sequencer-ports=n (for alsaseq only)",
3971 "               Set the number of opened sequencer ports (default is 4)",
3972 #endif
3973 #if defined(IA_WINSYN) || defined(IA_PORTMIDISYN) || defined(IA_NPSYN) || defined(IA_W32G_SYN)
3974 "             --rtsyn-latency=sec (for rtsyn only)",
3975 "               Set the realtime latency (sec)",
3976 "                 (default is 0.2 sec, minimum is 0.04 sec)",
3977 #endif
3978 "  -j         --[no-]realtime-load",
3979 "               Realtime load instrument (toggle on/off)",
3980 "  -K n       --adjust-key=n",
3981 "               Adjust key by n half tone (-24..24)",
3982 "  -k msec    --voice-queue=msec",
3983 "               Specify audio queue time limit to reduce voice",
3984 "  -L path    --patch-path=path",
3985 "               Append dir to search path",
3986 "  -M name    --pcm-file=name",
3987 "               Specify PCM filename (*.wav or *.aiff) to be played or:",
3988 "                 \"auto\" : Play *.mid.wav or *.mid.aiff",
3989 "                 \"none\" : Disable this feature (default)",
3990 "  -m msec    --decay-time=msec",
3991 "               Minimum time for a full volume sustained note to decay,",
3992 "                 0 disables",
3993 "  -N n       --interpolation=n",
3994 "               Set the interpolation parameter (depends on -EFresamp option)",
3995 "                 Linear interpolation is used if audio queue < 99%%",
3996 "                 cspline, lagrange:",
3997 "                   Toggle 4-point interpolation (default on)",
3998 "                 newton:",
3999 "                   n'th order Newton polynomial interpolation, n=1-57 odd",
4000 "                 gauss:",
4001 "                   n+1 point Gauss-like interpolation, n=1-34 (default 25)",
4002 "  -O mode    --output-mode=mode",
4003 "               Select output mode and format (see below for list)",
4004 #ifdef AU_FLAC
4005 "             --flac-verify (for Ogg FLAC only)",
4006 "               Verify a correct encoding",
4007 "             --flac-padding=n (for Ogg FLAC only)",
4008 "               Write a PADDING block of length n",
4009 "             --flac-complevel=n (for Ogg FLAC only)",
4010 "               Set compression level n:[0..8]",
4011 #ifdef AU_OGGFLAC
4012 "             --oggflac (for Ogg FLAC only)",
4013 "               Output OggFLAC stream (experimental)",
4014 #endif /* AU_OGGFLAC */
4015 #endif /* AU_FLAC */
4016 #ifdef AU_SPEEX
4017 "             --speex-quality=n (for Ogg Speex only)",
4018 "               Encoding quality n:[0..10]",
4019 "             --speex-vbr (for Ogg Speex only)",
4020 "               Enable variable bit-rate (VBR)",
4021 "             --speex-abr=n (for Ogg Speex only)",
4022 "               Enable average bit-rate (ABR) at rate bps",
4023 "             --speex-vad (for Ogg Speex only)",
4024 "               Enable voice activity detection (VAD)",
4025 "             --speex-dtx (for Ogg Speex only)",
4026 "               Enable file-based discontinuous transmission (DTX)",
4027 "             --speex-complexity=n (for Ogg Speex only)",
4028 "               Set encoding complexity n:[0-10]",
4029 "             --speex-nframes=n (for Ogg Speex only)",
4030 "               Number of frames per Ogg packet n:[0-10]",
4031 #endif
4032 "  -o file    --output-file=file",
4033 "               Output to another file (or device/server) (Use \"-\" for stdout)",
4034 #if defined(AU_PORTAUDIO) || defined(AU_WIN32)
4035 "               Set the output device no. (-1 shows available device no. list)",
4036 #endif
4037 "  -P file    --patch-file=file",
4038 "               Use patch file for all programs",
4039 "  -p n       --polyphony=n",
4040 "               Allow n-voice polyphony.  Optional auto polyphony reduction",
4041 "     (a)     --[no-]polyphony-reduction",
4042 "               Toggle automatic polyphony reduction.  Enabled by default",
4043 "  -Q n[,...] --mute=n[,...]",
4044 "               Ignore channel n (0: ignore all, -n: resume channel n)",
4045 "     (t)     --temper-mute=n[,...]",
4046 "               Quiet temperament type n (0..3: preset, 4..7: user-defined)",
4047 "             --preserve-silence",
4048 "               Do not drop initial silence.  Default: drop initial silence",
4049 "  -q sec/n   --audio-buffer=sec/n",
4050 "               Specify audio buffer in seconds",
4051 "                 sec: Maxmum buffer, n: Filled to start (default is 5.0/100%%)",
4052 "                 (size of 100%% equals device buffer size)",
4053 "  -R msec      Pseudo reveb effect (set every instrument's release to msec)",
4054 "                 if n=0, n is set to 800",
4055 "  -S n       --cache-size=n",
4056 "               Cache size (0 means no cache)",
4057 "  -s freq    --sampling-freq=freq",
4058 "               Set sampling frequency to freq (Hz or kHz)",
4059 "  -T n       --adjust-tempo=n",
4060 "               Adjust tempo to n%%,",
4061 "                 120=play MOD files with an NTSC Amiga's timing",
4062 "  -t code    --output-charset=code",
4063 "               Output text language code:",
4064 "                 code=auto  : Auto conversion by `LANG' environment variable",
4065 "                              (UNIX only)",
4066 "                      ascii : Convert unreadable characters to '.' (0x2e)",
4067 "                      nocnv : No conversion",
4068 "                      1251  : Convert from windows-1251 to koi8-r",
4069 #ifdef JAPANESE
4070 "                      euc   : EUC-japan",
4071 "                      jis   : JIS",
4072 "                      sjis  : shift JIS",
4073 #endif /* JAPANESE */
4074 "  -U         --[no-]unload-instruments",
4075 "               Unload instruments from memory between MIDI files",
4076 "  -V power   --volume-curve=power",
4077 "               Define the velocity/volume/expression curve",
4078 "                 amp = vol^power (auto: 0, linear: 1, ideal: ~1.661, GS: ~2)",
4079 "  -v         --version",
4080 "               Display TiMidity version information",
4081 "  -W mode    --wrd=mode",
4082 "               Select WRD interface (see below for list)",
4083 #ifdef __W32__
4084 "  -w mode    --rcpcv-dll=mode",
4085 "               Windows extensional modes:",
4086 "                 mode=r/R : Enable/Disable rcpcv.dll",
4087 #endif /* __W32__ */
4088 "  -x str     --config-string=str",
4089 "               Read configuration str from command line argument",
4090 "  -Z file    --freq-table=file",
4091 "               Load frequency table (Use \"pure\" for pure intonation)",
4092 "  pure<n>(m) --pure-intonation=n(m)",
4093 "               Initial keysig number <n> of sharp(+)/flat(-) (-7..7)",
4094 "                 'm' stands for minor mode",
4095 "  --module=n",
4096 "               Simulate behavior of specific synthesizer module by n",
4097 "                 n=0       : TiMidity++ Default (default)",
4098 "                   1-15    : GS family",
4099 "                   16-31   : XG family",
4100 "                   32-111  : SoundBlaster and other systhesizer modules",
4101 "                   112-127 : TiMidity++ specification purposes",
4102 		NULL
4103 	};
4104 	void show_ao_device_info(FILE *fp);
4105 	FILE *fp;
4106 	char version[32], *help_args[3];
4107 	int i, j;
4108 	char *h;
4109 	ControlMode *cmp, **cmpp;
4110 	char mark[128];
4111 	PlayMode *pmp, **pmpp;
4112 	WRDTracer *wlp, **wlpp;
4113 
4114 	fp = open_pager();
4115 	strcpy(version, (strcmp(timidity_version, "current")) ? "version " : "");
4116 	strcat(version, timidity_version);
4117 	help_args[0] = version;
4118 	help_args[1] = program_name;
4119 	help_args[2] = NULL;
4120 	for (i = 0, j = 0; (h = help_list[i]) != NULL; i++) {
4121 		if (strchr(h, '%')) {
4122 			if (*(strchr(h, '%') + 1) != '%')
4123 				fprintf(fp, h, help_args[j++]);
4124 			else
4125 				fprintf(fp, "%s", h);
4126 		} else
4127 			fputs(h, fp);
4128 		fputs(NLS, fp);
4129 	}
4130 	fputs(NLS, fp);
4131 	fputs("Effect options (-EF, --ext=F option):" NLS
4132 "  -EFdelay=d   Disable delay effect (default)" NLS
4133 "  -EFdelay=l   Enable Left delay" NLS
4134 "    [,msec]      `msec' is optional to specify left-right delay time" NLS
4135 "  -EFdelay=r   Enable Right delay" NLS
4136 "    [,msec]      `msec' is optional to specify left-right delay time" NLS
4137 "  -EFdelay=b   Enable rotate Both left and right" NLS
4138 "    [,msec]      `msec' is optional to specify left-right delay time" NLS
4139 "  -EFchorus=d  Disable MIDI chorus effect control" NLS
4140 "  -EFchorus=n  Enable Normal MIDI chorus effect control" NLS
4141 "    [,level]     `level' is optional to specify chorus level [0..127]" NLS
4142 "                 (default)" NLS
4143 "  -EFchorus=s  Surround sound, chorus detuned to a lesser degree" NLS
4144 "    [,level]     `level' is optional to specify chorus level [0..127]" NLS
4145 "  -EFreverb=d  Disable MIDI reverb effect control" NLS
4146 "  -EFreverb=n  Enable Normal MIDI reverb effect control" NLS
4147 "    [,level]     `level' is optional to specify reverb level [1..127]" NLS
4148 "  -EFreverb=g  Global reverb effect" NLS
4149 "    [,level]     `level' is optional to specify reverb level [1..127]" NLS
4150 "  -EFreverb=f  Enable Freeverb MIDI reverb effect control (default)" NLS
4151 "    [,level]     `level' is optional to specify reverb level [1..127]" NLS
4152 "  -EFreverb=G  Global Freeverb effect" NLS
4153 "    [,level]     `level' is optional to specify reverb level [1..127]" NLS
4154 "  -EFvlpf=d    Disable voice LPF" NLS
4155 "  -EFvlpf=c    Enable Chamberlin resonant LPF (12dB/oct) (default)" NLS
4156 "  -EFvlpf=m    Enable Moog resonant lowpass VCF (24dB/oct)" NLS
4157 "  -EFns=n      Enable the n th degree (type) noise shaping filter" NLS
4158 "                 n:[0..4] (for 8-bit linear encoding, default is 4)" NLS
4159 "                 n:[0..4] (for 16-bit linear encoding, default is 4)" NLS, fp);
4160 #ifndef FIXED_RESAMPLATION
4161 #ifdef HAVE_STRINGIZE
4162 #define tim_str_internal(x) #x
4163 #define tim_str(x) tim_str_internal(x)
4164 #else
4165 #define tim_str(x) "x"
4166 #endif
4167 	fputs("  -EFresamp=d  Disable resamplation", fp);
4168 	if (! strcmp(tim_str(DEFAULT_RESAMPLATION), "resample_none"))
4169 		fputs(" (default)", fp);
4170 	fputs(NLS, fp);
4171 	fputs("  -EFresamp=l  Enable Linear resample algorithm", fp);
4172 	if (! strcmp(tim_str(DEFAULT_RESAMPLATION), "resample_linear"))
4173 		fputs(" (default)", fp);
4174 	fputs(NLS, fp);
4175 	fputs("  -EFresamp=c  Enable C-spline resample algorithm", fp);
4176 	if (! strcmp(tim_str(DEFAULT_RESAMPLATION), "resample_cspline"))
4177 		fputs(" (default)", fp);
4178 	fputs(NLS, fp);
4179 	fputs("  -EFresamp=L  Enable Lagrange resample algorithm", fp);
4180 	if (! strcmp(tim_str(DEFAULT_RESAMPLATION), "resample_lagrange"))
4181 		fputs(" (default)", fp);
4182 	fputs(NLS, fp);
4183 	fputs("  -EFresamp=n  Enable Newton resample algorithm", fp);
4184 	if (! strcmp(tim_str(DEFAULT_RESAMPLATION), "resample_newton"))
4185 		fputs(" (default)", fp);
4186 	fputs(NLS, fp);
4187 	fputs("  -EFresamp=g  Enable Gauss-like resample algorithm", fp);
4188 	if (! strcmp(tim_str(DEFAULT_RESAMPLATION), "resample_gauss"))
4189 		fputs(" (default)", fp);
4190 	fputs(NLS
4191 "                 -EFresamp affects the behavior of -N option" NLS, fp);
4192 #endif
4193 	fputs(NLS, fp);
4194 	fputs("Alternative TiMidity sequencer extensional mode long options:" NLS
4195 "  --[no-]mod-wheel" NLS
4196 "  --[no-]portamento" NLS
4197 "  --[no-]vibrato" NLS
4198 "  --[no-]ch-pressure" NLS
4199 "  --[no-]mod-envelope" NLS
4200 "  --[no-]trace-text-meta" NLS
4201 "  --[no-]overlap-voice" NLS
4202 "  --[no-]temper-control" NLS
4203 "  --default-mid=<HH>" NLS
4204 "  --system-mid=<HH>" NLS
4205 "  --default-bank=n" NLS
4206 "  --force-bank=n" NLS
4207 "  --default-program=n/m" NLS
4208 "  --force-program=n/m" NLS
4209 "  --delay=(d|l|r|b)[,msec]" NLS
4210 "  --chorus=(d|n|s)[,level]" NLS
4211 "  --reverb=(d|n|g|f|G)[,level]" NLS
4212 "  --voice-lpf=(d|c|m)" NLS
4213 "  --noise-shaping=n" NLS, fp);
4214 #ifndef FIXED_RESAMPLATION
4215 	fputs("  --resample=(d|l|c|L|n|g)" NLS, fp);
4216 #endif
4217 	fputs(NLS, fp);
4218 	fputs("Available interfaces (-i, --interface option):" NLS, fp);
4219 	for (cmpp = ctl_list; (cmp = *cmpp) != NULL; cmpp++)
4220 		fprintf(fp, "  -i%c          %s" NLS,
4221 				cmp->id_character, cmp->id_name);
4222 #ifdef IA_DYNAMIC
4223 	fprintf(fp, "Supported dynamic load interfaces (%s):" NLS,
4224 			dynamic_lib_root);
4225 	memset(mark, 0, sizeof(mark));
4226 	for (cmpp = ctl_list; (cmp = *cmpp) != NULL; cmpp++)
4227 		mark[(int) cmp->id_character] = 1;
4228 	list_dyna_interface(fp, dynamic_lib_root, mark);
4229 #endif	/* IA_DYNAMIC */
4230 	fputs(NLS, fp);
4231 	fputs("Interface options (append to -i? option):" NLS
4232 "  `v'          more verbose (cumulative)" NLS
4233 "  `q'          quieter (cumulative)" NLS
4234 "  `t'          trace playing" NLS
4235 "  `l'          loop playing (some interface ignore this option)" NLS
4236 "  `r'          randomize file list arguments before playing" NLS
4237 "  `s'          sorting file list arguments before playing" NLS, fp);
4238 #ifdef IA_ALSASEQ
4239 	fputs("  `D'          daemonize TiMidity++ in background "
4240 			"(for alsaseq only)" NLS, fp);
4241 #endif
4242 	fputs(NLS, fp);
4243 	fputs("Alternative interface long options:" NLS
4244 "  --verbose=n" NLS
4245 "  --quiet=n" NLS
4246 "  --[no-]trace" NLS
4247 "  --[no-]loop" NLS
4248 "  --[no-]random" NLS
4249 "  --[no-]sort" NLS, fp);
4250 #ifdef IA_ALSASEQ
4251 	fputs("  --[no-]background" NLS, fp);
4252 #endif
4253 	fputs(NLS, fp);
4254 	fputs("Available output modes (-O, --output-mode option):" NLS, fp);
4255 	for (pmpp = play_mode_list; (pmp = *pmpp) != NULL; pmpp++)
4256 		fprintf(fp, "  -O%c          %s" NLS,
4257 				pmp->id_character, pmp->id_name);
4258 	fputs(NLS, fp);
4259 	fputs("Output format options (append to -O? option):" NLS
4260 "  `S'          stereo" NLS
4261 "  `M'          monophonic" NLS
4262 "  `s'          signed output" NLS
4263 "  `u'          unsigned output" NLS
4264 "  `1'          16-bit sample width" NLS
4265 "  `2'          24-bit sample width" NLS
4266 "  `8'          8-bit sample width" NLS
4267 "  `l'          linear encoding" NLS
4268 "  `U'          U-Law encoding" NLS
4269 "  `A'          A-Law encoding" NLS
4270 "  `x'          byte-swapped output" NLS, fp);
4271 	fputs(NLS, fp);
4272 	fputs("Alternative output format long options:" NLS
4273 "  --output-stereo" NLS
4274 "  --output-mono" NLS
4275 "  --output-signed" NLS
4276 "  --output-unsigned" NLS
4277 "  --output-16bit" NLS
4278 "  --output-24bit" NLS
4279 "  --output-8bit" NLS
4280 "  --output-linear" NLS
4281 "  --output-ulaw" NLS
4282 "  --output-alaw" NLS
4283 "  --[no-]output-swab" NLS, fp);
4284 	fputs(NLS, fp);
4285 	fputs("Available WRD interfaces (-W, --wrd option):" NLS, fp);
4286 	for (wlpp = wrdt_list; (wlp = *wlpp) != NULL; wlpp++)
4287 		fprintf(fp, "  -W%c          %s" NLS, wlp->id, wlp->name);
4288 	fputs(NLS, fp);
4289 	close_pager(fp);
4290 	exit(EXIT_SUCCESS);
4291 }
4292 
4293 #ifdef IA_DYNAMIC
list_dyna_interface(FILE * fp,char * path,char * mark)4294 static inline void list_dyna_interface(FILE *fp, char *path, char *mark)
4295 {
4296     URL dir;
4297     char fname[NAME_MAX];
4298     int cwd, dummy;
4299 	if ((dir = url_dir_open(path)) == NULL)
4300 		return;
4301 	cwd = open(".", 0);
4302 	if(chdir(path) != 0)
4303 		return;
4304 	while (url_gets(dir, fname, sizeof(fname)) != NULL)
4305 		if (strncmp(fname, "if_", 3) == 0) {
4306 			void* handle = NULL;
4307 			char path[NAME_MAX];
4308 			snprintf(path, NAME_MAX, ".%c%s", PATH_SEP, fname);
4309 			if((handle = dl_load_file(path))) {
4310 				ControlMode *(* loader)(void) = NULL;
4311 				char c;
4312 				for (c = 'A'; c <= 'z'; c++) {
4313 					char buf[20]; /* enough */
4314 					if(mark[(int)c]) continue;
4315 					sprintf(buf, "interface_%c_loader", c);
4316 					if((loader = dl_find_symbol(handle, buf))) {
4317 						fprintf(fp, "  -i%c          %s" NLS, c, loader()->id_name);
4318 						mark[(int)c] = 1;
4319 						break;
4320 					}
4321 				}
4322 				dl_free(handle);
4323 			}
4324 		}
4325 	dummy = fchdir(cwd);
4326 	dummy += close(cwd);
4327 	url_close(dir);
4328 }
4329 
dynamic_interface_module(int id_char)4330 ControlMode *dynamic_interface_module(int id_char)
4331 {
4332 	URL url;
4333 	char fname[BUFSIZ];
4334 	ControlMode *ctl = NULL;
4335 	int cwd, dummy;
4336 	void *handle;
4337 	ControlMode *(* inferface_loader)(void);
4338 
4339 	if ((url = url_dir_open(dynamic_lib_root)) == NULL)
4340 		return NULL;
4341 	cwd = open(".", 0);
4342 	if(chdir(dynamic_lib_root) != 0)
4343 		return NULL;
4344 	while (url_gets(url, fname, sizeof(fname)) != NULL) {
4345 		if (strncmp(fname, "if_", 3) == 0) {
4346 			char path[NAME_MAX], buff[20];
4347 			snprintf(path, NAME_MAX-1, ".%c%s", PATH_SEP, fname);
4348 			if((handle = dl_load_file(path)) == NULL)
4349 				continue;
4350 			sprintf(buff, "interface_%c_loader", id_char);
4351 			if((inferface_loader = dl_find_symbol(handle, buff)) == NULL) {
4352 				dl_free(handle);
4353 				continue;
4354 			}
4355 			ctl = inferface_loader();
4356 			if(ctl->id_character == id_char)
4357 				break;
4358 		}
4359 	}
4360 	dummy = fchdir(cwd);
4361 	dummy += close(cwd);
4362 	url_close(url);
4363 	return ctl;
4364 }
4365 #endif	/* IA_DYNAMIC */
4366 
parse_opt_i(const char * arg)4367 static inline int parse_opt_i(const char *arg)
4368 {
4369 	/* interface mode */
4370 	ControlMode *cmp, **cmpp;
4371 	int found = 0;
4372 
4373 	for (cmpp = ctl_list; (cmp = *cmpp) != NULL; cmpp++) {
4374 		if (cmp->id_character == *arg) {
4375 			found = 1;
4376 			ctl = cmp;
4377 #if defined(IA_W32GUI) || defined(IA_W32G_SYN)
4378 			cmp->verbosity = 1;
4379 			cmp->trace_playing = 0;
4380 			cmp->flags = 0;
4381 #endif	/* IA_W32GUI */
4382 			break;
4383 		}
4384 	}
4385 #ifdef IA_DYNAMIC
4386 	if (! found) {
4387 		cmp = dynamic_interface_module(*arg);
4388 		if(cmp) {
4389 			ctl = cmp;
4390 			found = 1;
4391 		}
4392 	}
4393 #endif	/* IA_DYNAMIC */
4394 	if (! found) {
4395 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
4396 				"Interface `%c' is not compiled in.", *arg);
4397 		return 1;
4398 	}
4399 	while (*(++arg))
4400 		switch (*arg) {
4401 		case 'v':
4402 			cmp->verbosity++;
4403 			break;
4404 		case 'q':
4405 			cmp->verbosity--;
4406 			break;
4407 		case 't':	/* toggle */
4408 			cmp->trace_playing = (cmp->trace_playing) ? 0 : 1;
4409 			break;
4410 		case 'l':
4411 			cmp->flags ^= CTLF_LIST_LOOP;
4412 			break;
4413 		case 'r':
4414 			cmp->flags ^= CTLF_LIST_RANDOM;
4415 			break;
4416 		case 's':
4417 			cmp->flags ^= CTLF_LIST_SORT;
4418 			break;
4419 		case 'a':
4420 			cmp->flags ^= CTLF_AUTOSTART;
4421 			break;
4422 		case 'x':
4423 			cmp->flags ^= CTLF_AUTOEXIT;
4424 			break;
4425 		case 'd':
4426 			cmp->flags ^= CTLF_DRAG_START;
4427 			break;
4428 		case 'u':
4429 			cmp->flags ^= CTLF_AUTOUNIQ;
4430 			break;
4431 		case 'R':
4432 			cmp->flags ^= CTLF_AUTOREFINE;
4433 			break;
4434 		case 'C':
4435 			cmp->flags ^= CTLF_NOT_CONTINUE;
4436 			break;
4437 #ifdef IA_ALSASEQ
4438 		case 'D':
4439 			cmp->flags ^= CTLF_DAEMONIZE;
4440 			break;
4441 #endif
4442 		default:
4443 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
4444 					"Unknown interface option `%c'", *arg);
4445 			return 1;
4446 		}
4447 	return 0;
4448 }
4449 
parse_opt_verbose(const char * arg)4450 static inline int parse_opt_verbose(const char *arg)
4451 {
4452 	/* --verbose */
4453 	ctl->verbosity += (arg) ? atoi(arg) : 1;
4454 	return 0;
4455 }
4456 
parse_opt_quiet(const char * arg)4457 static inline int parse_opt_quiet(const char *arg)
4458 {
4459 	/* --quiet */
4460 	ctl->verbosity -= (arg) ? atoi(arg) : 1;
4461 	return 0;
4462 }
4463 
parse_opt_trace(const char * arg)4464 static inline int parse_opt_trace(const char *arg)
4465 {
4466 	/* --[no-]trace */
4467 	ctl->trace_playing = y_or_n_p(arg);
4468 	return 0;
4469 }
4470 
parse_opt_loop(const char * arg)4471 static inline int parse_opt_loop(const char *arg)
4472 {
4473 	/* --[no-]loop */
4474 	return set_flag(&(ctl->flags), CTLF_LIST_LOOP, arg);
4475 }
4476 
parse_opt_random(const char * arg)4477 static inline int parse_opt_random(const char *arg)
4478 {
4479 	/* --[no-]random */
4480 	return set_flag(&(ctl->flags), CTLF_LIST_RANDOM, arg);
4481 }
4482 
parse_opt_sort(const char * arg)4483 static inline int parse_opt_sort(const char *arg)
4484 {
4485 	/* --[no-]sort */
4486 	return set_flag(&(ctl->flags), CTLF_LIST_SORT, arg);
4487 }
4488 
4489 #ifdef IA_ALSASEQ
parse_opt_background(const char * arg)4490 static inline int parse_opt_background(const char *arg)
4491 {
4492 	/* --[no-]background */
4493 	return set_flag(&(ctl->flags), CTLF_DAEMONIZE, arg);
4494 }
4495 
parse_opt_rt_prio(const char * arg)4496 static inline int parse_opt_rt_prio(const char *arg)
4497 {
4498 	/* --realtime-priority */
4499 	if (set_value(&opt_realtime_priority, atoi(arg), 0, 100,
4500 			"Realtime priority"))
4501 		return 1;
4502 	return 0;
4503 }
4504 
parse_opt_seq_ports(const char * arg)4505 static inline int parse_opt_seq_ports(const char *arg)
4506 {
4507 	/* --sequencer-ports */
4508 	if (set_value(&opt_sequencer_ports, atoi(arg), 1, 16,
4509 			"Number of sequencer ports"))
4510 		return 1;
4511 	return 0;
4512 }
4513 #endif
4514 
4515 #if defined(IA_W32GUI)
parse_opt_rtsyn_latency(const char * arg)4516 static inline int parse_opt_rtsyn_latency(const char *arg)
4517 {
4518 	return 0;
4519 }
4520 #endif
4521 #if defined(IA_WINSYN) || defined(IA_PORTMIDISYN) ||defined(IA_NPSYN) || defined(IA_W32G_SYN)
parse_opt_rtsyn_latency(const char * arg)4522 static inline int parse_opt_rtsyn_latency(const char *arg)
4523 {
4524 	double latency;
4525 
4526 	if (sscanf(arg, "%lf", &latency) == EOF)
4527 		latency = RTSYN_LATENCY;
4528 	rtsyn_set_latency(latency);
4529 	return 0;
4530 }
4531 #endif
4532 
parse_opt_j(const char * arg)4533 static inline int parse_opt_j(const char *arg)
4534 {
4535 	opt_realtime_playing = y_or_n_p(arg);
4536 	return 0;
4537 }
4538 
parse_opt_K(const char * arg)4539 static inline int parse_opt_K(const char *arg)
4540 {
4541 	/* key adjust */
4542 	if (set_value(&key_adjust, atoi(arg), -24, 24, "Key adjust"))
4543 		return 1;
4544 	return 0;
4545 }
4546 
parse_opt_k(const char * arg)4547 static inline int parse_opt_k(const char *arg)
4548 {
4549 	reduce_voice_threshold = atoi(arg);
4550 	return 0;
4551 }
4552 
parse_opt_L(char * arg)4553 static inline int parse_opt_L(char *arg)
4554 {
4555 	add_to_pathlist(arg);
4556 	try_config_again = 1;
4557 	return 0;
4558 }
4559 
parse_opt_M(const char * arg)4560 static inline int parse_opt_M(const char *arg)
4561 {
4562 	if (pcm_alternate_file)
4563 		free(pcm_alternate_file);
4564 	pcm_alternate_file = safe_strdup(arg);
4565 	return 0;
4566 }
4567 
parse_opt_m(const char * arg)4568 static inline int parse_opt_m(const char *arg)
4569 {
4570 	min_sustain_time = atoi(arg);
4571 	if (min_sustain_time < 0)
4572 		min_sustain_time = 0;
4573 	return 0;
4574 }
4575 
parse_opt_N(const char * arg)4576 static inline int parse_opt_N(const char *arg)
4577 {
4578 	int val;
4579 
4580 	switch (get_current_resampler()) {
4581 	case RESAMPLE_CSPLINE:
4582 	case RESAMPLE_LAGRANGE:
4583 		no_4point_interpolation = y_or_n_p(arg);
4584 		break;
4585 	case RESAMPLE_NEWTON:
4586 	case RESAMPLE_GAUSS:
4587 		if (! (val = atoi(arg)))
4588 			/* set to linear interpolation for compatibility */
4589 			set_current_resampler(RESAMPLE_LINEAR);
4590 		else if (set_resampler_parm(val)) {
4591 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Invalid -N value");
4592 			return 1;
4593 		}
4594 		break;
4595 	}
4596 	return 0;
4597 }
4598 
parse_opt_O(const char * arg)4599 static inline int parse_opt_O(const char *arg)
4600 {
4601 	/* output mode */
4602 	PlayMode *pmp, **pmpp;
4603 	int found = 0;
4604 
4605 	for (pmpp = play_mode_list; (pmp = *pmpp) != NULL; pmpp++)
4606 		if (pmp->id_character == *arg) {
4607 			found = 1;
4608 			play_mode = pmp;
4609 			break;
4610 		}
4611 	if (! found) {
4612 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
4613 				"Playmode `%c' is not compiled in.", *arg);
4614 		return 1;
4615 	}
4616 	while (*(++arg))
4617 		switch (*arg) {
4618 		case 'S':	/* stereo */
4619 			pmp->encoding &= ~PE_MONO;
4620 			break;
4621 		case 'M':
4622 			pmp->encoding |= PE_MONO;
4623 			break;
4624 		case 's':
4625 			pmp->encoding |= PE_SIGNED;
4626 			pmp->encoding &= ~(PE_ULAW | PE_ALAW);
4627 			break;
4628 		case 'u':
4629 			pmp->encoding &= ~PE_SIGNED;
4630 			pmp->encoding &= ~(PE_ULAW | PE_ALAW);
4631 			break;
4632 		case '1':	/* 1 for 16-bit */
4633 			pmp->encoding |= PE_16BIT;
4634 			pmp->encoding &= ~(PE_24BIT | PE_ULAW | PE_ALAW);
4635 			break;
4636 		case '2':	/* 2 for 24-bit */
4637 			pmp->encoding |= PE_24BIT;
4638 			pmp->encoding &= ~(PE_16BIT | PE_ULAW | PE_ALAW);
4639 			break;
4640 		case '8':
4641 			pmp->encoding &= ~(PE_16BIT | PE_24BIT);
4642 			break;
4643 		case 'l':	/* linear */
4644 			pmp->encoding &= ~(PE_ULAW | PE_ALAW);
4645 			break;
4646 		case 'U':	/* uLaw */
4647 			pmp->encoding |= PE_ULAW;
4648 			pmp->encoding &= ~(PE_SIGNED
4649 					| PE_16BIT | PE_24BIT | PE_ALAW | PE_BYTESWAP);
4650 			break;
4651 		case 'A':	/* aLaw */
4652 			pmp->encoding |= PE_ALAW;
4653 			pmp->encoding &= ~(PE_SIGNED
4654 					| PE_16BIT | PE_24BIT | PE_ULAW | PE_BYTESWAP);
4655 			break;
4656 		case 'x':
4657 			pmp->encoding ^= PE_BYTESWAP;	/* toggle */
4658 			pmp->encoding &= ~(PE_ULAW | PE_ALAW);
4659 			break;
4660 		default:
4661 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
4662 					"Unknown format modifier `%c'", *arg);
4663 			return 1;
4664 		}
4665 	return 0;
4666 }
4667 
parse_opt_output_stereo(const char * arg)4668 static inline int parse_opt_output_stereo(const char *arg)
4669 {
4670 	/* --output-stereo, --output-mono */
4671 	if (y_or_n_p(arg))
4672 		/* I first thought --mono should be the syntax sugar to
4673 		 * --stereo=no, but the source said stereo should be !PE_MONO,
4674 		 * not mono should be !PE_STEREO.  Perhaps I took a wrong
4675 		 * choice? -- mput
4676 		 */
4677 		play_mode->encoding &= ~PE_MONO;
4678 	else
4679 		play_mode->encoding |= PE_MONO;
4680 	return 0;
4681 }
4682 
parse_opt_output_signed(const char * arg)4683 static inline int parse_opt_output_signed(const char *arg)
4684 {
4685 	/* --output-singed, --output-unsigned */
4686 	if (set_flag(&(play_mode->encoding), PE_SIGNED, arg))
4687 		return 1;
4688 	play_mode->encoding &= ~(PE_ULAW | PE_ALAW);
4689 	return 0;
4690 }
4691 
parse_opt_output_bitwidth(const char * arg)4692 static inline int parse_opt_output_bitwidth(const char *arg)
4693 {
4694 	/* --output-16bit, --output-24bit, --output-8bit */
4695 	switch (*arg) {
4696 	case '1':	/* 16bit */
4697 		play_mode->encoding |= PE_16BIT;
4698 		play_mode->encoding &= ~(PE_24BIT | PE_ULAW | PE_ALAW);
4699 		return 0;
4700 	case '2':	/* 24bit */
4701 		play_mode->encoding |= PE_24BIT;
4702 		play_mode->encoding &= ~(PE_16BIT | PE_ULAW | PE_ALAW);
4703 		return 0;
4704 	case '8':	/* 8bit */
4705 		play_mode->encoding &= ~(PE_16BIT | PE_24BIT);
4706 		return 0;
4707 	default:
4708 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Invalid output bitwidth %s", arg);
4709 		return 1;
4710 	}
4711 }
4712 
parse_opt_output_format(const char * arg)4713 static inline int parse_opt_output_format(const char *arg)
4714 {
4715 	/* --output-linear, --output-ulaw, --output-alaw */
4716 	switch (*arg) {
4717 	case 'l':	/* linear */
4718 		play_mode->encoding &= ~(PE_ULAW | PE_ALAW);
4719 		return 0;
4720 	case 'u':	/* uLaw */
4721 		play_mode->encoding |= PE_ULAW;
4722 		play_mode->encoding &=
4723 				~(PE_SIGNED | PE_16BIT | PE_24BIT | PE_ALAW | PE_BYTESWAP);
4724 		return 0;
4725 	case 'a':	/* aLaw */
4726 		play_mode->encoding |= PE_ALAW;
4727 		play_mode->encoding &=
4728 				~(PE_SIGNED | PE_16BIT | PE_24BIT | PE_ULAW | PE_BYTESWAP);
4729 		return 0;
4730 	default:
4731 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Invalid output format %s", arg);
4732 		return 1;
4733 	}
4734 }
4735 
parse_opt_output_swab(const char * arg)4736 static inline int parse_opt_output_swab(const char *arg)
4737 {
4738 	/* --[no-]output-swab */
4739 	if (set_flag(&(play_mode->encoding), PE_BYTESWAP, arg))
4740 		return 1;
4741 	play_mode->encoding &= ~(PE_ULAW | PE_ALAW);
4742 	return 0;
4743 }
4744 
4745 #ifdef AU_FLAC
4746 extern void flac_set_option_verify(int);
4747 extern void flac_set_option_padding(int);
4748 extern void flac_set_compression_level(int);
4749 
parse_opt_flac_verify(const char * arg)4750 static inline int parse_opt_flac_verify(const char *arg)
4751 {
4752 	flac_set_option_verify(1);
4753 	return 0;
4754 }
4755 
parse_opt_flac_padding(const char * arg)4756 static inline int parse_opt_flac_padding(const char *arg)
4757 {
4758 	flac_set_option_padding(atoi(arg));
4759 	return 0;
4760 }
4761 
parse_opt_flac_complevel(const char * arg)4762 static inline int parse_opt_flac_complevel(const char *arg)
4763 {
4764 	flac_set_compression_level(atoi(arg));
4765 	return 0;
4766 }
4767 
4768 #ifdef AU_OGGFLAC
4769 extern void flac_set_option_oggflac(int);
4770 
parse_opt_flac_oggflac(const char * arg)4771 static inline int parse_opt_flac_oggflac(const char *arg)
4772 {
4773 	flac_set_option_oggflac(1);
4774 	return 0;
4775 }
4776 #endif /* AU_OGGFLAC */
4777 #endif /* AU_FLAC */
4778 
4779 #ifdef AU_SPEEX
4780 extern void speex_set_option_quality(int);
4781 extern void speex_set_option_vbr(int);
4782 extern void speex_set_option_abr(int);
4783 extern void speex_set_option_vad(int);
4784 extern void speex_set_option_dtx(int);
4785 extern void speex_set_option_complexity(int);
4786 extern void speex_set_option_nframes(int);
4787 
parse_opt_speex_quality(const char * arg)4788 static inline int parse_opt_speex_quality(const char *arg)
4789 {
4790 	speex_set_option_quality(atoi(arg));
4791 	return 0;
4792 }
4793 
parse_opt_speex_vbr(const char * arg)4794 static inline int parse_opt_speex_vbr(const char *arg)
4795 {
4796 	speex_set_option_vbr(1);
4797 	return 0;
4798 }
4799 
parse_opt_speex_abr(const char * arg)4800 static inline int parse_opt_speex_abr(const char *arg)
4801 {
4802 	speex_set_option_abr(atoi(arg));
4803 	return 0;
4804 }
4805 
parse_opt_speex_vad(const char * arg)4806 static inline int parse_opt_speex_vad(const char *arg)
4807 {
4808 	speex_set_option_vad(1);
4809 	return 0;
4810 }
4811 
parse_opt_speex_dtx(const char * arg)4812 static inline int parse_opt_speex_dtx(const char *arg)
4813 {
4814 	speex_set_option_dtx(1);
4815 	return 0;
4816 }
4817 
parse_opt_speex_complexity(const char * arg)4818 static inline int parse_opt_speex_complexity(const char *arg)
4819 {
4820 	speex_set_option_complexity(atoi(arg));
4821 	return 0;
4822 }
4823 
parse_opt_speex_nframes(const char * arg)4824 static inline int parse_opt_speex_nframes(const char *arg)
4825 {
4826 	speex_set_option_nframes(atoi(arg));
4827 	return 0;
4828 }
4829 #endif /* AU_SPEEX */
4830 
parse_opt_o(char * arg)4831 static inline int parse_opt_o(char *arg)
4832 {
4833 	if (opt_output_name)
4834 		free(opt_output_name);
4835 	opt_output_name = safe_strdup(url_expand_home_dir(arg));
4836 	return 0;
4837 }
4838 
parse_opt_P(const char * arg)4839 static inline int parse_opt_P(const char *arg)
4840 {
4841 	/* set overriding instrument */
4842 	strncpy(def_instr_name, arg, sizeof(def_instr_name) - 1);
4843 	def_instr_name[sizeof(def_instr_name) - 1] = '\0';
4844 	return 0;
4845 }
4846 
parse_opt_p(const char * arg)4847 static inline int parse_opt_p(const char *arg)
4848 {
4849 	if (set_value(&voices, atoi(arg), 1,
4850 			MAX_SAFE_MALLOC_SIZE / sizeof(Voice), "Polyphony"))
4851 		return 1;
4852 	max_voices = voices;
4853 	return 0;
4854 }
4855 
parse_opt_p1(const char * arg)4856 static inline int parse_opt_p1(const char *arg)
4857 {
4858 	/* --[no-]polyphony-reduction */
4859 	auto_reduce_polyphony = y_or_n_p(arg);
4860 	return 0;
4861 }
4862 
parse_opt_Q(const char * arg)4863 static inline int parse_opt_Q(const char *arg)
4864 {
4865 	const char *p = arg;
4866 
4867 	if (strchr(arg, 't'))
4868 		/* backward compatibility */
4869 		return parse_opt_Q1(arg);
4870 	if (set_channel_flag(&quietchannels, atoi(arg), "Quiet channel"))
4871 		return 1;
4872 	while ((p = strchr(p, ',')) != NULL)
4873 		if (set_channel_flag(&quietchannels, atoi(++p), "Quiet channel"))
4874 			return 1;
4875 	return 0;
4876 }
4877 
parse_opt_Q1(const char * arg)4878 static inline int parse_opt_Q1(const char *arg)
4879 {
4880 	/* --temper-mute */
4881 	int prog;
4882 	const char *p = arg;
4883 
4884 	if (set_value(&prog, atoi(arg), 0, 7, "Temperament program number"))
4885 		return 1;
4886 	temper_type_mute |= 1 << prog;
4887 	while ((p = strchr(p, ',')) != NULL) {
4888 		if (set_value(&prog, atoi(++p), 0, 7, "Temperament program number"))
4889 			return 1;
4890 		temper_type_mute |= 1 << prog;
4891 	}
4892 	return 0;
4893 }
4894 
parse_opt_preserve_silence(const char * arg)4895 static inline int parse_opt_preserve_silence(const char *arg)
4896 {
4897 	opt_preserve_silence = 1;
4898 	return 0;
4899 }
4900 
parse_opt_q(const char * arg)4901 static inline int parse_opt_q(const char *arg)
4902 {
4903 	char *max_buff = safe_strdup(arg);
4904 	char *fill_buff = strchr(max_buff, '/');
4905 
4906 	if (fill_buff != max_buff) {
4907 		if (opt_aq_max_buff)
4908 			free(opt_aq_max_buff);
4909 		opt_aq_max_buff = max_buff;
4910 	}
4911 	if (fill_buff) {
4912 		*fill_buff = '\0';
4913 		if (opt_aq_fill_buff)
4914 			free(opt_aq_fill_buff);
4915 		opt_aq_fill_buff = ++fill_buff;
4916 		opt_aq_fill_buff_free_needed = 0;
4917 	}
4918 	return 0;
4919 }
4920 
parse_opt_R(const char * arg)4921 static inline int parse_opt_R(const char *arg)
4922 {
4923 	/* I think pseudo reverb can now be retired... Computers are
4924 	 * enough fast to do a full reverb, don't they?
4925 	 */
4926 	if (atoi(arg) == -1)	/* reset */
4927 		modify_release = 0;
4928 	else {
4929 		if (set_val_i32(&modify_release, atoi(arg), 0, MAX_MREL,
4930 				"Modify Release"))
4931 			return 1;
4932 		if (modify_release == 0)
4933 			modify_release = DEFAULT_MREL;
4934 	}
4935 	return 0;
4936 }
4937 
parse_opt_S(const char * arg)4938 static inline int parse_opt_S(const char *arg)
4939 {
4940 	int suffix = arg[strlen(arg) - 1];
4941 	int32 figure;
4942 
4943 	switch (suffix) {
4944 	case 'M':
4945 	case 'm':
4946 		figure = 1 << 20;
4947 		break;
4948 	case 'K':
4949 	case 'k':
4950 		figure = 1 << 10;
4951 		break;
4952 	default:
4953 		figure = 1;
4954 		break;
4955 	}
4956 	allocate_cache_size = atof(arg) * figure;
4957 	return 0;
4958 }
4959 
parse_opt_s(const char * arg)4960 static inline int parse_opt_s(const char *arg)
4961 {
4962 	/* sampling rate */
4963 	int32 freq;
4964 
4965 	if ((freq = atoi(arg)) < 100)
4966 		freq = atof(arg) * 1000 + 0.5;
4967 	return set_val_i32(&opt_output_rate, freq,
4968 			MIN_OUTPUT_RATE, MAX_OUTPUT_RATE, "Resampling frequency");
4969 }
4970 
parse_opt_T(const char * arg)4971 static inline int parse_opt_T(const char *arg)
4972 {
4973 	/* tempo adjust */
4974 	int adjust;
4975 
4976 	if (set_value(&adjust, atoi(arg), 10, 400, "Tempo adjust"))
4977 		return 1;
4978 	tempo_adjust = 100.0 / adjust;
4979 	return 0;
4980 }
4981 
parse_opt_t(const char * arg)4982 static inline int parse_opt_t(const char *arg)
4983 {
4984 	if (output_text_code)
4985 		free(output_text_code);
4986 	output_text_code = safe_strdup(arg);
4987 	return 0;
4988 }
4989 
parse_opt_U(const char * arg)4990 static inline int parse_opt_U(const char *arg)
4991 {
4992 	free_instruments_afterwards = y_or_n_p(arg);
4993 	return 0;
4994 }
4995 
parse_opt_volume_curve(char * arg)4996 static inline int parse_opt_volume_curve(char *arg)
4997 {
4998 	if (atof(arg) < 0) {
4999 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
5000 				"Volume curve power must be >= 0", *arg);
5001 		return 1;
5002 	}
5003 	if (atof(arg) != 0) {
5004 		init_user_vol_table(atof(arg));
5005 		opt_user_volume_curve = 1;
5006 	}
5007 	return 0;
5008 }
5009 
5010 __attribute__((noreturn))
parse_opt_v(const char * arg)5011 static inline int parse_opt_v(const char *arg)
5012 {
5013 	const char *version_list[] = {
5014 #if defined(__BORLANDC__) || defined(__MRC__) || defined(__WATCOMC__) ||  defined(__DMC__)
5015 		"TiMidity++ ",
5016 				"",
5017 				NULL, NLS,
5018 		NLS,
5019 #else
5020 		"TiMidity++ ",
5021 				(strcmp(timidity_version, "current")) ? "version " : "",
5022 				timidity_version, NLS,
5023 		NLS,
5024 #endif
5025 		"Copyright (C) 1999-2018 Masanao Izumo <iz@onicos.co.jp>", NLS,
5026 		"Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>", NLS,
5027 		NLS,
5028 #ifdef __W32__
5029 		"Win32 version by Davide Moretti <dmoretti@iper.net>", NLS,
5030 		"              and Daisuke Aoki <dai@y7.net>", NLS,
5031 		NLS,
5032 #endif	/* __W32__ */
5033 		"This program is distributed in the hope that it will be useful,", NLS,
5034 		"but WITHOUT ANY WARRANTY; without even the implied warranty of", NLS,
5035 		"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the", NLS,
5036 		"GNU General Public License for more details.", NLS,
5037 	};
5038 	FILE *fp = open_pager();
5039 	int i;
5040 
5041 #if defined(__BORLANDC__) || defined(__MRC__)
5042 	if (strcmp(timidity_version, "current"))
5043 		version_list[1] = "version ";
5044 	version_list[2] = timidity_version;
5045 #endif
5046 	for (i = 0; i < sizeof(version_list) / sizeof(char *); i++)
5047 		fputs(version_list[i], fp);
5048 	close_pager(fp);
5049 	exit(EXIT_SUCCESS);
5050 }
5051 
parse_opt_W(char * arg)5052 static inline int parse_opt_W(char *arg)
5053 {
5054 	WRDTracer *wlp, **wlpp;
5055 
5056 	if (*arg == 'R') {	/* for WRD reader options */
5057 		put_string_table(&wrd_read_opts, arg + 1, strlen(arg + 1));
5058 		return 0;
5059 	}
5060 	for (wlpp = wrdt_list; (wlp = *wlpp) != NULL; wlpp++)
5061 		if (wlp->id == *arg) {
5062 			wrdt = wlp;
5063 			if (wrdt_open_opts)
5064 				free(wrdt_open_opts);
5065 			wrdt_open_opts = safe_strdup(arg + 1);
5066 			return 0;
5067 		}
5068 	ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
5069 			"WRD Tracer `%c' is not compiled in.", *arg);
5070 	return 1;
5071 }
5072 
5073 #ifdef __W32__
parse_opt_w(const char * arg)5074 static inline int parse_opt_w(const char *arg)
5075 {
5076 	switch (*arg) {
5077 #ifdef SMFCONV
5078 	case 'r':
5079 		opt_rcpcv_dll = 1;
5080 		return 0:
5081 	case 'R':
5082 		opt_rcpcv_dll = 0;
5083 		return 0;
5084 #else
5085 	case 'r':
5086 	case 'R':
5087 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
5088 				"-w%c option is not supported", *arg);
5089 		return 1;
5090 #endif	/* SMFCONV */
5091 	default:
5092 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "-w: Illegal mode `%c'", *arg);
5093 		return 1;
5094 	}
5095 }
5096 #endif	/* __W32__ */
5097 
parse_opt_x(char * arg)5098 static inline int parse_opt_x(char *arg)
5099 {
5100 	StringTableNode *st;
5101 
5102 	if ((st = put_string_table(&opt_config_string,
5103 			arg, strlen(arg))) != NULL)
5104 		expand_escape_string(st->string);
5105 	return 0;
5106 }
5107 
expand_escape_string(char * s)5108 static inline void expand_escape_string(char *s)
5109 {
5110 	char *t = s;
5111 
5112 	if (s == NULL)
5113 		return;
5114 	for (t = s; *s; s++)
5115 		if (*s == '\\') {
5116 			switch (*++s) {
5117 			case 'a':
5118 				*t++ = '\a';
5119 				break;
5120 			case 'b':
5121 				*t++ = '\b';
5122 				break;
5123 			case 't':
5124 				*t++ = '\t';
5125 				break;
5126 			case 'n':
5127 				*t++ = '\n';
5128 				break;
5129 			case 'f':
5130 				*t++ = '\f';
5131 				break;
5132 			case 'v':
5133 				*t++ = '\v';
5134 				break;
5135 			case 'r':
5136 				*t++ = '\r';
5137 				break;
5138 			case '\\':
5139 				*t++ = '\\';
5140 				break;
5141 			default:
5142 				if (! (*t++ = *s))
5143 					return;
5144 				break;
5145 			}
5146 		} else
5147 			*t++ = *s;
5148 	*t = *s;
5149 }
5150 
parse_opt_Z(char * arg)5151 static inline int parse_opt_Z(char *arg)
5152 {
5153 	/* load frequency table */
5154 	return load_table(arg);
5155 }
5156 
parse_opt_Z1(const char * arg)5157 static inline int parse_opt_Z1(const char *arg)
5158 {
5159 	/* --pure-intonation */
5160 	int keysig;
5161 
5162 	opt_pure_intonation = 1;
5163 	if (*arg) {
5164 		if (set_value(&keysig, atoi(arg), -7, 7,
5165 				"Initial keysig (number of #(+)/b(-)[m(minor)])"))
5166 			return 1;
5167 		opt_init_keysig = keysig;
5168 		if (strchr(arg, 'm'))
5169 			opt_init_keysig += 16;
5170 	}
5171 	return 0;
5172 }
5173 
parse_opt_default_module(const char * arg)5174 static inline int parse_opt_default_module(const char *arg)
5175 {
5176 	opt_default_module = atoi(arg);
5177 	if (opt_default_module < 0)
5178 		opt_default_module = 0;
5179 	return 0;
5180 }
5181 
5182 __attribute__((noreturn))
parse_opt_fail(const char * arg)5183 static inline int parse_opt_fail(const char *arg)
5184 {
5185 	/* getopt_long failed to recognize any options */
5186 	ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
5187 			"Could not understand option : try --help");
5188 	exit(EXIT_FAILURE);
5189 }
5190 
set_value(int * param,int i,int low,int high,char * name)5191 static inline int set_value(int *param, int i, int low, int high, char *name)
5192 {
5193 	int32 val;
5194 
5195 	if (set_val_i32(&val, i, low, high, name))
5196 		return 1;
5197 	*param = val;
5198 	return 0;
5199 }
5200 
set_val_i32(int32 * param,int32 i,int32 low,int32 high,char * name)5201 static inline int set_val_i32(int32 *param,
5202 		int32 i, int32 low, int32 high, char *name)
5203 {
5204 	if (i < low || i > high) {
5205 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
5206 				"%s must be between %d and %d", name, low, high);
5207 		return 1;
5208 	}
5209 	*param = i;
5210 	return 0;
5211 }
5212 
parse_val_float_t(FLOAT_T * param,const char * arg,FLOAT_T low,FLOAT_T high,const char * name,int f)5213 static int parse_val_float_t(FLOAT_T *param,
5214 		const char *arg, FLOAT_T low, FLOAT_T high, const char *name, int f)
5215 {
5216 	FLOAT_T value;
5217 	char *errp;
5218 
5219 	value = strtod(arg, &errp);
5220 	if (arg == errp) {
5221 		/* only when nothing was parsed */
5222 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Invalid %s", name);
5223 		return 1;
5224 	}
5225 	return set_val_float_t(param, value, low, high, name, f);
5226 }
5227 
set_val_float_t(FLOAT_T * param,FLOAT_T i,FLOAT_T low,FLOAT_T high,const char * name,int f)5228 static inline int set_val_float_t(FLOAT_T *param,
5229 		FLOAT_T i, FLOAT_T low, FLOAT_T high, const char *name, int f)
5230 {
5231 	if (i < low || i > high) {
5232 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
5233 				"%s must be between %.*f and %.*f", name, f, low, f, high);
5234 		return 1;
5235 	}
5236 	*param = i;
5237 	return 0;
5238 }
5239 
set_channel_flag(ChannelBitMask * flags,int32 i,char * name)5240 static inline int set_channel_flag(ChannelBitMask *flags, int32 i, char *name)
5241 {
5242 	if (i == 0) {
5243 		FILL_CHANNELMASK(*flags);
5244 		return 0;
5245 	} else if (abs(i) > MAX_CHANNELS) {
5246 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
5247 				"%s must be between (-)1 and (-)%d, or 0",
5248 						name, MAX_CHANNELS);
5249 		return 1;
5250 	}
5251 	if (i > 0)
5252 		SET_CHANNELMASK(*flags, i - 1);
5253 	else
5254 		UNSET_CHANNELMASK(*flags, -i - 1);
5255 	return 0;
5256 }
5257 
y_or_n_p(const char * arg)5258 static inline int y_or_n_p(const char *arg)
5259 {
5260 	if (arg) {
5261 		switch (arg[0]) {
5262 		case 'y':
5263 		case 'Y':
5264 		case 't':
5265 		case 'T':
5266 			return 1;
5267 		case 'n':
5268 		case 'N':
5269 		case 'f':
5270 		case 'F':
5271 		default:
5272 			return 0;
5273 		}
5274 	} else
5275 		return 1;
5276 }
5277 
set_flag(int32 * fields,int32 bitmask,const char * arg)5278 static inline int set_flag(int32 *fields, int32 bitmask, const char *arg)
5279 {
5280 	if (y_or_n_p(arg))
5281 		*fields |= bitmask;
5282 	else
5283 		*fields &= ~bitmask;
5284 	return 0;
5285 }
5286 
open_pager(void)5287 static inline FILE *open_pager(void)
5288 {
5289 #if ! defined(__MACOS__) && defined(HAVE_POPEN) && defined(HAVE_ISATTY) \
5290 		&& ! defined(IA_W32GUI) && ! defined(IA_W32G_SYN)
5291 	char *pager;
5292 
5293 	if (isatty(1) && (pager = getenv("PAGER")) != NULL)
5294 		return popen(pager, "w");
5295 #endif
5296 	return stdout;
5297 }
5298 
close_pager(FILE * fp)5299 static inline void close_pager(FILE *fp)
5300 {
5301 #if ! defined(__MACOS__) && defined(HAVE_POPEN) && defined(HAVE_ISATTY) \
5302 		&& ! defined(IA_W32GUI) && ! defined(IA_W32G_SYN)
5303 	if (fp != stdout)
5304 		pclose(fp);
5305 #endif
5306 }
5307 
interesting_message(void)5308 static void interesting_message(void)
5309 {
5310 	printf(
5311 "TiMidity++ %s%s -- MIDI to WAVE converter and player" NLS
5312 "Copyright (C) 1999-2018 Masanao Izumo <iz@onicos.co.jp>" NLS
5313 "Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>" NLS
5314 			NLS
5315 #ifdef __W32__
5316 "Win32 version by Davide Moretti <dmoretti@iper.net>" NLS
5317 "              and Daisuke Aoki <dai@y7.net>" NLS
5318 			NLS
5319 #endif /* __W32__ */
5320 "This program is free software; you can redistribute it and/or modify" NLS
5321 "it under the terms of the GNU General Public License as published by" NLS
5322 "the Free Software Foundation; either version 2 of the License, or" NLS
5323 "(at your option) any later version." NLS
5324 			NLS
5325 "This program is distributed in the hope that it will be useful," NLS
5326 "but WITHOUT ANY WARRANTY; without even the implied warranty of" NLS
5327 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the" NLS
5328 "GNU General Public License for more details." NLS
5329 			NLS
5330 "You should have received a copy of the GNU General Public License" NLS
5331 "along with this program; if not, write to the Free Software" NLS
5332 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA" NLS
5333 			NLS, (strcmp(timidity_version, "current")) ? "version " : "",
5334 			timidity_version);
5335 }
5336 
5337 /* -------- functions for getopt_long ends here --------- */
5338 
5339 #ifdef HAVE_SIGNAL
sigterm_exit(int sig)5340 static RETSIGTYPE sigterm_exit(int sig)
5341 {
5342     char s[4];
5343 #if defined(__MINGW32__) && !defined(HAVE_SSIZE_T)
5344     int dummy;
5345 #else
5346     ssize_t dummy;
5347 #endif
5348 
5349     /* NOTE: Here, fprintf is dangerous because it is not re-enterance
5350      * function.  It is possible coredump if the signal is called in printf's.
5351      */
5352 
5353     dummy = write(2, "Terminated sig=0x", 17);
5354     s[0] = "0123456789abcdef"[(sig >> 4) & 0xf];
5355     s[1] = "0123456789abcdef"[sig & 0xf];
5356     s[2] = '\n';
5357     dummy += write(2, s, 3);
5358 
5359     safe_exit(1);
5360 }
5361 #endif /* HAVE_SIGNAL */
5362 
timidity_arc_error_handler(char * error_message)5363 static void timidity_arc_error_handler(char *error_message)
5364 {
5365     extern int open_file_noise_mode;
5366     if(open_file_noise_mode)
5367 	ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "%s", error_message);
5368 }
5369 
5370 static PlayMode null_play_mode = {
5371     0,                          /* rate */
5372     0,                          /* encoding */
5373     0,                          /* flag */
5374     -1,                         /* fd */
5375     {0,0,0,0,0},                /* extra_param */
5376     "Null output device",       /* id_name */
5377     '\0',                       /* id_character */
5378     NULL,                       /* open_output */
5379     NULL,                       /* close_output */
5380     NULL,                       /* output_data */
5381     NULL,                       /* acntl */
5382     NULL                        /* detect */
5383 };
5384 
timidity_start_initialize(void)5385 MAIN_INTERFACE void timidity_start_initialize(void)
5386 {
5387     int i;
5388     static int drums[] = DEFAULT_DRUMCHANNELS;
5389     static int is_first = 1;
5390 #if defined(__FreeBSD__) && !defined(__alpha__)
5391     fp_except_t fpexp;
5392 #elif defined(__NetBSD__) || defined(__OpenBSD__)
5393     fp_except fpexp;
5394 #endif
5395 
5396 #if defined(FP_X_INV) && defined(FP_X_DZ) && \
5397   (defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__))
5398     fpexp = fpgetmask();
5399     fpsetmask(fpexp & ~(FP_X_INV|FP_X_DZ));
5400 #endif
5401 
5402     if(!output_text_code)
5403 	output_text_code = safe_strdup(OUTPUT_TEXT_CODE);
5404     if(!opt_aq_max_buff)
5405 	opt_aq_max_buff = safe_strdup("5.0");
5406     if(!opt_aq_fill_buff)
5407 	opt_aq_fill_buff = safe_strdup("100%");
5408 
5409     /* Check the byte order */
5410     i = 1;
5411 #ifdef LITTLE_ENDIAN
5412     if(*(char *)&i != 1)
5413 #else
5414     if(*(char *)&i == 1)
5415 #endif
5416     {
5417 	fprintf(stderr, "Byte order is miss configured.\n");
5418 	exit(1);
5419     }
5420 
5421     for(i = 0; i < MAX_CHANNELS; i++)
5422     {
5423 	memset(&(channel[i]), 0, sizeof(Channel));
5424     }
5425 
5426     CLEAR_CHANNELMASK(quietchannels);
5427     CLEAR_CHANNELMASK(default_drumchannels);
5428 
5429     for(i = 0; drums[i] > 0; i++)
5430 	SET_CHANNELMASK(default_drumchannels, drums[i] - 1);
5431 #if MAX_CHANNELS > 16
5432     for(i = 16; i < MAX_CHANNELS; i++)
5433 	if(IS_SET_CHANNELMASK(default_drumchannels, i & 0xF))
5434 	    SET_CHANNELMASK(default_drumchannels, i);
5435 #endif
5436 
5437     if(program_name == NULL)
5438 	program_name = "TiMidity";
5439     uudecode_unquote_html = 1;
5440     for(i = 0; i < MAX_CHANNELS; i++)
5441     {
5442 	default_program[i] = DEFAULT_PROGRAM;
5443 	memset(channel[i].drums, 0, sizeof(channel[i].drums));
5444     }
5445     arc_error_handler = timidity_arc_error_handler;
5446 
5447     if(play_mode == NULL) play_mode = &null_play_mode;
5448 
5449     if(is_first) /* initialize once time */
5450     {
5451 	got_a_configuration = 0;
5452 
5453 #ifdef SUPPORT_SOCKET
5454 	init_mail_addr();
5455 	if(url_user_agent == NULL)
5456 	{
5457 	    url_user_agent =
5458 		(char *)safe_malloc(10 + strlen(timidity_version));
5459 	    strcpy(url_user_agent, "TiMidity-");
5460 	    strcat(url_user_agent, timidity_version);
5461 	}
5462 #endif /* SUPPORT_SOCKET */
5463 
5464 	for(i = 0; url_module_list[i]; i++)
5465 	    url_add_module(url_module_list[i]);
5466 	init_string_table(&opt_config_string);
5467 	init_freq_table();
5468 	init_freq_table_tuning();
5469 	init_freq_table_pytha();
5470 	init_freq_table_meantone();
5471 	init_freq_table_pureint();
5472 	init_freq_table_user();
5473 	init_bend_fine();
5474 	init_bend_coarse();
5475 	init_tables();
5476 	init_gm2_pan_table();
5477 	init_attack_vol_table();
5478 	init_sb_vol_table();
5479 	init_modenv_vol_table();
5480 	init_def_vol_table();
5481 	init_gs_vol_table();
5482 	init_perceived_vol_table();
5483 	init_gm2_vol_table();
5484 #ifdef SUPPORT_SOCKET
5485 	url_news_connection_cache(URL_NEWS_CONN_CACHE);
5486 #endif /* SUPPORT_SOCKET */
5487 	for(i = 0; i < NSPECIAL_PATCH; i++)
5488 	    special_patch[i] = NULL;
5489 	init_midi_trace();
5490 	int_rand(-1);	/* initialize random seed */
5491 	int_rand(42);	/* the 1st number generated is not very random */
5492 	ML_RegisterAllLoaders ();
5493     }
5494 
5495     is_first = 0;
5496 }
5497 
timidity_pre_load_configuration(void)5498 MAIN_INTERFACE int timidity_pre_load_configuration(void)
5499 {
5500 #if defined(__W32__)
5501     /* Windows */
5502     char *strp;
5503     int check;
5504     char local[1024];
5505 
5506 #if defined ( IA_W32GUI ) || defined ( IA_W32G_SYN )
5507     extern char *ConfigFile;
5508     if(!ConfigFile[0]) {
5509       GetWindowsDirectory(ConfigFile, 1023 - 13);
5510       strcat(ConfigFile, "\\TIMIDITY.CFG");
5511     }
5512     strncpy(local, ConfigFile, sizeof(local) - 1);
5513     if((check = open(local, 0)) >= 0)
5514     {
5515 	close(check);
5516 	if(!read_config_file(local, 0, 0)) {
5517 	    got_a_configuration = 1;
5518 		return 0;
5519 	}
5520     }
5521 #endif
5522 
5523 	/* First, try read configuration file which is in the
5524      * TiMidity directory.
5525      */
5526     if(GetModuleFileName(NULL, local, 1023))
5527     {
5528         local[1023] = '\0';
5529 	if(strp = strrchr(local, '\\'))
5530 	{
5531 	    *(++strp)='\0';
5532 	    strncat(local,"TIMIDITY.CFG",sizeof(local)-strlen(local)-1);
5533 	    if((check = open(local, 0)) >= 0)
5534 	    {
5535 		close(check);
5536 		if(!read_config_file(local, 0, 0)) {
5537 		    got_a_configuration = 1;
5538 			return 0;
5539 		}
5540 	    }
5541 	}
5542 #if !defined ( IA_W32GUI ) && !defined ( IA_W32G_SYN )
5543     /* Next, try read system configuration file.
5544      * Default is C:\WINDOWS\TIMIDITY.CFG
5545      */
5546     GetWindowsDirectory(local, 1023 - 13);
5547     strcat(local, "\\TIMIDITY.CFG");
5548     if((check = open(local, 0)) >= 0)
5549     {
5550 	close(check);
5551 	if(!read_config_file(local, 0, 0)) {
5552 	    got_a_configuration = 1;
5553 		return 0;
5554 	}
5555     }
5556 #endif
5557 
5558     }
5559 
5560 #else
5561     /* UNIX */
5562     if(!read_config_file(CONFIG_FILE, 0, 0))
5563 		got_a_configuration = 1;
5564 #endif
5565 
5566     /* Try read configuration file which is in the
5567      * $HOME (or %HOME% for DOS) directory.
5568      * Please setup each user preference in $HOME/.timidity.cfg
5569      * (or %HOME%/timidity.cfg for DOS)
5570      */
5571     if(read_user_config_file()) {
5572 	ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
5573 		  "Error: Syntax error in ~/.timidity.cfg");
5574 	return 1;
5575     }
5576 
5577     return 0;
5578 }
5579 
timidity_post_load_configuration(void)5580 MAIN_INTERFACE int timidity_post_load_configuration(void)
5581 {
5582     int i, cmderr = 0;
5583 
5584 #ifdef IA_ALSASEQ
5585     /* If we're going to fork for daemon mode, we need to fork now, as
5586        certain output libraries (pulseaudio) become unhappy if initialized
5587        before forking and then being used from the child. */
5588     if (ctl->id_character == 'A' && (ctl->flags & CTLF_DAEMONIZE))
5589     {
5590 	int pid = fork();
5591 	FILE *pidf;
5592 	switch (pid)
5593 	{
5594 	    case 0:		// child is the daemon
5595 		break;
5596 	    case -1:		// error status return
5597 		exit(7);
5598 	    default:		// no error, doing well
5599 		if ((pidf = fopen( "/var/run/timidity.pid", "w" )) != NULL )
5600 		{
5601 		    fprintf( pidf, "%d\n", pid );
5602 		    fclose( pidf );
5603 		}
5604 		exit(0);
5605 	}
5606     }
5607 #endif
5608 
5609     if(play_mode == &null_play_mode)
5610     {
5611 	char *output_id;
5612 
5613 	output_id = getenv("TIMIDITY_OUTPUT_ID");
5614 #ifdef TIMIDITY_OUTPUT_ID
5615 	if(output_id == NULL)
5616 	    output_id = TIMIDITY_OUTPUT_ID;
5617 #endif /* TIMIDITY_OUTPUT_ID */
5618 	if(output_id != NULL)
5619 	{
5620 	    for(i = 0; play_mode_list[i]; i++)
5621 		if(play_mode_list[i]->id_character == *output_id)
5622 		{
5623 		    if (! play_mode_list[i]->detect ||
5624 			play_mode_list[i]->detect()) {
5625 			play_mode = play_mode_list[i];
5626 			break;
5627 		    }
5628 		}
5629 	}
5630     }
5631 
5632     if (play_mode == &null_play_mode) {
5633 	/* try to detect the first available device */
5634 	for(i = 0; play_mode_list[i]; i++) {
5635 	    /* check only the devices with detect callback */
5636 	    if (play_mode_list[i]->detect) {
5637 		if (play_mode_list[i]->detect()) {
5638 		    play_mode = play_mode_list[i];
5639 		    break;
5640 		}
5641 	    }
5642 	}
5643     }
5644 
5645     if (play_mode == &null_play_mode) {
5646 	fprintf(stderr, "Couldn't open output device" NLS);
5647 	exit(1);
5648     }
5649     else {
5650         /* apply changes made for null play mode to actual play mode */
5651         if(null_play_mode.encoding != 0) {
5652             play_mode->encoding = apply_encoding(play_mode->encoding, null_play_mode.encoding);
5653         }
5654         if(null_play_mode.rate != 0) {
5655             play_mode->rate = null_play_mode.rate;
5656         }
5657     }
5658 
5659     if(!got_a_configuration)
5660     {
5661 	if(try_config_again && !read_config_file(CONFIG_FILE, 0, 0))
5662 	    got_a_configuration = 1;
5663     }
5664 
5665     if(opt_config_string.nstring > 0)
5666     {
5667 	char **config_string_list;
5668 
5669 	config_string_list = make_string_array(&opt_config_string);
5670 	if(config_string_list != NULL)
5671 	{
5672 	    for(i = 0; config_string_list[i]; i++)
5673 	    {
5674 		if(!read_config_file(config_string_list[i], 1, 0))
5675 		    got_a_configuration = 1;
5676 		else
5677 		    cmderr++;
5678 	    }
5679 	    free(config_string_list[0]);
5680 	    free(config_string_list);
5681 	}
5682     }
5683 
5684     if(!got_a_configuration)
5685 	cmderr++;
5686     return cmderr;
5687 }
5688 
timidity_init_player(void)5689 MAIN_INTERFACE void timidity_init_player(void)
5690 {
5691     initialize_resampler_coeffs();
5692 
5693     /* Allocate voice[] */
5694     voice = (Voice *) safe_realloc(voice, max_voices * sizeof(Voice));
5695 	memset(voice, 0, max_voices * sizeof(Voice));
5696 
5697     /* Set play mode parameters */
5698     if(opt_output_rate != 0)
5699 	play_mode->rate = opt_output_rate;
5700     else if(play_mode->rate == 0)
5701 	play_mode->rate = DEFAULT_RATE;
5702 
5703     /* save defaults */
5704     COPY_CHANNELMASK(drumchannels, default_drumchannels);
5705     COPY_CHANNELMASK(drumchannel_mask, default_drumchannel_mask);
5706 
5707     if(opt_buffer_fragments != -1)
5708     {
5709 	if(play_mode->flag & PF_BUFF_FRAGM_OPT)
5710 	    play_mode->extra_param[0] = opt_buffer_fragments;
5711 	else
5712 	    ctl->cmsg(CMSG_WARNING, VERB_NORMAL,
5713 		      "%s: -B option is ignored", play_mode->id_name);
5714     }
5715 
5716 #ifdef SUPPORT_SOUNDSPEC
5717     if(view_soundspec_flag)
5718     {
5719 	open_soundspec();
5720 	soundspec_setinterval(spectrogram_update_sec);
5721     }
5722 #endif /* SOUNDSPEC */
5723 }
5724 
timidity_init_aq_buff(void)5725 void timidity_init_aq_buff(void)
5726 {
5727     double time1, /* max buffer */
5728 	   time2, /* init filled */
5729 	   base;  /* buffer of device driver */
5730 
5731     if(!IS_STREAM_TRACE)
5732 	return; /* Ignore */
5733 
5734     time1 = atof(opt_aq_max_buff);
5735     time2 = atof(opt_aq_fill_buff);
5736     base  = (double)aq_get_dev_queuesize() / play_mode->rate;
5737     if(strchr(opt_aq_max_buff, '%'))
5738     {
5739 	time1 = base * (time1 - 100) / 100.0;
5740 	if(time1 < 0)
5741 	    time1 = 0;
5742     }
5743     if(strchr(opt_aq_fill_buff, '%'))
5744 	time2 = base * time2 / 100.0;
5745     aq_set_soft_queue(time1, time2);
5746 }
5747 
timidity_play_main(int nfiles,char ** files)5748 MAIN_INTERFACE int timidity_play_main(int nfiles, char **files)
5749 {
5750     int need_stdin = 0, need_stdout = 0;
5751     int i;
5752     int output_fail = 0;
5753     int retval;
5754 
5755     if(nfiles == 0 && !strchr(INTERACTIVE_INTERFACE_IDS, ctl->id_character))
5756 	return 0;
5757 
5758     if(opt_output_name)
5759     {
5760 	play_mode->name = opt_output_name;
5761     if(!strcmp(opt_output_name, "-")){
5762 	    need_stdout = 1;
5763 #ifdef __W32__
5764     	setmode( fileno(stdout), O_BINARY );
5765 #endif
5766     }
5767     }
5768 
5769     for(i = 0; i < nfiles; i++)
5770 	if (!strcmp(files[i], "-")){
5771 	    need_stdin = 1;
5772 #ifdef __W32__
5773     	setmode( fileno(stdin), O_BINARY );
5774 #endif
5775 	}
5776 
5777     if(ctl->open(need_stdin, need_stdout))
5778     {
5779 	fprintf(stderr, "Couldn't open %s (`%c')" NLS,
5780 		ctl->id_name, ctl->id_character);
5781 	play_mode->close_output();
5782 	return 3;
5783     }
5784 
5785     if(wrdt->open(wrdt_open_opts))
5786     {
5787 	fprintf(stderr, "Couldn't open WRD Tracer: %s (`%c')" NLS,
5788 		wrdt->name, wrdt->id);
5789 	play_mode->close_output();
5790 	ctl->close();
5791 	return 1;
5792     }
5793 
5794 #ifdef BORLANDC_EXCEPTION
5795     __try
5796     {
5797 #endif /* BORLANDC_EXCEPTION */
5798 #ifdef __W32__
5799 
5800 #ifdef HAVE_SIGNAL
5801 	signal(SIGTERM, sigterm_exit);
5802 #endif
5803 	SetConsoleCtrlHandler(handler, TRUE);
5804 
5805 	ctl->cmsg(CMSG_INFO, VERB_DEBUG_SILLY,
5806 		  "Initialize for Critical Section");
5807 	InitializeCriticalSection(&critSect);
5808 	if(opt_evil_mode)
5809 	    if(!SetThreadPriority(GetCurrentThread(),
5810 				  THREAD_PRIORITY_ABOVE_NORMAL))
5811 		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
5812 			  "Error raising process priority");
5813 
5814 #else
5815 	/* UNIX */
5816 #ifdef HAVE_SIGNAL
5817 	signal(SIGINT, sigterm_exit);
5818 	signal(SIGTERM, sigterm_exit);
5819 #ifdef SIGPIPE
5820 	signal(SIGPIPE, sigterm_exit);    /* Handle broken pipe */
5821 #endif /* SIGPIPE */
5822 #endif /* HAVE_SIGNAL */
5823 
5824 #endif
5825 
5826 	/* Open output device */
5827 	ctl->cmsg(CMSG_INFO, VERB_DEBUG_SILLY,
5828 		  "Open output: %c, %s",
5829 		  play_mode->id_character,
5830 		  play_mode->id_name);
5831 
5832 	if (play_mode->flag & PF_PCM_STREAM) {
5833 	    play_mode->extra_param[1] = aq_calc_fragsize();
5834 	    ctl->cmsg(CMSG_INFO, VERB_DEBUG_SILLY,
5835 		      "requesting fragment size: %d",
5836 		      play_mode->extra_param[1]);
5837 	}
5838 #if !defined ( IA_W32GUI ) && !defined ( IA_W32G_SYN )
5839 	if(play_mode->open_output() < 0)
5840 	{
5841 	    ctl->cmsg(CMSG_FATAL, VERB_NORMAL,
5842 		      "Couldn't open %s (`%c')",
5843 		      play_mode->id_name, play_mode->id_character);
5844 	    output_fail = 1;
5845 	    ctl->close();
5846 	    return 2;
5847 	}
5848 #endif /* IA_W32GUI */
5849 	if(!control_ratio)
5850 	{
5851 	    control_ratio = play_mode->rate / CONTROLS_PER_SECOND;
5852 	    if(control_ratio < 1)
5853 		control_ratio = 1;
5854 	    else if (control_ratio > MAX_CONTROL_RATIO)
5855 		control_ratio = MAX_CONTROL_RATIO;
5856 	}
5857 
5858 	init_load_soundfont();
5859 	if(!output_fail)
5860 	{
5861 	    aq_setup();
5862 	    timidity_init_aq_buff();
5863 	}
5864 	if(allocate_cache_size > 0)
5865 	    resamp_cache_reset();
5866 
5867 	if (def_prog >= 0)
5868 		set_default_program(def_prog);
5869 	if (*def_instr_name)
5870 		set_default_instrument(def_instr_name);
5871 
5872 	if(ctl->flags & CTLF_LIST_RANDOM)
5873 	    randomize_string_list(files, nfiles);
5874 	else if(ctl->flags & CTLF_LIST_SORT)
5875 	    sort_pathname(files, nfiles);
5876 
5877 	/* Return only when quitting */
5878 	ctl->cmsg(CMSG_INFO, VERB_DEBUG_SILLY,
5879 		  "pass_playing_list() nfiles=%d", nfiles);
5880 
5881 	retval=ctl->pass_playing_list(nfiles, files);
5882 
5883 	if(intr)
5884 	    aq_flush(1);
5885 
5886 #ifdef XP_UNIX
5887 	return 0;
5888 #endif /* XP_UNIX */
5889 
5890 	play_mode->close_output();
5891 	ctl->close();
5892 	wrdt->close();
5893 #ifdef __W32__
5894 	DeleteCriticalSection (&critSect);
5895 #endif
5896 
5897 #ifdef BORLANDC_EXCEPTION
5898     } __except(1) {
5899 	fprintf(stderr, "\nError!!!\nUnexpected Exception Occured!\n");
5900 	if(play_mode->fd != -1)
5901 	{
5902 		play_mode->purge_output();
5903 		play_mode->close_output();
5904 	}
5905 	ctl->close();
5906 	wrdt->close();
5907 	DeleteCriticalSection (&critSect);
5908 	exit(EXIT_FAILURE);
5909     }
5910 #endif /* BORLANDC_EXCEPTION */
5911 
5912 #ifdef SUPPORT_SOUNDSPEC
5913     if(view_soundspec_flag)
5914 	close_soundspec();
5915 #endif /* SUPPORT_SOUNDSPEC */
5916 
5917     free_archive_files();
5918 #ifdef SUPPORT_SOCKET
5919     url_news_connection_cache(URL_NEWS_CLOSE_CACHE);
5920 #endif /* SUPPORT_SOCKET */
5921 
5922     return retval;
5923 }
5924 
5925 #ifdef IA_W32GUI
5926 int w32gSecondTiMidity(int opt, int argc, char **argv);
5927 int w32gSecondTiMidityExit(void);
5928 int w32gLoadDefaultPlaylist(void);
5929 int w32gSaveDefaultPlaylist(void);
5930 extern int volatile save_playlist_once_before_exit_flag;
5931 #endif /* IA_W32GUI */
5932 
5933 #if defined(__W32__) && !defined(WINDRV)
5934 typedef BOOL (WINAPI *SetDllDirectoryAProc)(LPCSTR lpPathName);
5935 
5936 /*! Remove the current directory for the search path of LoadLibrary. Returns 0 if failed. */
w32_reset_dll_directory(void)5937 static int w32_reset_dll_directory(void)
5938 {
5939 	HMODULE module;
5940 	SetDllDirectoryAProc setDllDirectory;
5941 	if ((module = GetModuleHandle(TEXT("Kernel32.dll"))) == NULL)
5942 		return 0;
5943 	if ((setDllDirectory = (SetDllDirectoryAProc)GetProcAddress(module, TEXT("SetDllDirectoryA"))) == NULL)
5944 		return 0;
5945 	/* Microsoft Security Advisory 2389418 */
5946 	return (*setDllDirectory)("") != 0;
5947 }
5948 #endif
5949 
5950 #if defined ( IA_W32GUI ) || defined ( IA_W32G_SYN )
5951 static int CoInitializeOK = 0;
5952 #endif
5953 
5954 #if !defined(ANOTHER_MAIN) || defined(__W32__)
5955 #ifdef __W32__ /* Windows */
5956 #if defined(IA_W32GUI) && !defined(__CYGWIN32__) && !defined(__MINGW32__) \
5957 		|| defined(IA_W32G_SYN) /* _MSC_VER, _BORLANDC_, __WATCOMC__ */
win_main(int argc,char ** argv)5958 int win_main(int argc, char **argv)
5959 #else /* Cygwin, MinGW or console */
5960 int __cdecl main(int argc, char **argv)
5961 #endif
5962 #else /* UNIX */
5963 int main(int argc, char **argv)
5964 #endif
5965 {
5966 	int c, err, i;
5967 	int nfiles;
5968 	char **files;
5969 	char *files_nbuf = NULL;
5970 	int main_ret;
5971 	int longind;
5972 #if defined(DANGEROUS_RENICE) && !defined(__W32__) && !defined(main)
5973 	/*
5974 	 * THIS CODES MUST EXECUTE BEGINNING OF MAIN FOR SECURITY.
5975 	 * DON'T PUT ANY CODES ABOVE.
5976 	 */
5977 #include <sys/resource.h>
5978 	int uid;
5979 #ifdef sun
5980 	extern int setpriority(int which, id_t who, int prio);
5981 	extern int setreuid(int ruid, int euid);
5982 #endif
5983 
5984 	uid = getuid();
5985 	if (setpriority(PRIO_PROCESS, 0, DANGEROUS_RENICE) < 0) {
5986 		perror("setpriority");
5987 		fprintf(stderr, "Couldn't set priority to %d.", DANGEROUS_RENICE);
5988 	}
5989 	setreuid(uid, uid);
5990 #endif
5991 #if defined(REDIRECT_STDOUT)
5992 	memcpy(stdout, fopen(REDIRECT_STDOUT, "a+"), sizeof(FILE));
5993 	printf("TiMidity++ start\n");
5994 	fflush(stdout);
5995 #endif
5996 #if defined(__W32__) && !defined(WINDRV)
5997 	(void)w32_reset_dll_directory();
5998 #endif
5999 #ifdef main
6000 {
6001 	static int maincnt = 0;
6002 
6003 	if (maincnt++ > 0) {
6004 		do {
6005 			argc--, argv++;
6006 		} while (argv[0][0] == '-');
6007 		ctl->pass_playing_list(argc, argv);
6008 		return 0;
6009 	}
6010 }
6011 #endif
6012 #ifdef IA_DYNAMIC
6013 {
6014 	dynamic_lib_root = safe_strdup(SHARED_LIB_PATH);
6015 	dl_init(argc, argv);
6016 }
6017 #endif /* IA_DYNAMIC */
6018 	if ((program_name = pathsep_strrchr(argv[0])))
6019 		program_name++;
6020 	else
6021 		program_name = argv[0];
6022 	if (strncmp(program_name, "timidity", 8) == 0)
6023 		;
6024 	else if (strncmp(program_name, "kmidi", 5) == 0)
6025 		set_ctl("q");
6026 	else if (strncmp(program_name, "tkmidi", 6) == 0)
6027 		set_ctl("k");
6028 	else if (strncmp(program_name, "gtkmidi", 6) == 0)
6029 		set_ctl("g");
6030 	else if (strncmp(program_name, "xmmidi", 6) == 0)
6031 		set_ctl("m");
6032 	else if (strncmp(program_name, "xawmidi", 7) == 0)
6033 		set_ctl("a");
6034 	else if (strncmp(program_name, "xskinmidi", 9) == 0)
6035 		set_ctl("i");
6036 	if (argc == 1 && !strchr(INTERACTIVE_INTERFACE_IDS, ctl->id_character)) {
6037 		interesting_message();
6038 		return 0;
6039 	}
6040 	timidity_start_initialize();
6041 #if defined (IA_W32GUI) || defined (IA_W32G_SYN)
6042 	if (CoInitialize(NULL) == S_OK)
6043 		CoInitializeOK = 1;
6044 	w32g_initialize();
6045 #ifdef IA_W32GUI
6046 	/* Secondary TiMidity Execute */
6047 	/*	FirstLoadIniFile(); */
6048 	if (w32gSecondTiMidity(SecondMode,argc,argv) == FALSE)
6049 		return 0;
6050 #endif
6051 	for (c = 1; c < argc; c++)
6052 		if (is_directory(argv[c])) {
6053 			char *p;
6054 
6055 			p = (char *) safe_malloc(strlen(argv[c]) + 2);
6056 			strcpy(p, argv[c]);
6057 			directory_form(p);
6058 			argv[c] = p;
6059 		}
6060 #endif /* IA_W32GUI || IA_W32G_SYN */
6061 #if defined(IA_WINSYN) || defined(IA_PORTMIDISYN) || defined(IA_NPSYN) || defined(IA_W32G_SYN)
6062 	opt_sf_close_each_file = 0;
6063 #endif
6064 	optind = longind = 0;
6065 #if defined(__CYGWIN__)
6066 	optreset = 1;
6067 #endif
6068 #ifdef __W32__
6069 	while ((c = getopt_long(argc, argv, optcommands, longopts, &longind)) > 0)
6070 		if ((err = set_tim_opt_long_cfg(c, optarg, longind)) != 0)
6071 			break;
6072 #endif
6073 	if (got_a_configuration != 1){
6074 		if ((err = timidity_pre_load_configuration()) != 0)
6075 			return err;
6076 	}
6077 	optind = longind = 0;
6078 #if defined(__CYGWIN__)
6079 	optreset = 1;
6080 #endif
6081 	while ((c = getopt_long(argc, argv, optcommands, longopts, &longind)) > 0)
6082 		if ((err = set_tim_opt_long(c, optarg, longind)) != 0)
6083 			break;
6084 	err += timidity_post_load_configuration();
6085 	/* If there were problems, give up now */
6086 	if (err || (optind >= argc
6087 			&& !strchr(INTERACTIVE_INTERFACE_IDS, ctl->id_character))) {
6088 		if (!got_a_configuration) {
6089 #ifdef __W32__
6090 			char config1[1024], config2[1024];
6091 
6092 			memset(config1, 0, sizeof(config1));
6093 			memset(config2, 0, sizeof(config2));
6094 #if defined(IA_W32GUI) || defined(IA_W32G_SYN)
6095 {
6096 			extern char *ConfigFile;
6097 
6098 			strncpy(config1, ConfigFile, sizeof(config1) - 1);
6099 }
6100 #else /* !IA_W32GUI && !IA_W32G_SYN */
6101 			GetWindowsDirectory(config1, 1023 - 13);
6102 			strcat(config1, "\\TIMIDITY.CFG");
6103 #endif
6104 			if (GetModuleFileName(NULL, config2, 1023)) {
6105 				char *strp;
6106 
6107 				config2[1023] = '\0';
6108 				if (strp = strrchr(config2, '\\')) {
6109 					*(++strp) = '\0';
6110 					strncat(config2, "TIMIDITY.CFG",
6111 							sizeof(config2) - strlen(config2) - 1);
6112 				}
6113 			}
6114 			ctl->cmsg(CMSG_FATAL, VERB_NORMAL,
6115 					"%s: Can't read any configuration file.\n"
6116 					"Please check %s or %s", program_name, config1, config2);
6117 #else
6118 			ctl->cmsg(CMSG_FATAL, VERB_NORMAL,
6119 					"%s: Can't read any configuration file.\n"
6120 					"Please check " CONFIG_FILE, program_name);
6121 #endif /* __W32__ */
6122 		} else
6123 			ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
6124 					"Try %s -h for help", program_name);
6125 /* Try to continue if it is Windows version */
6126 #if !defined(IA_W32GUI) && !defined(IA_W32G_SYN)
6127 		return 1; /* problems with command line */
6128 #endif
6129 	}
6130 	timidity_init_player();
6131 	nfiles = argc - optind;
6132 	files  = argv + optind;
6133 	if (nfiles > 0
6134 			&& ctl->id_character != 'r' && ctl->id_character != 'A'
6135 			&& ctl->id_character != 'W' && ctl->id_character != 'N'
6136 			&& ctl->id_character != 'P')
6137 		files = expand_file_archives(files, &nfiles);
6138 	if (nfiles > 0)
6139 		files_nbuf = files[0];
6140 #if !defined(IA_W32GUI) && !defined(IA_W32G_SYN)
6141 	if (dumb_error_count)
6142 		sleep(1);
6143 #endif
6144 #ifdef IA_W32GUI
6145 	w32gLoadDefaultPlaylist();
6146 	main_ret = timidity_play_main(nfiles, files);
6147 	if (save_playlist_once_before_exit_flag) {
6148 		save_playlist_once_before_exit_flag = 0;
6149 		w32gSaveDefaultPlaylist();
6150 	}
6151 	w32gSecondTiMidityExit();
6152 	if (CoInitializeOK)
6153 		CoUninitialize();
6154 	w32g_free_playlist();
6155 	w32g_uninitialize();
6156 	w32g_free_doc();
6157 #else
6158 #ifdef IA_NPSYN
6159 	timeBeginPeriod(1);
6160 #endif
6161 	main_ret = timidity_play_main(nfiles, files);
6162 #ifdef IA_NPSYN
6163 	timeEndPeriod(1);
6164 #endif
6165 #ifdef IA_W32G_SYN
6166 	if (CoInitializeOK)
6167 		CoUninitialize();
6168 	w32g_uninitialize();
6169 #endif /* IA_W32G_SYN */
6170 #endif /* IA_W32GUI */
6171 #ifdef SUPPORT_SOCKET
6172 	if (url_user_agent)
6173 		free(url_user_agent);
6174 	if (url_http_proxy_host)
6175 		free(url_http_proxy_host);
6176 	if (url_ftp_proxy_host)
6177 		free(url_ftp_proxy_host);
6178 	if (user_mailaddr)
6179 		free(user_mailaddr);
6180 #endif
6181 #ifdef IA_DYNAMIC
6182 	if (dynamic_lib_root)
6183 		free(dynamic_lib_root);
6184 #endif
6185 	if (pcm_alternate_file)
6186 		free(pcm_alternate_file);
6187 	if (opt_output_name)
6188 		free(opt_output_name);
6189 	if (opt_aq_max_buff)
6190 		free(opt_aq_max_buff);
6191 	if (opt_aq_fill_buff && opt_aq_fill_buff_free_needed)
6192 		free(opt_aq_fill_buff);
6193 	if (output_text_code)
6194 		free(output_text_code);
6195 	if (wrdt_open_opts)
6196 		free(wrdt_open_opts);
6197 	if (nfiles > 0
6198 			&& ctl->id_character != 'r' && ctl->id_character != 'A'
6199 			&& ctl->id_character != 'W' && ctl->id_character != 'N'
6200 			&& ctl->id_character != 'P') {
6201 		free(files_nbuf);
6202 		free(files);
6203 	}
6204 	free_soft_queue();
6205 	free_instruments(0);
6206 	free_soundfonts();
6207 	free_cache_data();
6208 	free_wrd();
6209 	free_readmidi();
6210 	free_global_mblock();
6211 	tmdy_free_config();
6212 	free_reverb_buffer();
6213 	free_effect_buffers();
6214 	free(voice);
6215 	free_gauss_table();
6216 	for (i = 0; i < MAX_CHANNELS; i++)
6217 		free_drum_effect(i);
6218 	return main_ret;
6219 }
6220 #endif /* !ANOTHER_MAIN || __W32__ */
6221 
6222