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