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