#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/param.h>
#include <convert.h>
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
const char *opt_string = "pf:o:i:FTD?";
char *Stdin;
char *Stdout;
char *Suffix = (char *)".AUDCVTMP";
char *progname;
char *fake_argv[] = {(char *)"-", NULL};
extern char *optarg;
extern int optind;
int Statistics = 0;
int Debug = 0;
void init_header(AudioHdr&);
void usage();
int
main(int argc, char *argv[])
{
AudioUnixfile* ifp = NULL;
AudioUnixfile* ofp = NULL;
AudioHdr ihdr;
AudioHdr ohdr;
char *infile = NULL;
char *outfile = NULL;
char *realfile = NULL;
char *out_fmt = NULL;
AudioError err;
int c;
int pflag = 0;
int fflag = 0;
int stdin_seen = 0;
int israw = 0;
format_type ofmt = F_SUN;
format_type ifmt = F_SUN;
format_type fmt = F_SUN;
off_t o_offset = 0;
off_t i_offset = 0;
int i;
struct stat st;
setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
if (progname = strrchr(argv[0], '/')) {
progname++;
} else {
progname = argv[0];
}
Stdin = MGET("(stdin)");
Stdout = MGET("(stdout)");
init_header(ihdr);
init_header(ohdr);
if (strcmp(progname, "ulaw2pcm") == 0) {
(void) parse_format((char *)"ulaw", ihdr, ifmt, i_offset);
(void) parse_format((char *)"pcm", ohdr, ofmt, o_offset);
} else if (strcmp(progname, "pcm2ulaw") == 0) {
(void) parse_format((char *)"pcm", ihdr, ifmt, i_offset);
(void) parse_format((char *)"ulaw", ohdr, ofmt, o_offset);
} else if (strcmp(progname, "adpcm_enc") == 0) {
(void) parse_format((char *)"ulaw", ihdr, ifmt, i_offset);
(void) parse_format((char *)"g721", ohdr, ofmt, o_offset);
} else if (strcmp(progname, "adpcm_dec") == 0) {
(void) parse_format((char *)"g721", ihdr, ifmt, i_offset);
(void) parse_format((char *)"ulaw", ohdr, ofmt, o_offset);
} else if (strcmp(progname, "raw2audio") == 0) {
(void) parse_format((char *)"ulaw", ihdr, ifmt, i_offset);
(void) parse_format((char *)"ulaw", ohdr, ofmt, o_offset);
israw++;
pflag++;
} else if (argc <= 1) {
usage();
}
while ((c = getopt(argc, argv, opt_string)) != -1) {
switch (c) {
#ifdef DEBUG
case 'D':
Debug++;
break;
#endif
case 'p':
if (outfile != NULL) {
Err(MGET("can't use -p with -o\n"));
exit(1);
}
pflag++;
break;
case 'F':
fflag++;
break;
case 'f':
out_fmt = optarg;
if (parse_format(out_fmt, ohdr, ofmt, o_offset) == -1)
exit(1);
if (o_offset != 0) {
Err(MGET("can't specify an offset with -f\n"));
exit(1);
}
break;
case 'o':
if (pflag) {
Err(MGET("can't use -o with -p\n"));
exit(1);
}
outfile = optarg;
break;
case 'i':
if (parse_format(optarg, ihdr, ifmt, i_offset) == -1) {
exit(1);
}
israw++;
break;
default:
case '?':
usage();
}
}
if (optind >= argc) {
argv = fake_argv;
argc = 1;
optind = 0;
pflag = 0;
}
for (; optind < argc; optind++) {
if (strcmp(argv[optind], "-i") == 0) {
init_header(ihdr);
i_offset = 0;
ifmt = F_SUN;
if (parse_format(argv[++optind], ihdr, ifmt, i_offset)
== -1) {
exit(1);
}
israw++;
} else if (strcmp(argv[optind], "-") == 0) {
if (pflag) {
Err(MGET("can't use %s with -p flag\n"),
Stdin);
continue;
}
if (stdin_seen) {
Err(MGET("already used stdin for input\n"));
continue;
} else {
stdin_seen++;
}
infile = Stdin;
} else {
infile = argv[optind];
}
ifp =
open_input_file(infile, ihdr, israw, fflag, i_offset, fmt);
if (!ifp) {
continue;
}
if ((err = ifp->Open()) != AUDIO_SUCCESS) {
Err(MGET("open error on input file %s - %s\n"),
infile, err.msg());
exit(1);
}
ifp->Reference();
if ((ofp == NULL) && !pflag) {
ohdr = ifp->GetHeader();
ohdr = ifp->GetHeader();
ofmt = ifmt;
if (out_fmt) {
if (parse_format(out_fmt, ohdr, ofmt, o_offset)
== -1) {
exit(1);
}
}
if (verify_conversion(ifp->GetHeader(), ohdr) == -1) {
exit(3);
}
char *infoString;
int infoStringLen;
infoString = ifp->GetInfostring(infoStringLen);
ofp = create_output_file(outfile, ohdr, ofmt,
infoString);
} else if (pflag) {
ohdr = ifp->GetHeader();
ofmt = ifmt;
if (out_fmt) {
if (parse_format(out_fmt, ohdr, ofmt, o_offset)
== -1) {
exit(1);
}
}
realfile = infile;
get_realfile(realfile, &st);
if (access(realfile, W_OK)) {
perror(infile);
Err(MGET("cannot rewrite in place\n"));
exit(1);
}
i = strlen(realfile) + strlen(Suffix) + 1;
outfile = (char *)malloc((unsigned)i);
if (outfile == NULL) {
Err(MGET("out of memory\n"));
exit(1);
}
(void) sprintf(outfile, "%s%s", realfile, Suffix);
if (verify_conversion(ifp->GetHeader(), ohdr) == -1) {
exit(3);
}
if (noop_conversion(ifp->GetHeader(), ohdr,
fmt, ofmt, i_offset, o_offset)) {
if (Debug)
Err(MGET(
"%s: no-op conversion...skipping\n"),
infile);
continue;
}
char *infoString;
int infoStringLen;
infoString = ifp->GetInfostring(infoStringLen);
ofp = create_output_file(outfile, ohdr, ofmt,
infoString);
}
if (!pflag && (verify_conversion(ifp->GetHeader(), ohdr)
== -1)) {
exit(3);
}
if (do_convert(ifp, ofp) == -1) {
exit(4);
}
ifp->Close();
ifp->Dereference();
if (pflag) {
delete(ofp);
if (rename(outfile, realfile) < 0) {
perror(outfile);
Err(MGET("error renaming %s to %s"),
outfile, realfile);
exit(1);
}
if (chmod(realfile, (int)st.st_mode) < 0) {
Err(MGET("WARNING: could not reset mode of"));
perror(realfile);
}
}
}
if (!pflag) {
delete(ofp);
}
return (0);
}
void
init_header(
AudioHdr& hdr)
{
hdr.encoding = NONE;
hdr.sample_rate = 0;
hdr.samples_per_unit = 0;
hdr.bytes_per_unit = 0;
hdr.channels = 0;
}
extern "C" { void _doprnt(char *, ...); }
void
Err(char *format, ...)
{
va_list ap;
va_start(ap, format);
fprintf(stderr, "%s: ", progname);
_doprnt(format, ap, stderr);
fflush(stderr);
va_end(ap);
}
void
usage()
{
fprintf(stderr, MGET(
"Convert between audio file formats and data encodings -- usage:\n"
"\t%s [-pF] [-f outfmt] [-o outfile] [[-i infmt] [file ...]] ...\n"
"where:\n"
"\t-p\tConvert files in place\n"
"\t-F\tForce interpretation of -i (ignore existing file hdr)\n"
"\t-f\tOutput format description\n"
"\t-o\tOutput file (default: stdout)\n"
"\t-i\tInput format description\n"
"\tfile\tList of files to convert (default: stdin)\n\n"
"Format Description:\n"
"\tkeyword=value[,keyword=value...]\n"
"where:\n"
"\tKeywords:\tValues:\n"
"\trate\t\tSample Rate in samples/second\n"
"\tchannels\tNumber of interleaved channels\n"
"\tencoding\tAudio encoding. One of:\n"
"\t\t\t ulaw, alaw, g721, g723,\n"
"\t\t\t linear8, linear16, linear32\n"
"\t\t\t pcm (same as linear16)\n"
"\t\t\t voice (ulaw,mono,rate=8k)\n"
"\t\t\t cd (linear16,stereo,rate=44.1k)\n"
"\t\t\t dat (linear16,stereo,rate=48k)\n"
"\tformat\t\tFile format. One of:\n"
"\t\t\t sun, raw (no format)\n"
"\toffset\t\tByte offset (raw input only)\n"),
progname);
exit(1);
}