this diff is to slightly clean up aucat headers and shouldn't change
its behavior. Since there are a lot of changes, it's worth testing it,
imo.

-- Alexandre

Index: lib/libsndio/aucat.c
===================================================================
RCS file: /cvs/src/lib/libsndio/aucat.c,v
retrieving revision 1.41
diff -u -p -r1.41 aucat.c
--- lib/libsndio/aucat.c        5 Jun 2010 16:00:52 -0000       1.41
+++ lib/libsndio/aucat.c        17 Oct 2010 12:03:03 -0000
@@ -261,11 +261,7 @@ sio_open_aucat(const char *str, unsigned
        AMSG_INIT(&hdl->wmsg);
        hdl->wmsg.cmd = AMSG_HELLO;
        hdl->wmsg.u.hello.version = AMSG_VERSION;
-       hdl->wmsg.u.hello.proto = 0;
-       if (mode & SIO_PLAY)
-               hdl->wmsg.u.hello.proto |= AMSG_PLAY;
-       if (mode & SIO_REC)
-               hdl->wmsg.u.hello.proto |= AMSG_REC;
+       hdl->wmsg.u.hello.mode = mode;
        strlcpy(hdl->wmsg.u.hello.who, __progname,
            sizeof(hdl->wmsg.u.hello.who));
        strlcpy(hdl->wmsg.u.hello.opt, opt,
Index: lib/libsndio/mio_thru.c
===================================================================
RCS file: /cvs/src/lib/libsndio/mio_thru.c,v
retrieving revision 1.10
diff -u -p -r1.10 mio_thru.c
--- lib/libsndio/mio_thru.c     21 Jul 2010 23:00:16 -0000      1.10
+++ lib/libsndio/mio_thru.c     17 Oct 2010 12:03:03 -0000
@@ -119,11 +119,7 @@ thru_open(const char *str, char *sock, u
        AMSG_INIT(&msg);
        msg.cmd = AMSG_HELLO;
        msg.u.hello.version = AMSG_VERSION;
-       msg.u.hello.proto = 0;
-       if (mode & MIO_IN)
-               msg.u.hello.proto |= AMSG_MIDIIN;
-       if (mode & MIO_OUT)
-               msg.u.hello.proto |= AMSG_MIDIOUT;
+       msg.u.hello.mode = mode;
        strlcpy(msg.u.hello.opt, opt, sizeof(msg.u.hello.opt));
        strlcpy(msg.u.hello.who, __progname, sizeof(msg.u.hello.who));
        n = write(s, &msg, sizeof(struct amsg));
Index: usr.bin/aucat/abuf.h
===================================================================
RCS file: /cvs/src/usr.bin/aucat/abuf.h,v
retrieving revision 1.22
diff -u -p -r1.22 abuf.h
--- usr.bin/aucat/abuf.h        6 Apr 2010 20:07:01 -0000       1.22
+++ usr.bin/aucat/abuf.h        17 Oct 2010 12:03:03 -0000
@@ -19,11 +19,6 @@
 
 #include <sys/queue.h>
 
-#define XRUN_IGNORE    0       /* on xrun silently insert/discard samples */
-#define XRUN_SYNC      1       /* catchup to sync to the mix/sub */
-#define XRUN_ERROR     2       /* xruns are errors, eof/hup buffer */
-#define MIDI_MSGMAX    16      /* max size of MIDI messaage */
-
 struct aproc;
 struct aparams;
 
@@ -62,6 +57,7 @@ struct abuf {
                        unsigned used;  /* bytes used from ``msg'' */
                        unsigned idx;   /* actual MIDI message size */
                        unsigned len;   /* MIDI message length */
+#define MIDI_MSGMAX    16              /* max size of MIDI messaage */
                        unsigned char msg[MIDI_MSGMAX];
                } midi;
        } r;
@@ -75,7 +71,7 @@ struct abuf {
                } mix;
                struct {
                        unsigned done;  /* frames copied */
-                       unsigned xrun;  /* overrun policy */
+                       unsigned xrun;  /* overrun policy, one of XRUN_XXX */
                        int silence;    /* silence to add on next write */
                } sub;
        } w;
Index: usr.bin/aucat/amsg.h
===================================================================
RCS file: /cvs/src/usr.bin/aucat/amsg.h,v
retrieving revision 1.17
diff -u -p -r1.17 amsg.h
--- usr.bin/aucat/amsg.h        5 Jun 2010 12:45:48 -0000       1.17
+++ usr.bin/aucat/amsg.h        17 Oct 2010 12:03:03 -0000
@@ -18,6 +18,7 @@
 #define AMSG_H
 
 #include <stdint.h>
+#include "conf.h"
 
 /*
  * WARNING: since the protocol may be simultaneously used by static
@@ -46,9 +47,6 @@ struct amsg {
        union {
                struct amsg_par {
                        uint8_t legacy_mode;    /* compat for old libs */
-#define AMSG_IGNORE    0                       /* loose sync */
-#define AMSG_SYNC      1                       /* resync after xrun */
-#define AMSG_ERROR     2                       /* kill the stream */
                        uint8_t xrun;           /* one of above */
                        uint8_t bps;            /* bytes per sample */
                        uint8_t bits;           /* actually used bits */
@@ -84,13 +82,7 @@ struct amsg {
                        uint32_t ctl;
                } vol;
                struct amsg_hello {
-#define AMSG_PLAY      0x1                     /* audio playback */
-#define AMSG_REC       0x2                     /* audio recording */
-#define AMSG_MIDIIN    0x4                     /* MIDI thru input */
-#define AMSG_MIDIOUT   0x8                     /* MIDI thru output */
-#define AMSG_MON       0x10                    /* audio monitoring */
-#define AMSG_RECMASK   (AMSG_REC | AMSG_MON)   /* can record ? */
-                       uint16_t proto;         /* protocol type */
+                       uint16_t mode;          /* bitmap of MODE_XXX */
 #define AMSG_VERSION   3
                        uint8_t version;        /* protocol version */
                        uint8_t reserved1[5];   /* for future use */
Index: usr.bin/aucat/aproc.c
===================================================================
RCS file: /cvs/src/usr.bin/aucat/aproc.c,v
retrieving revision 1.59
diff -u -p -r1.59 aproc.c
--- usr.bin/aucat/aproc.c       7 May 2010 07:15:50 -0000       1.59
+++ usr.bin/aucat/aproc.c       17 Oct 2010 12:03:05 -0000
@@ -1042,6 +1042,10 @@ mix_setmaster(struct aproc *p)
         * uses channels that have no intersection, they are 
         * counted only once because they don't need to 
         * share their volume
+        *
+        * XXX: this is wrong, this is not optimal if we have two
+        *      buckets of N and N' clients, in which case we should
+        *      get 1/N and 1/N' respectively
         */
        n = 0;
        LIST_FOREACH(i, &p->ins, ient) {
@@ -1081,41 +1085,6 @@ mix_clear(struct aproc *p)
 
        p->u.mix.lat = 0;
        obuf->w.mix.todo = 0;
-}
-
-void
-mix_prime(struct aproc *p)
-{
-       struct abuf *obuf = LIST_FIRST(&p->outs);
-       unsigned todo, count;
-
-       for (;;) {
-               if (!ABUF_WOK(obuf))
-                       break;
-               todo = p->u.mix.maxlat - p->u.mix.lat;
-               mix_bzero(obuf, todo);
-               count = obuf->w.mix.todo;
-               if (count > todo)
-                       count = todo;
-               if (count == 0)
-                       break;
-               obuf->w.mix.todo -= count;
-               p->u.mix.lat += count;
-               abuf_wcommit(obuf, count);
-               if (APROC_OK(p->u.mix.mon))
-                       mon_snoop(p->u.mix.mon, obuf, 0, count);
-               abuf_flush(obuf);
-       }
-#ifdef DEBUG
-       if (debug_level >= 3) {
-               aproc_dbg(p);
-               dbg_puts(": prime: lat/maxlat=");
-               dbg_puti(p->u.mix.lat);
-               dbg_puts("/");
-               dbg_puti(p->u.mix.maxlat);
-               dbg_puts("\n");
-       }
-#endif
 }
 
 /*
Index: usr.bin/aucat/aucat.c
===================================================================
RCS file: /cvs/src/usr.bin/aucat/aucat.c,v
retrieving revision 1.105
diff -u -p -r1.105 aucat.c
--- usr.bin/aucat/aucat.c       8 Sep 2010 22:07:26 -0000       1.105
+++ usr.bin/aucat/aucat.c       17 Oct 2010 12:03:05 -0000
@@ -691,7 +691,7 @@ aucat_main(int argc, char **argv)
                if (n_flag) {
                        d = dev_new_loop(&cd->ipar, &cd->opar, cd->bufsz);
                } else {
-                       d = dev_new_sio(cd->path, cd->mode,
+                       d = dev_new_sio(cd->path, cd->mode | MODE_MIDIMASK,
                            &cd->ipar, &cd->opar, cd->bufsz, cd->round,
                            cd->hold);
                }
@@ -744,7 +744,7 @@ aucat_main(int argc, char **argv)
                        SLIST_REMOVE_HEAD(&cd->opts, entry);
                        opt_new(cs->path, d, &cs->opar, &cs->ipar,
                            MIDI_TO_ADATA(cs->vol), cs->mmc,
-                           cs->join, cs->mode);
+                           cs->join, cs->mode | MODE_MIDIMASK);
                        free(cs);
                }
                free(cd);
@@ -1018,7 +1018,7 @@ midicat_main(int argc, char **argv)
                while (!SLIST_EMPTY(&cd->opts)) {
                        cs = SLIST_FIRST(&cd->opts);
                        SLIST_REMOVE_HEAD(&cd->opts, entry);
-                       opt_new(cs->path, d, NULL, NULL, 0, 0, 0, 0);
+                       opt_new(cs->path, d, NULL, NULL, 0, 0, 0, 
MODE_MIDIMASK);
                        free(cs);
                }
                free(cd);
Index: usr.bin/aucat/conf.h
===================================================================
RCS file: /cvs/src/usr.bin/aucat/conf.h,v
retrieving revision 1.15
diff -u -p -r1.15 conf.h
--- usr.bin/aucat/conf.h        6 Apr 2010 20:07:01 -0000       1.15
+++ usr.bin/aucat/conf.h        17 Oct 2010 12:03:06 -0000
@@ -47,4 +47,25 @@ extern int debug_level;
  */
 #define MTC_SEC                        2400    /* 1 second is 2400 ticks */
 
+/*
+ * device or sub-device mode, must be a superset of corresponding SIO_XXX
+ * and MIO_XXX constants
+ */
+#define MODE_PLAY      0x01    /* allowed to play */
+#define MODE_REC       0x02    /* allowed to rec */
+#define MODE_MIDIOUT   0x04    /* allowed to read midi */
+#define MODE_MIDIIN    0x08    /* allowed to write midi */
+#define MODE_MON       0x10    /* allowed to monitor */
+#define MODE_LOOP      0x20    /* deviceless mode */
+#define MODE_RECMASK   (MODE_REC | MODE_MON)
+#define MODE_AUDIOMASK (MODE_REC | MODE_MON | MODE_PLAY)
+#define MODE_MIDIMASK  (MODE_MIDIIN | MODE_MIDIOUT)
+
+/*
+ * underrun/overrun policies, must be the same as SIO_XXX
+ */
+#define XRUN_IGNORE    0       /* on xrun silently insert/discard samples */
+#define XRUN_SYNC      1       /* catchup to sync to the mix/sub */
+#define XRUN_ERROR     2       /* xruns are errors, eof/hup buffer */
+
 #endif /* !defined(CONF_H) */
Index: usr.bin/aucat/dev.c
===================================================================
RCS file: /cvs/src/usr.bin/aucat/dev.c,v
retrieving revision 1.63
diff -u -p -r1.63 dev.c
--- usr.bin/aucat/dev.c 31 Jul 2010 08:46:56 -0000      1.63
+++ usr.bin/aucat/dev.c 17 Oct 2010 12:03:07 -0000
@@ -166,7 +166,7 @@ dev_new_loop(struct aparams *dipar, stru
        d->rate = rate;
        d->reqround = (bufsz + 1) / 2;
        d->reqbufsz = d->reqround * 2;
-       d->reqmode = MODE_PLAY | MODE_REC | MODE_LOOP;
+       d->reqmode = MODE_PLAY | MODE_REC | MODE_LOOP | MODE_MIDIMASK;
        d->pstate = DEV_CLOSED;
        d->hold = 0;
        d->path = "loop";
@@ -188,7 +188,7 @@ dev_new_thru(void)
                perror("malloc");
                exit(1);
        }
-       d->reqmode = 0;
+       d->reqmode = MODE_MIDIMASK;
        d->pstate = DEV_CLOSED;
        d->hold = 0;
        d->path = "midithru";
@@ -289,8 +289,11 @@ dev_open(struct dev *d)
         * Create the midi control end, or a simple thru box
         * if there's no device
         */
-       d->midi = (d->mode == 0) ? thru_new("thru") : ctl_new("ctl", d);
-       d->midi->refs++;
+       if (d->mode & MODE_MIDIMASK) {
+               d->midi = (d->mode & (MODE_PLAY | MODE_RECMASK)) ?
+                   ctl_new("ctl", d) : thru_new("thru");
+               d->midi->refs++;
+       }
 
        /*
         * Create mixer, demuxer and monitor
Index: usr.bin/aucat/midi.c
===================================================================
RCS file: /cvs/src/usr.bin/aucat/midi.c,v
retrieving revision 1.28
diff -u -p -r1.28 midi.c
--- usr.bin/aucat/midi.c        6 Jul 2010 01:12:45 -0000       1.28
+++ usr.bin/aucat/midi.c        17 Oct 2010 12:03:08 -0000
@@ -560,20 +560,19 @@ ctl_getidx(struct aproc *p, char *who)
                        umap |= (1 << i);
        } 
        for (unit = 0; ; unit++) {
-               if (unit == CTL_NSLOT)
+               if (unit == CTL_NSLOT) {
+#ifdef DEBUG
+                       if (debug_level >= 1) {
+                               dbg_puts(name);
+                               dbg_puts(": too many instances");
+                       }
+#endif
                        return -1;
+               }
                if ((umap & (1 << unit)) == 0)
                        break;
        }
-#ifdef DEBUG
-       if (debug_level >= 3) {
-               aproc_dbg(p);
-               dbg_puts(": new control name is ");
-               dbg_puts(name);
-               dbg_putu(unit);
-               dbg_puts("\n");
-       }
-#endif
+
        /*
         * find a free controller slot with the same name/unit
         */
@@ -583,7 +582,8 @@ ctl_getidx(struct aproc *p, char *who)
                    slot->unit == unit) {
 #ifdef DEBUG
                        if (debug_level >= 3) {
-                               aproc_dbg(p);
+                               dbg_puts(name);
+                               dbg_putu(unit);
                                dbg_puts(": found slot ");
                                dbg_putu(i);
                                dbg_puts("\n");
@@ -608,8 +608,16 @@ ctl_getidx(struct aproc *p, char *who)
                        bestidx = i;
                }
        }
-       if (bestidx == CTL_NSLOT)
+       if (bestidx == CTL_NSLOT) {
+#ifdef DEBUG
+               if (debug_level >= 1) {
+                       dbg_puts(name);
+                       dbg_putu(unit);
+                       dbg_puts(": out of mixer slots\n");
+               }
+#endif
                return -1;
+       }
        slot = p->u.ctl.slot + bestidx;
        if (slot->name[0] != '\0')
                slot->vol = MIDI_MAXCTL;
@@ -618,7 +626,8 @@ ctl_getidx(struct aproc *p, char *who)
        slot->unit = unit;
 #ifdef DEBUG
        if (debug_level >= 3) {
-               aproc_dbg(p);
+               dbg_puts(name);
+               dbg_putu(unit);
                dbg_puts(": overwritten slot ");
                dbg_putu(bestidx);
                dbg_puts("\n");
Index: usr.bin/aucat/opt.h
===================================================================
RCS file: /cvs/src/usr.bin/aucat/opt.h,v
retrieving revision 1.8
diff -u -p -r1.8 opt.h
--- usr.bin/aucat/opt.h 4 Jun 2010 06:15:28 -0000       1.8
+++ usr.bin/aucat/opt.h 17 Oct 2010 12:03:08 -0000
@@ -31,16 +31,7 @@ struct opt {
        struct aparams rpar;    /* template for clients read params */
        int mmc;                /* true if MMC control enabled */
        int join;               /* true if join/expand enabled */
-#define MODE_PLAY      0x1     /* allowed to play */
-#define MODE_REC       0x2     /* allowed to rec */
-#define MODE_MIDIIN    0x4     /* allowed to read midi */
-#define MODE_MIDIOUT   0x8     /* allowed to write midi */
-#define MODE_MON       0x10    /* allowed to monitor */
-#define MODE_LOOP      0x20    /* deviceless mode */
-#define MODE_RECMASK   (MODE_REC | MODE_MON)
-#define MODE_AUDIOMASK (MODE_REC | MODE_MON | MODE_PLAY)
-#define MODE_MIDIMASK  (MODE_MIDIIN | MODE_MIDIOUT)
-       unsigned mode;          /* bitmap of above */
+       unsigned mode;          /* bitmap of MODE_XXX */
        struct dev *dev;        /* device to which we're attached */
 };
 
Index: usr.bin/aucat/sock.c
===================================================================
RCS file: /cvs/src/usr.bin/aucat/sock.c,v
retrieving revision 1.50
diff -u -p -r1.50 sock.c
--- usr.bin/aucat/sock.c        5 Jun 2010 16:00:52 -0000       1.50
+++ usr.bin/aucat/sock.c        17 Oct 2010 12:03:09 -0000
@@ -57,7 +57,9 @@ struct fileops sock_ops = {
 void
 sock_dbg(struct sock *f)
 {
-       static char *pstates[] = { "hel", "ini", "sta", "rdy", "run", "mid" };
+       static char *pstates[] = {
+               "hel", "ini", "sta", "rdy", "run", "stp", "mid"
+       };
        static char *rstates[] = { "rdat", "rmsg", "rret" };
        static char *wstates[] = { "widl", "wmsg", "wdat" };
        struct aproc *midi;
@@ -180,7 +182,7 @@ rsock_opos(struct aproc *p, struct abuf 
 {
        struct sock *f = (struct sock *)p->u.io.file;
 
-       if (f->mode & AMSG_RECMASK)
+       if (f->mode & MODE_RECMASK)
                return;
 
        f->delta += delta;
@@ -279,7 +281,7 @@ wsock_ipos(struct aproc *p, struct abuf 
 {
        struct sock *f = (struct sock *)p->u.io.file;
 
-       if (!(f->mode & AMSG_RECMASK))
+       if (!(f->mode & MODE_RECMASK))
                return;
 
        f->delta += delta;
@@ -351,7 +353,7 @@ sock_new(struct fileops *ops, int fd)
        f->mode = 0;
        f->opt = NULL;
        f->dev = NULL;
-       f->xrun = AMSG_IGNORE;
+       f->xrun = XRUN_IGNORE;
        f->delta = 0;
        f->tickpending = 0;
        f->startpos = 0;
@@ -413,14 +415,14 @@ sock_allocbuf(struct sock *f)
 
        bufsz = f->bufsz + f->dev->bufsz / f->dev->round * f->round;
        f->pstate = SOCK_START;
-       if (f->mode & AMSG_PLAY) {
+       if (f->mode & MODE_PLAY) {
                rbuf = abuf_new(bufsz, &f->rpar);
                aproc_setout(f->pipe.file.rproc, rbuf);
                if (!ABUF_WOK(rbuf) || (f->pipe.file.state & FILE_EOF))
                        f->pstate = SOCK_READY;
                f->rmax = bufsz * aparams_bpf(&f->rpar);
        }
-       if (f->mode & AMSG_RECMASK) {
+       if (f->mode & MODE_RECMASK) {
                wbuf = abuf_new(bufsz, &f->wpar);
                aproc_setin(f->pipe.file.wproc, wbuf);
                f->walign = f->round;
@@ -442,7 +444,7 @@ sock_allocbuf(struct sock *f)
                dbg_puts("\n");
        }
 #endif
-       if (f->mode & AMSG_PLAY) {
+       if (f->mode & MODE_PLAY) {
                f->pstate = SOCK_START;
        } else {
                f->pstate = SOCK_READY;
@@ -490,9 +492,7 @@ sock_startreq(void *arg)
        }
 #endif
        (void)sock_attach(f, 0);
-}
-
-/*
+}/*
  * Callback invoked by MMC stop
  */
 void
@@ -542,7 +542,7 @@ sock_quitreq(void *arg)
 }
 
 /*
- * Attach play and/or record buffers to dev->mix and/or dev->sub.
+ * Attach play and/or record buffers to the device
  */
 void
 sock_attach(struct sock *f, int force)
@@ -591,7 +591,7 @@ sock_attach(struct sock *f, int force)
            wbuf, &f->wpar, 
            f->opt->join ? f->opt->wpar.cmax - f->opt->wpar.cmin + 1 : 0,
            f->xrun, f->opt->maxweight);
-       if (f->mode & AMSG_PLAY)
+       if (f->mode & MODE_PLAY)
                dev_setvol(f->dev, rbuf, MIDI_TO_ADATA(f->vol));
 
        /*
@@ -835,7 +835,7 @@ sock_setpar(struct sock *f)
                f->rpar.le = f->wpar.le = p->le ? 1 : 0;
        if (AMSG_ISSET(p->msb))
                f->rpar.msb = f->wpar.msb = p->msb ? 1 : 0;
-       if (AMSG_ISSET(p->rchan) && (f->mode & AMSG_RECMASK)) {
+       if (AMSG_ISSET(p->rchan) && (f->mode & MODE_RECMASK)) {
                if (p->rchan < 1)
                        p->rchan = 1;
                if (p->rchan > NCHAN_MAX)
@@ -855,7 +855,7 @@ sock_setpar(struct sock *f)
                }
 #endif
        }
-       if (AMSG_ISSET(p->pchan) && (f->mode & AMSG_PLAY)) {
+       if (AMSG_ISSET(p->pchan) && (f->mode & MODE_PLAY)) {
                if (p->pchan < 1)
                        p->pchan = 1;
                if (p->pchan > NCHAN_MAX)
@@ -905,9 +905,9 @@ sock_setpar(struct sock *f)
 #endif
        }
        if (AMSG_ISSET(p->xrun)) {
-               if (p->xrun != AMSG_IGNORE &&
-                   p->xrun != AMSG_SYNC &&
-                   p->xrun != AMSG_ERROR) {
+               if (p->xrun != XRUN_IGNORE &&
+                   p->xrun != XRUN_SYNC &&
+                   p->xrun != XRUN_ERROR) {
 #ifdef DEBUG
                        if (debug_level >= 1) {
                                sock_dbg(f);
@@ -919,8 +919,8 @@ sock_setpar(struct sock *f)
                        return 0;
                }
                f->xrun = p->xrun;
-               if (f->opt->mmc && f->xrun == AMSG_IGNORE)
-                       f->xrun = AMSG_SYNC;
+               if (f->opt->mmc && f->xrun == XRUN_IGNORE)
+                       f->xrun = XRUN_SYNC;
 #ifdef DEBUG
                if (debug_level >= 3) {
                        sock_dbg(f);
@@ -931,7 +931,7 @@ sock_setpar(struct sock *f)
 #endif
        }
        if (AMSG_ISSET(p->appbufsz)) {
-               rate = (f->mode & AMSG_PLAY) ? f->rpar.rate : f->wpar.rate;
+               rate = (f->mode & MODE_PLAY) ? f->rpar.rate : f->wpar.rate;
                min = 1;
                max = 1 + rate / f->dev->round;
                min *= f->round;
@@ -961,11 +961,11 @@ sock_setpar(struct sock *f)
                        dbg_puts(f->pipe.file.name);
                dbg_puts(": buffer size = ");
                dbg_putu(f->bufsz);
-               if (f->mode & AMSG_PLAY) {
+               if (f->mode & MODE_PLAY) {
                        dbg_puts(", play = ");
                        aparams_dbg(&f->rpar);
                }
-               if (f->mode & AMSG_RECMASK) {
+               if (f->mode & MODE_RECMASK) {
                        dbg_puts(", rec:");
                        aparams_dbg(&f->wpar);
                }
@@ -979,18 +979,19 @@ sock_setpar(struct sock *f)
  * allocate buffers, so client can start filling write-end.
  */
 void
-sock_midiattach(struct sock *f, unsigned mode)
+sock_midiattach(struct sock *f)
 {
        struct abuf *rbuf = NULL, *wbuf = NULL;
        
-       if (mode & AMSG_MIDIOUT) {
+       if (f->mode & MODE_MIDIOUT) {
                rbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
                aproc_setout(f->pipe.file.rproc, rbuf);
        }
-       if (mode & AMSG_MIDIIN) {
+       if (f->mode & MODE_MIDIIN) {
                wbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
                aproc_setin(f->pipe.file.wproc, wbuf);
        }
+       f->pstate = SOCK_MIDI;
        dev_midiattach(f->dev, rbuf, wbuf);
 }
 
@@ -1004,8 +1005,8 @@ sock_hello(struct sock *f)
                sock_dbg(f);
                dbg_puts(": hello from <");
                dbg_puts(p->who);
-               dbg_puts(">, proto = ");
-               dbg_putx(p->proto);
+               dbg_puts(">, mode = ");
+               dbg_putx(p->mode);
                dbg_puts(", ver ");
                dbg_putu(p->version);
                dbg_puts("\n");
@@ -1017,7 +1018,26 @@ sock_hello(struct sock *f)
                        sock_dbg(f);
                        dbg_puts(": ");
                        dbg_putu(p->version);
-                       dbg_puts(": bad version\n");
+                       dbg_puts(": unsupported protocol version\n");
+               }
+#endif
+               return 0;
+       }
+       switch (p->mode) {
+       case MODE_MIDIIN:
+       case MODE_MIDIOUT:
+       case MODE_MIDIOUT | MODE_MIDIIN:
+       case MODE_REC:
+       case MODE_PLAY:
+       case MODE_PLAY | MODE_REC:
+               break;
+       default:
+#ifdef DEBUG
+               if (debug_level >= 1) {
+                       sock_dbg(f);
+                       dbg_puts(": ");
+                       dbg_putx(p->mode);
+                       dbg_puts(": unsupported mode\n");
                }
 #endif
                return 0;
@@ -1027,85 +1047,45 @@ sock_hello(struct sock *f)
                return 0;
        if (!dev_ref(f->opt->dev))
                return 0;
+       if ((p->mode & MODE_REC) && (f->opt->mode & MODE_MON)) {
+               p->mode &= ~MODE_REC;
+               p->mode |= MODE_MON;
+       }
        f->dev = f->opt->dev;
-
-       if (APROC_OK(f->dev->midi) && (p->proto & (AMSG_MIDIIN | 
AMSG_MIDIOUT))) {
-               if (p->proto & ~(AMSG_MIDIIN | AMSG_MIDIOUT)) {
+       f->mode = (p->mode & f->opt->mode) & f->dev->mode;
 #ifdef DEBUG
-                       if (debug_level >= 1) {
-                               sock_dbg(f);
-                               dbg_puts(": ");
-                               dbg_putx(p->proto);
-                               dbg_puts(": bad hello protocol\n");
-                       }
-#endif
-                       return 0;
-               }
-               f->mode = p->proto;
-               f->pstate = SOCK_MIDI;
-               sock_midiattach(f, p->proto);
-               return 1;
+       if (debug_level >= 3) {
+               sock_dbg(f);
+               dbg_puts(": using mode = ");
+               dbg_putx(f->mode);
+               dbg_puts("\n");
        }
-       if (f->opt->mode & MODE_RECMASK)
-               f->wpar = f->opt->wpar;
-       if (f->opt->mode & MODE_PLAY)
-               f->rpar = f->opt->rpar;
-       if (f->opt->mmc)
-               f->xrun = AMSG_SYNC;
-       f->bufsz = f->dev->bufsz;
-       f->round = f->dev->round;
-       if ((p->proto & ~(AMSG_PLAY | AMSG_REC)) != 0 ||
-           (p->proto &  (AMSG_PLAY | AMSG_REC)) == 0) {
+#endif
+       if (f->mode != p->mode) {
 #ifdef DEBUG
                if (debug_level >= 1) {
                        sock_dbg(f);
-                       dbg_puts(": ");
-                       dbg_putx(p->proto);
-                       dbg_puts(": unsupported hello protocol\n");
+                       dbg_puts(": requested mode not available\n");
                }
 #endif
                return 0;
        }
-       f->mode = 0;
-       if (p->proto & AMSG_PLAY) {
-               if (!APROC_OK(f->dev->mix) || !(f->opt->mode & MODE_PLAY)) {
-#ifdef DEBUG
-                       if (debug_level >= 1) {
-                               sock_dbg(f);
-                               dbg_puts(": playback not available\n");
-                       }
-#endif
-                       return 0;
-               }
-               f->mode |= AMSG_PLAY;
-       }
-       if (p->proto & AMSG_REC) {
-               if (!(APROC_OK(f->dev->sub)    && (f->opt->mode & MODE_REC)) &&
-                   !(APROC_OK(f->dev->submon) && (f->opt->mode & MODE_MON))) {
-#ifdef DEBUG
-                       if (debug_level >= 1) {
-                               sock_dbg(f);
-                               dbg_puts(": recording not available\n");
-                       }
-#endif
-                       return 0;
-               }
-               f->mode |= (f->opt->mode & MODE_MON) ? AMSG_MON : AMSG_REC;
-       }
-       if (APROC_OK(f->dev->midi)) {
-               f->slot = ctl_slotnew(f->dev->midi,
-                    p->who, &ctl_sockops, f,
-                    f->opt->mmc);
-               if (f->slot < 0) {
-#ifdef DEBUG
-                       if (debug_level >= 1) {
-                               sock_dbg(f);
-                               dbg_puts(": out of mixer slots\n");
-                       }
-#endif
-                       return 0;
-               }
+       if (f->mode & (MODE_MIDIOUT | MODE_MIDIIN)) {
+               sock_midiattach(f);
+               return 1;
        }
+       if (f->mode & MODE_PLAY)
+               f->rpar = f->opt->rpar;
+       if (f->mode & MODE_RECMASK)
+               f->wpar = f->opt->wpar;
+       f->xrun = (f->opt->mmc) ? XRUN_SYNC : XRUN_IGNORE;
+       f->bufsz = f->dev->bufsz;
+       f->round = f->dev->round;
+       f->slot = ctl_slotnew(f->dev->midi, p->who,
+           &ctl_sockops, f,
+           f->opt->mmc);
+       if (f->slot < 0)
+               return 0;
        f->pstate = SOCK_INIT;
        return 1;
 }
@@ -1139,7 +1119,7 @@ sock_execmsg(struct sock *f)
                        aproc_del(f->pipe.file.rproc);
                        return 0;
                }
-               if (!(f->mode & AMSG_PLAY)) {
+               if (!(f->mode & MODE_PLAY)) {
 #ifdef DEBUG
                        if (debug_level >= 1) {
                                sock_dbg(f);
@@ -1295,7 +1275,7 @@ sock_execmsg(struct sock *f)
                AMSG_INIT(m);
                m->cmd = AMSG_GETPAR;
                m->u.par.legacy_mode = f->mode;
-               if (f->mode & AMSG_PLAY) {
+               if (f->mode & MODE_PLAY) {
                        m->u.par.bits = f->rpar.bits;
                        m->u.par.bps = f->rpar.bps;
                        m->u.par.sig = f->rpar.sig;
@@ -1304,7 +1284,7 @@ sock_execmsg(struct sock *f)
                        m->u.par.rate = f->rpar.rate;
                        m->u.par.pchan = f->rpar.cmax - f->rpar.cmin + 1;
                }
-               if (f->mode & AMSG_RECMASK) {
+               if (f->mode & MODE_RECMASK) {
                        m->u.par.bits = f->wpar.bits;
                        m->u.par.bps = f->wpar.bps;
                        m->u.par.sig = f->wpar.sig;
@@ -1446,7 +1426,7 @@ sock_execmsg(struct sock *f)
                        dbg_puts(": RRET done\n");
                }
 #endif
-               if (f->pstate == SOCK_MIDI && (f->mode & AMSG_MIDIOUT)) {
+               if (f->pstate == SOCK_MIDI && (f->mode & MODE_MIDIOUT)) {
                        f->rstate = SOCK_RDATA;
                        f->rtodo = 0;
                } else {
@@ -1660,7 +1640,7 @@ sock_return(struct sock *f)
                        dbg_puts(": sent RRET message\n");
                }
 #endif
-               if (f->pstate == SOCK_MIDI && (f->mode & AMSG_MIDIOUT)) {
+               if (f->pstate == SOCK_MIDI && (f->mode & MODE_MIDIOUT)) {
                        f->rstate = SOCK_RDATA;
                        f->rtodo = 0;
                } else {
Index: usr.bin/aucat/sock.h
===================================================================
RCS file: /cvs/src/usr.bin/aucat/sock.h,v
retrieving revision 1.17
diff -u -p -r1.17 sock.h
--- usr.bin/aucat/sock.h        5 Jun 2010 12:45:48 -0000       1.17
+++ usr.bin/aucat/sock.h        17 Oct 2010 12:03:09 -0000
@@ -50,7 +50,7 @@ struct sock {
 #define SOCK_STOP      5               /* draining rec buffers */
 #define SOCK_MIDI      6               /* raw byte stream (midi) */
        unsigned pstate;                /* one of the above */
-       unsigned mode;                  /* a set of AMSG_PLAY, AMSG_REC */
+       unsigned mode;                  /* bitmask of MODE_XXX */
        struct aparams rpar;            /* read (ie play) parameters */
        struct aparams wpar;            /* write (ie rec) parameters */
        int delta;                      /* pos. change to send */

Reply via email to