1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright 1993-2003 Sun Microsystems, Inc. All rights reserved.
24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate */
26*7c478bd9Sstevel@tonic-gate
27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*7c478bd9Sstevel@tonic-gate
29*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
30*7c478bd9Sstevel@tonic-gate #include <stdio.h>
31*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
32*7c478bd9Sstevel@tonic-gate #include <string.h>
33*7c478bd9Sstevel@tonic-gate #include <unistd.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
38*7c478bd9Sstevel@tonic-gate
39*7c478bd9Sstevel@tonic-gate #include <Audio.h>
40*7c478bd9Sstevel@tonic-gate #include <AudioFile.h>
41*7c478bd9Sstevel@tonic-gate #include <AudioPipe.h>
42*7c478bd9Sstevel@tonic-gate #include <AudioRawPipe.h>
43*7c478bd9Sstevel@tonic-gate #include <AudioLib.h>
44*7c478bd9Sstevel@tonic-gate #include <AudioHdr.h>
45*7c478bd9Sstevel@tonic-gate
46*7c478bd9Sstevel@tonic-gate #include <libaudio.h>
47*7c478bd9Sstevel@tonic-gate #include <audio/au.h>
48*7c478bd9Sstevel@tonic-gate
49*7c478bd9Sstevel@tonic-gate extern char *Stdin;
50*7c478bd9Sstevel@tonic-gate extern char *Stdout;
51*7c478bd9Sstevel@tonic-gate
52*7c478bd9Sstevel@tonic-gate #include <convert.h>
53*7c478bd9Sstevel@tonic-gate
54*7c478bd9Sstevel@tonic-gate // append contents of buffer to output audio stream.
55*7c478bd9Sstevel@tonic-gate
56*7c478bd9Sstevel@tonic-gate AudioError
write_output(AudioBuffer * buf,AudioStream * ofp)57*7c478bd9Sstevel@tonic-gate write_output(AudioBuffer* buf, AudioStream* ofp)
58*7c478bd9Sstevel@tonic-gate {
59*7c478bd9Sstevel@tonic-gate unsigned char *cp;
60*7c478bd9Sstevel@tonic-gate size_t len;
61*7c478bd9Sstevel@tonic-gate Double pos;
62*7c478bd9Sstevel@tonic-gate AudioError err;
63*7c478bd9Sstevel@tonic-gate
64*7c478bd9Sstevel@tonic-gate pos = ofp->GetLength();
65*7c478bd9Sstevel@tonic-gate len = (size_t)buf->GetHeader().Time_to_Bytes(buf->GetLength());
66*7c478bd9Sstevel@tonic-gate cp = (unsigned char *)buf->GetAddress();
67*7c478bd9Sstevel@tonic-gate err = ofp->WriteData(cp, len, pos);
68*7c478bd9Sstevel@tonic-gate return (err);
69*7c478bd9Sstevel@tonic-gate }
70*7c478bd9Sstevel@tonic-gate
71*7c478bd9Sstevel@tonic-gate // open input file and return ptr to AudioUnixFile object
72*7c478bd9Sstevel@tonic-gate // path is the path to the file (or set to Stdin if standard input).
73*7c478bd9Sstevel@tonic-gate // ihdr is the input header (only used for openning raw files)
74*7c478bd9Sstevel@tonic-gate // israw flags if it's a raw file. if fflag is set, ignore an
75*7c478bd9Sstevel@tonic-gate // any existing header on raw files. offset indicates where to
76*7c478bd9Sstevel@tonic-gate // start reading the file (raw files only ??).
open_input_file(const char * path,const AudioHdr ihdr,int israw,int fflag,off_t offset,format_type & fmt)77*7c478bd9Sstevel@tonic-gate AudioUnixfile *open_input_file(const char *path, const AudioHdr ihdr,
78*7c478bd9Sstevel@tonic-gate int israw, int fflag, off_t offset,
79*7c478bd9Sstevel@tonic-gate format_type& fmt)
80*7c478bd9Sstevel@tonic-gate {
81*7c478bd9Sstevel@tonic-gate AudioUnixfile* ifp;
82*7c478bd9Sstevel@tonic-gate int fd;
83*7c478bd9Sstevel@tonic-gate int file_type; // ignore this ...
84*7c478bd9Sstevel@tonic-gate int infosize; // ignore this ...
85*7c478bd9Sstevel@tonic-gate au_filehdr_t fhdr;
86*7c478bd9Sstevel@tonic-gate Audio_hdr ohdr; // ignore this ...
87*7c478bd9Sstevel@tonic-gate unsigned int hsize;
88*7c478bd9Sstevel@tonic-gate
89*7c478bd9Sstevel@tonic-gate // need to let caller know what format this is. so far, only raw
90*7c478bd9Sstevel@tonic-gate // and sun are supported....
91*7c478bd9Sstevel@tonic-gate fmt = (israw ? F_RAW : F_SUN);
92*7c478bd9Sstevel@tonic-gate
93*7c478bd9Sstevel@tonic-gate // no file
94*7c478bd9Sstevel@tonic-gate if (!path) {
95*7c478bd9Sstevel@tonic-gate // no file? shouldn't happen. bomb out.
96*7c478bd9Sstevel@tonic-gate Err(MGET("no input file specified\n"));
97*7c478bd9Sstevel@tonic-gate exit(1);
98*7c478bd9Sstevel@tonic-gate }
99*7c478bd9Sstevel@tonic-gate
100*7c478bd9Sstevel@tonic-gate // deal with stdin
101*7c478bd9Sstevel@tonic-gate if (path == Stdin) {
102*7c478bd9Sstevel@tonic-gate if (isatty(fileno(stdin))) {
103*7c478bd9Sstevel@tonic-gate Err(MGET(
104*7c478bd9Sstevel@tonic-gate "Stdin is a tty, please specify an input file\n"));
105*7c478bd9Sstevel@tonic-gate exit(1);
106*7c478bd9Sstevel@tonic-gate }
107*7c478bd9Sstevel@tonic-gate if (israw) {
108*7c478bd9Sstevel@tonic-gate // XXX - need to check if stdin has a file
109*7c478bd9Sstevel@tonic-gate // header and ignore it if fflag not set.
110*7c478bd9Sstevel@tonic-gate ifp = new AudioRawPipe(fileno(stdin),
111*7c478bd9Sstevel@tonic-gate (FileAccess)ReadOnly, ihdr, path,
112*7c478bd9Sstevel@tonic-gate offset);
113*7c478bd9Sstevel@tonic-gate } else {
114*7c478bd9Sstevel@tonic-gate ifp = new AudioPipe(fileno(stdin), (FileAccess)ReadOnly,
115*7c478bd9Sstevel@tonic-gate path);
116*7c478bd9Sstevel@tonic-gate }
117*7c478bd9Sstevel@tonic-gate
118*7c478bd9Sstevel@tonic-gate if (!ifp) {
119*7c478bd9Sstevel@tonic-gate Err(MGET("can't open pipe to %s, skipping...\n"),
120*7c478bd9Sstevel@tonic-gate Stdin);
121*7c478bd9Sstevel@tonic-gate }
122*7c478bd9Sstevel@tonic-gate return (ifp);
123*7c478bd9Sstevel@tonic-gate }
124*7c478bd9Sstevel@tonic-gate
125*7c478bd9Sstevel@tonic-gate // fall through for real files ...
126*7c478bd9Sstevel@tonic-gate if (israw) {
127*7c478bd9Sstevel@tonic-gate if ((fd = open(path, O_RDONLY)) < 0) {
128*7c478bd9Sstevel@tonic-gate Err(MGET("can't open %s, skipping...\n"), path);
129*7c478bd9Sstevel@tonic-gate perror(MGET("open"));
130*7c478bd9Sstevel@tonic-gate return (NULL);
131*7c478bd9Sstevel@tonic-gate }
132*7c478bd9Sstevel@tonic-gate if (!fflag) {
133*7c478bd9Sstevel@tonic-gate // check if file already has a hdr.
134*7c478bd9Sstevel@tonic-gate if (hsize = read(fd, (char *)&fhdr, sizeof (fhdr))
135*7c478bd9Sstevel@tonic-gate < 0) {
136*7c478bd9Sstevel@tonic-gate perror("read");
137*7c478bd9Sstevel@tonic-gate exit(1);
138*7c478bd9Sstevel@tonic-gate }
139*7c478bd9Sstevel@tonic-gate if (lseek(fd, 0, 0) < 0) { // reset
140*7c478bd9Sstevel@tonic-gate perror("lseek");
141*7c478bd9Sstevel@tonic-gate exit(1);
142*7c478bd9Sstevel@tonic-gate }
143*7c478bd9Sstevel@tonic-gate if (hsize != sizeof (fhdr)) {
144*7c478bd9Sstevel@tonic-gate // no hdr - file too small,
145*7c478bd9Sstevel@tonic-gate // assume data is ok (tho it
146*7c478bd9Sstevel@tonic-gate // probably won't be) ...
147*7c478bd9Sstevel@tonic-gate ifp = new AudioRawPipe(fd, (FileAccess)ReadOnly,
148*7c478bd9Sstevel@tonic-gate ihdr, path, offset);
149*7c478bd9Sstevel@tonic-gate } else {
150*7c478bd9Sstevel@tonic-gate // Check the validity of the
151*7c478bd9Sstevel@tonic-gate // header and get the size of
152*7c478bd9Sstevel@tonic-gate // the info field
153*7c478bd9Sstevel@tonic-gate if (audio_decode_filehdr(fd,
154*7c478bd9Sstevel@tonic-gate (unsigned char *)&fhdr, &file_type, &ohdr,
155*7c478bd9Sstevel@tonic-gate &infosize) == AUDIO_SUCCESS) {
156*7c478bd9Sstevel@tonic-gate close(fd); // create AudioFile()
157*7c478bd9Sstevel@tonic-gate // issue a warning
158*7c478bd9Sstevel@tonic-gate Err(
159*7c478bd9Sstevel@tonic-gate MGET("%s has a file header, ignoring -i ...\n"),
160*7c478bd9Sstevel@tonic-gate path);
161*7c478bd9Sstevel@tonic-gate fmt = F_SUN; // was raw ...
162*7c478bd9Sstevel@tonic-gate ifp = new AudioFile(path,
163*7c478bd9Sstevel@tonic-gate (FileAccess)ReadOnly);
164*7c478bd9Sstevel@tonic-gate } else {
165*7c478bd9Sstevel@tonic-gate // no hdr, create AudioRawPipe.
166*7c478bd9Sstevel@tonic-gate ifp = new AudioRawPipe(fd,
167*7c478bd9Sstevel@tonic-gate (FileAccess)ReadOnly, ihdr,
168*7c478bd9Sstevel@tonic-gate path, offset);
169*7c478bd9Sstevel@tonic-gate }
170*7c478bd9Sstevel@tonic-gate }
171*7c478bd9Sstevel@tonic-gate
172*7c478bd9Sstevel@tonic-gate } else { // force flag - don't even look for header
173*7c478bd9Sstevel@tonic-gate ifp = new AudioRawPipe(fd, (FileAccess)ReadOnly, ihdr,
174*7c478bd9Sstevel@tonic-gate path, offset);
175*7c478bd9Sstevel@tonic-gate }
176*7c478bd9Sstevel@tonic-gate } else {
177*7c478bd9Sstevel@tonic-gate ifp = new AudioFile(path, (FileAccess)ReadOnly);
178*7c478bd9Sstevel@tonic-gate }
179*7c478bd9Sstevel@tonic-gate
180*7c478bd9Sstevel@tonic-gate if (!ifp) {
181*7c478bd9Sstevel@tonic-gate Err(MGET("can't open %s, skipping...\n"), path);
182*7c478bd9Sstevel@tonic-gate }
183*7c478bd9Sstevel@tonic-gate return (ifp);
184*7c478bd9Sstevel@tonic-gate }
185*7c478bd9Sstevel@tonic-gate
186*7c478bd9Sstevel@tonic-gate // given a path, find the file it really points to (if it's a
187*7c478bd9Sstevel@tonic-gate // sym-link). return it's stat buf and real path.
188*7c478bd9Sstevel@tonic-gate void
get_realfile(char * & path,struct stat * st)189*7c478bd9Sstevel@tonic-gate get_realfile(char *&path, struct stat *st)
190*7c478bd9Sstevel@tonic-gate {
191*7c478bd9Sstevel@tonic-gate static char tmpf[MAXPATHLEN]; // for reading sym-link
192*7c478bd9Sstevel@tonic-gate int err; // for stat err
193*7c478bd9Sstevel@tonic-gate
194*7c478bd9Sstevel@tonic-gate // first see if it's a sym-link and find real file
195*7c478bd9Sstevel@tonic-gate err = 0;
196*7c478bd9Sstevel@tonic-gate while (err == 0) {
197*7c478bd9Sstevel@tonic-gate if (err = lstat(path, st) < 0) {
198*7c478bd9Sstevel@tonic-gate perror("lstat");
199*7c478bd9Sstevel@tonic-gate exit(1);
200*7c478bd9Sstevel@tonic-gate }
201*7c478bd9Sstevel@tonic-gate if (!err && S_ISLNK(st->st_mode)) {
202*7c478bd9Sstevel@tonic-gate err = readlink(path, tmpf,
203*7c478bd9Sstevel@tonic-gate (sizeof (tmpf) - 1));
204*7c478bd9Sstevel@tonic-gate if (err > 0) {
205*7c478bd9Sstevel@tonic-gate tmpf[err] = '\0';
206*7c478bd9Sstevel@tonic-gate path = tmpf;
207*7c478bd9Sstevel@tonic-gate err = 0;
208*7c478bd9Sstevel@tonic-gate }
209*7c478bd9Sstevel@tonic-gate } else {
210*7c478bd9Sstevel@tonic-gate break;
211*7c478bd9Sstevel@tonic-gate }
212*7c478bd9Sstevel@tonic-gate }
213*7c478bd9Sstevel@tonic-gate
214*7c478bd9Sstevel@tonic-gate }
215*7c478bd9Sstevel@tonic-gate
216*7c478bd9Sstevel@tonic-gate // create output audio file. if no path is supplied, use stdout.
217*7c478bd9Sstevel@tonic-gate // returns a ptr to an AudioUnixFile object.
218*7c478bd9Sstevel@tonic-gate
219*7c478bd9Sstevel@tonic-gate AudioUnixfile*
create_output_file(const char * path,const AudioHdr ohdr,format_type ofmt,const char * infoString)220*7c478bd9Sstevel@tonic-gate create_output_file(
221*7c478bd9Sstevel@tonic-gate const char *path,
222*7c478bd9Sstevel@tonic-gate const AudioHdr ohdr,
223*7c478bd9Sstevel@tonic-gate format_type ofmt,
224*7c478bd9Sstevel@tonic-gate const char *infoString)
225*7c478bd9Sstevel@tonic-gate {
226*7c478bd9Sstevel@tonic-gate AudioUnixfile* ofp = 0;
227*7c478bd9Sstevel@tonic-gate AudioError err; // for error msgs
228*7c478bd9Sstevel@tonic-gate int fd;
229*7c478bd9Sstevel@tonic-gate
230*7c478bd9Sstevel@tonic-gate if (!path) {
231*7c478bd9Sstevel@tonic-gate if (isatty(fileno(stdout))) {
232*7c478bd9Sstevel@tonic-gate Err(
233*7c478bd9Sstevel@tonic-gate MGET("Stdout is a tty, please specify an output file\n"));
234*7c478bd9Sstevel@tonic-gate exit(1);
235*7c478bd9Sstevel@tonic-gate }
236*7c478bd9Sstevel@tonic-gate
237*7c478bd9Sstevel@tonic-gate path = Stdout;
238*7c478bd9Sstevel@tonic-gate if (ofmt == F_RAW) {
239*7c478bd9Sstevel@tonic-gate if (!(ofp = new AudioRawPipe(fileno(stdout),
240*7c478bd9Sstevel@tonic-gate (FileAccess)WriteOnly, ohdr,
241*7c478bd9Sstevel@tonic-gate path))) {
242*7c478bd9Sstevel@tonic-gate Err(
243*7c478bd9Sstevel@tonic-gate MGET("can't create audio raw stdout pipe\n"));
244*7c478bd9Sstevel@tonic-gate exit(1);
245*7c478bd9Sstevel@tonic-gate }
246*7c478bd9Sstevel@tonic-gate } else if (ofmt == F_SUN) {
247*7c478bd9Sstevel@tonic-gate if (!(ofp = new AudioPipe(fileno(stdout),
248*7c478bd9Sstevel@tonic-gate (FileAccess)WriteOnly, path))) {
249*7c478bd9Sstevel@tonic-gate Err(
250*7c478bd9Sstevel@tonic-gate MGET("can't create audio pipe for stdout\n"));
251*7c478bd9Sstevel@tonic-gate exit(1);
252*7c478bd9Sstevel@tonic-gate }
253*7c478bd9Sstevel@tonic-gate } else {
254*7c478bd9Sstevel@tonic-gate // XXX - should never happen ...
255*7c478bd9Sstevel@tonic-gate Err(MGET("can't create output file, unknown format\n"));
256*7c478bd9Sstevel@tonic-gate exit(1);
257*7c478bd9Sstevel@tonic-gate }
258*7c478bd9Sstevel@tonic-gate } else {
259*7c478bd9Sstevel@tonic-gate if (ofmt == F_RAW) {
260*7c478bd9Sstevel@tonic-gate // first open file, then attach pipe to it
261*7c478bd9Sstevel@tonic-gate if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC,
262*7c478bd9Sstevel@tonic-gate 0666)) < 0) {
263*7c478bd9Sstevel@tonic-gate perror(MGET("open"));
264*7c478bd9Sstevel@tonic-gate Err(MGET("can't create output file %s\n"),
265*7c478bd9Sstevel@tonic-gate path);
266*7c478bd9Sstevel@tonic-gate exit(1);
267*7c478bd9Sstevel@tonic-gate }
268*7c478bd9Sstevel@tonic-gate if (!(ofp = new AudioRawPipe(fd, (FileAccess)WriteOnly,
269*7c478bd9Sstevel@tonic-gate ohdr, path))) {
270*7c478bd9Sstevel@tonic-gate Err(MGET("can't create raw audio pipe %s\n"),
271*7c478bd9Sstevel@tonic-gate path);
272*7c478bd9Sstevel@tonic-gate exit(1);
273*7c478bd9Sstevel@tonic-gate }
274*7c478bd9Sstevel@tonic-gate } else if (ofmt == F_SUN) {
275*7c478bd9Sstevel@tonic-gate if (!(ofp = new AudioFile(path,
276*7c478bd9Sstevel@tonic-gate (FileAccess)ReadWrite))) {
277*7c478bd9Sstevel@tonic-gate Err(MGET("can't create output file %s\n"),
278*7c478bd9Sstevel@tonic-gate path);
279*7c478bd9Sstevel@tonic-gate exit(1);
280*7c478bd9Sstevel@tonic-gate }
281*7c478bd9Sstevel@tonic-gate } else {
282*7c478bd9Sstevel@tonic-gate // XXX - should never happen ...
283*7c478bd9Sstevel@tonic-gate Err(MGET("can't create output file, unknown format\n"));
284*7c478bd9Sstevel@tonic-gate exit(1);
285*7c478bd9Sstevel@tonic-gate }
286*7c478bd9Sstevel@tonic-gate }
287*7c478bd9Sstevel@tonic-gate
288*7c478bd9Sstevel@tonic-gate // set the info string.
289*7c478bd9Sstevel@tonic-gate ofp->SetInfostring(infoString, -1);
290*7c478bd9Sstevel@tonic-gate
291*7c478bd9Sstevel@tonic-gate // set the header and create the output audio object
292*7c478bd9Sstevel@tonic-gate if ((err = ofp->SetHeader(ohdr)) != AUDIO_SUCCESS) {
293*7c478bd9Sstevel@tonic-gate Err(MGET("can't set hdr on output file: %s\n"), err.msg());
294*7c478bd9Sstevel@tonic-gate exit(1);
295*7c478bd9Sstevel@tonic-gate }
296*7c478bd9Sstevel@tonic-gate if ((err = ofp->Create()) != AUDIO_SUCCESS) {
297*7c478bd9Sstevel@tonic-gate Err(MGET("can't create output file: %s\n"), err.msg());
298*7c478bd9Sstevel@tonic-gate exit(1);
299*7c478bd9Sstevel@tonic-gate }
300*7c478bd9Sstevel@tonic-gate
301*7c478bd9Sstevel@tonic-gate return (ofp);
302*7c478bd9Sstevel@tonic-gate }
303