4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1993-2001 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
34 #include <sys/types.h>
37 #include <sys/param.h>
41 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
42 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
45 const char *opt_string
= "pf:o:i:FTD?";
49 char *Suffix
= (char *)".AUDCVTMP";
51 char *progname
; // program name
52 char *fake_argv
[] = {(char *)"-", NULL
}; // stdin with no args
60 void init_header(AudioHdr
&);
67 AudioUnixfile
* ifp
= NULL
; // input & output audio objects
68 AudioUnixfile
* ofp
= NULL
;
69 AudioHdr ihdr
; // input/output headers
71 char *infile
= NULL
; // input/output file names
73 char *realfile
= NULL
;
74 char *out_fmt
= NULL
; // output fmt string
75 AudioError err
; // for error msgs
77 int pflag
= 0; // in place flag
78 int fflag
= 0; // ignore header (force conversion)
79 int stdin_seen
= 0; // already read stdin
80 int israw
= 0; // once we've seen -i, it's raw data
81 format_type ofmt
= F_SUN
; // output format type
82 format_type ifmt
= F_SUN
; // expected input format type
83 format_type fmt
= F_SUN
; // actual input format type
84 off_t o_offset
= 0; // output offset (ignored)
85 off_t i_offset
= 0; // input offset
89 setlocale(LC_ALL
, "");
90 (void) textdomain(TEXT_DOMAIN
);
92 // basename of program
93 if (progname
= strrchr(argv
[0], '/')) {
98 Stdin
= MGET("(stdin)");
99 Stdout
= MGET("(stdout)");
101 // init the input & output headers
105 // some conversions depend on invocation name. we'll create
106 // default input/output formats based on argv[0] that
107 // can be overridden by -o or -i options.
108 if (strcmp(progname
, "ulaw2pcm") == 0) {
109 (void) parse_format((char *)"ulaw", ihdr
, ifmt
, i_offset
);
110 (void) parse_format((char *)"pcm", ohdr
, ofmt
, o_offset
);
111 } else if (strcmp(progname
, "pcm2ulaw") == 0) {
112 (void) parse_format((char *)"pcm", ihdr
, ifmt
, i_offset
);
113 (void) parse_format((char *)"ulaw", ohdr
, ofmt
, o_offset
);
114 } else if (strcmp(progname
, "adpcm_enc") == 0) {
115 (void) parse_format((char *)"ulaw", ihdr
, ifmt
, i_offset
);
116 (void) parse_format((char *)"g721", ohdr
, ofmt
, o_offset
);
117 } else if (strcmp(progname
, "adpcm_dec") == 0) {
118 (void) parse_format((char *)"g721", ihdr
, ifmt
, i_offset
);
119 (void) parse_format((char *)"ulaw", ohdr
, ofmt
, o_offset
);
120 } else if (strcmp(progname
, "raw2audio") == 0) {
121 (void) parse_format((char *)"ulaw", ihdr
, ifmt
, i_offset
);
122 (void) parse_format((char *)"ulaw", ohdr
, ofmt
, o_offset
);
125 } else if (argc
<= 1) {
126 // audioconvert with no arguments
130 // now parse the rest of the arg's
131 while ((c
= getopt(argc
, argv
, opt_string
)) != -1) {
135 // enable debug messages
140 // convert files in place
141 if (outfile
!= NULL
) {
142 Err(MGET("can't use -p with -o\n"));
148 // force treatment of audio files as raw files
153 // save format string to parse later, but verify now
155 if (parse_format(out_fmt
, ohdr
, ofmt
, o_offset
) == -1)
158 Err(MGET("can't specify an offset with -f\n"));
164 Err(MGET("can't use -o with -p\n"));
170 // if bogus input header, exit ...
171 if (parse_format(optarg
, ihdr
, ifmt
, i_offset
) == -1) {
182 // XXX - should check argument consistency here....
184 // If no args left, we're taking input from stdin.
185 // In this case, make argv point to a fake argv with "-" as a file
186 // name, and set optind and argc apropriately so we'll go through
187 // the loop below once.
188 if (optind
>= argc
) {
193 * XXX - we turn off pflag if stdin is the only input file.
194 * this is kind of a hack. if invoked as raw2audio, pflag
195 * it turned on. if no files are given, we want to turn
196 * it off, otherwise we'll complain about using -p with
197 * stdin, which won't make sense if invoked as raw2audio.
198 * instead, just silently ignore. the message is still given
199 * and stdin is ignored if it's specified as one of several
205 // From this point on we're looking at file names or -i args
206 // for input format specs.
207 for (; optind
< argc
; optind
++) {
208 // new input format spec.
209 if (strcmp(argv
[optind
], "-i") == 0) {
213 // if bogus input header, exit ...
214 if (parse_format(argv
[++optind
], ihdr
, ifmt
, i_offset
)
219 } else if (strcmp(argv
[optind
], "-") == 0) {
220 // ignore stdin argument if in place
222 Err(MGET("can't use %s with -p flag\n"),
228 Err(MGET("already used stdin for input\n"));
236 infile
= argv
[optind
];
239 // if no audio object returned, just continue to the next
240 // file. if a fatal error occurs, open_input_file()
241 // will exit the program.
243 open_input_file(infile
, ihdr
, israw
, fflag
, i_offset
, fmt
);
248 if ((err
= ifp
->Open()) != AUDIO_SUCCESS
) {
249 Err(MGET("open error on input file %s - %s\n"),
255 // create the output file if not created yet, or if
256 // converting in place. ofp will be NULL only the first
257 // time through. use the header of the first input file
258 // to base the output format on - then create the output
259 // header w/the output format spec.
260 if ((ofp
== NULL
) && !pflag
) {
262 ohdr
= ifp
->GetHeader();
263 ohdr
= ifp
->GetHeader();
265 // just use input hdr if no output hdr spec
267 if (parse_format(out_fmt
, ohdr
, ofmt
, o_offset
)
273 // need to check before output is opened ...
274 if (verify_conversion(ifp
->GetHeader(), ohdr
) == -1) {
275 // XXX - bomb out or skip?
279 // Create the file and set the info string.
282 infoString
= ifp
->GetInfostring(infoStringLen
);
283 ofp
= create_output_file(outfile
, ohdr
, ofmt
,
288 // create new output header based on each input file
289 ohdr
= ifp
->GetHeader();
291 // just use input hdr if no output hdr spec
293 if (parse_format(out_fmt
, ohdr
, ofmt
, o_offset
)
299 // get the *real* path of the infile (follow sym-links),
300 // and the stat info.
302 get_realfile(realfile
, &st
);
304 // if the file is read-only, give up
305 if (access(realfile
, W_OK
)) {
306 // XXX - do we really want to exit?
308 Err(MGET("cannot rewrite in place\n"));
312 // this is now the output file.
313 i
= strlen(realfile
) + strlen(Suffix
) + 1;
314 outfile
= (char *)malloc((unsigned)i
);
315 if (outfile
== NULL
) {
316 Err(MGET("out of memory\n"));
319 (void) sprintf(outfile
, "%s%s", realfile
, Suffix
);
321 // outfile will get re-assigned to a tmp file
322 if (verify_conversion(ifp
->GetHeader(), ohdr
) == -1) {
323 // XXX - bomb out or skip?
327 // If no conversion, just skip the file
328 if (noop_conversion(ifp
->GetHeader(), ohdr
,
329 fmt
, ofmt
, i_offset
, o_offset
)) {
332 "%s: no-op conversion...skipping\n"),
337 // Get the input info string.
340 infoString
= ifp
->GetInfostring(infoStringLen
);
341 ofp
= create_output_file(outfile
, ohdr
, ofmt
,
345 // verify that it's a valid conversion by looking at the
346 // file headers. (this will be called twice for the first
347 // file if *not* converting in place. that's ok....
348 if (!pflag
&& (verify_conversion(ifp
->GetHeader(), ohdr
)
350 // XXX - bomb out or skip file if invalid conversion?
354 // do the conversion, if error, bomb out
355 if (do_convert(ifp
, ofp
) == -1) {
362 // if in place, finish up by renaming the outfile to
363 // back to the infile.
365 delete(ofp
); // will close and deref, etc.
367 if (rename(outfile
, realfile
) < 0) {
369 Err(MGET("error renaming %s to %s"),
373 /* Set the permissions to match the original */
374 if (chmod(realfile
, (int)st
.st_mode
) < 0) {
375 Err(MGET("WARNING: could not reset mode of"));
382 delete(ofp
); // close output file
385 exit(0); // outta here!
389 // initialize audio hdr to default val's
396 hdr
.samples_per_unit
= 0;
397 hdr
.bytes_per_unit
= 0;
401 extern "C" { void _doprnt(char *, ...); }
403 // report a fatal error and exit
405 Err(char *format
, ...)
409 va_start(ap
, format
);
410 fprintf(stderr
, "%s: ", progname
);
411 _doprnt(format
, ap
, stderr
);
419 fprintf(stderr
, MGET(
420 "Convert between audio file formats and data encodings -- usage:\n"
421 "\t%s [-pF] [-f outfmt] [-o outfile] [[-i infmt] [file ...]] ...\n"
423 "\t-p\tConvert files in place\n"
424 "\t-F\tForce interpretation of -i (ignore existing file hdr)\n"
425 "\t-f\tOutput format description\n"
426 "\t-o\tOutput file (default: stdout)\n"
427 "\t-i\tInput format description\n"
428 "\tfile\tList of files to convert (default: stdin)\n\n"
429 "Format Description:\n"
430 "\tkeyword=value[,keyword=value...]\n"
432 "\tKeywords:\tValues:\n"
433 "\trate\t\tSample Rate in samples/second\n"
434 "\tchannels\tNumber of interleaved channels\n"
435 "\tencoding\tAudio encoding. One of:\n"
436 "\t\t\t ulaw, alaw, g721, g723,\n"
437 "\t\t\t linear8, linear16, linear32\n"
438 "\t\t\t pcm (same as linear16)\n"
439 "\t\t\t voice (ulaw,mono,rate=8k)\n"
440 "\t\t\t cd (linear16,stereo,rate=44.1k)\n"
441 "\t\t\t dat (linear16,stereo,rate=48k)\n"
442 "\tformat\t\tFile format. One of:\n"
443 "\t\t\t sun, raw (no format)\n"
444 "\toffset\t\tByte offset (raw input only)\n"),