Print this page
10101 audio tools need smatch fixes
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/audio/audioplay/audioplay.c
+++ new/usr/src/cmd/audio/audioplay/audioplay.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 +/*
27 + * Copyright (c) 2018, Joyent, Inc.
28 + */
29 +
26 30 /* Command-line audio play utility */
27 31
28 32 #include <stdio.h>
29 33 #include <errno.h>
30 34 #include <ctype.h>
31 35 #include <string.h>
32 36 #include <stdlib.h>
33 37 #include <fcntl.h>
34 38 #include <signal.h>
35 39 #include <locale.h>
36 40 #include <limits.h> /* All occurances of INT_MAX used to be ~0 (by MCA) */
37 41 #include <unistd.h>
38 42 #include <stropts.h>
39 43 #include <sys/types.h>
40 44 #include <sys/file.h>
41 45 #include <sys/stat.h>
42 46 #include <sys/param.h>
43 47 #include <sys/ioctl.h>
44 48 #include <sys/mman.h>
45 49 #include <netinet/in.h>
46 50
47 51 #include <libaudio.h>
48 52 #include <audio_device.h>
49 53 #include <audio_encode.h>
50 54
51 55 /* localization stuff */
52 56 #define MGET(s) (char *)gettext(s)
53 57
54 58 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
55 59 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
56 60 #endif
57 61
58 62 #define Error (void) fprintf
59 63
60 64
61 65 /* Local variables */
62 66 static char *prog;
63 67
64 68 static char prog_opts[] = "VEiv:d:?"; /* getopt() flags */
65 69
66 70 static char *Stdin;
67 71
68 72 #define MAX_GAIN (100) /* maximum gain */
69 73
70 74 /*
71 75 * This defines the tolerable sample rate error as a ratio between the
72 76 * sample rates of the audio data and the audio device.
73 77 */
74 78 #define SAMPLE_RATE_THRESHOLD (.01)
75 79
76 80 #define BUFFER_LEN 10 /* seconds - for file i/o */
77 81 #define ADPCM_SIZE (1000*8) /* adpcm conversion output buf size */
78 82 #define SWAP_SIZE (8192)
79 83 /* swap bytes conversion output buf size */
80 84
81 85 static unsigned Volume = INT_MAX; /* output volume */
82 86 static double Savevol; /* saved volume level */
83 87
84 88 static int Verbose = FALSE; /* verbose messages */
85 89 static int Immediate = FALSE;
86 90 /* don't hang waiting for device */
87 91 static int Errdetect = FALSE; /* don't worry about underrun */
88 92 static char *Audio_dev = "/dev/audio";
89 93
90 94 static int NetEndian = TRUE; /* endian nature of the machine */
91 95
92 96 static int Audio_fd = -1;
93 97 /* file descriptor for audio device */
94 98 static int Audio_ctlfd = -1;
95 99 /* file descriptor for control device */
96 100 static Audio_hdr Save_hdr;
97 101 /* saved audio header for device */
98 102 static Audio_hdr Dev_hdr; /* audio header for device */
99 103 static char *Ifile; /* current filename */
100 104 static Audio_hdr File_hdr; /* audio header for file */
101 105 static unsigned Decode = AUDIO_ENCODING_NONE;
102 106 /* decode type, if any */
103 107
104 108 static unsigned char *buf = NULL; /* dynamically alloc'd */
105 109 static unsigned bufsiz = 0; /* size of output buffer */
106 110 static unsigned char adpcm_buf[ADPCM_SIZE + 32];
107 111 /* for adpcm conversion */
108 112 static unsigned char swap_buf[SWAP_SIZE + 32];
109 113 /* for byte swap conversion */
110 114 static unsigned char *inbuf;
111 115 /* current input buffer pointer */
112 116 static unsigned insiz; /* current input buffer size */
113 117
114 118 /*
115 119 * The decode_g72x() function is capable of decoding only one channel
116 120 * at a time and so multichannel data must be decomposed (using demux()
117 121 * function below ) into its constituent channels and each passed
118 122 * separately to the decode_g72x() function. Encoded input channels are
119 123 * stored in **in_ch_data and decoded output channels in **out_ch_data.
120 124 * Once each channel has been decoded they are recombined (see mux()
121 125 * function below) before being written to the audio device. For each
122 126 * channel and adpcm state structure is created.
123 127 */
124 128
125 129 /* adpcm state structures */
126 130 static struct audio_g72x_state *adpcm_state = NULL;
127 131 static unsigned char **in_ch_data = NULL; /* input channels */
128 132 static unsigned char **out_ch_data = NULL; /* output channels */
129 133 static int out_ch_size; /* output channel size */
130 134
131 135 static char *Audio_path = NULL;
132 136 /* path to search for audio files */
133 137
134 138 /* Global variables */
135 139 extern int getopt(int, char *const *, const char *);
136 140 extern int optind;
137 141 extern char *optarg;
138 142
139 143 /* Local functions */
140 144 static void usage(void);
141 145 static void sigint(int sig);
142 146 static void open_audio(void);
143 147 static int path_open(char *fname, int flags, mode_t mode, char *path);
144 148 static int parse_unsigned(char *str, unsigned *dst, char *flag);
145 149 static int reconfig(void);
146 150 static void initmux(int unitsz, int unitsp);
147 151 static void demux(int unitsz, int cnt);
148 152 static void mux(char *);
149 153 static void freemux(void);
150 154
151 155
152 156 static void
153 157 usage(void)
154 158 {
155 159 Error(stderr, MGET("Play an audio file -- usage:\n"
156 160 "\t%s [-iV] [-v vol] [-d dev] [file ...]\n"
157 161 "where:\n"
158 162 "\t-i\tDon't hang if audio device is busy\n"
159 163 "\t-V\tPrint verbose warning messages\n"
160 164 "\t-v\tSet output volume (0 - %d)\n"
161 165 "\t-d\tSpecify audio device (default: /dev/audio)\n"
162 166 "\tfile\tList of files to play\n"
163 167 "\t\tIf no files specified, read stdin\n"),
164 168 prog, MAX_GAIN);
165 169 exit(1);
166 170 }
167 171
168 172 static void
169 173 sigint(int sig)
170 174 {
171 175 /* flush output queues before exiting */
172 176 if (Audio_fd >= 0) {
173 177 (void) audio_flush_play(Audio_fd);
174 178
175 179 /* restore saved parameters */
176 180 if (Volume != INT_MAX)
177 181 (void) audio_set_play_gain(Audio_fd, &Savevol);
178 182 if ((Audio_ctlfd >= 0) &&
179 183 (audio_cmp_hdr(&Save_hdr, &Dev_hdr) != 0)) {
180 184 (void) audio_set_play_config(Audio_fd, &Save_hdr);
181 185 }
182 186 }
183 187 exit(1);
184 188 }
185 189
186 190 /* Open the audio device and initalize it. */
187 191 static void
188 192 open_audio(void)
189 193 {
190 194 int err;
191 195 double vol;
192 196
193 197 /* Return if already open */
194 198 if (Audio_fd >= 0)
195 199 return;
196 200
197 201 /* Try opening without waiting, first */
198 202 Audio_fd = open(Audio_dev, O_WRONLY | O_NONBLOCK);
199 203 if ((Audio_fd < 0) && (errno == EBUSY)) {
200 204 if (Immediate) {
201 205 Error(stderr, MGET("%s: %s is busy\n"),
202 206 prog, Audio_dev);
203 207 exit(1);
204 208 }
205 209 if (Verbose) {
206 210 Error(stderr, MGET("%s: waiting for %s..."),
207 211 prog, Audio_dev);
208 212 (void) fflush(stderr);
209 213 }
210 214 /* Now hang until it's open */
211 215 Audio_fd = open(Audio_dev, O_WRONLY);
212 216 if (Verbose)
213 217 Error(stderr, (Audio_fd < 0) ? "\n" : MGET("open\n"));
214 218 }
215 219 if (Audio_fd < 0) {
216 220 Error(stderr, MGET("%s: error opening "), prog);
217 221 perror(Audio_dev);
218 222 exit(1);
219 223 }
220 224
221 225 /* Clear the non-blocking flag (in System V it persists after open) */
222 226 (void) fcntl(Audio_fd, F_SETFL,
223 227 (fcntl(Audio_fd, F_GETFL, 0) & ~(O_NDELAY | O_NONBLOCK)));
224 228
225 229 /* Get the device output encoding configuration */
226 230 if (audio_get_play_config(Audio_fd, &Dev_hdr) != AUDIO_SUCCESS) {
227 231 Error(stderr, MGET("%s: %s is not an audio device\n"),
228 232 prog, Audio_dev);
229 233 exit(1);
230 234 }
231 235
232 236 /* If -v flag, set the output volume now */
233 237 if (Volume != INT_MAX) {
234 238 vol = (double)Volume / (double)MAX_GAIN;
235 239 (void) audio_get_play_gain(Audio_fd, &Savevol);
236 240 err = audio_set_play_gain(Audio_fd, &vol);
237 241 if (err != AUDIO_SUCCESS) {
238 242 Error(stderr,
239 243 MGET("%s: could not set output volume for %s\n"),
240 244 prog, Audio_dev);
241 245 exit(1);
242 246 }
243 247 }
244 248 }
245 249
246 250 /* Play a list of audio files. */
247 251 int
248 252 main(int argc, char **argv) {
249 253 int errorStatus = 0;
250 254 int i;
251 255 int c;
252 256 int cnt;
253 257 int file_type;
254 258 int rem;
255 259 int outsiz;
256 260 int tsize;
257 261 int len;
258 262 int err;
259 263 int ifd;
260 264 int stdinseen;
261 265 int regular;
262 266 int swapBytes;
263 267 int frame;
264 268 char *outbuf;
265 269 caddr_t mapaddr;
266 270 struct stat st;
267 271 char *cp;
268 272 char ctldev[MAXPATHLEN];
269 273
270 274 (void) setlocale(LC_ALL, "");
271 275 (void) textdomain(TEXT_DOMAIN);
272 276
273 277 /* Get the program name */
274 278 prog = strrchr(argv[0], '/');
275 279 if (prog == NULL)
276 280 prog = argv[0];
277 281 else
278 282 prog++;
279 283 Stdin = MGET("(stdin)");
280 284
281 285 /* Check AUDIODEV environment for audio device name */
282 286 if (cp = getenv("AUDIODEV")) {
283 287 Audio_dev = cp;
284 288 }
285 289
286 290 /* Parse the command line arguments */
287 291 err = 0;
288 292 while ((i = getopt(argc, argv, prog_opts)) != EOF) {
289 293 switch (i) {
290 294 case 'v':
291 295 if (parse_unsigned(optarg, &Volume, "-v")) {
292 296 err++;
293 297 } else if (Volume > MAX_GAIN) {
294 298 Error(stderr, MGET("%s: invalid value "
295 299 "for -v\n"), prog);
296 300 err++;
297 301 }
298 302 break;
299 303 case 'd':
300 304 Audio_dev = optarg;
301 305 break;
302 306 case 'V':
303 307 Verbose = TRUE;
304 308 break;
305 309 case 'E':
306 310 Errdetect = TRUE;
307 311 break;
308 312 case 'i':
309 313 Immediate = TRUE;
310 314 break;
311 315 case '?':
312 316 usage();
313 317 /*NOTREACHED*/
314 318 }
315 319 }
316 320 if (err > 0)
317 321 exit(1);
318 322
319 323 argc -= optind; /* update arg pointers */
320 324 argv += optind;
321 325
322 326 /* Validate and open the audio device */
323 327 err = stat(Audio_dev, &st);
324 328 if (err < 0) {
325 329 Error(stderr, MGET("%s: cannot stat "), prog);
326 330 perror(Audio_dev);
327 331 exit(1);
328 332 }
329 333 if (!S_ISCHR(st.st_mode)) {
330 334 Error(stderr, MGET("%s: %s is not an audio device\n"), prog,
331 335 Audio_dev);
332 336 exit(1);
333 337 }
334 338
335 339 /* This should probably use audio_cntl instead of open_audio */
336 340 if ((argc <= 0) && isatty(fileno(stdin))) {
337 341 Error(stderr, MGET("%s: No files and stdin is a tty.\n"), prog);
338 342 exit(1);
339 343 }
340 344
341 345 /* Check on the -i status now. */
342 346 Audio_fd = open(Audio_dev, O_WRONLY | O_NONBLOCK);
343 347 if ((Audio_fd < 0) && (errno == EBUSY)) {
344 348 if (Immediate) {
345 349 Error(stderr, MGET("%s: %s is busy\n"), prog,
346 350 Audio_dev);
347 351 exit(1);
348 352 }
349 353 }
350 354 (void) close(Audio_fd);
351 355 Audio_fd = -1;
352 356
353 357 /* Try to open the control device and save the current format */
354 358 (void) snprintf(ctldev, sizeof (ctldev), "%sctl", Audio_dev);
355 359 Audio_ctlfd = open(ctldev, O_RDWR);
356 360 if (Audio_ctlfd >= 0) {
357 361 /*
358 362 * wait for the device to become available then get the
359 363 * controls. We want to save the format that is left when the
360 364 * device is in a quiescent state. So wait until then.
361 365 */
362 366 Audio_fd = open(Audio_dev, O_WRONLY);
363 367 (void) close(Audio_fd);
364 368 Audio_fd = -1;
365 369 if (audio_get_play_config(Audio_ctlfd, &Save_hdr)
366 370 != AUDIO_SUCCESS) {
367 371 (void) close(Audio_ctlfd);
368 372 Audio_ctlfd = -1;
369 373 }
370 374 }
371 375
372 376 /* store AUDIOPATH so we don't keep doing getenv() */
373 377 Audio_path = getenv("AUDIOPATH");
374 378
375 379 /* Set up SIGINT handler to flush output */
376 380 (void) signal(SIGINT, sigint);
377 381
378 382 /* Set the endian nature of the machine. */
379 383 if ((ulong_t)1 != htonl((ulong_t)1)) {
380 384 NetEndian = FALSE;
381 385 }
382 386
383 387 /* If no filenames, read stdin */
384 388 stdinseen = FALSE;
385 389 if (argc <= 0) {
386 390 Ifile = Stdin;
387 391 } else {
388 392 Ifile = *argv++;
389 393 argc--;
390 394 }
391 395
392 396 /* Loop through all filenames */
393 397 do {
394 398 /* Interpret "-" filename to mean stdin */
395 399 if (strcmp(Ifile, "-") == 0)
396 400 Ifile = Stdin;
397 401
398 402 if (Ifile == Stdin) {
399 403 if (stdinseen) {
400 404 Error(stderr,
401 405 MGET("%s: stdin already processed\n"),
402 406 prog);
403 407 goto nextfile;
404 408 }
405 409 stdinseen = TRUE;
406 410 ifd = fileno(stdin);
407 411 } else {
408 412 if ((ifd = path_open(Ifile, O_RDONLY, 0, Audio_path))
409 413 < 0) {
410 414 Error(stderr, MGET("%s: cannot open "), prog);
411 415 perror(Ifile);
412 416 errorStatus++;
413 417 goto nextfile;
414 418 }
415 419 }
416 420
417 421 /* Check to make sure this is an audio file */
418 422 err = audio_read_filehdr(ifd, &File_hdr, &file_type,
419 423 (char *)NULL, 0);
420 424 if (err != AUDIO_SUCCESS) {
421 425 Error(stderr,
422 426 MGET("%s: %s is not a valid audio file\n"),
423 427 prog, Ifile);
424 428 errorStatus++;
425 429 goto closeinput;
426 430 }
427 431
428 432 /* If G.72X adpcm, set flags for conversion */
429 433 if ((File_hdr.encoding == AUDIO_ENCODING_G721) &&
430 434 (File_hdr.samples_per_unit == 2) &&
431 435 (File_hdr.bytes_per_unit == 1)) {
432 436 Decode = AUDIO_ENCODING_G721;
433 437 File_hdr.encoding = AUDIO_ENCODING_ULAW;
434 438 File_hdr.samples_per_unit = 1;
435 439 File_hdr.bytes_per_unit = 1;
436 440 adpcm_state = (struct audio_g72x_state *)malloc
437 441 (sizeof (*adpcm_state) * File_hdr.channels);
438 442 for (i = 0; i < File_hdr.channels; i++) {
439 443 g721_init_state(&adpcm_state[i]);
440 444 }
441 445 } else if ((File_hdr.encoding == AUDIO_ENCODING_G723) &&
442 446 (File_hdr.samples_per_unit == 8) &&
443 447 (File_hdr.bytes_per_unit == 3)) {
444 448 Decode = AUDIO_ENCODING_G723;
445 449 File_hdr.encoding = AUDIO_ENCODING_ULAW;
446 450 File_hdr.samples_per_unit = 1;
447 451 File_hdr.bytes_per_unit = 1;
448 452 adpcm_state = (struct audio_g72x_state *)malloc
449 453 (sizeof (*adpcm_state) * File_hdr.channels);
450 454 for (i = 0; i < File_hdr.channels; i++) {
451 455 g723_init_state(&adpcm_state[i]);
452 456 }
453 457 } else {
454 458 Decode = AUDIO_ENCODING_NONE;
455 459 }
456 460
457 461 /* Check the device configuration */
458 462 open_audio();
459 463 if (audio_cmp_hdr(&Dev_hdr, &File_hdr) != 0) {
460 464 /*
461 465 * The device does not match the input file.
462 466 * Wait for any old output to drain, then attempt
463 467 * to reconfigure the audio device to match the
464 468 * input data.
465 469 */
466 470 if (audio_drain(Audio_fd, FALSE) != AUDIO_SUCCESS) {
467 471 /* Flush any remaining audio */
468 472 (void) ioctl(Audio_fd, I_FLUSH, FLUSHW);
469 473
470 474 Error(stderr, MGET("%s: "), prog);
471 475 perror(MGET("AUDIO_DRAIN error"));
472 476 exit(1);
473 477 }
474 478
475 479 /* Flush any remaining audio */
476 480 (void) ioctl(Audio_fd, I_FLUSH, FLUSHW);
477 481
478 482 if (!reconfig()) {
479 483 errorStatus++;
480 484 goto closeinput;
481 485 }
482 486 }
483 487
484 488
485 489 /* try to do the mmaping - for regular files only ... */
486 490 err = fstat(ifd, &st);
487 491 if (err < 0) {
488 492 Error(stderr, MGET("%s: cannot stat "), prog);
489 493 perror(Ifile);
490 494 exit(1);
491 495 }
492 496 regular = (S_ISREG(st.st_mode));
493 497
494 498
495 499 /* If regular file, map it. Else, allocate a buffer */
496 500 mapaddr = 0;
497 501
498 502 /*
499 503 * This should compare to MAP_FAILED not -1, can't
500 504 * find MAP_FAILED
501 505 */
502 506 if (regular && ((mapaddr = mmap(0, st.st_size, PROT_READ,
503 507 MAP_SHARED, ifd, 0)) != MAP_FAILED)) {
504 508
505 509 (void) madvise(mapaddr, st.st_size, MADV_SEQUENTIAL);
506 510
507 511 /* Skip the file header and set the proper size */
508 512 cnt = lseek(ifd, 0, SEEK_CUR);
509 513 if (cnt < 0) {
510 514 perror("lseek");
511 515 exit(1);
512 516 }
513 517 inbuf = (unsigned char *) mapaddr + cnt;
514 518 len = cnt = st.st_size - cnt;
515 519 } else { /* Not a regular file, or map failed */
516 520
517 521 /* mark is so. */
518 522 mapaddr = 0;
519 523
520 524 /* Allocate buffer to hold 10 seconds of data */
521 525 cnt = BUFFER_LEN * File_hdr.sample_rate *
522 526 File_hdr.bytes_per_unit * File_hdr.channels;
523 527 if (bufsiz != cnt) {
524 528 if (buf != NULL) {
525 529 (void) free(buf);
526 530 }
527 531 buf = (unsigned char *) malloc(cnt);
528 532 if (buf == NULL) {
529 533 Error(stderr,
530 534 MGET("%s: couldn't allocate %dK "
531 535 "buf\n"), prog, bufsiz / 1000);
532 536 exit(1);
533 537 }
534 538 inbuf = buf;
535 539 bufsiz = cnt;
536 540 }
537 541 }
538 542
539 543 /* Set buffer sizes and pointers for conversion, if any */
540 544 switch (Decode) {
541 545 default:
542 546 case AUDIO_ENCODING_NONE:
543 547 insiz = bufsiz;
544 548 outbuf = (char *)buf;
545 549 break;
546 550 case AUDIO_ENCODING_G721:
547 551 insiz = ADPCM_SIZE / 2;
548 552 outbuf = (char *)adpcm_buf;
549 553 initmux(1, 2);
550 554 break;
551 555 case AUDIO_ENCODING_G723:
552 556 insiz = (ADPCM_SIZE * 3) / 8;
553 557 outbuf = (char *)adpcm_buf;
554 558 initmux(3, 8);
555 559 break;
556 560 }
557 561
558 562 /*
559 563 * 8-bit audio isn't a problem, however 16-bit audio is.
560 564 * If the file is an endian that is different from the machine
561 565 * then the bytes will need to be swapped.
562 566 *
563 567 * Note: Because the G.72X conversions produce 8bit output,
564 568 * they don't require a byte swap before display and so
565 569 * this scheme works just fine. If a conversion is added
566 570 * that produces a 16 bit result and therefore requires
567 571 * byte swapping before output, then a mechanism
568 572 * for chaining the two conversions will have to be built.
569 573 *
570 574 * Note: The following if() could be simplified, but then
571 575 * it gets to be very hard to read. So it's left as is.
572 576 */
573 577
574 578 if (File_hdr.bytes_per_unit == 2 &&
575 579 ((!NetEndian && file_type == FILE_AIFF) ||
576 580 (!NetEndian && file_type == FILE_AU) ||
577 581 (NetEndian && file_type == FILE_WAV))) {
578 582 swapBytes = TRUE;
579 583 } else {
580 584 swapBytes = FALSE;
581 585 }
582 586
583 587 if (swapBytes) {
584 588 /* Read in interal number of sample frames. */
585 589 frame = File_hdr.bytes_per_unit * File_hdr.channels;
586 590 insiz = (SWAP_SIZE / frame) * frame;
587 591 /* make the output buffer the swap buffer. */
588 592 outbuf = (char *)swap_buf;
589 593 }
590 594
591 595 /*
592 596 * At this point, we're all ready to copy the data.
593 597 */
594 598 if (mapaddr == 0) { /* Not mmapped, do it a buffer at a time. */
595 599 inbuf = buf;
596 600 frame = File_hdr.bytes_per_unit * File_hdr.channels;
597 601 rem = 0;
598 602 while ((cnt = read(ifd, inbuf+rem, insiz-rem)) >= 0) {
599 603 /*
600 604 * We need to ensure only an integral number of
601 605 * samples is ever written to the audio device.
602 606 */
603 607 cnt = cnt + rem;
604 608 rem = cnt % frame;
605 609 cnt = cnt - rem;
606 610
607 611 /*
608 612 * If decoding adpcm, or swapping bytes do it
609 613 * now.
610 614 *
611 615 * We treat the swapping like a separate
612 616 * encoding here because the G.72X encodings
613 617 * decode to single byte output samples. If
614 618 * another encoding is added and it produces
615 619 * multi-byte output samples this will have to
616 620 * be changed.
617 621 */
618 622 if (Decode == AUDIO_ENCODING_G721) {
619 623 outsiz = 0;
620 624 demux(1, cnt / File_hdr.channels);
621 625 for (c = 0; c < File_hdr.channels; c++) {
622 626 err = g721_decode(in_ch_data[c],
623 627 cnt / File_hdr.channels,
624 628 &File_hdr,
625 629 (void*)out_ch_data[c],
626 630 &tsize,
627 631 &adpcm_state[c]);
628 632 outsiz = outsiz + tsize;
629 633 if (err != AUDIO_SUCCESS) {
630 634 Error(stderr, MGET(
631 635 "%s: error decoding g721\n"),
632 636 prog);
633 637 errorStatus++;
634 638 break;
635 639 }
636 640 }
637 641 mux(outbuf);
638 642 cnt = outsiz;
639 643 } else if (Decode == AUDIO_ENCODING_G723) {
640 644 outsiz = 0;
641 645 demux(3, cnt / File_hdr.channels);
642 646 for (c = 0; c < File_hdr.channels; c++) {
643 647 err = g723_decode(in_ch_data[c],
644 648 cnt / File_hdr.channels,
645 649 &File_hdr,
646 650 (void*)out_ch_data[c],
647 651 &tsize,
648 652 &adpcm_state[c]);
649 653 outsiz = outsiz + tsize;
650 654 if (err != AUDIO_SUCCESS) {
651 655 Error(stderr, MGET(
652 656 "%s: error decoding g723\n"),
653 657 prog);
654 658 errorStatus++;
655 659 break;
656 660 }
657 661 }
658 662 mux(outbuf);
659 663 cnt = outsiz;
660 664 } else if (swapBytes) {
661 665 swab((char *)inbuf, outbuf, cnt);
662 666 }
663 667
664 668 /* If input EOF, write an eof marker */
665 669 err = write(Audio_fd, outbuf, cnt);
666 670
667 671 if (err < 0) {
668 672 perror("write");
669 673 errorStatus++;
670 674 break;
671 675 } else if (err != cnt) {
672 676 Error(stderr,
673 677 MGET("%s: output error: "), prog);
674 678 perror("");
675 679 errorStatus++;
676 680 break;
677 681 }
678 682 if (cnt == 0) {
679 683 break;
680 684 }
681 685 /* Move remainder to the front of the buffer */
682 686 if (rem != 0) {
683 687 (void *)memcpy(inbuf, inbuf + cnt, rem);
684 688 }
685 689
686 690 }
687 691 if (cnt < 0) {
688 692 Error(stderr, MGET("%s: error reading "), prog);
689 693 perror(Ifile);
690 694 errorStatus++;
691 695 }
692 696 } else { /* We're mmaped */
693 697 if ((Decode != AUDIO_ENCODING_NONE) || swapBytes) {
694 698
695 699 /* Transform data if we have to. */
696 700 for (i = 0; i <= len; i += cnt) {
697 701 cnt = insiz;
698 702 if ((i + cnt) > len) {
699 703 cnt = len - i;
700 704 }
701 705 if (Decode == AUDIO_ENCODING_G721) {
702 706 outsiz = 0;
703 707 demux(1, cnt / File_hdr.channels);
704 708 for (c = 0; c < File_hdr.channels;
705 709 c++) {
706 710 err = g721_decode(
707 711 in_ch_data[c],
708 712 cnt / File_hdr.channels,
709 713 &File_hdr,
710 714 (void*)out_ch_data[c],
711 715 &tsize,
712 716 &adpcm_state[c]);
713 717 outsiz = outsiz + tsize;
714 718 if (err != AUDIO_SUCCESS) {
715 719 Error(stderr, MGET(
716 720 "%s: error decoding "
717 721 "g721\n"), prog);
718 722 errorStatus++;
719 723 break;
720 724 }
721 725 }
722 726 mux(outbuf);
723 727 } else if
724 728 (Decode == AUDIO_ENCODING_G723) {
725 729 outsiz = 0;
726 730 demux(3,
727 731 cnt / File_hdr.channels);
728 732 for (c = 0;
729 733 c < File_hdr.channels;
730 734 c++) {
731 735 err = g723_decode(
732 736 in_ch_data[c],
733 737 cnt /
734 738 File_hdr.channels,
735 739 &File_hdr,
736 740 (void*)out_ch_data[c],
737 741 &tsize,
738 742 &adpcm_state[c]);
739 743 outsiz = outsiz + tsize;
740 744 if (err != AUDIO_SUCCESS) {
741 745 Error(stderr, MGET(
742 746 "%s: error "
743 747 "decoding g723\n"),
744 748 prog);
745 749 errorStatus++;
746 750 break;
747 751 }
748 752 }
749 753 mux(outbuf);
750 754 } else if (swapBytes) {
751 755 swab((char *)inbuf, outbuf,
752 756 cnt);
753 757 outsiz = cnt;
754 758 }
755 759 inbuf += cnt;
756 760
757 761 /* If input EOF, write an eof marker */
758 762 err = write(Audio_fd, (char *)outbuf,
759 763 outsiz);
760 764 if (err < 0) {
761 765 perror("write");
762 766 errorStatus++;
763 767 } else if (outsiz == 0) {
764 768 break;
765 769 }
766 770
767 771 }
768 772 } else {
769 773 /* write the whole thing at once! */
770 774 err = write(Audio_fd, inbuf, len);
771 775 if (err < 0) {
772 776 perror("write");
773 777 errorStatus++;
774 778 }
775 779 if (err != len) {
776 780 Error(stderr,
777 781 MGET("%s: output error: "), prog);
778 782 perror("");
779 783 errorStatus++;
780 784 }
781 785 err = write(Audio_fd, inbuf, 0);
782 786 if (err < 0) {
783 787 perror("write");
784 788 errorStatus++;
785 789 }
786 790 }
787 791 }
788 792
789 793 /* Free memory if decoding ADPCM */
790 794 switch (Decode) {
791 795 case AUDIO_ENCODING_G721:
792 796 case AUDIO_ENCODING_G723:
793 797 freemux();
794 798 break;
↓ open down ↓ |
759 lines elided |
↑ open up ↑ |
795 799 default:
796 800 break;
797 801 }
798 802
799 803 closeinput:;
800 804 if (mapaddr != 0)
801 805 (void) munmap(mapaddr, st.st_size);
802 806 (void) close(ifd); /* close input file */
803 807 if (Errdetect) {
804 808 cnt = 0;
805 - audio_set_play_error(Audio_fd, (unsigned int *)&cnt);
809 + (void) audio_set_play_error(Audio_fd,
810 + (unsigned int *)&cnt);
806 811 if (cnt) {
807 812 Error(stderr,
808 813 MGET("%s: output underflow in %s\n"),
809 814 Ifile, prog);
810 815 errorStatus++;
811 816 }
812 817 }
813 818 nextfile:;
814 819 } while ((argc > 0) && (argc--, (Ifile = *argv++) != NULL));
815 820
816 821 /*
817 822 * Though drain is implicit on close(), it's performed here
818 823 * to ensure that the volume is reset after all output is complete.
819 824 */
820 825 (void) audio_drain(Audio_fd, FALSE);
821 826
822 827 /* Flush any remaining audio */
823 828 (void) ioctl(Audio_fd, I_FLUSH, FLUSHW);
824 829
825 830 if (Volume != INT_MAX)
826 831 (void) audio_set_play_gain(Audio_fd, &Savevol);
827 832 if ((Audio_ctlfd >= 0) && (audio_cmp_hdr(&Save_hdr, &Dev_hdr) != 0)) {
828 833 (void) audio_set_play_config(Audio_fd, &Save_hdr);
829 834 }
830 835 (void) close(Audio_fd); /* close output */
831 836 return (errorStatus);
832 837 }
833 838
834 839
835 840 /*
836 841 * Try to reconfigure the audio device to match the file encoding.
837 842 * If this fails, we should attempt to make the input data match the
838 843 * device encoding. For now, we give up on this file.
839 844 *
840 845 * Returns TRUE if successful. Returns FALSE if not.
841 846 */
842 847 static int
843 848 reconfig(void)
844 849 {
845 850 int err;
846 851 char msg[AUDIO_MAX_ENCODE_INFO];
847 852
848 853 Dev_hdr = File_hdr;
849 854 err = audio_set_play_config(Audio_fd, &Dev_hdr);
850 855
851 856 switch (err) {
852 857 case AUDIO_SUCCESS:
853 858 return (TRUE);
854 859
855 860 case AUDIO_ERR_NOEFFECT:
856 861 /*
857 862 * Couldn't change the device.
858 863 * Check to see if we're nearly compatible.
859 864 * audio_cmp_hdr() returns >0 if only sample rate difference.
860 865 */
861 866 if (audio_cmp_hdr(&Dev_hdr, &File_hdr) > 0) {
862 867 double ratio;
863 868
864 869 ratio = (double)abs((int)
865 870 (Dev_hdr.sample_rate - File_hdr.sample_rate)) /
866 871 (double)File_hdr.sample_rate;
867 872 if (ratio <= SAMPLE_RATE_THRESHOLD) {
868 873 if (Verbose) {
869 874 Error(stderr,
870 875 MGET("%s: WARNING: %s sampled at "
871 876 "%d, playing at %d\n"),
872 877 prog, Ifile, File_hdr.sample_rate,
873 878 Dev_hdr.sample_rate);
874 879 }
875 880 return (TRUE);
876 881 }
877 882 Error(stderr,
878 883 MGET("%s: %s sample rate %d not available\n"),
879 884 prog, Ifile, File_hdr.sample_rate);
880 885 return (FALSE);
881 886 }
882 887 (void) audio_enc_to_str(&File_hdr, msg);
883 888 Error(stderr, MGET("%s: %s encoding not available: %s\n"),
884 889 prog, Ifile, msg);
885 890 return (FALSE);
886 891
887 892 default:
888 893 Error(stderr,
889 894 MGET("%s: %s audio encoding type not available\n"),
890 895 prog, Ifile);
891 896 exit(1);
892 897 }
893 898 return (TRUE);
894 899 }
895 900
896 901
897 902 /* Parse an unsigned integer */
898 903 static int
899 904 parse_unsigned(char *str, unsigned *dst, char *flag)
900 905 {
901 906 char x;
902 907
903 908 if (sscanf(str, "%u%c", dst, &x) != 1) {
904 909 Error(stderr, MGET("%s: invalid value for %s\n"), prog, flag);
905 910 return (1);
906 911 }
907 912 return (0);
908 913 }
909 914
910 915 /*
911 916 * Search for fname in path and open. Ignore path not opened O_RDONLY.
912 917 * Note: in general path can be a list of ':' separated paths to search
913 918 * through.
914 919 */
915 920 static int
916 921 path_open(char *fname, int flags, mode_t mode, char *path)
917 922 {
918 923 char fullpath[MAXPATHLEN]; /* full path of file */
919 924 char *buf; /* malloc off the tmp buff */
920 925 char *cp;
921 926 struct stat st;
922 927
923 928 if (!fname) { /* bogus */
924 929 return (-1);
925 930 }
926 931
927 932 /*
928 933 * cases where we don't bother checking path:
929 934 * - no path
930 935 * - file not opened O_RDONLY
931 936 * - not a relative path (i.e. starts with /, ./, or ../).
932 937 */
933 938
934 939 if ((!path) || (flags != O_RDONLY) || (*fname == '/') ||
935 940 (strncmp(fname, "./", strlen("./")) == 0) ||
936 941 (strncmp(fname, "../", strlen("../")) == 0)) {
937 942 return (open(fname, flags, mode));
938 943 }
939 944
940 945 /*
941 946 * Malloc off a buffer to hold the path variable.
942 947 * This is NOT limited to MAXPATHLEN characters as
943 948 * it may contain multiple paths.
944 949 */
945 950 buf = malloc(strlen(path) + 1);
946 951
947 952 /*
948 953 * if first character is ':', but not the one following it,
949 954 * skip over it - or it'll be interpreted as "./". it's OK
950 955 * to have "::" since that does mean "./".
951 956 */
952 957
953 958 if ((path[0] == ':') && (path[1] != ':')) {
954 959 (void) strncpy(buf, path+1, strlen(path));
955 960 } else {
956 961 (void) strncpy(buf, path, strlen(path));
957 962 }
958 963
959 964 for (path = buf; path && *path; ) {
960 965 if (cp = strchr(path, ':')) {
961 966 *cp++ = NULL; /* now pts to next path element */
962 967 }
963 968
964 969 /* the safest way to create the path string :-) */
965 970 if (*path) {
966 971 (void) strncpy(fullpath, path, MAXPATHLEN);
967 972 (void) strncat(fullpath, "/", MAXPATHLEN);
968 973 } else {
969 974 /* a NULL path element means "./" */
970 975 (void) strncpy(fullpath, "./", MAXPATHLEN);
971 976 }
972 977 (void) strncat(fullpath, fname, MAXPATHLEN);
973 978
974 979 /* see if there's a match */
975 980 if (stat(fullpath, &st) >= 0) {
976 981 if (S_ISREG(st.st_mode)) {
977 982 /* got a match! */
978 983 if (Verbose) {
979 984 Error(stderr,
980 985 MGET("%s: Found %s in path "
981 986 "at %s\n"),
982 987 prog, fname, fullpath);
983 988 }
984 989 return (open(fullpath, flags, mode));
985 990 }
986 991 }
987 992
988 993 /* go on to the next one */
989 994 path = cp;
990 995 }
991 996
992 997 /*
993 998 * if we fall through with no match, just do a normal file open
994 999 */
995 1000 return (open(fname, flags, mode));
996 1001 }
997 1002
998 1003
999 1004 /*
1000 1005 * initmux()
1001 1006 *
1002 1007 * Description:
1003 1008 * Allocates memory for carrying out demultiplexing/multiplexing.
1004 1009 *
1005 1010 * Arguments:
1006 1011 * int unitsz Bytes per unit
1007 1012 * int unitsp Samples per unit
1008 1013 *
1009 1014 * Returns:
1010 1015 * void
1011 1016 */
1012 1017 static void
1013 1018 initmux(int unitsz, int unitsp)
1014 1019 {
1015 1020 int c; /* Channel */
1016 1021 int in_ch_size; /* Input channel size */
1017 1022
1018 1023 /* Size of each input channel */
1019 1024 in_ch_size = insiz / File_hdr.channels;
1020 1025
1021 1026 /* Size of each output channel */
1022 1027 out_ch_size = in_ch_size * unitsp / unitsz;
1023 1028
1024 1029 /* Allocate pointers to input channels */
1025 1030 in_ch_data = malloc(sizeof (unsigned char *) * File_hdr.channels);
1026 1031
1027 1032 if (in_ch_data == NULL) {
1028 1033 Error(stderr, MGET("%s: couldn't allocate %dK buf\n"),
1029 1034 prog, sizeof (unsigned char *) * File_hdr.channels / 1000);
1030 1035 exit(1);
1031 1036 }
1032 1037
1033 1038 /* Allocate input channels */
1034 1039 for (c = 0; c < File_hdr.channels; c++) {
1035 1040 in_ch_data[c] = malloc(sizeof (unsigned char) * in_ch_size);
1036 1041
1037 1042 if (in_ch_data[c] == NULL) {
1038 1043 Error(stderr, MGET("%s: couldn't allocate %dK buf\n"),
1039 1044 prog, in_ch_size / 1000);
1040 1045 exit(1);
1041 1046 }
1042 1047 }
1043 1048
1044 1049 /* Allocate pointers to output channels */
1045 1050 out_ch_data = malloc(sizeof (unsigned char *) * File_hdr.channels);
1046 1051
1047 1052 if (out_ch_data == NULL) {
1048 1053 Error(stderr, MGET("%s: couldn't allocate %dK buf\n"),
1049 1054 prog, sizeof (unsigned char *) * File_hdr.channels / 1000);
1050 1055 exit(1);
1051 1056 }
1052 1057
1053 1058 /* Allocate output channels */
1054 1059 for (c = 0; c < File_hdr.channels; c++) {
1055 1060 out_ch_data[c] = malloc(sizeof (unsigned char) * out_ch_size);
1056 1061
1057 1062 if (out_ch_data[c] == NULL) {
1058 1063 Error(stderr, MGET("%s: couldn't allocate %dK buf\n"),
1059 1064 prog, out_ch_size / 1000);
1060 1065 exit(1);
1061 1066 }
1062 1067 }
1063 1068 }
1064 1069
1065 1070 /*
1066 1071 * demux()
1067 1072 *
1068 1073 * Description:
1069 1074 * Split a multichannel signal into separate channels.
1070 1075 *
1071 1076 * Arguments:
1072 1077 * int unitsz Bytes per unit
1073 1078 * int cnt Bytes to process
1074 1079 *
1075 1080 * Returns:
1076 1081 * void
1077 1082 */
1078 1083 static void
1079 1084 demux(int unitsz, int cnt)
1080 1085 {
1081 1086 int c; /* Channel */
1082 1087 int s; /* Sample */
1083 1088 int b; /* Byte */
1084 1089 int tp; /* Pointer into current data */
1085 1090 int dp; /* Pointer into target data */
1086 1091
1087 1092 /* Split */
1088 1093 for (c = 0; c < File_hdr.channels; c++) {
1089 1094 for (s = 0; s < cnt / unitsz; s++) {
1090 1095 tp = s * unitsz;
1091 1096 dp = (s * File_hdr.channels + c) * unitsz;
1092 1097 for (b = 0; b < unitsz; b++) {
1093 1098 in_ch_data[c][tp + b] = inbuf[dp + b];
1094 1099 }
1095 1100 }
1096 1101 }
1097 1102 }
1098 1103
1099 1104 /*
1100 1105 * mux()
1101 1106 *
1102 1107 * Description:
1103 1108 * Combine separate channels to produce a multichannel signal.
1104 1109 *
1105 1110 * Arguments:
1106 1111 * char *outbuf Combined signal
1107 1112 *
1108 1113 * Returns:
1109 1114 * void
1110 1115 */
1111 1116 static void
1112 1117 mux(char *outbuf)
1113 1118 {
1114 1119 int c; /* Channel */
1115 1120 int s; /* Sample */
1116 1121
1117 1122 /* Combine */
1118 1123 for (c = 0; c < File_hdr.channels; c++) {
1119 1124 for (s = 0; s < out_ch_size; s++) {
1120 1125 outbuf[File_hdr.channels * s + c] = out_ch_data[c][s];
1121 1126 }
1122 1127 }
1123 1128 }
1124 1129
1125 1130 /*
1126 1131 * freemux()
1127 1132 *
1128 1133 * Description:
1129 1134 * Free memory used in multiplexing/demultiplexing.
1130 1135 *
1131 1136 * Arguments:
1132 1137 * void
1133 1138 *
1134 1139 * Returns:
1135 1140 * void
1136 1141 */
1137 1142 static void
1138 1143 freemux(void)
1139 1144 {
1140 1145 int c; /* Channel */
1141 1146
1142 1147 /* Free */
1143 1148 for (c = 0; c < File_hdr.channels; c++) {
1144 1149 free(in_ch_data[c]);
1145 1150 free(out_ch_data[c]);
1146 1151 free(&adpcm_state[c]);
1147 1152 }
1148 1153
1149 1154 free(in_ch_data);
1150 1155 free(out_ch_data);
1151 1156 }
↓ open down ↓ |
336 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX