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