1 /*
2 ********************************************************************************
3 File: cmdarg.c
4
5 Tab size: 4
6 Max line length: 80
7 Programmer: Volker Kuhlmann
8
9
10 wav2cdr 2.3.4 Copyright (C) 1997, 1998, 1999, 2000, 2006 Volker Kuhlmann
11 This program is free software under the terms of the GNU General Public License
12 version 2 (or later, at your option).
13 See the file COPYING for details about license terms and warranty.
14 <VolkerKuhlmann@gmx.de>
15
16
17 DESCRIPTION:
18
19 Scans and checks the command line arguments.
20
21
22 CONDITIONALS:
23 see wav2cdr.c
24
25
26 HISTORY:
27 see wav2cdr.c, and ChangeLog
28
29 ********************************************************************************
30 */
31
32
33
34 #include <stddef.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include <errno.h>
40 #include <limits.h>
41 #include <assert.h>
42 #include <time.h>
43 #include <math.h>
44
45 #include "chelp.h"
46
47 #include "wav2cdr.h"
48
49 #ifdef HAS_GNUGETOPT
50 #include "getopt.h"
51 #else
52 #include "mygetopt.h"
53 #endif
54
55
56 /*
57 Global + local variables
58 */
59 extern FILE
60 *msgfile; /* where to display cmd args and progress */
61
62 #ifdef DEBUG
63 extern FILE
64 *dbgfile; /* where to display debug output */
65 #endif
66
67 static cmdarg_t
68 cmdarg = CMDARG_DEFAULT; /* cmd args, set to default values */
69
70 /* size of input data in bytes, not counting headers
71 size not available when == -1 (therefore must be a signed type)
72 Can not make this int because that may be only 16 bit.
73 Can not make this size_t because that is usually unsigned int.
74 Should be the same type as get_file_size().
75 */
76 static signed long input_size;
77
78
79
80 /*
81 Local function prototypes
82 */
83 static signed long get_num_unit (const string *s);
84 #ifdef GET_UINT16
85 static UINT16 get_uint16_bytes (const char *s);
86 static UINT16 get_uint16_blocks (const char *s);
87 #endif
88 static void check_monotonous_cuts (void);
89 static signed long get_neg_cut (signed long cut);
90
91
92
93 /*
94 Parse command line and do some checks for consistency.
95 In: argc, argv
96 Out: ---
97 Return: ---
98 */
scan_cmd_args(int argc,char ** argv)99 void scan_cmd_args (int argc, char **argv)
100 {
101 int lidx
102 #ifdef DEBUG
103 = -99
104 #endif
105 ;
106 int r = 1;
107 enum { /* all must be != 0, and != any of the short option letters */
108 o_in = 1, o_out, o_iscale, o_fscale, o_ssil, o_esil,
109 o_indflt, o_inwav, o_incdr, o_inraw,
110 o_todflt, o_toraw, o_tocdr, o_towav,
111 o_swapwords0, o_swapwords1, o_silthresh, o_sildelay, o_fadein, o_fadeout
112 };
113 const string shortoptions[] = "hIiOour:Vw:";
114 const struct option longoptions[] = {
115 {"h", no_argument, (int *) &cmdarg.usage, 'u'},
116 {"u", no_argument, (int *) &cmdarg.usage, 'u'},
117 {"usage", no_argument, (int *) &cmdarg.usage, 'u'},
118 {"help", no_argument, (int *) &cmdarg.help, 'H'},
119 {"tocdr", no_argument, NULL, o_tocdr},
120 {"towav", no_argument, NULL, o_towav},
121 {"toraw", no_argument, NULL, o_toraw},
122 {"inraw", no_argument, NULL, o_inraw},
123 {"inwav", no_argument, NULL, o_inwav},
124 {"incdr", no_argument, NULL, o_incdr},
125 #if 0
126 {"ifmt", required_argument, NULL, o_iformat},
127 {"ofmt", required_argument, NULL, o_oformat},
128 #endif
129 {"monostereo", no_argument, (int *) &cmdarg.monostereo, TRUE},
130 {"inbig", no_argument, NULL, 'I'},
131 {"I", no_argument, NULL, 'I'},
132 {"inlittle", no_argument, NULL, 'i'},
133 {"i", no_argument, NULL, 'i'},
134 {"outbig", no_argument, NULL, 'O'},
135 {"O", no_argument, NULL, 'O'},
136 {"outlittle", no_argument, NULL, 'o'},
137 {"o", no_argument, NULL, 'o'},
138 {"swapchannels", no_argument, NULL, o_swapwords1},
139 /*{"swch", no_argument, NULL, o_swapwords1},*/
140 {"noswapchannels", no_argument, NULL, o_swapwords0},
141 /*{"noswch", no_argument, NULL, o_swapwords0},*/
142 {"infile", required_argument, NULL, o_in},
143 /*{"if", required_argument, NULL, o_in},*/
144 {"outfile", required_argument, NULL, o_out},
145 /*{"of", required_argument, NULL, o_out},*/
146 {"iscale", required_argument, NULL, o_iscale},
147 {"fscale", required_argument, NULL, o_fscale},
148 {"cut", no_argument, NULL, 'c'},
149 {"startsilence", required_argument, NULL, o_ssil},
150 {"ss", required_argument, NULL, o_ssil},
151 {"endsilence", required_argument, NULL, o_esil},
152 {"es", required_argument, NULL, o_esil},
153 {"silencecuts", no_argument, (int *) &cmdarg.silencecuts, TRUE},
154 {"silenceinfo", no_argument, (int *) &cmdarg.silenceinfo, TRUE},
155 {"silencethresh", required_argument, NULL, o_silthresh},
156 {"silencedelay", required_argument, NULL, o_sildelay},
157 {"fadein", required_argument, NULL, o_fadein},
158 {"fadeout", required_argument, NULL, o_fadeout},
159 {"quiet", no_argument, (int *) &cmdarg.quiet, TRUE},
160 {"version", no_argument, NULL, 'V'},
161 {"verbose", no_argument, (int *) &cmdarg.verbose, TRUE},
162 {NULL, no_argument, NULL, 0}
163 };
164
165 /* assignments by getopt will assign a size of int into boolean fields
166 of cmdarg */
167 assert (sizeof(BOOL)==sizeof(int));
168
169 #ifdef DEBUG
170 dbgfile = stderr;
171 DBGPRINTF1 ("long options: %i\n",
172 sizeof(longoptions) / sizeof(struct option));
173 #endif
174 optind = 0; /* tell getopt to init */
175 while (r != -1) {
176 r = getopt_long (argc, argv, shortoptions, longoptions, &lidx);
177 DBGPRINTF3 ("getopt() ret: x%02x '%c', optind: %i",
178 r!=-1 ? r : 0xff, ((r>=32) AND (r<127)) ? r : ' ', optind);
179 DBGPRINTF3 (", optopt '%c' x%02x, lidx: %i",
180 optopt, optopt, lidx);
181 DBGPRINTF1 (", optarg: %s\n", optarg != NULL ? optarg : "(NULL)");
182 switch (r) {
183 case 'h':
184 case 'u':
185 cmdarg.usage = TRUE;
186 break;
187 case 'V':
188 cmdarg.version = TRUE;
189 break;
190 case o_swapwords1:
191 cmdarg.swapwords = TRUE;
192 break;
193 case o_swapwords0:
194 cmdarg.swapwords = FALSE;
195 break;
196 case o_inraw:
197 cmdarg.informat = AF_raw;
198 cmdarg.little_input = RAW_FORMAT_DEFAULT_IS_LITTLE;
199 break;
200 case o_inwav:
201 cmdarg.informat = AF_wav;
202 cmdarg.little_input = TRUE;
203 break;
204 case o_incdr:
205 cmdarg.informat = AF_cdr;
206 cmdarg.little_input = FALSE;
207 break;
208 case o_tocdr:
209 cmdarg.outformat = AF_cdr;
210 cmdarg.little_output = FALSE;
211 break;
212 case o_towav:
213 cmdarg.outformat = AF_wav;
214 cmdarg.little_output = TRUE;
215 break;
216 case o_toraw:
217 cmdarg.outformat = AF_raw;
218 cmdarg.little_output = RAW_FORMAT_DEFAULT_IS_LITTLE;
219 break;
220 case 'I':
221 cmdarg.little_input = FALSE;
222 if (cmdarg.informat == AF_wav)
223 exit_error (ERR_CMDARG, "can't read wav in big endian", NULL);
224 break;
225 case 'i':
226 cmdarg.little_input = TRUE;
227 if (cmdarg.informat == AF_cdr)
228 exit_error (ERR_CMDARG, "can't read cdr in little endian", NULL);
229 break;
230 case 'O':
231 cmdarg.little_output = FALSE;
232 if (cmdarg.outformat == AF_wav)
233 exit_error (ERR_CMDARG, "must write wav in little endian", NULL);
234 break;
235 case 'o':
236 cmdarg.little_output = TRUE;
237 if (cmdarg.outformat == AF_cdr)
238 exit_error (ERR_CMDARG, "must write cdr in big endian", NULL);
239 break;
240 case o_in:
241 case 'r':
242 cmdarg.infilename = optarg;
243 break;
244 case o_out:
245 case 'w':
246 cmdarg.outfilename = optarg;
247 break;
248 case o_iscale:
249 r = sscanf (optarg, "%li", &cmdarg.iscale);
250 if (r != 1)
251 exit_error (ERR_CMDARG,
252 "with number (syntax): ", optarg);
253 break;
254 case o_fscale:
255 r = sscanf (optarg, "%f", &cmdarg.fscale);
256 if (r != 1)
257 exit_error (ERR_CMDARG,
258 "with floating point number (syntax): ", optarg);
259 break;
260 case 'c':
261 cmdarg.numcuts = 1; /* set marker that the option was there */
262 break;
263 case o_ssil:
264 cmdarg.startsilence = get_silence_value (optarg);
265 break;
266 case o_esil:
267 cmdarg.endsilence = get_silence_value (optarg);
268 break;
269 case o_silthresh:
270 cmdarg.silence_thresh = get_num_unit (optarg) / CDAUDIOSECTORSIZE;
271 break;
272 case o_sildelay:
273 cmdarg.silence_delay = get_num_unit (optarg) / CDAUDIOSECTORSIZE;
274 break;
275 case o_fadein:
276 cmdarg.fadein = get_num_unit (optarg);
277 break;
278 case o_fadeout:
279 cmdarg.fadeout = get_num_unit (optarg);
280 break;
281 case 0:
282 case -1:
283 break;
284 case '?':
285 /* some error, optopt knows more */
286 /* this test falls over for long options with option->val == 0 */
287 if (optopt == 0x00)
288 exit_error (ERR_CMDARG, "unknown option: ", argv[optind - 1]);
289 if ((strchr (shortoptions, optopt) != NULL)
290 OR NOT isprint (optopt))
291 exit_error (ERR_CMDARG, argv[optind - 1], " requires an argument");
292 else {
293 string s[2];
294 s[0] = isprint (optopt) ? optopt : ' '; s[1] = '\0';
295 exit_error (ERR_CMDARG, "unknown short option: ", s);
296 }
297 default:
298 /* internal error */
299 {
300 string buf[20];
301 sprintf (buf, "%i", r);
302 exit_error (ERR_INTERNAL, "can't handle getopt() return val ", buf);
303 }
304 }
305 }
306 #ifdef DEBUG
307 DBGPRINTF2 ("End scan. optind: %i argc = %i\n", optind, argc);
308 { int i; for (i = 0; i < argc; i++)
309 DBGPRINTF2 (" argv %i %s\n", i, argv[i]);
310 }
311 #endif
312
313 /* use remaining options to fill up filenames or cut numbers
314 (but not both) */
315 while (optind < argc) {
316 #if 0
317 /* (if not starting with '-' or exactly "-") */
318 if ((argv[optind][0] == '-') AND (argv[optind][1] != '\0'))
319 exit_error (ERR_CMDARG, "unknown option ", argv[optind]);
320 #endif
321 if (cmdarg.numcuts) {
322 cmdarg.numcuts = argc - optind;
323 cmdarg.cutstarts = &argv[optind];
324 break; /* remaining args are cut numbers */
325 }
326 if (cmdarg.infilename == NULL)
327 cmdarg.infilename = argv[optind];
328 else {
329 if (cmdarg.outfilename == NULL)
330 cmdarg.outfilename = argv[optind];
331 else
332 exit_error (ERR_CMDARG, "can not handle ", argv[optind]);
333 }
334 optind++;
335 }
336
337 /* treat name "-" the same as stdin/stdout */
338 /* this must be before main() calls check_cmd_args() */
339 if ((cmdarg.infilename != NULL)
340 AND (strcmp (cmdarg.infilename, "-") == 0))
341 cmdarg.infilename = NULL;
342 if ((cmdarg.outfilename != NULL)
343 AND (strcmp (cmdarg.outfilename, "-") == 0))
344 cmdarg.outfilename = NULL;
345
346 /* when finding silence, set output format to raw and byte order to local */
347 /* this should really go into the big switch() above */
348 if (cmdarg.silenceinfo)
349 cmdarg.silencecuts = TRUE;
350 if (cmdarg.silencecuts) {
351 cmdarg.outformat = AF_raw;
352 cmdarg.little_output = is_localhost_little ();
353 }
354
355 } /* scan_cmd_args() */
356
357
358
359 /*
360 Determine how to use stdout and stderr for messages, output, and
361 debugging output
362 */
set_message_output(void)363 void set_message_output (void)
364 {
365 /* determine where messages and debugging output go to */
366 msgfile = stdout;
367 if (cmdarg.outfilename == NULL)
368 msgfile = stderr;
369 #ifdef DEBUG
370 dbgfile = msgfile;
371 #endif
372 if (cmdarg.quiet)
373 msgfile = open_message_file ();
374 } /* set_message_output() */
375
376
377
378 /*
379 Check consistency of command line arguments
380 */
check_cmd_args(void)381 void check_cmd_args (void)
382 {
383 int hs;
384
385 #if 0
386 if (cmdarg.fscale < 0.0)
387 exit_error (ERR_CMDARG, "negative scale factor makes no sense",
388 NULL);
389 if (cmdarg.iscale < 0)
390 exit_error (ERR_CMDARG, "negative scale factor makes no sense",
391 NULL);
392 #endif
393 if ((cmdarg.iscale < SCALE_MIN)
394 OR (cmdarg.iscale > SCALE_MAX)
395 OR ((signed long) cmdarg.fscale < SCALE_MIN)
396 OR ((signed long) cmdarg.fscale > SCALE_MAX))
397 exit_error (ERR_CMDARG, "scale factor out of range", NULL);
398 if (cmdarg.iscale < 0 OR cmdarg.fscale < 0.0)
399 fprintf (msgfile, "Scale factor is negative. "
400 "Will proceed and assume you know what you are doing.\n");
401
402 /* initialise input data size */
403 input_size = get_file_size (cmdarg.infilename, stdin);
404 /* Adjust the input data size to the amount of actual data only,
405 excluding any headers. FIXME: this is dodgy... */
406 hs = get_af_header_size (cmdarg.informat);
407 if (input_size != -1)
408 input_size -= (input_size >= (signed long) hs) ? hs : input_size;
409
410 if (cmdarg.numcuts > 0) {
411 if ((cmdarg.numcuts > 2) AND (cmdarg.outfilename == NULL))
412 exit_error (ERR_CMDARG,
413 "can not cut more than 1 part to stdout", "");
414 if (cmdarg.numcuts == 1)
415 exit_error (ERR_CMDARG, "must have >= 2 cut numbers", "");
416 check_monotonous_cuts ();
417 }
418
419 if (cmdarg.help) {
420 msgfile = stdout;
421 help ();
422 }
423 if (cmdarg.usage) {
424 msgfile = stdout;
425 usage ();
426 }
427 if (cmdarg.version) {
428 msgfile = stdout;
429 version ();
430 }
431
432 if ((cmdarg.iscale != 100) AND (cmdarg.fscale != 1.0)) {
433 fprintf (msgfile,
434 "Both integer and float scale given - float scale ignored.\n");
435 cmdarg.fscale = 1.0;
436 }
437
438 if (((unsigned long) cmdarg.silence_thresh > USHRT_MAX)
439 OR ((unsigned long) cmdarg.silence_delay > USHRT_MAX))
440 exit_error (ERR_CMDARG,
441 "silence threshold and delay must be positive 16 bit", "");
442
443 if (cmdarg.silence_delay == 0)
444 exit_error (ERR_CMDARG,
445 "silence delay must be >= 1", "");
446
447 if (cmdarg.fadeout > 0 AND cmdarg.numcuts == 0 AND input_size == -1)
448 exit_error (ERR_CMDARG,
449 "can't fade out when input size can't be determined", "");
450
451 } /* check_cmd_args() */
452
453
454
455 /*
456 Check whether cut numbers are monotonous.
457 */
check_monotonous_cuts(void)458 static void check_monotonous_cuts (void)
459 {
460 int j;
461 unsigned long this, next;
462 string buf[80];
463
464 for (j = 0, this = get_cut_value (0); j < (cmdarg.numcuts - 1); j++) {
465 next = get_cut_value (j + 1);
466 if (next < this) {
467 sprintf (buf, "cut number (N+1) not >= (N) (%li not >= %li)",
468 next, this);
469 exit_error (ERR_CMDARG, buf, NULL);
470 }
471 this = next;
472 }
473 } /* check_monotonous_cuts() */
474
475
476
477 /*
478 Display the current state of internal variables.
479 Writes to the stream msgfile.
480 In: ---
481 Out: ---
482 Return: ---
483 */
showcmdargs(void)484 void showcmdargs (void)
485 {
486 const string
487 yes[] = "yes",
488 no[] = "no",
489 big[] = "big",
490 little[] = "little";
491 const string *AF_nameidx[] = AF_NAMEIDX;
492 cdseccount_t firstcut = 0, lastcut = 0;
493 string insize[80], silence[80];
494 string stasil[TIMESTRSIZE], endsil[TIMESTRSIZE];
495 string filength[TIMESTRSIZE], folength[TIMESTRSIZE];
496 string stime[TIMESTRSIZE], sfirstcut[TIMESTRSIZE], slastcut[TIMESTRSIZE];
497
498 timeprintf (stasil, cmdarg.startsilence);
499 timeprintf (endsil, cmdarg.endsilence);
500 timeprintf (filength, cmdarg.fadein);
501 timeprintf (folength, cmdarg.fadeout);
502
503 if (input_size == -1)
504 strcpy (insize, "not sizeable/seekable (reading pipe?)");
505 else {
506 timeprintf (stime, (unsigned long) input_size);
507 sprintf (insize, "%li b = %li C = %li s = %s min",
508 (long) input_size,
509 (long) input_size / CDAUDIOSECTORSIZE,
510 /*(float) input_size / CDAUDIOSECTORSIZE / CDSECTORSPERSEC*/
511 input_size / CDAUDIOSECTORSIZE / CDSECTORSPERSEC,
512 stime
513 );
514 }
515
516 if (cmdarg.numcuts > 0) {
517 firstcut = get_cut_value (0);
518 lastcut = get_cut_value (cmdarg.numcuts - 1);
519 }
520 timeprintf (sfirstcut, firstcut * CDAUDIOSECTORSIZE);
521 timeprintf (slastcut, lastcut * CDAUDIOSECTORSIZE);
522 if (cmdarg.silencecuts)
523 sprintf (silence, "%s (threshold %li, delay %li C = %.2f s)",
524 yes, cmdarg.silence_thresh, cmdarg.silence_delay,
525 (float) cmdarg.silence_delay / CDSECTORSPERSEC);
526 else
527 strcpy (silence, no);
528
529 fprintf (msgfile,
530 "Host is: %s\n"
531 "Byte order in, out: %s -> %s\n"
532 "Format in, out: %s -> %s\n"
533 "Scale: %li%%, * %f\n"
534 "Swap channels: %s\n"
535 "Do ->mono->stereo: %s\n"
536 "Find silences: %s %s\n"
537 "Add silence: %li C = %s min, %li C = %s min\n"
538 "Fade-in / -out: %li C = %s min, %li C = %s min\n"
539 "Input data size: %s\n"
540 "Number of cuts: %i\n"
541 "Skipping before: %s min = %li C (excl) (first cut)\n"
542 "Skipping after: %s min = %li C (incl) (last cut)\n"
543 "Input filename: %s\n"
544 "Output filename: %s%s\n"
545 "-\n",
546 is_localhost_little () ? little : big,
547 cmdarg.little_input ? little : big,
548 cmdarg.little_output ? little : big,
549 AF_nameidx[cmdarg.informat],
550 AF_nameidx[cmdarg.outformat],
551 cmdarg.iscale,
552 cmdarg.fscale,
553 cmdarg.swapwords ? yes : no,
554 cmdarg.monostereo ? yes : no,
555 silence, cmdarg.silenceinfo ? "[INFO]" : "",
556 cmdarg.startsilence / CDAUDIOSECTORSIZE, stasil,
557 cmdarg.endsilence / CDAUDIOSECTORSIZE, endsil,
558 cmdarg.fadein / CDAUDIOSECTORSIZE, filength,
559 cmdarg.fadeout / CDAUDIOSECTORSIZE, folength,
560 insize,
561 cmdarg.numcuts,
562 sfirstcut, firstcut,
563 slastcut, lastcut,
564 STRSTDIN(cmdarg.infilename),
565 STRSTDOUT(cmdarg.outfilename),
566 cmdarg.outfilename != NULL ? ".%02d" : ""
567 );
568
569 } /* showcmdargs() */
570
571
572
573 /*
574 Generic: get size number, in bytes
575 Converts a number (integer) with an optional unit,
576 units: type:
577 b int (bytes),
578 c or C int (audio CD sectors, default),
579 s float (seconds of CD audio)
580 In: string representation of the number
581 Out: ---
582 Return: number IN BYTES, always a multiple of CDAUDIOSECTORSIZE
583 */
get_num_unit(const string * s)584 static signed long get_num_unit (const string *s)
585 {
586 signed long int i;
587 float sec;
588 char unit[] = "\0";
589 int r;
590
591 r = sscanf (s, "%li%1s", &i, unit);
592 if (r == 1)
593 unit[0] = 'C'; /* default unit */
594 if (r < 1 OR (r == 2 AND strchr ("bscC.", unit[0]) == NULL))
595 exit_error (ERR_CMDARG, "number/unit syntax: ", s);
596 if (r == 2 AND unit[0] == '.') {
597 unit[0] = '\0';
598 r = sscanf (s, "%f%1s", &sec, unit);
599 if (r == 2 AND strchr ("bcC", unit[0]) != NULL)
600 exit_error (ERR_CMDARG,
601 "number/unit syntax (fractions not with b, c): ", s);
602 if (r < 1 OR unit[0] != 's')
603 exit_error (ERR_CMDARG, "number/unit syntax: ", s);
604 unit[0] = 'S';
605 }
606 DBGPRINTF3 ("<< get val: %li %2.2f %c", i, sec, unit[0]);
607
608 switch (unit[0]) {
609 case 'c':
610 case 'C': /* audio CD sectors */
611 i *= CDAUDIOSECTORSIZE;
612 break;
613 case 'b': /* bytes */
614 i = ((i + (CDAUDIOSECTORSIZE / 2)) / CDAUDIOSECTORSIZE)
615 * CDAUDIOSECTORSIZE;
616 break;
617 case 's': /* seconds of CD audio */
618 i *= (signed long) CDSECTORSPERSEC * (signed long) CDAUDIOSECTORSIZE;
619 break;
620 case 'S':
621 i = ((signed long) (sec * (float) CDSECTORSPERSEC + 0.5))
622 * (signed long) CDAUDIOSECTORSIZE;
623 break;
624 default:
625 exit_error (ERR_INTERNAL, "switch", NULL);
626 }
627 DBGPRINTF1 (" new val: %li >>\n", i);
628
629 return i;
630
631 } /* get_num_unit */
632
633
634
635 /*
636 Get a positive 16 bit value. Uses get_num_unit().
637 In: string representation of the number
638 Out: ---
639 Return: number
640 */
641 #ifdef GET_UINT16
get_uint16_bytes(const char * s)642 static UINT16 get_uint16_bytes (const char *s)
643 {
644 signed long l;
645
646 l = get_num_unit (s);
647 if (l < 0 OR l > USHRT_MAX)
648 exit_error (ERR_CMDARG, "number must be positive 16 bit: ", s);
649 return (UINT16) l;
650
651 } /* get_uint16_bytes() */
652 #endif
653
654
655
656 /*
657 Get a positive 16 bit value, in CDAUDIOSECTORSIZE size units.
658 Uses get_num_unit().
659 In: string representation of the number
660 Out: ---
661 Return: number
662 */
663 #ifdef GET_UINT16
get_uint16_blocks(const char * s)664 static UINT16 get_uint16_blocks (const char *s)
665 {
666 signed long l;
667
668 l = get_num_unit (s) / CDAUDIOSECTORSIZE;
669 if (l < 0 OR l > USHRT_MAX)
670 exit_error (ERR_CMDARG, "number must be positive 16 bit: ", s);
671 return (UINT16) l;
672
673 } /* get_uint16_blocks() */
674 #endif
675
676
677
678 /*
679 In: ---
680 Out: ---
681 Return: Input size in full CD blocks, or -1 if not available
682 */
get_input_size_in_cd_blocks(void)683 signed long get_input_size_in_cd_blocks (void)
684 {
685 signed long size;
686
687 if (input_size == -1)
688 return -1;
689
690 /* this is file format dependent!!, but input_size allows for that */
691 size = (input_size / CDAUDIOSECTORSIZE);
692 if ((size * CDAUDIOSECTORSIZE) < input_size)
693 size++; /* measure from the true end of the cdr file */
694 return size;
695
696 } /* get_input_size_in_cd_blocks() */
697
698
699
700 /*
701 Calculates the cut position from the file size for negative cut numbers.
702 Expects the input data size to be initialised.
703 */
get_neg_cut(signed long cut)704 static signed long get_neg_cut (signed long cut)
705 {
706 signed long pos, size;
707
708 if (input_size == -1)
709 exit_error (ERR_CMDARG,
710 "cut numbers must not be negative when input can't be sized",
711 NULL);
712
713 size = get_input_size_in_cd_blocks ();
714 pos = size - (-cut);
715 if (pos < 0) {
716 string buf[100];
717 sprintf (buf,
718 "cut %li C before start of input with length %li b = %li C",
719 (long) cut, (long) input_size, (long) size);
720 exit_error (ERR_CMDARG, buf, NULL);
721 }
722 return pos;
723 } /* get_neg_cut() */
724
725
726
727 /*
728 Get the Nth cut value.
729 The value returned is positive and in audio CD sectors!
730 Expects the input data size to be initialised.
731 */
get_cut_value(int n)732 unsigned long get_cut_value (int n)
733 {
734 signed long cut, l = 0;
735
736 cut = get_num_unit (cmdarg.cutstarts[n]) / CDAUDIOSECTORSIZE;
737 l = cut;
738 if ((cut == 0L) AND (n == (cmdarg.numcuts - 1))) {
739 /* a 0 as last cut number means all the rest;
740 if input size is not available it's better to use the theoretical
741 maximum file size than to fail */
742 if (input_size != -1)
743 l = get_neg_cut (cut);
744 else
745 l = ULONG_MAX / CDAUDIOSECTORSIZE;
746 } else if (cut < 0) {
747 /* negative cut number - calculate from file size */
748 if (input_size == -1)
749 exit_error (ERR_CMDARG,
750 "cut numbers must not be negative when input can't be sized",
751 NULL);
752 else
753 l = get_neg_cut (cut);
754 }
755
756 DBGPRINTF2 ("get_cut_value(%i): %li\n", n, (long) l);
757 return (unsigned long) l;
758
759 } /* get_cut_value() */
760
761
762
763 /*
764 Get a silence value.
765 The value returned is in bytes.
766 */
get_silence_value(const string * s)767 unsigned long get_silence_value (const string *s)
768 {
769 signed long l;
770
771 l = get_num_unit (s);
772 if (l < 0L)
773 exit_error (ERR_CMDARG,
774 "negative silence number does not make sense", NULL);
775 return (unsigned long) l;
776
777 } /* get_silence_value() */
778
779
780
781 /*
782 Return the command arg info
783 In: buffer
784 Out: initialised command arg info struct
785 Return: ---
786 */
get_cmdarg_info(cmdarg_t * pcmdarg)787 void get_cmdarg_info (cmdarg_t *pcmdarg)
788 {
789 *pcmdarg = cmdarg;
790 }
791
792
793
794 /*
795 Init a processing info struct, from cmdargs and otherwise
796 In: buffer
797 Out: initialised process info struct
798 Return: ---
799 */
init_process_info(process_t * pinfo)800 void init_process_info (process_t *pinfo)
801 {
802 pinfo->n_in = pinfo->n_returned = 0;
803
804 pinfo->first = TRUE;
805 pinfo->last = FALSE;
806
807 pinfo->little_host = is_localhost_little ();
808 pinfo->from_little = cmdarg.little_input;
809 pinfo->to_little = cmdarg.little_output;
810 pinfo->iscale = cmdarg.iscale;
811 pinfo->fscale = cmdarg.fscale;
812 pinfo->swap_channels = cmdarg.swapwords;
813 pinfo->monostereo = cmdarg.monostereo ? MS_TOMONOSTEREO : MS_NONE;
814 pinfo->silencecuts = cmdarg.silencecuts;
815 pinfo->silence_thresh = cmdarg.silence_thresh;
816 pinfo->silence_delay = cmdarg.silence_delay;
817 pinfo->silence_val = cmdarg.verbose;
818 pinfo->fadein = 0;
819 pinfo->fadeout = 0;
820
821 } /* init_process_info() */
822
823
824
825 /* EOF cmdarg.c */
826 /******************************************************************************/
827