Annotation of src/usr.bin/aucat/aucat.c, Revision 1.25
1.25 ! ratchov 1: /* $OpenBSD: aucat.c,v 1.24 2008/06/02 17:08:51 ratchov Exp $ */
1.1 kstailey 2: /*
1.15 ratchov 3: * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
1.1 kstailey 4: *
1.15 ratchov 5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17: /*
18: * TODO:
19: *
20: * (not yet)add a silent/quiet/verbose/whatever flag, but be sure
21: * that by default the user is notified when one of the following
22: * (cpu consuming) aproc is created: mix, sub, conv
23: *
24: * (hard) use parsable encoding names instead of the lookup
25: * table. For instance, [s|u]bits[le|be][/bytes{msb|lsb}], example
26: * s8, s16le, s24le/3msb. This would give names that correspond to
27: * what use most linux-centric apps, but for which we have an
28: * algorithm to convert the name to a aparams structure.
29: *
30: * (easy) uses {chmin-chmax} instead of chmin:chmax notation for
31: * channels specification to match the notation used in rmix.
32: *
33: * (easy) use comma-separated parameters syntax, example:
34: * s24le/3msb,{3-6},48000 so we don't have to use three -e, -r, -c
35: * flags, but only one -p flag that specify one or more parameters.
36: *
37: * (hard) dont create mix (sub) if there's only one input (output)
38: *
39: * (hard) if all inputs are over, the mixer terminates and closes
40: * the write end of the device. It should continue writing zeros
41: * until the recording is over (or be able to stop write end of
42: * the device)
43: *
44: * (hard) implement -n flag (no device) to connect all inputs to
45: * the outputs.
46: *
47: * (hard) ignore input files that are not audible (because channels
48: * they provide are not used on the output). Similarly ignore
49: * outputs that are zero filled (because channels they consume are
50: * not provided).
51: *
52: * (easy) do we need -d flag ?
1.1 kstailey 53: */
54:
1.15 ratchov 55: #include <sys/param.h>
1.1 kstailey 56: #include <sys/types.h>
1.15 ratchov 57: #include <sys/queue.h>
1.13 uwe 58:
1.15 ratchov 59: #include <err.h>
1.1 kstailey 60: #include <fcntl.h>
1.15 ratchov 61: #include <signal.h>
1.1 kstailey 62: #include <stdio.h>
1.4 millert 63: #include <stdlib.h>
1.8 david 64: #include <string.h>
1.1 kstailey 65: #include <unistd.h>
1.15 ratchov 66: #include <varargs.h>
1.1 kstailey 67:
1.15 ratchov 68: #include "conf.h"
69: #include "aparams.h"
70: #include "aproc.h"
71: #include "abuf.h"
72: #include "file.h"
73: #include "dev.h"
1.11 jaredy 74:
1.13 uwe 75: /*
1.15 ratchov 76: * Format for file headers.
1.1 kstailey 77: */
1.15 ratchov 78: #define HDR_AUTO 0 /* guess by looking at the file name */
79: #define HDR_RAW 1 /* no headers, ie openbsd native ;-) */
80: #define HDR_WAV 2 /* microsoft riff wave */
1.7 deraadt 81:
1.15 ratchov 82: int debug_level = 0;
83: volatile int quit_flag = 0;
1.22 ratchov 84:
1.15 ratchov 85: /*
86: * List of allowed encodings and their names.
87: */
88: struct enc {
89: char *name;
90: struct aparams par;
91: } enc_list[] = {
92: /* name bps, bits, le, sign, msb, unused */
93: { "s8", { 1, 8, 1, 1, 1, 0, 0, 0 } },
94: { "u8", { 1, 8, 1, 0, 1, 0, 0, 0 } },
95: { "s16le", { 2, 16, 1, 1, 1, 0, 0, 0 } },
96: { "u16le", { 2, 16, 1, 0, 1, 0, 0, 0 } },
97: { "s16be", { 2, 16, 0, 1, 1, 0, 0, 0 } },
98: { "u16be", { 2, 16, 0, 0, 1, 0, 0, 0 } },
99: { "s24le", { 4, 24, 1, 1, 1, 0, 0, 0 } },
100: { "u24le", { 4, 24, 1, 0, 1, 0, 0, 0 } },
101: { "s24be", { 4, 24, 0, 1, 1, 0, 0, 0 } },
102: { "u24be", { 4, 24, 0, 0, 1, 0, 0, 0 } },
103: { "s32le", { 4, 32, 1, 1, 1, 0, 0, 0 } },
104: { "u32le", { 4, 32, 1, 0, 1, 0, 0, 0 } },
105: { "s32be", { 4, 32, 0, 1, 1, 0, 0, 0 } },
106: { "u32be", { 4, 32, 0, 0, 1, 0, 0, 0 } },
107: { "s24le3", { 3, 24, 1, 1, 1, 0, 0, 0 } },
108: { "u24le3", { 3, 24, 1, 0, 1, 0, 0, 0 } },
109: { "s24be3", { 3, 24, 0, 1, 1, 0, 0, 0 } },
110: { "u24be3", { 3, 24, 0, 0, 1, 0, 0, 0 } },
111: { "s20le3", { 3, 20, 1, 1, 1, 0, 0, 0 } },
112: { "u20le3", { 3, 20, 1, 0, 1, 0, 0, 0 } },
113: { "s20be3", { 3, 20, 0, 1, 1, 0, 0, 0 } },
114: { "u20be3", { 3, 20, 0, 0, 1, 0, 0, 0 } },
115: { "s18le3", { 3, 18, 1, 1, 1, 0, 0, 0 } },
116: { "u18le3", { 3, 18, 1, 0, 1, 0, 0, 0 } },
117: { "s18be3", { 3, 18, 0, 1, 1, 0, 0, 0 } },
118: { "u18be3", { 3, 18, 0, 0, 1, 0, 0, 0 } },
119: { NULL, { 0, 0, 0, 0, 0, 0, 0, 0 } }
120: };
1.13 uwe 121:
1.11 jaredy 122: /*
1.15 ratchov 123: * Search an encoding in the above table. On success fill encoding
124: * part of "par" and return 1, otherwise return 0.
1.1 kstailey 125: */
1.15 ratchov 126: unsigned
127: enc_lookup(char *name, struct aparams *par)
128: {
129: struct enc *e;
130:
131: for (e = enc_list; e->name != NULL; e++) {
132: if (strcmp(e->name, name) == 0) {
133: par->bps = e->par.bps;
134: par->bits = e->par.bits;
135: par->sig = e->par.sig;
136: par->le = e->par.le;
137: par->msb = e->par.msb;
138: return 1;
139: }
140: }
141: return 0;
142: }
143:
144: void
145: usage(void)
1.1 kstailey 146: {
1.15 ratchov 147: extern char *__progname;
1.4 millert 148:
1.15 ratchov 149: fprintf(stderr,
1.18 jmc 150: "usage: %s [-qu] [-C min:max] [-c min:max] [-d level] "
1.16 jmc 151: "[-E enc] [-e enc]\n"
152: "\t[-f device] [-H fmt] [-h fmt] [-i file] [-o file] [-R rate]\n"
1.25 ! ratchov 153: "\t[-r rate] [-X policy] [-x policy]\n",
1.15 ratchov 154: __progname);
155: }
156:
157: void
158: opt_ch(struct aparams *par)
159: {
160: if (sscanf(optarg, "%u:%u", &par->cmin, &par->cmax) != 2 ||
161: par->cmin > CHAN_MAX || par->cmax > CHAN_MAX ||
162: par->cmin > par->cmax)
163: err(1, "%s: bad channel range", optarg);
164: }
1.13 uwe 165:
1.15 ratchov 166: void
167: opt_rate(struct aparams *par)
168: {
169: if (sscanf(optarg, "%u", &par->rate) != 1 ||
170: par->rate < RATE_MIN || par->rate > RATE_MAX)
171: err(1, "%s: bad sample rate", optarg);
172: }
1.13 uwe 173:
1.15 ratchov 174: void
175: opt_enc(struct aparams *par)
176: {
177: if (!enc_lookup(optarg, par))
178: err(1, "%s: bad encoding", optarg);
179: }
1.4 millert 180:
1.15 ratchov 181: int
182: opt_hdr(void)
183: {
184: if (strcmp("auto", optarg) == 0)
185: return HDR_AUTO;
186: if (strcmp("raw", optarg) == 0)
187: return HDR_RAW;
188: if (strcmp("wav", optarg) == 0)
189: return HDR_WAV;
190: err(1, "%s: bad header specification", optarg);
1.1 kstailey 191: }
192:
1.22 ratchov 193: int
194: opt_xrun(void)
195: {
196: if (strcmp("ignore", optarg) == 0)
197: return XRUN_IGNORE;
198: if (strcmp("sync", optarg) == 0)
199: return XRUN_SYNC;
200: if (strcmp("error", optarg) == 0)
201: return XRUN_ERROR;
202: errx(1, "%s: onderrun/overrun policy", optarg);
203: }
204:
1.13 uwe 205: /*
1.15 ratchov 206: * Arguments of -i and -o opations are stored in a list.
1.13 uwe 207: */
1.15 ratchov 208: struct farg {
209: SLIST_ENTRY(farg) entry;
210: struct aparams par; /* last requested format */
211: unsigned vol; /* last requested volume */
212: char *name; /* optarg pointer (no need to copy it */
213: int hdr; /* header format */
1.22 ratchov 214: int xrun; /* overrun/underrun policy */
1.15 ratchov 215: int fd; /* file descriptor for I/O */
216: struct aproc *proc; /* rpipe_xxx our wpipe_xxx */
217: struct abuf *buf;
218: };
1.13 uwe 219:
1.15 ratchov 220: SLIST_HEAD(farglist, farg);
1.13 uwe 221:
1.15 ratchov 222: /*
223: * Add a farg entry to the given list, corresponding
224: * to the given file name.
225: */
226: void
227: opt_file(struct farglist *list,
1.22 ratchov 228: struct aparams *par, unsigned vol, int hdr, int xrun, char *optarg)
1.15 ratchov 229: {
230: struct farg *fa;
231: size_t namelen;
232:
233: fa = malloc(sizeof(struct farg));
234: if (fa == NULL)
235: err(1, "%s", optarg);
236:
237: if (hdr == HDR_AUTO) {
238: namelen = strlen(optarg);
239: if (namelen >= 4 &&
240: strcasecmp(optarg + namelen - 4, ".wav") == 0) {
241: fa->hdr = HDR_WAV;
242: DPRINTF("%s: assuming wav file format\n", optarg);
243: } else {
244: fa->hdr = HDR_RAW;
245: DPRINTF("%s: assuming headerless file\n", optarg);
1.13 uwe 246: }
1.15 ratchov 247: } else
248: fa->hdr = hdr;
1.22 ratchov 249: fa->xrun = xrun;
1.15 ratchov 250: fa->par = *par;
251: fa->vol = vol;
252: fa->name = optarg;
253: fa->proc = NULL;
254: SLIST_INSERT_HEAD(list, fa, entry);
255: }
1.13 uwe 256:
1.15 ratchov 257: /*
258: * Open an input file and setup converter if necessary.
259: */
260: void
1.17 jakemsr 261: newinput(struct farg *fa, struct aparams *npar, unsigned nfr, int quiet_flag)
1.15 ratchov 262: {
263: int fd;
264: struct file *f;
265: struct aproc *p, *c;
266: struct abuf *buf, *nbuf;
267:
268: if (strcmp(fa->name, "-") == 0) {
269: fd = STDIN_FILENO;
270: if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
271: warn("stdin");
272: fa->name = "stdin";
273: } else {
274: fd = open(fa->name, O_RDONLY | O_NONBLOCK, 0666);
275: if (fd < 0)
276: err(1, "%s", fa->name);
1.13 uwe 277: }
1.15 ratchov 278: f = file_new(fd, fa->name);
279: if (fa->hdr == HDR_WAV) {
280: if (!wav_readhdr(fd, &fa->par, &f->rbytes))
281: exit(1);
1.13 uwe 282: }
1.15 ratchov 283: buf = abuf_new(nfr, aparams_bpf(&fa->par));
284: p = rpipe_new(f);
285: aproc_setout(p, buf);
286: if (!aparams_eq(&fa->par, npar)) {
1.17 jakemsr 287: if (!quiet_flag) {
288: fprintf(stderr, "%s: ", fa->name);
289: aparams_print2(&fa->par, npar);
290: fprintf(stderr, "\n");
291: }
1.15 ratchov 292: nbuf = abuf_new(nfr, aparams_bpf(npar));
293: c = conv_new(fa->name, &fa->par, npar);
294: aproc_setin(c, buf);
295: aproc_setout(c, nbuf);
296: fa->buf = nbuf;
297: } else
298: fa->buf = buf;
299: fa->proc = p;
300: fa->fd = fd;
301: }
1.13 uwe 302:
1.15 ratchov 303: /*
304: * Open an output file and setup converter if necessary.
305: */
306: void
1.17 jakemsr 307: newoutput(struct farg *fa, struct aparams *npar, unsigned nfr, int quiet_flag)
1.15 ratchov 308: {
309: int fd;
310: struct file *f;
311: struct aproc *p, *c;
312: struct abuf *buf, *nbuf;
313:
314: if (strcmp(fa->name, "-") == 0) {
315: fd = STDOUT_FILENO;
316: if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
317: warn("stdout");
318: fa->name = "stdout";
319: } else {
320: fd = open(fa->name,
321: O_WRONLY | O_TRUNC | O_CREAT | O_NONBLOCK, 0666);
322: if (fd < 0)
323: err(1, "%s", fa->name);
324: }
325: f = file_new(fd, fa->name);
326: if (fa->hdr == HDR_WAV) {
327: f->wbytes = WAV_DATAMAX;
328: if (!wav_writehdr(fd, &fa->par))
329: exit(1);
1.13 uwe 330: }
1.15 ratchov 331: buf = abuf_new(nfr, aparams_bpf(&fa->par));
332: p = wpipe_new(f);
333: aproc_setin(p, buf);
334: if (!aparams_eq(&fa->par, npar)) {
1.17 jakemsr 335: if (!quiet_flag) {
336: fprintf(stderr, "%s: ", fa->name);
337: aparams_print2(npar, &fa->par);
338: fprintf(stderr, "\n");
339: }
1.15 ratchov 340: c = conv_new(fa->name, npar, &fa->par);
341: nbuf = abuf_new(nfr, aparams_bpf(npar));
342: aproc_setin(c, nbuf);
343: aproc_setout(c, buf);
344: fa->buf = nbuf;
345: } else
346: fa->buf = buf;
347: fa->proc = p;
348: fa->fd = fd;
349: }
1.13 uwe 350:
1.15 ratchov 351: void
352: sighdl(int s)
353: {
354: if (quit_flag)
355: _exit(1);
356: quit_flag = 1;
1.13 uwe 357: }
358:
1.1 kstailey 359: int
1.15 ratchov 360: main(int argc, char **argv)
1.1 kstailey 361: {
1.23 ratchov 362: sigset_t sigset;
1.15 ratchov 363: struct sigaction sa;
1.22 ratchov 364: int c, u_flag, quiet_flag, ohdr, ihdr, ixrun, oxrun;
1.15 ratchov 365: struct farg *fa;
366: struct farglist ifiles, ofiles;
367: struct aparams ipar, opar, dipar, dopar, cipar, copar;
368: unsigned ivol, ovol;
369: unsigned dinfr, donfr, cinfr, confr;
1.19 ratchov 370: char *devpath, *dbgenv;
1.15 ratchov 371: unsigned n;
372: struct aproc *rec, *play, *mix, *sub, *conv;
373: struct file *dev, *f;
374: struct abuf *buf, *cbuf;
1.21 ratchov 375: const char *errstr;
1.15 ratchov 376: int fd;
377:
1.19 ratchov 378: dbgenv = getenv("AUCAT_DEBUG");
379: if (dbgenv) {
1.21 ratchov 380: debug_level = strtonum(dbgenv, 0, 4, &errstr);
381: if (errstr)
382: errx(1, "AUCAT_DEBUG is %s: %s", errstr, dbgenv);
1.19 ratchov 383: }
384:
1.15 ratchov 385: aparams_init(&ipar, 0, 1, 44100);
386: aparams_init(&opar, 0, 1, 44100);
387:
1.17 jakemsr 388: u_flag = quiet_flag = 0;
1.15 ratchov 389: devpath = NULL;
390: SLIST_INIT(&ifiles);
391: SLIST_INIT(&ofiles);
392: ihdr = ohdr = HDR_AUTO;
1.22 ratchov 393: ixrun = oxrun = XRUN_IGNORE;
1.15 ratchov 394: ivol = ovol = MIDI_TO_ADATA(127);
395:
1.22 ratchov 396: while ((c = getopt(argc, argv, "c:C:e:E:r:R:h:H:x:X:i:o:f:qu"))
397: != -1) {
1.15 ratchov 398: switch (c) {
399: case 'h':
400: ihdr = opt_hdr();
401: break;
402: case 'H':
403: ohdr = opt_hdr();
404: break;
1.22 ratchov 405: case 'x':
406: ixrun = opt_xrun();
407: break;
408: case 'X':
409: oxrun = opt_xrun();
410: break;
1.15 ratchov 411: case 'c':
412: opt_ch(&ipar);
413: break;
414: case 'C':
415: opt_ch(&opar);
416: break;
417: case 'e':
418: opt_enc(&ipar);
419: break;
420: case 'E':
421: opt_enc(&opar);
422: break;
423: case 'r':
424: opt_rate(&ipar);
425: break;
426: case 'R':
427: opt_rate(&opar);
428: break;
429: case 'i':
1.22 ratchov 430: opt_file(&ifiles, &ipar, 127, ihdr, ixrun, optarg);
1.15 ratchov 431: break;
432: case 'o':
1.22 ratchov 433: opt_file(&ofiles, &opar, 127, ohdr, oxrun, optarg);
1.15 ratchov 434: break;
1.4 millert 435: case 'f':
1.15 ratchov 436: if (devpath)
437: err(1, "only one -f allowed");
438: devpath = optarg;
439: dipar = ipar;
440: dopar = opar;
441: break;
1.17 jakemsr 442: case 'q':
443: quiet_flag = 1;
444: break;
1.15 ratchov 445: case 'u':
446: u_flag = 1;
1.4 millert 447: break;
1.11 jaredy 448: default:
449: usage();
1.15 ratchov 450: exit(1);
1.4 millert 451: }
452: }
453: argc -= optind;
454: argv += optind;
455:
1.15 ratchov 456: if (!devpath) {
457: devpath = getenv("AUDIODEVICE");
458: if (devpath == NULL)
459: devpath = DEFAULT_DEVICE;
460: dipar = ipar;
461: dopar = opar;
462: }
463:
464: if (SLIST_EMPTY(&ifiles) && SLIST_EMPTY(&ofiles) && argc > 0) {
465: /*
466: * Legacy mode: if no -i or -o options are provided, and
467: * there are arguments then assume the arguments are files
468: * to play.
469: */
470: for (c = 0; c < argc; c++)
471: if (legacy_play(devpath, argv[c]) != 0) {
1.17 jakemsr 472: errx(1, "%s: could not play\n", argv[c]);
1.15 ratchov 473: }
474: exit(0);
475: } else if (argc > 0) {
1.11 jaredy 476: usage();
1.15 ratchov 477: exit(1);
478: }
479:
480: sigfillset(&sa.sa_mask);
481: sa.sa_flags = SA_RESTART;
482: sa.sa_handler = sighdl;
483: if (sigaction(SIGINT, &sa, NULL) < 0)
484: err(1, "sigaction");
1.23 ratchov 485:
486: sigemptyset(&sigset);
487: (void)sigaddset(&sigset, SIGTSTP);
488: (void)sigaddset(&sigset, SIGCONT);
489: if (sigprocmask(SIG_BLOCK, &sigset, NULL))
490: err(1, "sigprocmask");
1.15 ratchov 491:
492: file_start();
493: play = rec = mix = sub = NULL;
494:
495: aparams_init(&cipar, CHAN_MAX, 0, RATE_MIN);
496: aparams_init(&copar, CHAN_MAX, 0, RATE_MAX);
497:
498: /*
499: * Iterate over all inputs and outputs and find the maximum
500: * sample rate and channel number.
501: */
502: SLIST_FOREACH(fa, &ifiles, entry) {
503: if (cipar.cmin > fa->par.cmin)
504: cipar.cmin = fa->par.cmin;
505: if (cipar.cmax < fa->par.cmax)
506: cipar.cmax = fa->par.cmax;
507: if (cipar.rate < fa->par.rate)
508: cipar.rate = fa->par.rate;
509: }
510: SLIST_FOREACH(fa, &ofiles, entry) {
511: if (copar.cmin > fa->par.cmin)
512: copar.cmin = fa->par.cmin;
513: if (copar.cmax < fa->par.cmax)
514: copar.cmax = fa->par.cmax;
515: if (copar.rate > fa->par.rate)
516: copar.rate = fa->par.rate;
517: }
518:
519: /*
520: * Open the device and increase the maximum sample rate.
521: * channel number to include those used by the device
522: */
523: if (!u_flag) {
524: dipar = copar;
525: dopar = cipar;
526: }
527: fd = dev_init(devpath,
528: !SLIST_EMPTY(&ofiles) ? &dipar : NULL,
529: !SLIST_EMPTY(&ifiles) ? &dopar : NULL, &dinfr, &donfr);
530: if (fd < 0)
531: exit(1);
532: if (!SLIST_EMPTY(&ofiles)) {
1.17 jakemsr 533: if (!quiet_flag) {
534: fprintf(stderr, "%s: recording ", devpath);
535: aparams_print(&dipar);
536: fprintf(stderr, "\n");
537: }
1.15 ratchov 538: if (copar.cmin > dipar.cmin)
539: copar.cmin = dipar.cmin;
540: if (copar.cmax < dipar.cmax)
541: copar.cmax = dipar.cmax;
542: if (copar.rate > dipar.rate)
543: copar.rate = dipar.rate;
544: dinfr *= DEFAULT_NBLK;
545: DPRINTF("%s: using %ums rec buffer\n", devpath,
546: 1000 * dinfr / dipar.rate);
547: }
548: if (!SLIST_EMPTY(&ifiles)) {
1.17 jakemsr 549: if (!quiet_flag) {
550: fprintf(stderr, "%s: playing ", devpath);
551: aparams_print(&dopar);
552: fprintf(stderr, "\n");
553: }
1.15 ratchov 554: if (cipar.cmin > dopar.cmin)
555: cipar.cmin = dopar.cmin;
556: if (cipar.cmax < dopar.cmax)
557: cipar.cmax = dopar.cmax;
558: if (cipar.rate < dopar.rate)
559: cipar.rate = dopar.rate;
560: donfr *= DEFAULT_NBLK;
561: DPRINTF("%s: using %ums play buffer\n", devpath,
562: 1000 * donfr / dopar.rate);
563: }
564:
565: /*
566: * Create buffers for the device.
567: */
568: dev = file_new(fd, devpath);
569: if (!SLIST_EMPTY(&ofiles)) {
570: rec = rpipe_new(dev);
571: sub = sub_new();
572: }
573: if (!SLIST_EMPTY(&ifiles)) {
574: play = wpipe_new(dev);
575: mix = mix_new();
576: }
577:
578: /*
579: * Calculate sizes of buffers using "common" parameters, to
580: * have roughly the same duration as device buffers.
581: */
582: cinfr = donfr * cipar.rate / dopar.rate;
583: confr = dinfr * copar.rate / dipar.rate;
584:
585: /*
586: * Create buffers for all input and output pipes.
587: */
588: SLIST_FOREACH(fa, &ifiles, entry) {
1.17 jakemsr 589: newinput(fa, &cipar, cinfr, quiet_flag);
1.22 ratchov 590: if (mix) {
1.15 ratchov 591: aproc_setin(mix, fa->buf);
1.22 ratchov 592: fa->buf->xrun = fa->xrun;
593: }
1.17 jakemsr 594: if (!quiet_flag) {
595: fprintf(stderr, "%s: reading ", fa->name);
596: aparams_print(&fa->par);
597: fprintf(stderr, "\n");
598: }
1.15 ratchov 599: }
600: SLIST_FOREACH(fa, &ofiles, entry) {
1.17 jakemsr 601: newoutput(fa, &copar, confr, quiet_flag);
1.22 ratchov 602: if (sub) {
1.15 ratchov 603: aproc_setout(sub, fa->buf);
1.22 ratchov 604: fa->buf->xrun = fa->xrun;
605: }
1.17 jakemsr 606: if (!quiet_flag) {
607: fprintf(stderr, "%s: writing ", fa->name);
608: aparams_print(&fa->par);
609: fprintf(stderr, "\n");
610: }
1.15 ratchov 611: }
1.13 uwe 612:
1.15 ratchov 613: /*
614: * Connect the multiplexer to the device input.
615: */
616: if (sub) {
617: buf = abuf_new(dinfr, aparams_bpf(&dipar));
618: aproc_setout(rec, buf);
619: if (!aparams_eq(&copar, &dipar)) {
1.17 jakemsr 620: if (!quiet_flag) {
621: fprintf(stderr, "%s: ", devpath);
622: aparams_print2(&dipar, &copar);
623: fprintf(stderr, "\n");
624: }
1.15 ratchov 625: conv = conv_new("subconv", &dipar, &copar);
626: cbuf = abuf_new(confr, aparams_bpf(&copar));
627: aproc_setin(conv, buf);
628: aproc_setout(conv, cbuf);
629: aproc_setin(sub, cbuf);
630: } else
631: aproc_setin(sub, buf);
632: }
1.13 uwe 633:
1.15 ratchov 634: /*
635: * Normalize input levels and connect the mixer to the device
636: * output.
637: */
638: if (mix) {
639: n = 0;
640: SLIST_FOREACH(fa, &ifiles, entry)
641: n++;
642: SLIST_FOREACH(fa, &ifiles, entry)
643: fa->buf->mixvol /= n;
644: buf = abuf_new(donfr, aparams_bpf(&dopar));
645: aproc_setin(play, buf);
646: if (!aparams_eq(&cipar, &dopar)) {
1.17 jakemsr 647: if (!quiet_flag) {
648: fprintf(stderr, "%s: ", devpath);
649: aparams_print2(&cipar, &dopar);
650: fprintf(stderr, "\n");
651: }
1.15 ratchov 652: conv = conv_new("mixconv", &cipar, &dopar);
653: cbuf = abuf_new(cinfr, aparams_bpf(&cipar));
654: aproc_setout(conv, buf);
655: aproc_setin(conv, cbuf);
656: aproc_setout(mix, cbuf);
657: } else
658: aproc_setout(mix, buf);
659: }
1.13 uwe 660:
1.15 ratchov 661: /*
662: * start audio
663: */
664: if (play != NULL) {
1.17 jakemsr 665: if (!quiet_flag)
666: fprintf(stderr, "filling buffers...\n");
1.24 ratchov 667: buf = LIST_FIRST(&play->ibuflist);
1.15 ratchov 668: while (!quit_flag) {
669: /* no more devices to poll */
670: if (!file_poll())
671: break;
672: /* eof */
673: if (dev->state & FILE_EOF)
1.24 ratchov 674: break;
675: /* device is blocked and play buffer is full */
676: if ((dev->events & POLLOUT) && !ABUF_WOK(buf))
1.15 ratchov 677: break;
1.4 millert 678: }
679: }
1.17 jakemsr 680: if (!quiet_flag)
681: fprintf(stderr, "starting device...\n");
1.15 ratchov 682: dev_start(dev->fd);
1.22 ratchov 683: if (mix)
684: mix->u.mix.flags |= MIX_DROP;
685: if (sub)
686: sub->u.sub.flags |= SUB_DROP;
1.15 ratchov 687: while (!quit_flag) {
688: if (!file_poll())
689: break;
690: }
1.11 jaredy 691:
1.17 jakemsr 692: if (!quiet_flag)
693: fprintf(stderr, "draining buffers...\n");
1.11 jaredy 694:
1.15 ratchov 695: /*
696: * generate EOF on all files that do input, so
697: * once buffers are drained, everything will be cleaned
698: */
699: LIST_FOREACH(f, &file_list, entry) {
700: if ((f->events) & POLLIN || (f->state & FILE_ROK))
701: file_eof(f);
702: }
703: for (;;) {
704: if (!file_poll())
705: break;
706: }
707: SLIST_FOREACH(fa, &ofiles, entry) {
708: if (fa->hdr == HDR_WAV)
709: wav_writehdr(fa->fd, &fa->par);
710: close(fa->fd);
711: DPRINTF("%s: closed\n", fa->name);
712: }
713: dev_stop(dev->fd);
714: file_stop();
715: return 0;
1.1 kstailey 716: }