Initially aucat was designed to handle one device only so multiple
audio devices used to be supported simply by starting multiple aucat
processes (one per device), very simple. Then (~1.5 years ago) we
added support for multiple audio devices (ie multiple -f options), and
now it's time to finish the job and add a "device number" component in
sndio(7) device names. 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]
where <type> is:
* "rsnd" -- raw sound device, ie direct access to /dev/audioN
* "snd" -- aucat socket to audio device (was "aucat" before)
* "rmidi" -- raw midi port, ie direct access to /dev/rmidiN
* "midi" -- access to midi ports through aucat (not implemented yet)
* "midithru" -- aucat socket to midi thru box
the <unit> number won't be used anymore, except if multiple aucat
instances are running on the same box (ie we keep it as a
developper-only tool).
the device number (<devnum> above) 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 for midi) option.
There's a compatibility hook to keep old names working if only one
aucat server is running.
Please read the sndio(7) man page, and test this diff. Especially if
you have a weired setup (involving multiple devices, MIDI control or
remote devices).
-- Alexandre
Index: usr.bin/aucat/aucat.c
===================================================================
RCS file: /cvs/src/usr.bin/aucat/aucat.c,v
retrieving revision 1.124
diff -u -p -r1.124 aucat.c
--- usr.bin/aucat/aucat.c 18 Oct 2011 21:04:26 -0000 1.124
+++ usr.bin/aucat/aucat.c 8 Nov 2011 19:18:16 -0000
@@ -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, i
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,16 +547,20 @@ 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 (dev_list == NULL)
+ mkdev(DEFAULT_DEV, 0, bufsz, round, hold, autovol);
+ for (d = dev_list; d != NULL; d = d->next) {
+ if ((d->reqmode & (MODE_PLAYREC | MODE_MIDIMASK)) != 0)
+ continue;
+ mkopt("default", d, &rpar, &ppar, mode, vol, mmc, join);
+ server = 1;
+ }
+ if (wav_list) {
+ if (server)
+ errx(1, "-io not allowed in server mode");
+ if ((d = dev_list) && d->next)
+ errx(1, "single device required 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;
Index: usr.bin/aucat/dev.c
===================================================================
RCS file: /cvs/src/usr.bin/aucat/dev.c,v
retrieving revision 1.67
diff -u -p -r1.67 dev.c
--- usr.bin/aucat/dev.c 12 Oct 2011 07:20:04 -0000 1.67
+++ usr.bin/aucat/dev.c 8 Nov 2011 19:18:17 -0000
@@ -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, un
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 ");
Index: usr.bin/aucat/dev.h
===================================================================
RCS file: /cvs/src/usr.bin/aucat/dev.h,v
retrieving revision 1.30
diff -u -p -r1.30 dev.h
--- usr.bin/aucat/dev.h 12 Oct 2011 07:20:04 -0000 1.30
+++ usr.bin/aucat/dev.h 8 Nov 2011 19:18:17 -0000
@@ -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 *);
Index: usr.bin/aucat/opt.c
===================================================================
RCS file: /cvs/src/usr.bin/aucat/opt.c,v
retrieving revision 1.11
diff -u -p -r1.11 opt.c
--- usr.bin/aucat/opt.c 12 Oct 2011 07:20:04 -0000 1.11
+++ usr.bin/aucat/opt.c 8 Nov 2011 19:18:18 -0000
@@ -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, str
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, str
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, str
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, str
*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,15 +115,19 @@ opt_new(char *name, struct dev *dev, str
}
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 (o->dev->num != num)
+ continue;
if (strcmp(name, o->name) == 0) {
#ifdef DEBUG
if (debug_level >= 3) {
- dbg_puts(o->name);
+ dbg_putu(num);
+ dbg_puts(".");
+ dbg_puts(name);
dbg_puts(": option found\n");
}
#endif
@@ -132,6 +136,8 @@ opt_byname(char *name)
}
#ifdef DEBUG
if (debug_level >= 3) {
+ dbg_putu(num);
+ dbg_puts(".");
dbg_puts(name);
dbg_puts(": option not found\n");
}
Index: usr.bin/aucat/opt.h
===================================================================
RCS file: /cvs/src/usr.bin/aucat/opt.h,v
retrieving revision 1.10
diff -u -p -r1.10 opt.h
--- usr.bin/aucat/opt.h 12 Oct 2011 07:20:04 -0000 1.10
+++ usr.bin/aucat/opt.h 8 Nov 2011 19:18:18 -0000
@@ -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) */
Index: usr.bin/aucat/sock.c
===================================================================
RCS file: /cvs/src/usr.bin/aucat/sock.c,v
retrieving revision 1.60
diff -u -p -r1.60 sock.c
--- usr.bin/aucat/sock.c 3 Jun 2011 16:22:34 -0000 1.60
+++ usr.bin/aucat/sock.c 8 Nov 2011 19:18:19 -0000
@@ -1033,7 +1033,7 @@ 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;
if (!dev_ref(f->opt->dev))
Index: lib/libsndio/amsg.h
===================================================================
RCS file: /cvs/src/lib/libsndio/amsg.h,v
retrieving revision 1.3
diff -u -p -r1.3 amsg.h
--- lib/libsndio/amsg.h 17 Oct 2011 21:09:11 -0000 1.3
+++ lib/libsndio/amsg.h 8 Nov 2011 19:18:19 -0000
@@ -82,8 +82,10 @@ struct amsg {
uint16_t mode; /* bitmap of MODE_XXX */
#define AMSG_VERSION 5
uint8_t version; /* protocol version */
- uint8_t reserved1[5]; /* for future use */
- char opt[12]; /* profile name */
+ uint8_t devnum; /* device number */
+ uint32_t _reserved[1]; /* for future use */
+#define AMSG_OPTMAX 12
+ char opt[AMSG_OPTMAX]; /* profile name */
char who[12]; /* hint for leases */
} hello;
struct amsg_auth {
Index: lib/libsndio/aucat.c
===================================================================
RCS file: /cvs/src/lib/libsndio/aucat.c,v
retrieving revision 1.52
diff -u -p -r1.52 aucat.c
--- lib/libsndio/aucat.c 22 Oct 2011 10:23:44 -0000 1.52
+++ lib/libsndio/aucat.c 8 Nov 2011 19:18:19 -0000
@@ -149,7 +149,7 @@ aucat_rdata(struct aucat *hdl, void *buf
hdl->rstate = RSTATE_MSG;
hdl->rtodo = sizeof(struct amsg);
}
- DPRINTF("aucat_rdata: read: n = %zd\n", n);
+ DPRINTFN(2, "aucat_rdata: read: n = %zd\n", n);
return n;
}
@@ -191,7 +191,7 @@ aucat_wdata(struct aucat *hdl, const voi
}
return 0;
}
- DPRINTF("aucat_wdata: write: n = %zd\n", n);
+ DPRINTFN(2, "aucat_wdata: write: n = %zd\n", n);
hdl->wtodo -= n;
if (hdl->wtodo == 0) {
hdl->wstate = WSTATE_IDLE;
@@ -282,18 +282,13 @@ bad_gen:
}
int
-aucat_connect_tcp(struct aucat *hdl, char *host, char *unit)
+aucat_connect_tcp(struct aucat *hdl, char *host, unsigned unit)
{
int s, error, opt;
struct addrinfo *ailist, *ai, aihints;
- unsigned port;
char serv[NI_MAXSERV];
- if (sscanf(unit, "%u", &port) != 1) {
- DPRINTF("%s: bad unit number\n", unit);
- return 0;
- }
- snprintf(serv, sizeof(serv), "%u", port + AUCAT_PORT);
+ snprintf(serv, sizeof(serv), "%u", unit + AUCAT_PORT);
memset(&aihints, 0, sizeof(struct addrinfo));
aihints.ai_socktype = SOCK_STREAM;
aihints.ai_protocol = IPPROTO_TCP;
@@ -334,7 +329,7 @@ aucat_connect_tcp(struct aucat *hdl, cha
}
int
-aucat_connect_un(struct aucat *hdl, char *unit)
+aucat_connect_un(struct aucat *hdl, unsigned unit)
{
struct sockaddr_un ca;
socklen_t len = sizeof(struct sockaddr_un);
@@ -343,7 +338,7 @@ aucat_connect_un(struct aucat *hdl, char
uid = geteuid();
snprintf(ca.sun_path, sizeof(ca.sun_path),
- "/tmp/aucat-%u/%s%s", uid, AUCAT_PATH, unit);
+ "/tmp/aucat-%u/%s%u", uid, AUCAT_PATH, unit);
ca.sun_family = AF_UNIX;
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s < 0)
@@ -354,7 +349,7 @@ aucat_connect_un(struct aucat *hdl, char
DPERROR(ca.sun_path);
/* try shared server */
snprintf(ca.sun_path, sizeof(ca.sun_path),
- "/tmp/aucat/%s%s", AUCAT_PATH, unit);
+ "/tmp/aucat/%s%u", AUCAT_PATH, unit);
while (connect(s, (struct sockaddr *)&ca, len) < 0) {
if (errno == EINTR)
continue;
@@ -368,43 +363,90 @@ aucat_connect_un(struct aucat *hdl, char
return 1;
}
+static const char *
+parsedev(const char *str, unsigned *rval)
+{
+ const char *p = str;
+ unsigned val;
+
+ for (val = 0; *p >= '0' && *p <= '9'; p++) {
+ val = 10 * val + (*p - '0');
+ if (val >= 16) {
+ DPRINTF("%s: number too large\n", str);
+ return NULL;
+ }
+ }
+ if (p == str) {
+ DPRINTF("%s: number expected\n", str);
+ return NULL;
+ }
+ *rval = val;
+ return p;
+}
+
+static const char *
+parsestr(const char *str, char *rstr, unsigned max)
+{
+ const char *p = str;
+
+ while (*p != '\0' && *p != ',' && *p != '/') {
+ if (--max == 0) {
+ DPRINTF("%s: string too long\n", str);
+ return NULL;
+ }
+ *rstr++ = *p++;
+ }
+ if (str == p) {
+ DPRINTF("%s: string expected\n", str);
+ return NULL;
+ }
+ *rstr = '\0';
+ return p;
+}
+
int
-aucat_open(struct aucat *hdl, const char *str, unsigned mode)
+aucat_open(struct aucat *hdl, const char *str, unsigned mode, unsigned type)
{
extern char *__progname;
- int eof, hashost;
- char unit[4], *sep, *opt;
- char host[NI_MAXHOST];
-
- if (str == NULL)
- str = "0";
- sep = strchr(str, '/');
- if (sep == NULL) {
- hashost = 0;
- } else {
- if (sep - str >= sizeof(host)) {
- DPRINTF("aucat_open: %s: host too long\n", str);
+ int eof;
+ char host[NI_MAXHOST], opt[AMSG_OPTMAX];
+ const char *p = str;
+ unsigned unit, devnum;
+
+ if (*p == '@') {
+ p = parsestr(++p, host, NI_MAXHOST);
+ if (p == NULL)
return 0;
- }
- memcpy(host, str, sep - str);
- host[sep - str] = '\0';
- hashost = 1;
- str = sep + 1;
- }
- sep = strchr(str, '.');
- if (sep == NULL) {
- opt = "default";
- strlcpy(unit, str, sizeof(unit));
- } else {
- opt = sep + 1;
- if (sep - str >= sizeof(unit)) {
- DPRINTF("aucat_init: %s: too long\n", str);
+ } else
+ *host = '\0';
+ if (*p == ',') {
+ p = parsedev(++p, &unit);
+ if (p == NULL)
return 0;
- }
- strlcpy(unit, str, opt - str);
+ } else
+ unit = 0;
+ if (*p != '/' && *p != ':') {
+ DPRINTF("%s: '/' expected\n", str);
+ return 0;
+ }
+ p = parsedev(++p, &devnum);
+ if (p == NULL)
+ return 0;
+ if (*p == '.') {
+ p = parsestr(++p, opt, AMSG_OPTMAX);
+ if (p == NULL)
+ return 0;
+ } else
+ strlcpy(opt, "default", AMSG_OPTMAX);
+ if (*p != '\0') {
+ DPRINTF("%s: junk at end of dev name\n", p);
+ return 0;
}
- DPRINTF("aucat_init: trying %s -> %s.%s\n", str, unit, opt);
- if (hashost) {
+ if (type)
+ devnum += 16; /* XXX */
+ DPRINTF("aucat_open: host=%s unit=%u devnum=%u opt=%s\n",
+ host, unit, devnum, opt);
+ if (host[0] != '\0') {
if (!aucat_connect_tcp(hdl, host, unit))
return 0;
} else {
@@ -434,6 +476,7 @@ aucat_open(struct aucat *hdl, const char
hdl->wmsg.cmd = htonl(AMSG_HELLO);
hdl->wmsg.u.hello.version = AMSG_VERSION;
hdl->wmsg.u.hello.mode = htons(mode);
+ hdl->wmsg.u.hello.devnum = devnum;
strlcpy(hdl->wmsg.u.hello.who, __progname,
sizeof(hdl->wmsg.u.hello.who));
strlcpy(hdl->wmsg.u.hello.opt, opt,
@@ -502,6 +545,6 @@ aucat_revents(struct aucat *hdl, struct
{
int revents = pfd->revents;
- DPRINTF("aucat_revents: revents: %x\n", revents);
+ DPRINTFN(2, "aucat_revents: revents: %x\n", revents);
return revents;
}
Index: lib/libsndio/aucat.h
===================================================================
RCS file: /cvs/src/lib/libsndio/aucat.h,v
retrieving revision 1.3
diff -u -p -r1.3 aucat.h
--- lib/libsndio/aucat.h 17 Oct 2011 21:09:11 -0000 1.3
+++ lib/libsndio/aucat.h 8 Nov 2011 19:18:19 -0000
@@ -20,7 +20,7 @@ int aucat_rmsg(struct aucat *, int *);
int aucat_wmsg(struct aucat *, int *);
size_t aucat_rdata(struct aucat *, void *, size_t, int *);
size_t aucat_wdata(struct aucat *, const void *, size_t, unsigned, int *);
-int aucat_open(struct aucat *, const char *, unsigned);
+int aucat_open(struct aucat *, const char *, unsigned, unsigned);
void aucat_close(struct aucat *, int);
int aucat_pollfd(struct aucat *, struct pollfd *, int);
int aucat_revents(struct aucat *, struct pollfd *);
Index: lib/libsndio/debug.h
===================================================================
RCS file: /cvs/src/lib/libsndio/debug.h,v
retrieving revision 1.1
diff -u -p -r1.1 debug.h
--- lib/libsndio/debug.h 16 Apr 2011 10:52:22 -0000 1.1
+++ lib/libsndio/debug.h 8 Nov 2011 19:18:19 -0000
@@ -20,6 +20,12 @@
#ifdef DEBUG
#include <stdio.h>
+#define DPRINTFN(n, ...) \
+ do { \
+ if (sndio_debug >= (n)) \
+ fprintf(stderr, __VA_ARGS__); \
+ } while(0)
+
#define DPRINTF(...) \
do { \
if (sndio_debug > 0) \
@@ -36,6 +42,7 @@ void sndio_debug_init(void);
extern int sndio_debug;
#else
#define DPRINTF(...) do {} while(0)
+#define DPRINTFN(...) do {} while(0)
#define DPERROR(s) do {} while(0)
#endif
Index: lib/libsndio/mio.c
===================================================================
RCS file: /cvs/src/lib/libsndio/mio.c,v
retrieving revision 1.12
diff -u -p -r1.12 mio.c
--- lib/libsndio/mio.c 17 Oct 2011 21:09:11 -0000 1.12
+++ lib/libsndio/mio.c 8 Nov 2011 19:18:19 -0000
@@ -34,12 +34,9 @@
struct mio_hdl *
mio_open(const char *str, unsigned mode, int nbio)
{
- static char prefix_midithru[] = "midithru";
- static char prefix_rmidi[] = "rmidi";
- static char prefix_aucat[] = "aucat";
struct mio_hdl *hdl;
- char *sep;
- int len;
+ size_t len;
+ int c;
#ifdef DEBUG
sndio_debug_init();
@@ -49,26 +46,23 @@ mio_open(const char *str, unsigned mode,
if (str == NULL && !issetugid())
str = getenv("MIDIDEVICE");
if (str == NULL) {
- hdl = mio_aucat_open("0", mode, nbio);
+ hdl = mio_aucat_open("/0", mode, nbio, 1);
if (hdl != NULL)
return hdl;
- return mio_rmidi_open("0", mode, nbio);
+ return mio_rmidi_open("/0", mode, nbio);
}
- sep = strchr(str, ':');
- if (sep == NULL) {
- DPRINTF("mio_open: %s: ':' missing in device name\n", str);
- return NULL;
+ for (len = 0; (c = str[len]) != '\0'; len++) {
+ /* XXX: remove ':' compat bits */
+ if (c == ':' || c == '@' || c == '/' || c == ',')
+ break;
}
- len = sep - str;
- if (len == (sizeof(prefix_midithru) - 1) &&
- memcmp(str, prefix_midithru, len) == 0)
- return mio_aucat_open(sep + 1, mode, nbio);
- if (len == (sizeof(prefix_aucat) - 1) &&
- memcmp(str, prefix_aucat, len) == 0)
- return mio_aucat_open(sep + 1, mode, nbio);
- if (len == (sizeof(prefix_rmidi) - 1) &&
- memcmp(str, prefix_rmidi, len) == 0)
- return mio_rmidi_open(sep + 1, mode, nbio);
+ if (strncmp("snd", str, len) == 0 ||
+ strncmp("aucat", str, len) == 0)
+ return mio_aucat_open(str + len, mode, nbio, 0);
+ if (strncmp("midithru", str, len) == 0)
+ return mio_aucat_open(str + len, mode, nbio, 1);
+ if (strncmp("rmidi", str, len) == 0)
+ return mio_rmidi_open(str + len, mode, nbio);
DPRINTF("mio_open: %s: unknown device type\n", str);
return NULL;
}
Index: lib/libsndio/mio_aucat.c
===================================================================
RCS file: /cvs/src/lib/libsndio/mio_aucat.c,v
retrieving revision 1.5
diff -u -p -r1.5 mio_aucat.c
--- lib/libsndio/mio_aucat.c 17 Oct 2011 21:09:11 -0000 1.5
+++ lib/libsndio/mio_aucat.c 8 Nov 2011 19:18:19 -0000
@@ -52,14 +52,14 @@ static struct mio_ops mio_aucat_ops = {
};
struct mio_hdl *
-mio_aucat_open(const char *str, unsigned mode, int nbio)
+mio_aucat_open(const char *str, unsigned mode, int nbio, unsigned type)
{
struct mio_aucat_hdl *hdl;
hdl = malloc(sizeof(struct mio_aucat_hdl));
if (hdl == NULL)
return NULL;
- if (!aucat_open(&hdl->aucat, str, mode))
+ if (!aucat_open(&hdl->aucat, str, mode, type))
goto bad;
mio_create(&hdl->mio, &mio_aucat_ops, mode, nbio);
if (!aucat_setfl(&hdl->aucat, nbio, &hdl->mio.eof))
Index: lib/libsndio/mio_priv.h
===================================================================
RCS file: /cvs/src/lib/libsndio/mio_priv.h,v
retrieving revision 1.7
diff -u -p -r1.7 mio_priv.h
--- lib/libsndio/mio_priv.h 17 Oct 2011 21:09:11 -0000 1.7
+++ lib/libsndio/mio_priv.h 8 Nov 2011 19:18:19 -0000
@@ -42,7 +42,7 @@ struct mio_ops {
};
struct mio_hdl *mio_rmidi_open(const char *, unsigned, int);
-struct mio_hdl *mio_aucat_open(const char *, unsigned, int);
+struct mio_hdl *mio_aucat_open(const char *, unsigned, int, unsigned);
void mio_create(struct mio_hdl *, struct mio_ops *, unsigned, int);
void mio_destroy(struct mio_hdl *);
Index: lib/libsndio/mio_rmidi.c
===================================================================
RCS file: /cvs/src/lib/libsndio/mio_rmidi.c,v
retrieving revision 1.9
diff -u -p -r1.9 mio_rmidi.c
--- lib/libsndio/mio_rmidi.c 16 Apr 2011 10:52:22 -0000 1.9
+++ lib/libsndio/mio_rmidi.c 8 Nov 2011 19:18:20 -0000
@@ -56,6 +56,15 @@ mio_rmidi_open(const char *str, unsigned
struct mio_rmidi_hdl *hdl;
char path[PATH_MAX];
+ switch (*str) {
+ case '/':
+ case ':': /* XXX: for backward compat */
+ str++;
+ break;
+ default:
+ DPRINTF("sio_sun_open: %s: '/<devnum>' expected\n", str);
+ return NULL;
+ }
hdl = malloc(sizeof(struct mio_rmidi_hdl));
if (hdl == NULL)
return NULL;
Index: lib/libsndio/sio.c
===================================================================
RCS file: /cvs/src/lib/libsndio/sio.c,v
retrieving revision 1.6
diff -u -p -r1.6 sio.c
--- lib/libsndio/sio.c 9 May 2011 17:34:14 -0000 1.6
+++ lib/libsndio/sio.c 8 Nov 2011 19:18:20 -0000
@@ -33,17 +33,6 @@
#define SIO_PAR_MAGIC 0x83b905a4
-struct sio_backend {
- char *prefix;
- struct sio_hdl *(*open)(const char *, unsigned, int);
-};
-
-static struct sio_backend backends[] = {
- { "aucat", sio_aucat_open },
- { "sun", sio_sun_open },
- { NULL, NULL }
-};
-
void
sio_initpar(struct sio_par *par)
{
@@ -54,10 +43,9 @@ sio_initpar(struct sio_par *par)
struct sio_hdl *
sio_open(const char *str, unsigned mode, int nbio)
{
- struct sio_backend *b;
struct sio_hdl *hdl;
- char *sep;
- int len;
+ size_t len;
+ int c;
#ifdef DEBUG
sndio_debug_init();
@@ -67,22 +55,22 @@ sio_open(const char *str, unsigned mode,
if (str == NULL && !issetugid())
str = getenv("AUDIODEVICE");
if (str == NULL) {
- for (b = backends; b->prefix != NULL; b++) {
- hdl = b->open(NULL, mode, nbio);
- if (hdl != NULL)
- return hdl;
- }
- return NULL;
+ hdl = sio_aucat_open("/0", mode, nbio);
+ if (hdl != NULL)
+ return hdl;
+ return sio_sun_open("", mode, nbio);
}
- sep = strchr(str, ':');
- if (sep == NULL) {
- DPRINTF("sio_open: %s: ':' missing in device name\n", str);
- return NULL;
+ for (len = 0; (c = str[len]) != '\0'; len++) {
+ /* XXX: remove ':' compat bits */
+ if (c == ':' || c == '@' || c == '/' || c == ',')
+ break;
}
- len = sep - str;
- for (b = backends; b->prefix != NULL; b++) {
- if (strlen(b->prefix) == len && memcmp(b->prefix, str, len) ==
0)
- return b->open(sep + 1, mode, nbio);
+ if (strncmp("snd", str, len) == 0 ||
+ strncmp("aucat", str, len) == 0)
+ return sio_aucat_open(str + len, mode, nbio);
+ if (strncmp("rsnd", str, len) == 0 ||
+ strncmp("sun", str, len) == 0) {
+ return sio_sun_open(str + len, mode, nbio);
}
DPRINTF("sio_open: %s: unknown device type\n", str);
return NULL;
Index: lib/libsndio/sio_aucat.c
===================================================================
RCS file: /cvs/src/lib/libsndio/sio_aucat.c,v
retrieving revision 1.8
diff -u -p -r1.8 sio_aucat.c
--- lib/libsndio/sio_aucat.c 17 Oct 2011 21:09:11 -0000 1.8
+++ lib/libsndio/sio_aucat.c 8 Nov 2011 19:18:20 -0000
@@ -109,7 +109,7 @@ sio_aucat_runmsg(struct sio_aucat_hdl *h
delta = ntohl(hdl->aucat.rmsg.u.ts.delta);
hdl->maxwrite += delta * hdl->wbpf;
hdl->delta += delta;
- DPRINTF("aucat: move = %d, delta = %d, maxwrite = %d\n",
+ DPRINTFN(2, "aucat: move = %d, delta = %d, maxwrite = %d\n",
delta, hdl->delta, hdl->maxwrite);
if (hdl->delta >= 0) {
sio_onmove_cb(&hdl->sio, hdl->delta);
@@ -156,7 +156,7 @@ sio_aucat_open(const char *str, unsigned
hdl = malloc(sizeof(struct sio_aucat_hdl));
if (hdl == NULL)
return NULL;
- if (!aucat_open(&hdl->aucat, str, mode)) {
+ if (!aucat_open(&hdl->aucat, str, mode, 0)) {
free(hdl);
return NULL;
}
@@ -466,7 +466,7 @@ sio_aucat_revents(struct sio_hdl *sh, st
}
if (hdl->sio.eof)
return POLLHUP;
- DPRINTF("sio_aucat_revents: %x\n", revents & hdl->events);
+ DPRINTFN(2, "sio_aucat_revents: %x\n", revents & hdl->events);
return revents & (hdl->events | POLLHUP);
}
Index: lib/libsndio/sio_sun.c
===================================================================
RCS file: /cvs/src/lib/libsndio/sio_sun.c,v
retrieving revision 1.3
diff -u -p -r1.3 sio_sun.c
--- lib/libsndio/sio_sun.c 3 May 2011 20:15:23 -0000 1.3
+++ lib/libsndio/sio_sun.c 8 Nov 2011 19:18:21 -0000
@@ -343,8 +343,24 @@ sio_sun_open(const char *str, unsigned m
struct sio_par par;
char path[PATH_MAX];
- if (str == NULL)
- str = "";
+ switch (*str) {
+ case '/':
+ case ':':
+ /* XXX: for backward compat */
+ str++;
+ break;
+ case '\0':
+ /*
+ * XXX: allow ``rsnd'' to map to /dev/audio symlink for
+ * compatibility, remove this once aucat is enabled
+ * by default and default device selection is done
+ * using aucat
+ */
+ break;
+ default:
+ DPRINTF("sio_sun_open: %s: '/<devnum>' expected\n", str);
+ return NULL;
+ }
hdl = malloc(sizeof(struct sio_sun_hdl));
if (hdl == NULL)
return NULL;
Index: lib/libsndio/sndio.7
===================================================================
RCS file: /cvs/src/lib/libsndio/sndio.7,v
retrieving revision 1.7
diff -u -p -r1.7 sndio.7
--- lib/libsndio/sndio.7 18 Oct 2011 07:07:25 -0000 1.7
+++ lib/libsndio/sndio.7 8 Nov 2011 19:18:21 -0000
@@ -68,73 +68,77 @@ From the user's perspective every audio
.Xr aucat 1
service has a name of the form:
.Bd -literal -offset center
-type:[hostname/]unit[.option]
+type[@hostname][,unit]/devnum[.option]
.Ed
.Pp
This information is used by audio and MIDI applications to determine
how to access the audio device or MIDI port.
-.Bl -tag -width "option"
+.Bl -tag -width "hostname"
.It Pa type
The type of the audio device or MIDI port.
-Possible values for audio devices are
-.Pa aucat
-and
-.Pa sun ,
-corresponding to
-.Xr aucat 1
-sockets and hardware
+Possible values are:
+.Pp
+.Bl -tag -width "midithru" -offset 3n -compact
+.It Pa rsnd
+Raw
.Xr audio 4
-devices.
-Possible values for MIDI ports are
-.Pa aucat
-and
-.Pa rmidi
-corresponding to
-.Xr aucat 1
-software MIDI thru boxes or control ports and hardware
+device.
+.It Pa rmidi
+Raw
.Xr midi 4
-ports respectively.
+port.
+.It Pa snd
+Audio device exposed by
+.Xr aucat 1
+.It Pa midithru
+MIDI thru box created with
+.Xr aucat 1
+.El
.It Pa hostname
-The hostname where the remote
+The hostname or address where the remote
.Xr aucat 1
server to connect to is running.
.It Pa unit
+The number of the
+.Xr aucat 1
+server to connect to, corresponds to the integer specified unsing the
+.Fl U
+option of
+.Xr aucat 1 .
+Useful only if multiple
+.Xr aucat 1
+servers are running on the same system.
+.It Pa devnum
+Device number.
For hardware audio or MIDI ports, this corresponds to
the character device minor number.
For audio devices or MIDI ports created with
.Xr aucat 1
-it corresponds to the server
-.Em unit
-number, typically 0.
+it corresponds to the number of the corresponding
+.Fl fM
+option on the command line.
.It Pa option
-Corresponds to the profile string registered using the
+Corresponds to the sub-device string registered using the
.Fl s
option of
.Xr aucat 1 .
-Only meaningful for
-.Pa aucat
-device types.
.El
.Pp
For example:
.Pp
-.Bl -tag -width "aucat:0.rear" -offset 3n -compact
-.It Pa sun:0
+.Bl -tag -width "snd/0.rear" -offset 3n -compact
+.It Pa rsnd/0
First hardware audio device.
-.It Pa aucat:0
-Default audio device of the first
-.Xr aucat 1
-audio server.
-.It Pa aucat:0.rear
-First
-.Xr aucat 1
-server;
-device registered with
-.Fl s Fa rear .
-.It Pa rmidi:5
+.It Pa rmidi/5
Hardware MIDI port number 5.
-.It Pa aucat:0
-First software MIDI thru box or control port created with
+.It Pa snd/0
+First audio device exposed by
+.Xr aucat 1 .
+.It Pa snd/0.rear
+Sub-device registered with
+.Fl s Fa rear .
+.It Pa midithru/0
+First MIDI thru box created with
.Xr aucat 1 .
.El
.Sh AUTHENTICATION