From 110322a67c5c9ec93b508d90b6fedc349bf0742c Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Sun, 16 Nov 2008 20:44:04 +0000 Subject: allow aucat to listen on multiple sockets. Each socket carries its channel and volume settings allowing multiple configuration to coexist. Mostly useful for envy(4)-like devices, but can be used to force different apps to use different settings. --- usr.bin/aucat/aucat.1 | 63 ++++++++++++++++++++++-------- usr.bin/aucat/aucat.c | 101 +++++++++++++++++++++++++++++-------------------- usr.bin/aucat/listen.c | 13 ++++++- usr.bin/aucat/sock.c | 12 +++--- 4 files changed, 124 insertions(+), 65 deletions(-) (limited to 'usr.bin') diff --git a/usr.bin/aucat/aucat.1 b/usr.bin/aucat/aucat.1 index 65738b5fb4b..cdf54c75eb1 100644 --- a/usr.bin/aucat/aucat.1 +++ b/usr.bin/aucat/aucat.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: aucat.1,v 1.34 2008/11/16 18:34:04 jmc Exp $ +.\" $OpenBSD: aucat.1,v 1.35 2008/11/16 20:44:03 ratchov Exp $ .\" .\" Copyright (c) 2006 Alexandre Ratchov .\" @@ -33,6 +33,7 @@ .Op Fl i Ar file .Op Fl o Ar file .Op Fl r Ar rate +.Op Fl s Ar file .Op Fl v Ar volume .Op Fl x Ar policy .Ek @@ -78,7 +79,7 @@ If the option argument is .Sq - then standard input will be used. .It Fl l -Listen for incoming connections on a Unix domain socket. +Listen for incoming connections on Unix domain sockets. A client might use .Nm instead of the regular @@ -87,9 +88,9 @@ device for audio input and output in order to share the physical device with other clients. The default socket path is .Pa /tmp/aucat.sock -but it can be changed with the -.Ev AUCAT_SOCKET -environment variable. +but other paths can be used with the +.Fl s +option. .It Fl o Ar file Add this file to the list of files in which to store recorded samples. If the option argument is @@ -98,6 +99,11 @@ then standard output will be used. .It Fl r Ar rate Sample rate in Hertz of the playback or record stream. The default is 44100Hz. +.It Fl s Ar file +Add this path to the list of sockets to listen on. +Meaningful in server mode only (i.e. when the +.Fl l +option is used). .It Fl u Normally .Nm @@ -148,19 +154,22 @@ or .Dv SIGUSR2 , it increases or decreases debug level, respectively. .Pp -Settings for input -.Pq Fl i -and output +Settings for input files +.Pq Fl i , +output files .Pq Fl o -files can be changed using the -.Fl Ccehrx +and sockets +.Pq Fl s +can be changed using the +.Fl Ccehrvx options. The last -.Fl Ccehrx +.Fl Ccehrvx options specified before an -.Fl i -or +.Fl i , .Fl o +and +.Fl s are applied to .Ar file . .Pp @@ -304,12 +313,10 @@ If the device does not support the encoding, .Nm will exit with an error. .Sh ENVIRONMENT -.Bl -tag -width "AUCAT_SOCKETXXX" -compact +.Bl -tag -width "AUDIODEVICE" -compact .It Ev AUCAT_DEBUG The debug level: may be a value between 0 and 4. -.It Ev AUCAT_SOCKET -Path to the Unix domain socket to use. .It Ev AUDIODEVICE The audio device to use. .El @@ -351,6 +358,30 @@ full-duplex: .Bd -literal -offset indent $ aucat -i drums.raw -i bass.raw -o guitar.raw .Ed +.Pp +The following will start +.Nm +in server mode with the default parameters. +.Bd -literal -offset indent +$ aucat -l +.Ed +.Pp +The following will start +.Nm +in server mode with the default parameters, but will create an +additional socket for output to channels 2:3 only (rear speakers +on most cards). +.Bd -literal -offset indent +$ aucat -l -s /tmp/aucat.sock -c 2:3 -s /tmp/aucat.sock.rear +.Ed +.Pp +The following will start +.Nm +in server mode creating the defaut socket with low volume and +an additional socket for high volume output. +.Bd -literal -offset indent +$ aucat -l -v 65 -s /tmp/aucat.sock -v 127 -s /tmp/aucat.sock.max +.Ed .Sh SEE ALSO .Xr audioctl 1 , .Xr cdio 1 , diff --git a/usr.bin/aucat/aucat.c b/usr.bin/aucat/aucat.c index d6cf1dcc0ff..ac09696e513 100644 --- a/usr.bin/aucat/aucat.c +++ b/usr.bin/aucat/aucat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aucat.c,v 1.41 2008/11/16 18:34:56 ratchov Exp $ */ +/* $OpenBSD: aucat.c,v 1.42 2008/11/16 20:44:03 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov * @@ -110,7 +110,7 @@ usage(void) fprintf(stderr, "usage: %s [-lu] [-b nsamples] [-C min:max] [-c min:max] [-e enc] " "[-f device]\n" - "\t[-h fmt] [-i file] [-o file] [-r rate] [-v volume] " + "\t[-h fmt] [-i file] [-o file] [-r rate] [-s path] [-v volume] " "[-x policy]\n", __progname); } @@ -174,11 +174,12 @@ opt_xrun(void) } /* - * Arguments of -i and -o opations are stored in a list. + * Arguments of -i, -o and -s options are stored in a list. */ struct farg { SLIST_ENTRY(farg) entry; - struct aparams par; /* last requested format */ + struct aparams ipar; /* input (read) parameters */ + struct aparams opar; /* output (write) parameters */ unsigned vol; /* last requested volume */ char *name; /* optarg pointer (no need to copy it */ int hdr; /* header format */ @@ -192,8 +193,9 @@ SLIST_HEAD(farglist, farg); * to the given file name. */ void -opt_file(struct farglist *list, - struct aparams *par, unsigned vol, int hdr, int xrun, char *optarg) +farg_add(struct farglist *list, + struct aparams *ipar, struct aparams *opar, unsigned vol, + int hdr, int xrun, char *optarg) { struct farg *fa; size_t namelen; @@ -215,7 +217,8 @@ opt_file(struct farglist *list, } else fa->hdr = hdr; fa->xrun = xrun; - fa->par = *par; + fa->ipar = *ipar; + fa->opar = *opar; fa->vol = vol; fa->name = optarg; SLIST_INSERT_HEAD(list, fa, entry); @@ -246,13 +249,13 @@ newinput(struct farg *fa) /* * XXX : we should round rate, right ? */ - f = wav_new_in(&wav_ops, fd, fa->name, &fa->par, fa->hdr); - nfr = dev_bufsz * fa->par.rate / dev_rate; - buf = abuf_new(nfr, &fa->par); + f = wav_new_in(&wav_ops, fd, fa->name, &fa->ipar, fa->hdr); + nfr = dev_bufsz * fa->ipar.rate / dev_rate; + buf = abuf_new(nfr, &fa->ipar); proc = rpipe_new((struct file *)f); aproc_setout(proc, buf); abuf_fill(buf); /* XXX: move this in dev_attach() ? */ - dev_attach(fa->name, buf, &fa->par, fa->xrun, + dev_attach(fa->name, buf, &fa->ipar, fa->xrun, NULL, NULL, 0, ADATA_UNIT); dev_setvol(buf, MIDI_TO_ADATA(fa->vol)); } @@ -283,12 +286,12 @@ newoutput(struct farg *fa) /* * XXX : we should round rate, right ? */ - f = wav_new_out(&wav_ops, fd, fa->name, &fa->par, fa->hdr); - nfr = dev_bufsz * fa->par.rate / dev_rate; + f = wav_new_out(&wav_ops, fd, fa->name, &fa->opar, fa->hdr); + nfr = dev_bufsz * fa->opar.rate / dev_rate; proc = wpipe_new((struct file *)f); - buf = abuf_new(nfr, &fa->par); + buf = abuf_new(nfr, &fa->opar); aproc_setin(proc, buf); - dev_attach(fa->name, NULL, NULL, 0, buf, &fa->par, fa->xrun, 0); + dev_attach(fa->name, NULL, NULL, 0, buf, &fa->opar, fa->xrun, 0); } int @@ -296,11 +299,11 @@ main(int argc, char **argv) { int c, u_flag, l_flag, hdr, xrun, suspend = 0; struct farg *fa; - struct farglist ifiles, ofiles; + struct farglist ifiles, ofiles, sfiles; struct aparams ipar, opar, dipar, dopar; struct sigaction sa; unsigned bufsz; - char *devpath, *dbgenv, *listenpath; + char *devpath, *dbgenv; const char *errstr; extern char *malloc_options; unsigned volctl; @@ -321,12 +324,13 @@ main(int argc, char **argv) devpath = NULL; SLIST_INIT(&ifiles); SLIST_INIT(&ofiles); + SLIST_INIT(&sfiles); hdr = HDR_AUTO; xrun = XRUN_IGNORE; volctl = MIDI_MAXCTL; bufsz = 44100 * 4 / 15; /* XXX: use milliseconds, not frames */ - while ((c = getopt(argc, argv, "b:c:C:e:r:h:x:v:i:o:f:lu")) != -1) { + while ((c = getopt(argc, argv, "b:c:C:e:r:h:x:v:i:o:f:lus:")) != -1) { switch (c) { case 'h': hdr = opt_hdr(); @@ -352,10 +356,16 @@ main(int argc, char **argv) opt_vol(&volctl); break; case 'i': - opt_file(&ifiles, &ipar, volctl, hdr, xrun, optarg); + farg_add(&ifiles, &ipar, &opar, volctl, + hdr, xrun, optarg); break; case 'o': - opt_file(&ofiles, &opar, 127, hdr, xrun, optarg); + farg_add(&ofiles, &ipar, &opar, volctl, + hdr, xrun, optarg); + break; + case 's': + farg_add(&sfiles, &ipar, &opar, volctl, + hdr, xrun, optarg); break; case 'f': if (devpath) @@ -407,7 +417,9 @@ main(int argc, char **argv) } if (l_flag && (!SLIST_EMPTY(&ofiles) || !SLIST_EMPTY(&ifiles))) - errx(1, "can't use -l with -o or -i"); + errx(1, "can't use -l and -s with -o or -i"); + if (!l_flag && !SLIST_EMPTY(&sfiles)) + errx(1, "can't use -s without -l"); if (!u_flag && !l_flag) { /* @@ -418,23 +430,31 @@ main(int argc, char **argv) aparams_init(&dipar, NCHAN_MAX - 1, 0, RATE_MAX); aparams_init(&dopar, NCHAN_MAX - 1, 0, RATE_MIN); SLIST_FOREACH(fa, &ifiles, entry) { - if (dopar.cmin > fa->par.cmin) - dopar.cmin = fa->par.cmin; - if (dopar.cmax < fa->par.cmax) - dopar.cmax = fa->par.cmax; - if (dopar.rate < fa->par.rate) - dopar.rate = fa->par.rate; + if (dopar.cmin > fa->ipar.cmin) + dopar.cmin = fa->ipar.cmin; + if (dopar.cmax < fa->ipar.cmax) + dopar.cmax = fa->ipar.cmax; + if (dopar.rate < fa->ipar.rate) + dopar.rate = fa->ipar.rate; } SLIST_FOREACH(fa, &ofiles, entry) { - if (dipar.cmin > fa->par.cmin) - dipar.cmin = fa->par.cmin; - if (dipar.cmax < fa->par.cmax) - dipar.cmax = fa->par.cmax; - if (dipar.rate > fa->par.rate) - dipar.rate = fa->par.rate; + if (dipar.cmin > fa->opar.cmin) + dipar.cmin = fa->opar.cmin; + if (dipar.cmax < fa->opar.cmax) + dipar.cmax = fa->opar.cmax; + if (dipar.rate > fa->opar.rate) + dipar.rate = fa->opar.rate; } } + /* + * if there are no sockets paths provided use the default + */ + if (l_flag && SLIST_EMPTY(&sfiles)) { + farg_add(&sfiles, &dopar, &dipar, + MIDI_MAXCTL, HDR_RAW, XRUN_IGNORE, DEFAULT_SOCKET); + } + quit_flag = 0; sigfillset(&sa.sa_mask); sa.sa_flags = SA_RESTART; @@ -460,14 +480,6 @@ main(int argc, char **argv) (l_flag || !SLIST_EMPTY(&ifiles)) ? &dopar : NULL, bufsz, l_flag); - if (l_flag) { - listenpath = getenv("AUCAT_SOCKET"); - if (!listenpath) - listenpath = DEFAULT_SOCKET; - (void)listen_new(&listen_ops, listenpath, - &dipar, &dopar, MIDI_TO_ADATA(volctl)); - } - /* * Create buffers for all input and output pipes. */ @@ -483,6 +495,13 @@ main(int argc, char **argv) newoutput(fa); free(fa); } + while (!SLIST_EMPTY(&sfiles)) { + fa = SLIST_FIRST(&sfiles); + SLIST_REMOVE_HEAD(&sfiles, entry); + (void)listen_new(&listen_ops, fa->name, + &fa->opar, &fa->ipar, MIDI_TO_ADATA(fa->vol)); + free(fa); + } /* * loop, start audio diff --git a/usr.bin/aucat/listen.c b/usr.bin/aucat/listen.c index ce76e5787b7..6676a26ee78 100644 --- a/usr.bin/aucat/listen.c +++ b/usr.bin/aucat/listen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: listen.c,v 1.4 2008/11/16 18:34:56 ratchov Exp $ */ +/* $OpenBSD: listen.c,v 1.5 2008/11/16 20:44:03 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov * @@ -87,6 +87,15 @@ listen_new(struct fileops *ops, char *path, f->wpar = *wpar; f->rpar = *rpar; f->maxweight = maxweight; +#ifdef DEBUG + if (debug_level > 0) { + fprintf(stderr, "listen_new: %s: wpar=", f->path); + aparams_print(&f->wpar); + fprintf(stderr, ", rpar="); + aparams_print(&f->rpar); + fprintf(stderr, ", vol=%u\n", f->maxweight); + } +#endif return f; } @@ -114,7 +123,7 @@ listen_revents(struct file *file, struct pollfd *pfd) int sock; if (pfd->revents & POLLIN) { - DPRINTF("listen_revents: accepting connection\n"); + DPRINTF("listen_revents: %s: accepting connection\n", f->path); caddrlen = sizeof(caddrlen); sock = accept(f->fd, &caddr, &caddrlen); if (sock < 0) { diff --git a/usr.bin/aucat/sock.c b/usr.bin/aucat/sock.c index c1a3a2094a9..26f345937b8 100644 --- a/usr.bin/aucat/sock.c +++ b/usr.bin/aucat/sock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sock.c,v 1.6 2008/11/16 18:34:56 ratchov Exp $ */ +/* $OpenBSD: sock.c,v 1.7 2008/11/16 20:44:03 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov * @@ -610,8 +610,8 @@ sock_setpar(struct sock *f) p->rchan = NCHAN_MAX; f->wpar.cmin = f->templ_wpar.cmin; f->wpar.cmax = f->templ_wpar.cmin + p->rchan - 1; - if (f->wpar.cmax > NCHAN_MAX - 1) - f->wpar.cmax = NCHAN_MAX - 1; + if (f->wpar.cmax > f->templ_wpar.cmax) + f->wpar.cmax = f->templ_wpar.cmax; DPRINTF("sock_setpar: rchan -> %u:%u\n", f->wpar.cmin, f->wpar.cmax); } @@ -621,9 +621,9 @@ sock_setpar(struct sock *f) if (p->pchan > NCHAN_MAX) p->pchan = NCHAN_MAX; f->rpar.cmin = f->templ_rpar.cmin; - f->rpar.cmax = f->templ_wpar.cmin + p->pchan - 1; - if (f->rpar.cmax > NCHAN_MAX - 1) - f->rpar.cmax = NCHAN_MAX - 1; + f->rpar.cmax = f->templ_rpar.cmin + p->pchan - 1; + if (f->rpar.cmax > f->templ_rpar.cmax) + f->rpar.cmax = f->templ_rpar.cmax; DPRINTF("sock_setpar: pchan -> %u:%u\n", f->rpar.cmin, f->rpar.cmax); } -- cgit v1.2.3