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 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 ??). 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 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* 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