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

Reply via email to