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(&lification, 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(¶m->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(¶m->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