summaryrefslogtreecommitdiff
path: root/usr.bin/aucat
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2011-11-15 08:05:23 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2011-11-15 08:05:23 +0000
commit1d03551d3bdde57b6b26304c15d01e24fa830fd2 (patch)
treef427bbcfc086b18d7aae9e6201af95c20d4779ac /usr.bin/aucat
parent231448b73ea84fb6b44a1e2fad2383a7ae09872d (diff)
Add a "device number" component in sndio(7) device names, allowing a
single aucat instance to handle all audio and MIDI services. Since this partially breaks compatibility, this is a opportunitiy to fix few other design mistakes (eg ':' being used by inet6, type name vs api name confusion, etc..). This leads to the following names: type[@hostname][,unit]/devnum[.option] The device number is the minor device number for direct hardware access (ie the 'N' in /dev/audioN). For aucat, this is the occurence number of the -f (or -M) option. There's a compatibility hook to keep old names working if only one aucat server is running.
Diffstat (limited to 'usr.bin/aucat')
-rw-r--r--usr.bin/aucat/aucat.132
-rw-r--r--usr.bin/aucat/aucat.c39
-rw-r--r--usr.bin/aucat/dev.c68
-rw-r--r--usr.bin/aucat/dev.h5
-rw-r--r--usr.bin/aucat/opt.c39
-rw-r--r--usr.bin/aucat/opt.h4
-rw-r--r--usr.bin/aucat/sock.c14
7 files changed, 113 insertions, 88 deletions
diff --git a/usr.bin/aucat/aucat.1 b/usr.bin/aucat/aucat.1
index f6f85e9da41..7de491f11a1 100644
--- a/usr.bin/aucat/aucat.1
+++ b/usr.bin/aucat/aucat.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: aucat.1,v 1.91 2011/10/24 21:46:21 ratchov Exp $
+.\" $OpenBSD: aucat.1,v 1.92 2011/11/15 08:05:22 ratchov Exp $
.\"
.\" Copyright (c) 2006 Alexandre Ratchov <alex@caoua.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: October 24 2011 $
+.Dd $Mdocdate: November 15 2011 $
.Dt AUCAT 1
.Os
.Sh NAME
@@ -383,8 +383,8 @@ of both definitions are created.
The default
.Xr sndio 7
device is
-.Pa aucat:0
-.Pq also known as Pa aucat:0.default
+.Pa snd/0
+.Pq also known as Pa snd/0.default
.Pp
If
.Nm
@@ -572,29 +572,29 @@ are recommended:
.Pp
For instance, the following command will create two devices:
the default
-.Va aucat:0
+.Va snd/0
and a MIDI-controlled
-.Va aucat:0.mmc :
+.Va snd/0.mmc :
.Bd -literal -offset indent
$ aucat -l -r 48000 -z 400 -s default -t slave -s mmc
.Ed
.Pp
Streams connected to
-.Va aucat:0
+.Va snd/0
behave normally, while streams connected to
-.Va aucat:0.mmc
+.Va snd/0.mmc
wait for the MMC start signal and start synchronously.
Regardless of which device a stream is connected to,
its playback volume knob is exposed.
.Pp
For instance, the following command will play a file on the
-.Va aucat:0.mmc
+.Va snd/0.mmc
audio device, and give full control to MIDI software or hardware
connected to the
-.Va aucat:0.thru
+.Va snd/0.thru
MIDI port:
.Bd -literal -offset indent
-$ aucat -f aucat:0.mmc -t slave -q aucat:0.thru -i file.wav
+$ aucat -f snd/0.mmc -t slave -q midithru/0 -i file.wav
.Ed
.Pp
At this stage,
@@ -602,7 +602,7 @@ At this stage,
will start, stop and relocate automatically following all user
actions in the MIDI sequencer.
Note that the sequencer must use
-.Va aucat:0
+.Va snd/0
as the MTC source, i.e. the audio server, not the audio player.
.Sh ENVIRONMENT
.Bl -tag -width "AUCAT_COOKIE" -compact
@@ -639,9 +639,9 @@ Start
in server mode using default parameters, creating an
additional sub-device for output to channels 2:3 only (rear speakers
on most cards), exposing the
-.Pa aucat:0
+.Pa snd/0
and
-.Pa aucat:0.rear
+.Pa snd/0.rear
devices:
.Bd -literal -offset indent
$ aucat -l -s default -c 2:3 -s rear
@@ -651,9 +651,9 @@ Start
.Nm
in server mode, creating the default sub-device with low volume and
an additional sub-device for high volume output, exposing the
-.Pa aucat:0
+.Pa snd/0
and
-.Pa aucat:0.max
+.Pa snd/0.max
devices:
.Bd -literal -offset indent
$ aucat -l -v 65 -s default -v 127 -s max
diff --git a/usr.bin/aucat/aucat.c b/usr.bin/aucat/aucat.c
index 4031b37d1b3..ce80ccad1b5 100644
--- a/usr.bin/aucat/aucat.c
+++ b/usr.bin/aucat/aucat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aucat.c,v 1.124 2011/10/18 21:04:26 ratchov Exp $ */
+/* $OpenBSD: aucat.c,v 1.125 2011/11/15 08:05:22 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -71,6 +71,13 @@
#define DEFAULT_ROUND (44100 / 15)
#endif
+/*
+ * default device in server mode
+ */
+#ifndef DEFAULT_DEV
+#define DEFAULT_DEV "rsnd/0"
+#endif
+
#ifdef DEBUG
volatile sig_atomic_t debug_level = 1;
#endif
@@ -337,7 +344,10 @@ mkdev(char *path, int mode, int bufsz, int round, int hold, int autovol)
bufsz = round * 4;
} else if (!round)
round = bufsz / 4;
- return dev_new(path, mode, bufsz, round, hold, autovol);
+ d = dev_new(path, mode, bufsz, round, hold, autovol);
+ if (d == NULL)
+ exit(1);
+ return d;
}
struct opt *
@@ -537,20 +547,25 @@ main(int argc, char **argv)
fputs(usagestr, stderr);
exit(1);
}
- if (wav_list == NULL) {
- if (opt_list == NULL) {
- d = mkdev(NULL, 0, bufsz, round, 1, autovol);
- mkopt("default", d, &rpar, &ppar,
- mode, vol, mmc, join);
- server = 1;
- }
- } else {
- d = mkdev(NULL, 0, bufsz, round, 1, autovol);
- if ((d->reqmode & MODE_THRU) && !d->ctl_list) {
+ if (wav_list) {
+ if (server)
+ errx(1, "-io not allowed in server mode");
+ if ((d = dev_list) && d->next)
+ errx(1, "only one device allowed in non-server mode");
+ if ((d->reqmode & MODE_THRU) && d->ctl_list == NULL) {
if (!devctl_add(d, "default", MODE_MIDIMASK))
errx(1, "%s: can't open port", optarg);
d->reqmode |= MODE_MIDIMASK;
}
+ } else {
+ if (dev_list == NULL)
+ mkdev(DEFAULT_DEV, 0, bufsz, round, hold, autovol);
+ for (d = dev_list; d != NULL; d = d->next) {
+ if (opt_byname("default", d->num))
+ continue;
+ mkopt("default", d, &rpar, &ppar, mode, vol, mmc, join);
+ server = 1;
+ }
}
if (server) {
getbasepath(base, sizeof(base));
diff --git a/usr.bin/aucat/dev.c b/usr.bin/aucat/dev.c
index 449898b1078..90e0a6bd31b 100644
--- a/usr.bin/aucat/dev.c
+++ b/usr.bin/aucat/dev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.c,v 1.67 2011/10/12 07:20:04 ratchov Exp $ */
+/* $OpenBSD: dev.c,v 1.68 2011/11/15 08:05:22 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -62,27 +62,6 @@
* finished draining), then the device
* automatically switches to INIT or CLOSED
*/
-/*
- * TODO:
- *
- * priming buffer is not ok, because it will insert silence and
- * break synchronization to other programs.
- *
- * priming buffer in server mode is required, because f->bufsz may
- * be smaller than the server buffer and may cause underrun in the
- * dev_bufsz part of the buffer, in turn causing apps to break. It
- * doesn't hurt because we care only in synchronization between
- * clients.
- *
- * Priming is not required in non-server mode, because streams
- * actually start when they are in the READY state, and their
- * buffer is large enough to never cause underruns of dev_bufsz.
- *
- * Fix sock.c to allocate dev_bufsz, but to use only appbufsz --
- * or whatever -- but to avoid underruns in dev_bufsz. Then remove
- * this ugly hack.
- *
- */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -108,6 +87,21 @@ void dev_clear(struct dev *);
int devctl_open(struct dev *, struct devctl *);
struct dev *dev_list = NULL;
+unsigned dev_sndnum = 0, dev_thrnum = 0;
+
+#ifdef DEBUG
+void
+dev_dbg(struct dev *d)
+{
+ if (d->num >= DEV_NMAX) {
+ dbg_puts("thr");
+ dbg_putu(d->num - DEV_NMAX);
+ } else {
+ dbg_puts("snd");
+ dbg_putu(d->num);
+ }
+}
+#endif
/*
* Create a sndio device
@@ -117,12 +111,24 @@ dev_new(char *path, unsigned mode,
unsigned bufsz, unsigned round, unsigned hold, unsigned autovol)
{
struct dev *d;
+ unsigned *pnum;
d = malloc(sizeof(struct dev));
if (d == NULL) {
perror("malloc");
exit(1);
}
+ pnum = (mode & MODE_THRU) ? &dev_thrnum : &dev_sndnum;
+ if (*pnum == DEV_NMAX) {
+#ifdef DEBUG
+ if (debug_level >= 1)
+ dbg_puts("too many devices\n");
+#endif
+ return NULL;
+ }
+ d->num = (*pnum)++;
+ if (mode & MODE_THRU)
+ d->num += DEV_NMAX;
d->ctl_list = NULL;
d->path = path;
d->reqmode = mode;
@@ -135,7 +141,7 @@ dev_new(char *path, unsigned mode,
d->autostart = 0;
d->pstate = DEV_CLOSED;
d->next = dev_list;
- dev_list = d;
+ dev_list = d;
return d;
}
@@ -161,7 +167,7 @@ dev_init(struct dev *d)
{
if ((d->reqmode & (MODE_AUDIOMASK | MODE_MIDIMASK)) == 0) {
#ifdef DEBUG
- dbg_puts(d->path);
+ dev_dbg(d);
dbg_puts(": has no streams, skipped\n");
#endif
return 1;
@@ -177,7 +183,7 @@ dev_init(struct dev *d)
* Add a MIDI port to the device
*/
int
-devctl_add(struct dev *d, char *name, unsigned mode)
+devctl_add(struct dev *d, char *path, unsigned mode)
{
struct devctl *c;
@@ -186,7 +192,7 @@ devctl_add(struct dev *d, char *name, unsigned mode)
perror("malloc");
exit(1);
}
- c->path = name;
+ c->path = path;
c->mode = mode;
c->next = d->ctl_list;
d->ctl_list = c;
@@ -283,6 +289,8 @@ dev_open(struct dev *d)
if (f == NULL) {
#ifdef DEBUG
if (debug_level >= 1) {
+ dev_dbg(d);
+ dbg_puts(": ");
dbg_puts(d->path);
dbg_puts(": failed to open audio device\n");
}
@@ -296,7 +304,7 @@ dev_open(struct dev *d)
if ((d->mode & (MODE_PLAY | MODE_REC)) == 0) {
#ifdef DEBUG
if (debug_level >= 1) {
- dbg_puts(d->path);
+ dev_dbg(d);
dbg_puts(": mode not supported by device\n");
}
#endif
@@ -356,13 +364,13 @@ dev_open(struct dev *d)
#ifdef DEBUG
if (debug_level >= 2) {
if (d->mode & MODE_REC) {
- dbg_puts(d->path);
+ dev_dbg(d);
dbg_puts(": recording ");
aparams_dbg(&d->ipar);
dbg_puts("\n");
}
if (d->mode & MODE_PLAY) {
- dbg_puts(d->path);
+ dev_dbg(d);
dbg_puts(": playing ");
aparams_dbg(&d->opar);
dbg_puts("\n");
@@ -471,7 +479,7 @@ dev_open(struct dev *d)
#ifdef DEBUG
if (debug_level >= 2) {
if (d->mode & (MODE_PLAY | MODE_RECMASK)) {
- dbg_puts(d->path);
+ dev_dbg(d);
dbg_puts(": block size is ");
dbg_putu(d->round);
dbg_puts(" frames, using ");
diff --git a/usr.bin/aucat/dev.h b/usr.bin/aucat/dev.h
index e191a74fb57..a572401d9db 100644
--- a/usr.bin/aucat/dev.h
+++ b/usr.bin/aucat/dev.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.h,v 1.30 2011/10/12 07:20:04 ratchov Exp $ */
+/* $OpenBSD: dev.h,v 1.31 2011/11/15 08:05:22 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -37,6 +37,8 @@ struct dev {
unsigned autovol; /* auto adjust playvol ? */
unsigned autostart; /* don't wait for MMC start */
unsigned refcnt; /* number of openers */
+#define DEV_NMAX 16 /* max number of devices */
+ unsigned num; /* serial number */
#define DEV_CLOSED 0 /* closed */
#define DEV_INIT 1 /* stopped */
#define DEV_START 2 /* ready to start */
@@ -62,6 +64,7 @@ struct dev {
extern struct dev *dev_list;
+void dev_dbg(struct dev *);
int dev_init(struct dev *);
int dev_run(struct dev *);
int dev_ref(struct dev *);
diff --git a/usr.bin/aucat/opt.c b/usr.bin/aucat/opt.c
index d3a3e993a95..6bcf22b052c 100644
--- a/usr.bin/aucat/opt.c
+++ b/usr.bin/aucat/opt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: opt.c,v 1.11 2011/10/12 07:20:04 ratchov Exp $ */
+/* $OpenBSD: opt.c,v 1.12 2011/11/15 08:05:22 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -28,7 +28,8 @@
struct opt *opt_list = NULL;
struct opt *
-opt_new(char *name, struct dev *dev, struct aparams *wpar, struct aparams *rpar,
+opt_new(char *name, struct dev *dev,
+ struct aparams *wpar, struct aparams *rpar,
int maxweight, int mmc, int join, unsigned mode)
{
struct opt *o, **po;
@@ -41,10 +42,8 @@ opt_new(char *name, struct dev *dev, struct aparams *wpar, struct aparams *rpar,
exit(1);
}
c = name[len];
- if (c < 'a' && c > 'z' &&
- c < 'A' && c > 'Z' &&
- c < '0' && c > '9' &&
- c != '_') {
+ if ((c < 'a' || c > 'z') &&
+ (c < 'A' || c > 'Z')) {
fprintf(stderr, "%s: '%c' not allowed\n", name, c);
exit(1);
}
@@ -54,7 +53,6 @@ opt_new(char *name, struct dev *dev, struct aparams *wpar, struct aparams *rpar,
perror("opt_new: malloc");
exit(1);
}
- memcpy(o->name, name, len + 1);
if (mode & MODE_RECMASK)
o->wpar = (mode & MODE_MON) ? *rpar : *wpar;
if (mode & MODE_PLAY)
@@ -64,8 +62,10 @@ opt_new(char *name, struct dev *dev, struct aparams *wpar, struct aparams *rpar,
o->join = join;
o->mode = mode;
o->dev = dev;
+ memcpy(o->name, name, len + 1);
for (po = &opt_list; *po != NULL; po = &(*po)->next) {
- if (strcmp(o->name, (*po)->name) == 0) {
+ if (o->dev->num == (*po)->dev->num &&
+ strcmp(o->name, (*po)->name) == 0) {
fprintf(stderr, "%s: already defined\n", o->name);
exit(1);
}
@@ -74,9 +74,9 @@ opt_new(char *name, struct dev *dev, struct aparams *wpar, struct aparams *rpar,
*po = o;
#ifdef DEBUG
if (debug_level >= 2) {
+ dev_dbg(o->dev);
+ dbg_puts(".");
dbg_puts(o->name);
- dbg_puts("@");
- dbg_puts(o->dev->path);
dbg_puts(":");
if (o->mode & MODE_REC) {
dbg_puts(" rec=");
@@ -115,27 +115,16 @@ opt_new(char *name, struct dev *dev, struct aparams *wpar, struct aparams *rpar,
}
struct opt *
-opt_byname(char *name)
+opt_byname(char *name, unsigned num)
{
struct opt *o;
for (o = opt_list; o != NULL; o = o->next) {
- if (strcmp(name, o->name) == 0) {
-#ifdef DEBUG
- if (debug_level >= 3) {
- dbg_puts(o->name);
- dbg_puts(": option found\n");
- }
-#endif
+ if (o->dev->num != num)
+ continue;
+ if (strcmp(name, o->name) == 0)
return o;
- }
- }
-#ifdef DEBUG
- if (debug_level >= 3) {
- dbg_puts(name);
- dbg_puts(": option not found\n");
}
-#endif
return NULL;
}
diff --git a/usr.bin/aucat/opt.h b/usr.bin/aucat/opt.h
index c904fbbb9fa..adbbba392ec 100644
--- a/usr.bin/aucat/opt.h
+++ b/usr.bin/aucat/opt.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: opt.h,v 1.10 2011/10/12 07:20:04 ratchov Exp $ */
+/* $OpenBSD: opt.h,v 1.11 2011/11/15 08:05:22 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -40,6 +40,6 @@ extern struct opt *opt_list;
struct opt *opt_new(char *, struct dev *, struct aparams *, struct aparams *,
int, int, int, unsigned);
int opt_bind(struct opt *);
-struct opt *opt_byname(char *);
+struct opt *opt_byname(char *, unsigned);
#endif /* !defined(OPT_H) */
diff --git a/usr.bin/aucat/sock.c b/usr.bin/aucat/sock.c
index cab30a989e3..9bef95065a2 100644
--- a/usr.bin/aucat/sock.c
+++ b/usr.bin/aucat/sock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sock.c,v 1.60 2011/06/03 16:22:34 ratchov Exp $ */
+/* $OpenBSD: sock.c,v 1.61 2011/11/15 08:05:22 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -1033,9 +1033,19 @@ sock_hello(struct sock *f)
#endif
return 0;
}
- f->opt = opt_byname(p->opt);
+ f->opt = opt_byname(p->opt, AMSG_ISSET(p->devnum) ? p->devnum : 0);
if (f->opt == NULL)
return 0;
+#ifdef DEBUG
+ if (debug_level >= 3) {
+ sock_dbg(f);
+ dbg_puts(": using ");
+ dev_dbg(f->opt->dev);
+ dbg_puts(".");
+ dbg_puts(f->opt->name);
+ dbg_puts("\n");
+ }
+#endif
if (!dev_ref(f->opt->dev))
return 0;
if ((mode & MODE_REC) && (f->opt->mode & MODE_MON)) {