1 /* $Id: main.c,v 1.9 2006/09/16 10:36:23 toad32767 Exp $ */
2 /**
3 ** 2005, 2006 by Marco Trillo
4 ** This file is part of UModPlayer, and is released by
5 ** its autors to the Public Domain.
6 ** In case it's not legally possible, its autors grant
7 ** anyone the right to use, redistribute and modify
8 ** this software for any purpose, without any conditions,
9 ** unless such conditions are required by law.
10 **
11 ** THIS FILE COMES WITHOUT ANY WARRANTY. THE AUTHORS
12 ** SHALL NOT BE LIABLE FOR ANY DAMAGE RESULTING BY THE
13 ** USE OR MISUSE OF THIS SOFTWARE.
14 **/
15
16 #include <umodplayer.h>
17 #include <options.h>
18 #include <coresound.h>
19 #include <ipret.h>
20 #include <file_write.h>
21 #include <file_read.h>
22 #include <file_parse.h>
23 #include <text.h>
24
25 #include <signal.h>
26
27 /* global variables */
28 EXPORT struct file file = {FALSE, NULL, NULL}; /* the module file loaded */
29 EXPORT struct oFlags sets; /* settings (configuration) */
30 EXPORT char **rr = NULL; /* text to be printed out by the table callback */
31 EXPORT int startpos = 0; /* start position for exportings */
32 EXPORT int endpos = -1; /* end position for exportings */
33 EXPORT int CoreSound_BitsPerSample = 0; /* bits per sample */
34 EXPORT char *AudioDriver = NULL; /* audio driver */
35 EXPORT Bool AudioActive = FALSE; /* audio active */
36 EXPORT ao_device *AO_Device = NULL; /* device for LibAo */
37
38 /*
39 * Catch the SIGINT & SIGTERM signals
40 */
41 void
CatchSignal(int sig)42 CatchSignal(int sig)
43 {
44 if (AudioActive == TRUE)
45 CoreSound_Quit();
46 if (file.name != NULL)
47 UFreeFile();
48
49 notice("\n[exiting by signal %d]\n", sig);
50 exit(UM_OK);
51 }
52
53 /*
54 * Print the version banner
55 */
56 EXPORT void
PrintBanner()57 PrintBanner()
58 {
59 puts(UMODPLAYER_VERSION);
60 puts(COMPILATION_DATE);
61 }
62
63 /*
64 * Display the program usage
65 */
66 LOCAL void
DisplayUsage(char * progname)67 DisplayUsage(char *progname)
68 {
69 fprintf(stderr, "Usage: %s [<module file>] [<options>]\n\n"
70 "Options\n"
71 "-V : print the UModPlayer version and exit.\n"
72 "-i : Interactive mode (this is the default mode\n"
73 " when no module file is given on command line.\n"
74 "-q : Quiet; Do not print the status bar.\n"
75 "-a <pos> : Start playback/export at order position <pos>.\n"
76 "-z <pos> : End playback/export at order position <pos>.\n"
77 "-o <output file> : Export loaded module to <output file>.\n"
78 "-f <output format> : Select a format to export loaded module.\n"
79 " Available formats:\n"
80 " it, wav, aiff, s16se, s16le, s16be\n", progname);
81 fprintf(stderr, "-d : Use the default config scheme.\n"
82 "-w : Save the current config scheme.\n"
83 "-m <output file> : Export module text message to <output file>.\n"
84 "-s <output file> : Export module samplenames to <output file>.\n"
85 "-I <output file> : Export module instrumentnames to <output file>.\n");
86 fprintf(stderr, "Audio options:\n"
87 "-v <level> : Volume level (1-512)\n"
88 "-c <channels> : N. of channels. Possible values\n"
89 " 1 = mono ; 2 = stereo\n"
90 "-O <driver> : audio driver\n"
91 " alsa09, alsa, oss, sun, macosx, arts, irix, esd, null\n"
92 "-r <rate> : Sampling rate in Hz. Available values:\n"
93 " 11025, 16000, 22050, 24000, 32000, 44100\n"
94 "-M <mode> : Resampling mode. Available modes:\n"
95 " NO_INTERPOLATE, LINEAR, SPLINE, FIR_FILTER\n"
96 "+N,+R,+B,+S : Enable Noise Reduction, reverb, megabass\n"
97 " & surround.\n"
98 "-N,-R,-B,-S : Disable Noise Reduction, reverb, megabass\n"
99 " & surround.\n");
100 return;
101 }
102
103 /*
104 * A bogus monitor function for `no-status' mode.
105 */
106 void
QuietPlay()107 QuietPlay()
108 {
109 /* only interrupted when finished or killed by a signal */
110 for (;;) {
111 CoreSound_InjectPCM();
112
113 if (AudioActive == FALSE) {
114 CoreSound_Quit();
115 return;
116 }
117 }
118 }
119
120
121
122 /*
123 * umodplayer -- module player
124 */
125 EXPORT int
main(int argc,char ** argv)126 main(int argc, char **argv)
127 {
128 int i;
129 int interactive = 0, status = 1, saveSettings = 0;
130 char *ofile = NULL;
131 int ofmt = 0, obps = 16;
132 char *txt_ofile = NULL;
133 char *spl_ofile = NULL;
134 char *ins_ofile = NULL;
135
136 if (argc == 2 && (strcmp("--help", argv[1]) == 0 || strcmp("-h", argv[1]) == 0)) {
137 DisplayUsage(argv[0]);
138 exit(UM_OK);
139 }
140
141 InitOptions(&sets);
142
143 /*
144 * Parse the command line options
145 */
146 for (i = 1; i < argc; ++i) {
147 char *p = argv[i], *h;
148
149 /*
150 * (-)
151 */
152 if (*p == '-') {
153 switch (*(++p)) {
154 case 'i':
155 interactive = 1;
156 break;
157 case 'a':
158 i++;
159 if (argc <= i)
160 break;
161 startpos = atoi(argv[i]);
162 if (startpos < 0)
163 startpos = 0;
164 break;
165 case 'z':
166 i++;
167 if (argc <= i)
168 break;
169 endpos = atoi(argv[i]);
170 if (endpos <= startpos)
171 endpos = -1;
172 break;
173 case 'o':
174 i++;
175 if (argc <= i)
176 break;
177 ofile = argv[i];
178 h = strrchr(ofile, '.');
179 if (!h)
180 break;
181 if (strcasecmp(h, ".it") == 0)
182 ofmt = EXPORT_TYPE_IT;
183 else if (strcasecmp(h, ".wav") == 0)
184 ofmt = EXPORT_TYPE_WAV;
185 else if (strcasecmp(h, ".aiff") == 0
186 || strcasecmp(h, ".aif") == 0) {
187 obps = 16;
188 ofmt = EXPORT_TYPE_AIFF;
189 } else if (strcasecmp(h, ".pcm") == 0)
190 ofmt = EXPORT_TYPE_PCM | EXPORT_SYS_ENDIAN;
191 else if (strcasecmp(h, ".raw") == 0)
192 ofmt = EXPORT_TYPE_PCM | EXPORT_LTE_ENDIAN;
193 else
194 ofmt = 0;
195 break;
196 case 'f':
197 i++;
198 if (argc <= i)
199 break;
200 h = argv[i];
201 if (strcmp(h, "it") == 0)
202 ofmt = EXPORT_TYPE_IT;
203 else if (strcmp(h, "wav") == 0)
204 ofmt = EXPORT_TYPE_WAV;
205 else if (strcmp(h, "aiff16") == 0) {
206 ofmt = EXPORT_TYPE_AIFF;
207 obps = 16;
208 } else if (strcmp(h, "aiff24") == 0) {
209 ofmt = EXPORT_TYPE_AIFF;
210 obps = 24;
211 } else if (strcmp(h, "s16se") == 0)
212 ofmt = EXPORT_TYPE_PCM | EXPORT_SYS_ENDIAN;
213 else if (strcmp(h, "s16le") == 0)
214 ofmt = EXPORT_TYPE_PCM | EXPORT_LTE_ENDIAN;
215 else if (strcmp(h, "s16be") == 0)
216 ofmt = EXPORT_TYPE_PCM | EXPORT_BIG_ENDIAN;
217 else
218 fprintf(stderr, "Invalid format -- %s\n", h);
219 break;
220 case 'd':
221 DefaultOptions(&sets);
222 break;
223 case 'w':
224 saveSettings = 1;
225 break;
226 case 'm':
227 ++i;
228 if (argc <= i)
229 break;
230 txt_ofile = argv[i];
231 break;
232 case 's':
233 ++i;
234 if (argc <= i)
235 break;
236 spl_ofile = argv[i];
237 break;
238 case 'I':
239 ++i;
240 if (argc <= i)
241 break;
242 ins_ofile = argv[i];
243 break;
244 case 'v':
245 ++i;
246 if (argc <= i)
247 break;
248 sets.vol = (unsigned int) atol(argv[i]);
249 if (sets.vol > 768) /* XXX - not really sure about the Modplug limit */
250 sets.vol = 768;
251 if (sets.vol < 1)
252 sets.vol = 1;
253 break;
254 case 'c':
255 ++i;
256 if (argc <= i)
257 break;
258 sets.channels = atoi(argv[i]);
259 if (sets.channels < 1)
260 sets.channels = 1;
261 if (sets.channels > 2)
262 sets.channels = 2;
263 break;
264 case 'r':
265 ++i;
266 if (argc <= i)
267 break;
268 sets.samplerate = atoi(argv[i]);
269 switch (sets.samplerate) {
270 case 11025:
271 case 16000:
272 case 22050:
273 case 24000:
274 case 32000:
275 case 44100:
276 break;
277 default:
278 sets.samplerate = 44100;
279 }
280 break;
281 case 'M':
282 ++i;
283 if (argc <= i)
284 break;
285 h = argv[i];
286 if (strcmp(h, "NO_INTERPOLATE") == 0 ||
287 strcmp(h, "RESAMPLE") == 0) /* deprecated, compat. only */
288 sets.resampling = 0;
289 else if (strcmp(h, "LINEAR") == 0)
290 sets.resampling = 1;
291 else if (strcmp(h, "SPLINE") == 0)
292 sets.resampling = 2;
293 else if (strcmp(h, "FIR_FILTER") == 0)
294 sets.resampling = 3;
295 break;
296 case 'O':
297 ++i;
298 if (argc <= i)
299 break;
300 AudioDriver = argv[i];
301 break;
302 case 'q':
303 status = 0;
304 --(sets.verbosity);
305 break;
306 case 'V':
307 PrintBanner();
308 if (file.name != NULL)
309 UFreeFile();
310 exit(UM_OK);
311 break; /* NOTREACHED */
312
313 /* Disable options */
314 case 'N':
315 sets.flags &= (~MODPLUG_ENABLE_NOISE_REDUCTION);
316 break;
317 case 'R':
318 sets.flags &= (~MODPLUG_ENABLE_REVERB);
319 break;
320 case 'B':
321 sets.flags &= (~MODPLUG_ENABLE_MEGABASS);
322 break;
323 case 'S':
324 sets.flags &= (~MODPLUG_ENABLE_SURROUND);
325 break;
326 }
327
328 /*
329 * (+)
330 */
331 } else if (*p == '+') {
332 switch (*(++p)) {
333 /* Enable options */
334 case 'N':
335 sets.flags |= MODPLUG_ENABLE_NOISE_REDUCTION;
336 break;
337 case 'R':
338 sets.flags |= MODPLUG_ENABLE_REVERB;
339 break;
340 case 'B':
341 sets.flags |= MODPLUG_ENABLE_MEGABASS;
342 break;
343 case 'S':
344 sets.flags |= MODPLUG_ENABLE_SURROUND;
345 break;
346 }
347 } else {
348 file.name = argv[i];
349 file.malloc = FALSE;
350 }
351 }
352
353 if (file.name == NULL)
354 interactive = 1;
355
356 /* print version banner? */
357 if (status > 0 && sets.verbosity > 0) {
358 PrintBanner();
359 }
360
361 /* save settings? */
362 if (saveSettings == 1) {
363 SaveOptions(&sets);
364 }
365
366 /* load a file? */
367 if (file.name != NULL) {
368 ULoadFile();
369 }
370
371 /* export the loaded file? */
372 if (!interactive && file.name != NULL && ofile != NULL) {
373 int ret;
374
375 if (ofmt == 0) {
376 error("CAN'T guess format of <%s>\n", ofile);
377 exit(UM_ERR_INVAL);
378 }
379
380 switch (ofmt) {
381 case EXPORT_TYPE_IT:
382 #ifdef MODPLUG_CAN_SAVE
383 ret = ModPlug_ExportIT(file.mod, ofile);
384 #else
385 error("ModPlug compiled without 'save' support\n", stderr);
386 ret = 0;
387 #endif
388 break;
389 case EXPORT_TYPE_WAV:
390 ret = ((long) WriteWAV(ofile) > 0L);
391 break;
392 case EXPORT_TYPE_AIFF:
393 ret = (int) WriteAIFF(ofile, obps);
394 break;
395 case EXPORT_TYPE_PCM:
396 ret = ((long) WritePCM(ofile, ofmt) > 0L);
397 break;
398 default:
399 ret = 0;
400 }
401
402 UFreeFile();
403
404 if (!ret) {
405 error("export failed!\n");
406 exit(UM_ERR_INVAL);
407 } else {
408 exit(UM_OK);
409 }
410 }
411
412 /* save misc. stuff */
413 if (!interactive && file.name && txt_ofile)
414 SaveSongComments(txt_ofile);
415
416 if (!interactive && file.name && spl_ofile) {
417 int fd;
418
419 fd = open(spl_ofile, O_WRONLY | O_TRUNC | O_CREAT, 0644);
420 if (fd < 0) {
421 error("file creation error.\n");
422 } else {
423 DisplaySamples(fd);
424 close(fd);
425 }
426 }
427 if (!interactive && file.name && ins_ofile) {
428 int fd;
429
430 fd = open(ins_ofile, O_WRONLY | O_TRUNC | O_CREAT, 0644);
431 if (fd < 0) {
432 error("file creation error.\n");
433 } else {
434 DisplayInstruments(fd);
435 close(fd);
436 }
437 }
438 if (!interactive && file.name && (ofile || txt_ofile || spl_ofile || ins_ofile)) {
439 UFreeFile();
440 exit(UM_OK);
441 }
442
443 /* catch the SIGINT and SIGTERM signals */
444 signal(SIGINT, CatchSignal);
445 signal(SIGTERM, CatchSignal);
446
447 if (!interactive) {
448 if (file.name == NULL) {
449 error("file load: %s\n", strerror(errno));
450 exit(UM_ERR_IO);
451 }
452 if (status > 0) {
453 DrawInfoTable();
454 CoreSound_StartMonitor();
455 } else {
456 CoreSound_Start(QuietPlay);
457 }
458
459 UFreeFile();
460 exit(UM_OK);
461 } else {
462 /*
463 * Launch the command interpreter
464 */
465 notice("Launching the command interpreter...\n");
466 notice("Type 'help' and <ENTER> to get a list of available commands.\n");
467 notice("Configure the advanced features with the 'setadvanced' command.\n");
468 CommandInterpreter();
469 UFreeFile();
470 exit(UM_OK);
471 }
472
473 /* NOTREACHED */
474 return UM_OK;
475 }
476
477
478