diff options
-rw-r--r-- | usr.bin/aucat/abuf.c | 113 | ||||
-rw-r--r-- | usr.bin/aucat/abuf.h | 29 | ||||
-rw-r--r-- | usr.bin/aucat/amsg.h | 5 | ||||
-rw-r--r-- | usr.bin/aucat/aproc.c | 729 | ||||
-rw-r--r-- | usr.bin/aucat/aproc.h | 57 | ||||
-rw-r--r-- | usr.bin/aucat/aucat.1 | 72 | ||||
-rw-r--r-- | usr.bin/aucat/aucat.c | 299 | ||||
-rw-r--r-- | usr.bin/aucat/conf.h | 15 | ||||
-rw-r--r-- | usr.bin/aucat/dev.c | 366 | ||||
-rw-r--r-- | usr.bin/aucat/dev.h | 22 | ||||
-rw-r--r-- | usr.bin/aucat/file.c | 23 | ||||
-rw-r--r-- | usr.bin/aucat/headers.c | 22 | ||||
-rw-r--r-- | usr.bin/aucat/legacy.c | 6 | ||||
-rw-r--r-- | usr.bin/aucat/midi.c | 220 | ||||
-rw-r--r-- | usr.bin/aucat/midi.h | 6 | ||||
-rw-r--r-- | usr.bin/aucat/midicat.1 | 16 | ||||
-rw-r--r-- | usr.bin/aucat/opt.c | 42 | ||||
-rw-r--r-- | usr.bin/aucat/opt.h | 11 | ||||
-rw-r--r-- | usr.bin/aucat/pipe.c | 51 | ||||
-rw-r--r-- | usr.bin/aucat/pipe.h | 5 | ||||
-rw-r--r-- | usr.bin/aucat/siofile.c | 166 | ||||
-rw-r--r-- | usr.bin/aucat/siofile.h | 7 | ||||
-rw-r--r-- | usr.bin/aucat/sock.c | 338 | ||||
-rw-r--r-- | usr.bin/aucat/sock.h | 11 | ||||
-rw-r--r-- | usr.bin/aucat/wav.c | 740 | ||||
-rw-r--r-- | usr.bin/aucat/wav.h | 29 |
26 files changed, 1004 insertions, 2396 deletions
diff --git a/usr.bin/aucat/abuf.c b/usr.bin/aucat/abuf.c index a206a775d0b..fcffe898b70 100644 --- a/usr.bin/aucat/abuf.c +++ b/usr.bin/aucat/abuf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: abuf.c,v 1.19 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: abuf.c,v 1.20 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -105,9 +105,12 @@ abuf_new(unsigned nfr, struct aparams *par) /* * fill fifo pointers */ - buf->len = nfr; + buf->len = len; buf->used = 0; buf->start = 0; + buf->abspos = 0; + buf->silence = 0; + buf->drop = 0; buf->rproc = NULL; buf->wproc = NULL; buf->duplex = NULL; @@ -158,6 +161,9 @@ abuf_clear(struct abuf *buf) #endif buf->used = 0; buf->start = 0; + buf->abspos = 0; + buf->silence = 0; + buf->drop = 0; } /* @@ -185,7 +191,7 @@ abuf_rgetblk(struct abuf *buf, unsigned *rsize, unsigned ofs) if (count > used) count = used; *rsize = count; - return (unsigned char *)buf + sizeof(struct abuf) + start * buf->bpf; + return (unsigned char *)buf + sizeof(struct abuf) + start; } /* @@ -207,6 +213,7 @@ abuf_rdiscard(struct abuf *buf, unsigned count) buf->start += count; if (buf->start >= buf->len) buf->start -= buf->len; + buf->abspos += count; } /* @@ -253,7 +260,7 @@ abuf_wgetblk(struct abuf *buf, unsigned *rsize, unsigned ofs) if (count > avail) count = avail; *rsize = count; - return (unsigned char *)buf + sizeof(struct abuf) + end * buf->bpf; + return (unsigned char *)buf + sizeof(struct abuf) + end; } /* @@ -264,17 +271,47 @@ int abuf_flush_do(struct abuf *buf) { struct aproc *p; + unsigned count; - p = buf->rproc; - if (!p) - return 0; + if (buf->drop > 0) { + count = buf->drop; + if (count > buf->used) + count = buf->used; + if (count == 0) { #ifdef DEBUG - if (debug_level >= 4) { - aproc_dbg(p); - dbg_puts(": in\n"); - } + if (debug_level >= 4) { + abuf_dbg(buf); + dbg_puts(": flush: no data to drop\n"); + } +#endif + return 0; + } + abuf_rdiscard(buf, count); + buf->drop -= count; +#ifdef DEBUG + if (debug_level >= 4) { + abuf_dbg(buf); + dbg_puts(": flush: dropped "); + dbg_putu(count); + dbg_puts(", to drop = "); + dbg_putu(buf->drop); + dbg_puts("\n"); + } #endif - return p->ops->in(p, buf); + } else { + p = buf->rproc; + if (!p) + return 0; +#ifdef DEBUG + if (debug_level >= 4) { + aproc_dbg(p); + dbg_puts(": in\n"); + } +#endif + if (!p->ops->in(p, buf)) + return 0; + } + return 1; } /* @@ -285,17 +322,51 @@ int abuf_fill_do(struct abuf *buf) { struct aproc *p; - - p = buf->wproc; - if (!p) - return 0; + unsigned char *data; + unsigned count; + + if (buf->silence > 0) { + data = abuf_wgetblk(buf, &count, 0); + if (count >= buf->silence) + count = buf->silence; + if (count == 0) { #ifdef DEBUG - if (debug_level >= 4) { - aproc_dbg(p); - dbg_puts(": out\n"); - } + if (debug_level >= 4) { + abuf_dbg(buf); + dbg_puts(": fill: no space for silence\n"); + } +#endif + return 0; + } + memset(data, 0, count); + abuf_wcommit(buf, count); + buf->silence -= count; +#ifdef DEBUG + if (debug_level >= 4) { + abuf_dbg(buf); + dbg_puts(": fill: inerted "); + dbg_putu(count); + dbg_puts(", remaining silence = "); + dbg_putu(buf->silence); + dbg_puts("\n"); + } #endif - return p->ops->out(p, buf); + p = buf->wproc; + } else { + p = buf->wproc; + if (!p) + return 0; +#ifdef DEBUG + if (debug_level >= 4) { + aproc_dbg(p); + dbg_puts(": out\n"); + } +#endif + if (!p->ops->out(p, buf)) { + return 0; + } + } + return 1; } /* diff --git a/usr.bin/aucat/abuf.h b/usr.bin/aucat/abuf.h index a69495261b0..79c5e9a773d 100644 --- a/usr.bin/aucat/abuf.h +++ b/usr.bin/aucat/abuf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: abuf.h,v 1.20 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: abuf.h,v 1.21 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -39,6 +39,9 @@ struct abuf { unsigned start; /* offset where data starts */ unsigned used; /* valid data */ unsigned len; /* size of the ring */ + unsigned abspos; /* frame number of the start position */ + unsigned silence; /* silence to insert on next write */ + unsigned drop; /* bytes to drop on next read */ struct aproc *rproc; /* reader */ struct aproc *wproc; /* writer */ struct abuf *duplex; /* link to buffer of the other direction */ @@ -53,9 +56,8 @@ struct abuf { int weight; /* dynamic range */ int maxweight; /* max dynamic range allowed */ unsigned vol; /* volume within the dynamic range */ - unsigned done; /* frames ready */ + unsigned done; /* bytes ready */ unsigned xrun; /* underrun policy */ - int drop; /* frames to drop on next read */ } mix; struct { unsigned st; /* MIDI running status */ @@ -71,12 +73,11 @@ struct abuf { */ union { struct { - unsigned todo; /* frames to process */ + unsigned todo; /* bytes to process */ } mix; struct { - unsigned done; /* frames copied */ + unsigned done; /* bytes copied */ unsigned xrun; /* overrun policy */ - int silence; /* silence to add on next write */ } sub; } w; }; @@ -85,12 +86,12 @@ struct abuf { * the buffer contains at least one frame. This macro should * be used to check if the buffer can be flushed */ -#define ABUF_ROK(b) ((b)->used > 0) +#define ABUF_ROK(b) ((b)->used >= (b)->bpf) /* * there's room for at least one frame */ -#define ABUF_WOK(b) ((b)->len - (b)->used > 0) +#define ABUF_WOK(b) ((b)->len - (b)->used >= (b)->bpf) /* * the buffer is empty and has no writer anymore @@ -104,6 +105,18 @@ struct abuf { */ #define ABUF_HUP(b) (!ABUF_WOK(b) && (b)->rproc == NULL) +/* + * similar to !ABUF_WOK, but is used for file i/o, where + * operation may not involve an integer number of frames + */ +#define ABUF_FULL(b) ((b)->used == (b)->len) + +/* + * same as !ABUF_ROK, but used for files, where + * operations are byte orientated, not frame-oriented + */ +#define ABUF_EMPTY(b) ((b)->used == 0) + struct abuf *abuf_new(unsigned, struct aparams *); void abuf_del(struct abuf *); void abuf_dbg(struct abuf *); diff --git a/usr.bin/aucat/amsg.h b/usr.bin/aucat/amsg.h index 7da19f2e55e..c712c998ae3 100644 --- a/usr.bin/aucat/amsg.h +++ b/usr.bin/aucat/amsg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: amsg.h,v 1.13 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: amsg.h,v 1.14 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -87,8 +87,7 @@ struct amsg { #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 ? */ +#define AMSG_MIXER 0x10 /* MIDI mixer */ uint16_t proto; /* protocol type */ #define AMSG_VERSION 1 uint8_t version; /* protocol version */ diff --git a/usr.bin/aucat/aproc.c b/usr.bin/aucat/aproc.c index 4f71392a335..318326bbb42 100644 --- a/usr.bin/aucat/aproc.c +++ b/usr.bin/aucat/aproc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aproc.c,v 1.49 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: aproc.c,v 1.50 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -48,18 +48,6 @@ #include "dbg.h" #endif -/* - * Same as ABUF_ROK(), but consider that a buffer is - * readable if there's silence pending to be inserted - */ -#define MIX_ROK(buf) (ABUF_ROK(buf) || (buf)->r.mix.drop < 0) - -/* - * Same as ABUF_WOK(), but consider that a buffer is - * writeable if there are samples to drop - */ -#define SUB_WOK(buf) (ABUF_WOK(buf) || (buf)->w.sub.silence < 0) - #ifdef DEBUG void aproc_dbg(struct aproc *p) @@ -287,40 +275,20 @@ aproc_depend(struct aproc *p, struct aproc *dep) } int -rfile_do(struct aproc *p, unsigned todo, unsigned *done) -{ - struct abuf *obuf = LIST_FIRST(&p->obuflist); - struct file *f = p->u.io.file; - unsigned char *data; - unsigned n, count, off; - - off = p->u.io.partial; - data = abuf_wgetblk(obuf, &count, 0); - if (count > todo) - count = todo; - n = file_read(f, data + off, count * obuf->bpf - off); - if (n == 0) - return 0; - n += off; - p->u.io.partial = n % obuf->bpf; - count = n / obuf->bpf; - if (count > 0) - abuf_wcommit(obuf, count); - if (done) - *done = count; - return 1; -} - -int rfile_in(struct aproc *p, struct abuf *ibuf_dummy) { struct abuf *obuf = LIST_FIRST(&p->obuflist); struct file *f = p->u.io.file; + unsigned char *data; + unsigned count; - if (!ABUF_WOK(obuf) || !(f->state & FILE_ROK)) + if (ABUF_FULL(obuf) || !(f->state & FILE_ROK)) return 0; - if (!rfile_do(p, obuf->len, NULL)) + data = abuf_wgetblk(obuf, &count, 0); + count = file_read(f, data, count); + if (count == 0) return 0; + abuf_wcommit(obuf, count); if (!abuf_flush(obuf)) return 0; return 1; @@ -330,13 +298,18 @@ int rfile_out(struct aproc *p, struct abuf *obuf) { struct file *f = p->u.io.file; + unsigned char *data; + unsigned count; if (f->state & FILE_RINUSE) return 0; - if (!ABUF_WOK(obuf) || !(f->state & FILE_ROK)) + if (ABUF_FULL(obuf) || !(f->state & FILE_ROK)) return 0; - if (!rfile_do(p, obuf->len, NULL)) + data = abuf_wgetblk(obuf, &count, 0); + count = file_read(f, data, count); + if (count == 0) return 0; + abuf_wcommit(obuf, count); return 1; } @@ -349,12 +322,6 @@ rfile_done(struct aproc *p) if (f == NULL) return; /* - * disconnect from file structure - */ - f->rproc = NULL; - p->u.io.file = NULL; - - /* * all buffers must be detached before deleting f->wproc, * because otherwise it could trigger this code again */ @@ -362,18 +329,11 @@ rfile_done(struct aproc *p) if (obuf) abuf_eof(obuf); if (f->wproc) { + f->rproc = NULL; aproc_del(f->wproc); } else file_del(f); - -#ifdef DEBUG - if (debug_level >= 2 && p->u.io.partial > 0) { - aproc_dbg(p); - dbg_puts(": "); - dbg_putu(p->u.io.partial); - dbg_puts(" bytes lost in partial read\n"); - } -#endif + p->u.io.file = NULL; } void @@ -408,7 +368,6 @@ rfile_new(struct file *f) p = aproc_new(&rfile_ops, f->name); p->u.io.file = f; - p->u.io.partial = 0; f->rproc = p; return p; } @@ -422,12 +381,6 @@ wfile_done(struct aproc *p) if (f == NULL) return; /* - * disconnect from file structure - */ - f->wproc = NULL; - p->u.io.file = NULL; - - /* * all buffers must be detached before deleting f->rproc, * because otherwise it could trigger this code again */ @@ -435,54 +388,29 @@ wfile_done(struct aproc *p) if (ibuf) abuf_hup(ibuf); if (f->rproc) { + f->wproc = NULL; aproc_del(f->rproc); } else file_del(f); -#ifdef DEBUG - if (debug_level >= 2 && p->u.io.partial > 0) { - aproc_dbg(p); - dbg_puts(": "); - dbg_putu(p->u.io.partial); - dbg_puts(" bytes lost in partial write\n"); - } -#endif + p->u.io.file = NULL; } int -wfile_do(struct aproc *p, unsigned todo, unsigned *done) -{ - struct abuf *ibuf = LIST_FIRST(&p->ibuflist); - struct file *f = p->u.io.file; - unsigned char *data; - unsigned n, count, off; - - off = p->u.io.partial; - data = abuf_rgetblk(ibuf, &count, 0); - if (count > todo) - count = todo; - n = file_write(f, data + off, count * ibuf->bpf - off); - if (n == 0) - return 0; - n += off; - p->u.io.partial = n % ibuf->bpf; - count = n / ibuf->bpf; - if (count > 0) - abuf_rdiscard(ibuf, count); - if (done) - *done = count; - return 1; -} -int wfile_in(struct aproc *p, struct abuf *ibuf) { struct file *f = p->u.io.file; + unsigned char *data; + unsigned count; if (f->state & FILE_WINUSE) return 0; - if (!ABUF_ROK(ibuf) || !(f->state & FILE_WOK)) + if (ABUF_EMPTY(ibuf) || !(f->state & FILE_WOK)) return 0; - if (!wfile_do(p, ibuf->len, NULL)) + data = abuf_rgetblk(ibuf, &count, 0); + count = file_write(f, data, count); + if (count == 0) return 0; + abuf_rdiscard(ibuf, count); return 1; } @@ -491,13 +419,22 @@ wfile_out(struct aproc *p, struct abuf *obuf_dummy) { struct abuf *ibuf = LIST_FIRST(&p->ibuflist); struct file *f = p->u.io.file; + unsigned char *data; + unsigned count; if (!abuf_fill(ibuf)) return 0; - if (!ABUF_ROK(ibuf) || !(f->state & FILE_WOK)) + if (ABUF_EMPTY(ibuf) || !(f->state & FILE_WOK)) + return 0; + data = abuf_rgetblk(ibuf, &count, 0); + if (count == 0) { + /* XXX: this can't happen, right ? */ return 0; - if (!wfile_do(p, ibuf->len, NULL)) + } + count = file_write(f, data, count); + if (count == 0) return 0; + abuf_rdiscard(ibuf, count); return 1; } @@ -533,83 +470,45 @@ wfile_new(struct file *f) p = aproc_new(&wfile_ops, f->name); p->u.io.file = f; - p->u.io.partial = 0; f->wproc = p; return p; } /* - * Drop as much as possible samples from the reader end, - * negative values mean ``insert silence''. - */ -void -mix_drop(struct abuf *buf, int extra) -{ - unsigned count; - - buf->r.mix.drop += extra; - while (buf->r.mix.drop > 0) { - count = buf->r.mix.drop; - if (count > buf->used) - count = buf->used; - if (count == 0) { -#ifdef DEBUG - if (debug_level >= 4) { - abuf_dbg(buf); - dbg_puts(": drop: no data\n"); - } -#endif - return; - } - abuf_rdiscard(buf, count); - buf->r.mix.drop -= count; -#ifdef DEBUG - if (debug_level >= 4) { - abuf_dbg(buf); - dbg_puts(": dropped "); - dbg_putu(count); - dbg_puts(", to drop = "); - dbg_putu(buf->r.mix.drop); - dbg_puts("\n"); - } -#endif - } -} - -/* * Append the given amount of silence (or less if there's not enough - * space), and crank w.mix.todo accordingly. + * space), and crank mixitodo accordingly. */ void -mix_bzero(struct abuf *obuf) +mix_bzero(struct abuf *obuf, unsigned zcount) { short *odata; unsigned ocount; - odata = (short *)abuf_wgetblk(obuf, &ocount, obuf->w.mix.todo); - if (ocount == 0) - return; - memset(odata, 0, ocount * obuf->bpf); - obuf->w.mix.todo += ocount; #ifdef DEBUG if (debug_level >= 4) { abuf_dbg(obuf); dbg_puts(": bzero("); - dbg_putu(obuf->w.mix.todo); + dbg_putu(zcount); dbg_puts(")\n"); } #endif + odata = (short *)abuf_wgetblk(obuf, &ocount, obuf->w.mix.todo); + ocount -= ocount % obuf->bpf; + if (ocount > zcount) + ocount = zcount; + memset(odata, 0, ocount); + obuf->w.mix.todo += ocount; } /* * Mix an input block over an output block. */ -unsigned +void mix_badd(struct abuf *ibuf, struct abuf *obuf) { short *idata, *odata; unsigned i, j, icnt, onext, ostart; - unsigned scount, icount, ocount; + unsigned scount, icount, ocount, zcount; int vol; #ifdef DEBUG @@ -619,37 +518,31 @@ mix_badd(struct abuf *ibuf, struct abuf *obuf) dbg_putu(ibuf->r.mix.done); dbg_puts("/"); dbg_putu(obuf->w.mix.todo); - dbg_puts(", drop = "); - dbg_puti(ibuf->r.mix.drop); dbg_puts("\n"); } #endif /* - * Insert silence for xrun correction - */ - if (ibuf->r.mix.drop < 0) { - icount = -ibuf->r.mix.drop; - ocount = obuf->len - obuf->used; - if (ocount > obuf->w.mix.todo) - ocount = obuf->w.mix.todo; - scount = (icount < ocount) ? icount : ocount; - ibuf->r.mix.done += scount; - ibuf->r.mix.drop += scount; - } - - /* * Calculate the maximum we can read. */ idata = (short *)abuf_rgetblk(ibuf, &icount, 0); + icount /= ibuf->bpf; if (icount == 0) - return 0; + return; + + /* + * Zero-fill if necessary. + */ + zcount = ibuf->r.mix.done + icount * obuf->bpf; + if (zcount > obuf->w.mix.todo) + mix_bzero(obuf, zcount - obuf->w.mix.todo); /* * Calculate the maximum we can write. */ odata = (short *)abuf_wgetblk(obuf, &ocount, ibuf->r.mix.done); + ocount /= obuf->bpf; if (ocount == 0) - return 0; + return; vol = (ibuf->r.mix.weight * ibuf->r.mix.vol) >> ADATA_SHIFT; ostart = ibuf->cmin - obuf->cmin; @@ -665,30 +558,30 @@ mix_badd(struct abuf *ibuf, struct abuf *obuf) } odata += onext; } - abuf_rdiscard(ibuf, scount); - ibuf->r.mix.done += scount; + abuf_rdiscard(ibuf, scount * ibuf->bpf); + ibuf->r.mix.done += scount * obuf->bpf; #ifdef DEBUG if (debug_level >= 4) { abuf_dbg(ibuf); dbg_puts(": badd: done = "); + dbg_putu(scount); + dbg_puts(", todo = "); dbg_putu(ibuf->r.mix.done); dbg_puts("/"); dbg_putu(obuf->w.mix.todo); dbg_puts("\n"); } #endif - return scount; } /* * Handle buffer underrun, return 0 if stream died. */ int -mix_xrun(struct aproc *p, struct abuf *i) +mix_xrun(struct abuf *i, struct abuf *obuf) { - struct abuf *obuf = LIST_FIRST(&p->obuflist); - unsigned fdrop, remain; + unsigned fdrop; if (i->r.mix.done > 0) return 1; @@ -696,34 +589,22 @@ mix_xrun(struct aproc *p, struct abuf *i) abuf_hup(i); return 0; } - fdrop = obuf->w.mix.todo; + mix_bzero(obuf, obuf->len); + fdrop = obuf->w.mix.todo / obuf->bpf; #ifdef DEBUG if (debug_level >= 3) { abuf_dbg(i); dbg_puts(": underrun, dropping "); dbg_putu(fdrop); dbg_puts(" + "); - dbg_putu(i->r.mix.drop); + dbg_putu(i->drop / i->bpf); dbg_puts("\n"); } #endif - i->r.mix.done += fdrop; + i->r.mix.done += fdrop * obuf->bpf; if (i->r.mix.xrun == XRUN_SYNC) - mix_drop(i, fdrop); + i->drop += fdrop * i->bpf; else { - remain = fdrop % p->u.mix.round; - if (remain) - remain = p->u.mix.round - remain; - mix_drop(i, -(int)remain); - fdrop += remain; -#ifdef DEBUG - if (debug_level >= 3) { - abuf_dbg(i); - dbg_puts(": underrun, adding "); - dbg_putu(remain); - dbg_puts("\n"); - } -#endif abuf_opos(i, -(int)fdrop); if (i->duplex) { #ifdef DEBUG @@ -732,7 +613,7 @@ mix_xrun(struct aproc *p, struct abuf *i) dbg_puts(": full-duplex resync\n"); } #endif - sub_silence(i->duplex, -(int)fdrop); + i->duplex->drop += fdrop * i->duplex->bpf; abuf_ipos(i->duplex, -(int)fdrop); } } @@ -744,8 +625,6 @@ mix_in(struct aproc *p, struct abuf *ibuf) { struct abuf *i, *inext, *obuf = LIST_FIRST(&p->obuflist); unsigned odone; - unsigned maxwrite; - unsigned scount; #ifdef DEBUG if (debug_level >= 4) { @@ -761,50 +640,27 @@ mix_in(struct aproc *p, struct abuf *ibuf) dbg_puts("\n"); } #endif - if (!MIX_ROK(ibuf)) + if (!ABUF_ROK(ibuf)) return 0; - mix_bzero(obuf); - scount = 0; - odone = obuf->w.mix.todo; + odone = obuf->len; for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) { inext = LIST_NEXT(i, ient); - if (i->r.mix.drop >= 0 && !abuf_fill(i)) + if (!abuf_fill(i)) continue; /* eof */ - mix_drop(i, 0); - scount += mix_badd(i, obuf); + mix_badd(i, obuf); if (odone > i->r.mix.done) odone = i->r.mix.done; } - if (LIST_EMPTY(&p->ibuflist) || scount == 0) + if (LIST_EMPTY(&p->ibuflist) || odone == 0) return 0; -#ifdef DEBUG - if (debug_level >= 4) { - aproc_dbg(p); - dbg_puts(": maxwrite = "); - dbg_putu(p->u.mix.maxlat); - dbg_puts(" - "); - dbg_putu(p->u.mix.lat); - dbg_puts(" = "); - dbg_putu(p->u.mix.maxlat - p->u.mix.lat); - dbg_puts("\n"); - } -#endif - maxwrite = p->u.mix.maxlat - p->u.mix.lat; - if (maxwrite > 0) { - if (odone > maxwrite) - odone = maxwrite; - p->u.mix.lat += odone; - p->u.mix.abspos += odone; - LIST_FOREACH(i, &p->ibuflist, ient) { - i->r.mix.done -= odone; - } - abuf_wcommit(obuf, odone); - obuf->w.mix.todo -= odone; - if (APROC_OK(p->u.mix.mon)) - mon_snoop(p->u.mix.mon, obuf, obuf->used - odone, odone); - if (!abuf_flush(obuf)) - return 0; /* hup */ + p->u.mix.lat += odone / obuf->bpf; + LIST_FOREACH(i, &p->ibuflist, ient) { + i->r.mix.done -= odone; } + abuf_wcommit(obuf, odone); + obuf->w.mix.todo -= odone; + if (!abuf_flush(obuf)) + return 0; /* hup */ return 1; } @@ -813,8 +669,6 @@ mix_out(struct aproc *p, struct abuf *obuf) { struct abuf *i, *inext; unsigned odone; - unsigned maxwrite; - unsigned scount; #ifdef DEBUG if (debug_level >= 4) { @@ -832,34 +686,18 @@ mix_out(struct aproc *p, struct abuf *obuf) #endif if (!ABUF_WOK(obuf)) return 0; -#ifdef DEBUG - if (debug_level >= 4) { - aproc_dbg(p); - dbg_puts(": maxwrite = "); - dbg_putu(p->u.mix.maxlat); - dbg_puts(" - "); - dbg_putu(p->u.mix.lat); - dbg_puts(" = "); - dbg_putu(p->u.mix.maxlat - p->u.mix.lat); - dbg_puts("\n"); - } -#endif - maxwrite = p->u.mix.maxlat - p->u.mix.lat; - mix_bzero(obuf); - scount = 0; odone = obuf->len; for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) { inext = LIST_NEXT(i, ient); - if (i->r.mix.drop >= 0 && !abuf_fill(i)) + if (!abuf_fill(i)) continue; /* eof */ - mix_drop(i, 0); - if (maxwrite > 0 && !MIX_ROK(i)) { + if (!ABUF_ROK(i)) { if (p->flags & APROC_DROP) { - if (!mix_xrun(p, i)) + if (!mix_xrun(i, obuf)) continue; } } else - scount += mix_badd(i, obuf); + mix_badd(i, obuf); if (odone > i->r.mix.done) odone = i->r.mix.done; } @@ -870,31 +708,25 @@ mix_out(struct aproc *p, struct abuf *obuf) } if (!(p->flags & APROC_DROP)) return 0; + mix_bzero(obuf, obuf->len); odone = obuf->w.mix.todo; - p->u.mix.idle += odone; - } - if (maxwrite > 0) { - if (odone > maxwrite) - odone = maxwrite; - p->u.mix.lat += odone; - p->u.mix.abspos += odone; - LIST_FOREACH(i, &p->ibuflist, ient) { - i->r.mix.done -= odone; - } - abuf_wcommit(obuf, odone); - obuf->w.mix.todo -= odone; - if (APROC_OK(p->u.mix.mon)) - mon_snoop(p->u.mix.mon, obuf, obuf->used - odone, odone); + p->u.mix.idle += odone / obuf->bpf; } - if (scount == 0) + if (odone == 0) return 0; + p->u.mix.lat += odone / obuf->bpf; + LIST_FOREACH(i, &p->ibuflist, ient) { + i->r.mix.done -= odone; + } + abuf_wcommit(obuf, odone); + obuf->w.mix.todo -= odone; return 1; } void mix_eof(struct aproc *p, struct abuf *ibuf) { - struct abuf *i, *inext, *obuf = LIST_FIRST(&p->obuflist); + struct abuf *i, *obuf = LIST_FIRST(&p->obuflist); unsigned odone; mix_setmaster(p); @@ -910,11 +742,8 @@ mix_eof(struct aproc *p, struct abuf *ibuf) * Find a blocked input. */ odone = obuf->len; - for (i = LIST_FIRST(&p->ibuflist); i != NULL; i = inext) { - inext = LIST_NEXT(i, ient); - if (!abuf_fill(i)) - continue; - if (MIX_ROK(i) && i->r.mix.done < obuf->w.mix.todo) { + LIST_FOREACH(i, &p->ibuflist, ient) { + if (ABUF_ROK(i) && i->r.mix.done < obuf->w.mix.todo) { abuf_run(i); return; } @@ -952,7 +781,6 @@ mix_newin(struct aproc *p, struct abuf *ibuf) ibuf->r.mix.weight = ADATA_UNIT; ibuf->r.mix.maxweight = ADATA_UNIT; ibuf->r.mix.xrun = XRUN_IGNORE; - ibuf->r.mix.drop = 0; } void @@ -962,8 +790,8 @@ mix_newout(struct aproc *p, struct abuf *obuf) if (debug_level >= 3) { aproc_dbg(p); dbg_puts(": newin, will use "); - dbg_putu(obuf->len); - dbg_puts("\n"); + dbg_putu(obuf->len / obuf->bpf); + dbg_puts(" fr\n"); } #endif obuf->w.mix.todo = 0; @@ -972,7 +800,6 @@ mix_newout(struct aproc *p, struct abuf *obuf) void mix_opos(struct aproc *p, struct abuf *obuf, int delta) { - p->u.mix.lat -= delta; #ifdef DEBUG if (debug_level >= 4) { aproc_dbg(p); @@ -980,14 +807,13 @@ mix_opos(struct aproc *p, struct abuf *obuf, int delta) dbg_puti(p->u.mix.lat); dbg_puts("/"); dbg_puti(p->u.mix.maxlat); - dbg_puts("\n"); + dbg_puts(" fr\n"); } #endif - if (APROC_OK(p->u.mix.ctl)) + p->u.mix.lat -= delta; + if (p->u.mix.ctl) ctl_ontick(p->u.mix.ctl, delta); aproc_opos(p, obuf, delta); - if (APROC_OK(p->u.mix.mon)) - p->u.mix.mon->ops->ipos(p->u.mix.mon, NULL, delta); } struct aproc_ops mix_ops = { @@ -1004,16 +830,14 @@ struct aproc_ops mix_ops = { }; struct aproc * -mix_new(char *name, int maxlat, unsigned round, struct aproc *ctl) +mix_new(char *name, int maxlat, struct aproc *ctl) { struct aproc *p; p = aproc_new(&mix_ops, name); p->u.mix.idle = 0; p->u.mix.lat = 0; - p->u.mix.round = round; p->u.mix.maxlat = maxlat; - p->u.mix.abspos = 0; p->u.mix.ctl = ctl; return p; } @@ -1071,7 +895,6 @@ mix_clear(struct aproc *p) struct abuf *obuf = LIST_FIRST(&p->obuflist); p->u.mix.lat = 0; - p->u.mix.abspos = 0; obuf->w.mix.todo = 0; } @@ -1084,19 +907,16 @@ mix_prime(struct aproc *p) for (;;) { if (!ABUF_WOK(obuf)) break; - todo = p->u.mix.maxlat - p->u.mix.lat; + todo = (p->u.mix.maxlat - p->u.mix.lat) * obuf->bpf; if (todo == 0) break; - mix_bzero(obuf); + mix_bzero(obuf, obuf->len); count = obuf->w.mix.todo; if (count > todo) count = todo; obuf->w.mix.todo -= count; - p->u.mix.lat += count; - p->u.mix.abspos += count; + p->u.mix.lat += count / obuf->bpf; 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 @@ -1112,45 +932,6 @@ mix_prime(struct aproc *p) } /* - * Append as much as possible silence on the writer end - */ -void -sub_silence(struct abuf *buf, int extra) -{ - unsigned char *data; - unsigned count; - - buf->w.sub.silence += extra; - if (buf->w.sub.silence > 0) { - data = abuf_wgetblk(buf, &count, 0); - if (count >= buf->w.sub.silence) - count = buf->w.sub.silence; - if (count == 0) { -#ifdef DEBUG - if (debug_level >= 4) { - abuf_dbg(buf); - dbg_puts(": no space for silence\n"); - } -#endif - return; - } - memset(data, 0, count * buf->bpf); - abuf_wcommit(buf, count); - buf->w.sub.silence -= count; -#ifdef DEBUG - if (debug_level >= 4) { - abuf_dbg(buf); - dbg_puts(": appended "); - dbg_putu(count); - dbg_puts(", remaining silence = "); - dbg_putu(buf->w.sub.silence); - dbg_puts("\n"); - } -#endif - } -} - -/* * Copy data from ibuf to obuf. */ void @@ -1160,21 +941,12 @@ sub_bcopy(struct abuf *ibuf, struct abuf *obuf) unsigned i, j, ocnt, inext, istart; unsigned icount, ocount, scount; - /* - * Drop samples for xrun correction - */ - if (obuf->w.sub.silence < 0) { - scount = -obuf->w.sub.silence; - if (scount > ibuf->used) - scount = ibuf->used; - obuf->w.sub.done += scount; - obuf->w.sub.silence += scount; - } - idata = (short *)abuf_rgetblk(ibuf, &icount, obuf->w.sub.done); + icount /= ibuf->bpf; if (icount == 0) return; odata = (short *)abuf_wgetblk(obuf, &ocount, 0); + ocount /= obuf->bpf; if (ocount == 0) return; istart = obuf->cmin - ibuf->cmin; @@ -1190,14 +962,14 @@ sub_bcopy(struct abuf *ibuf, struct abuf *obuf) } idata += inext; } - abuf_wcommit(obuf, scount); - obuf->w.sub.done += scount; + abuf_wcommit(obuf, scount * obuf->bpf); + obuf->w.sub.done += scount * ibuf->bpf; #ifdef DEBUG if (debug_level >= 4) { abuf_dbg(obuf); dbg_puts(": bcopy "); dbg_putu(scount); - dbg_puts("\n"); + dbg_puts(" fr\n"); } #endif } @@ -1206,10 +978,9 @@ sub_bcopy(struct abuf *ibuf, struct abuf *obuf) * Handle buffer overruns. Return 0 if the stream died. */ int -sub_xrun(struct aproc *p, struct abuf *i) +sub_xrun(struct abuf *ibuf, struct abuf *i) { - struct abuf *ibuf = LIST_FIRST(&p->ibuflist); - unsigned fdrop, remain; + unsigned fdrop; if (i->w.sub.done > 0) return 1; @@ -1217,35 +988,20 @@ sub_xrun(struct aproc *p, struct abuf *i) abuf_eof(i); return 0; } - fdrop = ibuf->used; + fdrop = ibuf->used / ibuf->bpf; #ifdef DEBUG if (debug_level >= 3) { abuf_dbg(i); dbg_puts(": overrun, silence "); dbg_putu(fdrop); dbg_puts(" + "); - dbg_putu(i->w.sub.silence); + dbg_putu(i->silence / i->bpf); dbg_puts("\n"); } #endif - i->w.sub.done += fdrop; if (i->w.sub.xrun == XRUN_SYNC) - sub_silence(i, fdrop); + i->silence += fdrop * i->bpf; else { - remain = fdrop % p->u.sub.round; - if (remain) - remain = p->u.sub.round - remain; - sub_silence(i, -(int)remain); - fdrop += remain; -#ifdef DEBUG - if (debug_level >= 3) { - abuf_dbg(i); - dbg_puts(": overrun, adding "); - dbg_putu(remain); - dbg_puts("\n"); - } -#endif - abuf_ipos(i, -(int)fdrop); if (i->duplex) { #ifdef DEBUG @@ -1254,10 +1010,11 @@ sub_xrun(struct aproc *p, struct abuf *i) dbg_puts(": full-duplex resync\n"); } #endif - mix_drop(i->duplex, -(int)fdrop); + i->duplex->silence += fdrop * i->duplex->bpf; abuf_opos(i->duplex, -(int)fdrop); } } + i->w.sub.done += fdrop * ibuf->bpf; return 1; } @@ -1272,10 +1029,9 @@ sub_in(struct aproc *p, struct abuf *ibuf) idone = ibuf->len; for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) { inext = LIST_NEXT(i, oent); - sub_silence(i, 0); - if (!SUB_WOK(i)) { + if (!ABUF_WOK(i)) { if (p->flags & APROC_DROP) { - if (!sub_xrun(p, i)) + if (!sub_xrun(ibuf, i)) continue; } } else @@ -1293,7 +1049,7 @@ sub_in(struct aproc *p, struct abuf *ibuf) if (!(p->flags & APROC_DROP)) return 0; idone = ibuf->used; - p->u.sub.idle += idone; + p->u.sub.idle += idone / ibuf->bpf; } if (idone == 0) return 0; @@ -1301,9 +1057,7 @@ sub_in(struct aproc *p, struct abuf *ibuf) i->w.sub.done -= idone; } abuf_rdiscard(ibuf, idone); - abuf_opos(ibuf, idone); - p->u.sub.lat -= idone; - p->u.sub.abspos += idone; + p->u.sub.lat -= idone / ibuf->bpf; return 1; } @@ -1314,14 +1068,13 @@ sub_out(struct aproc *p, struct abuf *obuf) struct abuf *i, *inext; unsigned idone; - if (!SUB_WOK(obuf)) + if (!ABUF_WOK(obuf)) return 0; if (!abuf_fill(ibuf)) return 0; /* eof */ idone = ibuf->len; for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) { inext = LIST_NEXT(i, oent); - sub_silence(i, 0); sub_bcopy(ibuf, i); if (idone > i->w.sub.done) idone = i->w.sub.done; @@ -1334,9 +1087,7 @@ sub_out(struct aproc *p, struct abuf *obuf) i->w.sub.done -= idone; } abuf_rdiscard(ibuf, idone); - abuf_opos(ibuf, idone); - p->u.sub.lat -= idone; - p->u.sub.abspos += idone; + p->u.sub.lat -= idone / ibuf->bpf; return 1; } @@ -1349,7 +1100,7 @@ sub_eof(struct aproc *p, struct abuf *ibuf) void sub_hup(struct aproc *p, struct abuf *obuf) { - struct abuf *i, *inext, *ibuf = LIST_FIRST(&p->ibuflist); + struct abuf *i, *ibuf = LIST_FIRST(&p->ibuflist); unsigned idone; if (!aproc_inuse(p)) { @@ -1363,11 +1114,8 @@ sub_hup(struct aproc *p, struct abuf *obuf) * Find a blocked output. */ idone = ibuf->len; - for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) { - inext = LIST_NEXT(i, oent); - if (!abuf_flush(i)) - continue; - if (SUB_WOK(i) && i->w.sub.done < ibuf->used) { + LIST_FOREACH(i, &p->obuflist, oent) { + if (ABUF_WOK(i) && i->w.sub.done < ibuf->used) { abuf_run(i); return; } @@ -1396,7 +1144,6 @@ sub_newout(struct aproc *p, struct abuf *obuf) p->u.sub.idle = 0; obuf->w.sub.done = 0; obuf->w.sub.xrun = XRUN_IGNORE; - obuf->w.sub.silence = 0; } void @@ -1410,10 +1157,10 @@ sub_ipos(struct aproc *p, struct abuf *ibuf, int delta) dbg_puti(p->u.sub.lat); dbg_puts("/"); dbg_puti(p->u.sub.maxlat); - dbg_puts("\n"); + dbg_puts(" fr\n"); } #endif - if (APROC_OK(p->u.sub.ctl)) + if (p->u.sub.ctl) ctl_ontick(p->u.sub.ctl, delta); aproc_ipos(p, ibuf, delta); } @@ -1432,16 +1179,14 @@ struct aproc_ops sub_ops = { }; struct aproc * -sub_new(char *name, int maxlat, unsigned round, struct aproc *ctl) +sub_new(char *name, int maxlat, struct aproc *ctl) { struct aproc *p; p = aproc_new(&sub_ops, name); p->u.sub.idle = 0; p->u.sub.lat = 0; - p->u.sub.round = round; p->u.sub.maxlat = maxlat; - p->u.sub.abspos = 0; p->u.sub.ctl = ctl; return p; } @@ -1449,8 +1194,7 @@ sub_new(char *name, int maxlat, unsigned round, struct aproc *ctl) void sub_clear(struct aproc *p) { - p->u.sub.lat = 0; - p->u.sub.abspos = 0; + p->u.mix.lat = 0; } /* @@ -1477,10 +1221,12 @@ resamp_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf) * Calculate max frames readable at once from the input buffer. */ idata = (short *)abuf_rgetblk(ibuf, &icount, 0); - ifr = icount; + ifr = icount / ibuf->bpf; + icount = ifr * ibuf->bpf; odata = (short *)abuf_wgetblk(obuf, &ocount, 0); - ofr = ocount; + ofr = ocount / obuf->bpf; + ocount = ofr * obuf->bpf; /* * Partially copy structures into local variables, to avoid @@ -1512,8 +1258,6 @@ resamp_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf) #endif for (;;) { if (diff < 0) { - if (ifr == 0) - break; ctx_start ^= 1; ctx = ctxbuf + ctx_start; for (c = inch; c > 0; c--) { @@ -1521,10 +1265,9 @@ resamp_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf) ctx += RESAMP_NCTX; } diff += oblksz; - ifr--; - } else { - if (ofr == 0) + if (--ifr == 0) break; + } else { ctx = ctxbuf; for (c = onch; c > 0; c--) { s1 = ctx[ctx_start]; @@ -1533,7 +1276,8 @@ resamp_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf) *odata++ = s1 + (s2 - s1) * diff / (int)oblksz; } diff -= iblksz; - ofr--; + if (--ofr == 0) + break; } } p->u.resamp.diff = diff; @@ -1553,8 +1297,8 @@ resamp_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf) /* * Update FIFO pointers. */ - icount -= ifr; - ocount -= ofr; + icount -= ifr * ibuf->bpf; + ocount -= ofr * obuf->bpf; abuf_rdiscard(ibuf, icount); abuf_wcommit(obuf, ocount); } @@ -1677,9 +1421,11 @@ cmap_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf) * Calculate max frames readable at once from the input buffer. */ idata = (short *)abuf_rgetblk(ibuf, &icount, 0); + icount /= ibuf->bpf; if (icount == 0) return; odata = (short *)abuf_wgetblk(obuf, &ocount, 0); + ocount /= obuf->bpf; if (ocount == 0) return; scount = icount < ocount ? icount : ocount; @@ -1710,8 +1456,8 @@ cmap_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf) dbg_puts(" fr\n"); } #endif - abuf_rdiscard(ibuf, scount); - abuf_wcommit(obuf, scount); + abuf_rdiscard(ibuf, scount * ibuf->bpf); + abuf_wcommit(obuf, scount * obuf->bpf); } int @@ -1809,9 +1555,11 @@ enc_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf) * Calculate max frames readable at once from the input buffer. */ idata = (short *)abuf_rgetblk(ibuf, &icount, 0); + icount /= ibuf->bpf; if (icount == 0) return; odata = abuf_wgetblk(obuf, &ocount, 0); + ocount /= obuf->bpf; if (ocount == 0) return; scount = (icount < ocount) ? icount : ocount; @@ -1821,7 +1569,7 @@ enc_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf) aproc_dbg(p); dbg_puts(": bcopy "); dbg_putu(scount); - dbg_puts(" fr / "); + dbg_puts(" fr * "); dbg_putu(nch); dbg_puts(" ch\n"); } @@ -1857,8 +1605,8 @@ enc_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf) /* * Update FIFO pointers. */ - abuf_rdiscard(ibuf, scount); - abuf_wcommit(obuf, scount); + abuf_rdiscard(ibuf, scount * ibuf->bpf); + abuf_wcommit(obuf, scount * obuf->bpf); } int @@ -1967,9 +1715,11 @@ dec_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf) * Calculate max frames readable at once from the input buffer. */ idata = abuf_rgetblk(ibuf, &icount, 0); + icount /= ibuf->bpf; if (icount == 0) return; odata = (short *)abuf_wgetblk(obuf, &ocount, 0); + ocount /= obuf->bpf; if (ocount == 0) return; scount = (icount < ocount) ? icount : ocount; @@ -1979,7 +1729,7 @@ dec_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf) aproc_dbg(p); dbg_puts(": bcopy "); dbg_putu(scount); - dbg_puts(" fr / "); + dbg_puts(" fr * "); dbg_putu(nch); dbg_puts(" ch\n"); } @@ -2015,8 +1765,8 @@ dec_bcopy(struct aproc *p, struct abuf *ibuf, struct abuf *obuf) /* * Update FIFO pointers. */ - abuf_rdiscard(ibuf, scount); - abuf_wcommit(obuf, scount); + abuf_rdiscard(ibuf, scount * ibuf->bpf); + abuf_wcommit(obuf, scount * obuf->bpf); } int @@ -2102,168 +1852,3 @@ dec_new(char *name, struct aparams *par) #endif return p; } - -/* - * Commit and flush part of the output buffer - */ -void -mon_flush(struct aproc *p) -{ - struct abuf *obuf = LIST_FIRST(&p->obuflist); - unsigned count; - -#ifdef DEBUG - if (debug_level >= 4) { - aproc_dbg(p); - dbg_puts(": delta = "); - dbg_puti(p->u.mon.delta); - dbg_puts("/"); - dbg_putu(p->u.mon.bufsz); - dbg_puts(" pending = "); - dbg_puti(p->u.mon.pending); - dbg_puts("\n"); - } -#endif - if (p->u.mon.delta <= 0 || p->u.mon.pending == 0) - return; - count = p->u.mon.delta; - if (count > p->u.mon.pending) - count = p->u.mon.pending; - abuf_wcommit(obuf, count); - p->u.mon.pending -= count; - p->u.mon.delta -= count; - abuf_flush(obuf); -} - -/* - * Copy one block. - */ -void -mon_snoop(struct aproc *p, struct abuf *ibuf, unsigned pos, unsigned todo) -{ - struct abuf *obuf = LIST_FIRST(&p->obuflist); - unsigned scount, icount, ocount; - short *idata, *odata; - -#ifdef DEBUG - if (debug_level >= 4) { - aproc_dbg(p); - dbg_puts(": snoop "); - dbg_putu(pos); - dbg_puts(".."); - dbg_putu(todo); - dbg_puts("\n"); - } -#endif - if (!abuf_flush(obuf)) - return; - - while (todo > 0) { - /* - * Calculate max frames readable at once from the input buffer. - */ - idata = (short *)abuf_rgetblk(ibuf, &icount, pos); - odata = (short *)abuf_wgetblk(obuf, &ocount, p->u.mon.pending); - scount = (icount < ocount) ? icount : ocount; -#ifdef DEBUG - if (debug_level >= 4) { - aproc_dbg(p); - dbg_puts(": snooping "); - dbg_putu(scount); - dbg_puts(" fr\n"); - } - if (scount == 0) { - dbg_puts("monitor xrun, not allowed\n"); - dbg_panic(); - } -#endif - memcpy(odata, idata, scount * obuf->bpf); - p->u.mon.pending += scount; - todo -= scount; - pos += scount; - } - mon_flush(p); -} - -int -mon_in(struct aproc *p, struct abuf *ibuf) -{ -#ifdef DEBUG - dbg_puts("monitor can't have inputs to read\n"); - dbg_panic(); -#endif - return 0; -} - -/* - * put the monitor into ``empty'' state - */ -void -mon_clear(struct aproc *p) -{ - p->u.mon.pending = 0; - p->u.mon.delta = 0; -} - -int -mon_out(struct aproc *p, struct abuf *obuf) -{ - /* - * can't trigger monitored stream to produce data - */ - return 0; -} - -void -mon_eof(struct aproc *p, struct abuf *ibuf) -{ -#ifdef DEBUG - dbg_puts("monitor can't have inputs to eof\n"); - dbg_panic(); -#endif -} - -void -mon_hup(struct aproc *p, struct abuf *obuf) -{ - aproc_del(p); -} - -void -mon_ipos(struct aproc *p, struct abuf *ibuf, int delta) -{ - aproc_ipos(p, ibuf, delta); - p->u.mon.delta += delta; - mon_flush(p); -} - -struct aproc_ops mon_ops = { - "mon", - mon_in, - mon_out, - mon_eof, - mon_hup, - NULL, - NULL, - mon_ipos, - aproc_opos, - NULL -}; - -struct aproc * -mon_new(char *name, unsigned bufsz) -{ - struct aproc *p; - - p = aproc_new(&mon_ops, name); - p->u.mon.pending = 0; - p->u.mon.delta = 0; - p->u.mon.bufsz = bufsz; -#ifdef DEBUG - if (debug_level >= 3) { - aproc_dbg(p); - dbg_puts(": new\n"); - } -#endif - return p; -} diff --git a/usr.bin/aucat/aproc.h b/usr.bin/aucat/aproc.h index 6b2947c852b..7b910155d3f 100644 --- a/usr.bin/aucat/aproc.h +++ b/usr.bin/aucat/aproc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: aproc.h,v 1.30 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: aproc.h,v 1.31 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -130,37 +130,26 @@ struct aproc { union { /* follow type-specific data */ struct { /* file/device io */ struct file *file; /* file to read/write */ - unsigned partial; /* bytes of partial frame */ } io; struct { unsigned idle; /* frames since idleing */ - unsigned round; /* block size, for xruns */ int lat; /* current latency */ int maxlat; /* max latency allowed */ - unsigned abspos; /* frames produced */ - struct aproc *ctl; /* MIDI control/sync */ - struct aproc *mon; /* snoop output */ + struct aproc *ctl; } mix; struct { unsigned idle; /* frames since idleing */ - unsigned round; /* block size, for xruns */ int lat; /* current latency */ int maxlat; /* max latency allowed */ - unsigned abspos; /* frames consumed */ struct aproc *ctl; } sub; struct { - int delta; /* time position */ - unsigned bufsz; /* buffer size (latency) */ - unsigned pending; /* uncommited samples */ - } mon; - struct { #define RESAMP_NCTX 2 unsigned ctx_start; short ctx[NCHAN_MAX * RESAMP_NCTX]; unsigned iblksz, oblksz; int diff; - int idelta, odelta; /* remainder of resamp_xpos */ + int idelta, odelta; /* remainder of resamp_[io]pos */ } resamp; struct { short ctx[NCHAN_MAX]; @@ -202,8 +191,6 @@ struct aproc { struct ctl_ops { void (*vol)(void *, unsigned); void (*start)(void *); - void (*stop)(void *); - void (*loc)(void *, unsigned); } *ops; void *arg; unsigned unit; @@ -216,18 +203,6 @@ struct aproc { } u; }; -/* - * Check if the given pointer is a valid aproc structure. - * - * aproc structures are not free()'d immediately, because - * there may be pointers to them, instead the APROC_ZOMB flag - * is set which means that they should not be used. When - * aprocs reference counter reaches zero, they are actually - * freed - */ -#define APROC_OK(p) ((p) && !((p)->flags & APROC_ZOMB)) - - struct aproc *aproc_new(struct aproc_ops *, char *); void aproc_del(struct aproc *); void aproc_dbg(struct aproc *); @@ -235,40 +210,18 @@ void aproc_setin(struct aproc *, struct abuf *); void aproc_setout(struct aproc *, struct abuf *); int aproc_depend(struct aproc *, struct aproc *); -void aproc_ipos(struct aproc *, struct abuf *, int); -void aproc_opos(struct aproc *, struct abuf *, int); - struct aproc *rfile_new(struct file *); struct aproc *wfile_new(struct file *); -struct aproc *mix_new(char *, int, unsigned, struct aproc *); -struct aproc *sub_new(char *, int, unsigned, struct aproc *); +struct aproc *mix_new(char *, int, struct aproc *); +struct aproc *sub_new(char *, int, struct aproc *); struct aproc *resamp_new(char *, unsigned, unsigned); struct aproc *cmap_new(char *, struct aparams *, struct aparams *); struct aproc *enc_new(char *, struct aparams *); struct aproc *dec_new(char *, struct aparams *); -struct aproc *mon_new(char *, unsigned); - -int rfile_in(struct aproc *, struct abuf *); -int rfile_out(struct aproc *, struct abuf *); -void rfile_eof(struct aproc *, struct abuf *); -void rfile_hup(struct aproc *, struct abuf *); -void rfile_done(struct aproc *); -int rfile_do(struct aproc *, unsigned, unsigned *); - -int wfile_in(struct aproc *, struct abuf *); -int wfile_out(struct aproc *, struct abuf *); -void wfile_eof(struct aproc *, struct abuf *); -void wfile_hup(struct aproc *, struct abuf *); -void wfile_done(struct aproc *); -int wfile_do(struct aproc *, unsigned, unsigned *); void mix_setmaster(struct aproc *); void mix_clear(struct aproc *); void mix_prime(struct aproc *); -void mix_drop(struct abuf *, int); -void sub_silence(struct abuf *, int); void sub_clear(struct aproc *); -void mon_snoop(struct aproc *, struct abuf *, unsigned, unsigned); -void mon_clear(struct aproc *); #endif /* !defined(APROC_H) */ diff --git a/usr.bin/aucat/aucat.1 b/usr.bin/aucat/aucat.1 index e03e10364cc..d29af368242 100644 --- a/usr.bin/aucat/aucat.1 +++ b/usr.bin/aucat/aucat.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: aucat.1,v 1.64 2010/04/03 17:40:33 ratchov Exp $ +.\" $OpenBSD: aucat.1,v 1.65 2010/04/03 17:59:17 ratchov Exp $ .\" .\" Copyright (c) 2006 Alexandre Ratchov <alex@caoua.org> .\" @@ -33,7 +33,6 @@ .Op Fl i Ar file .Op Fl m Ar mode .Op Fl o Ar file -.Op Fl q Ar device .Op Fl r Ar rate .Op Fl s Ar name .Op Fl t Ar mode @@ -58,7 +57,7 @@ which does not convert on the fly and supports playback of .au files. The options are as follows: .Bl -tag -width Ds .It Fl b Ar nframes -The buffer size of the audio device in frames. +The buffer size in frames. A frame consists of one sample for each channel in the stream. This is the number of frames that will be buffered before being played and thus controls the playback latency. @@ -106,21 +105,15 @@ but other names can be used with the .Fl s option. .It Fl m Ar mode -Set the stream mode. +Set the server mode. Valid modes are .Ar play , .Ar rec , and -.Ar mon , -corresponding to playback, recording and monitoring. -A monitoring stream is a fake recording stream corresponding to -the mix of all playback streams. -Multiple modes can be specified, separated by commas, -but the same stream cannot be used for both recording and monitoring. +.Ar duplex , +for play-only, record-only, and full-duplex, respectively. The default is -.\" no spaces allowed between modes -.Ar play,rec -(i.e., full-duplex). +.Ar duplex . .It Fl n Loopback mode. Instead of using an audio device, send input streams @@ -132,11 +125,6 @@ Add this file to the list of files in which to store recorded samples. If the option argument is .Sq - then standard output will be used. -.It Fl q Ar device -The -.Xr sndio 7 -MIDI device to use for controlling stream volumes or -to start multiple streams synchronously. .It Fl r Ar rate Sample rate in Hertz of the playback or record stream. The default is 44100Hz. @@ -487,54 +475,6 @@ behave normally, while streams connected to wait for the MMC start signal and start synchronously. Regardless of which device a stream is connected to, its playback volume knob is exposed. -.Pp -If -.Nm -is used to play and record audio files, it offers -similar MIDI control. -.Nm -can open a -.Xr sndio 7 -MIDI device allowing MIDI hardware or software -to control playback and recording in real time. -.Pp -A MIDI channel is assigned to each stream, and the volume -is changed using the standard volume controller (number 7). -Streams created with -.Fl t Ar slave -are controlled by the following MMC (MIDI Machine Control) messages: -.Bl -tag -width relocateXXX -offset -indent -.It start -Start all streams synchronously. -By default, streams are created in stopped state. -.It stop -Playback or recording is stopped, and -the stream is rewinded back to the starting position. -.It relocate -Streams are relocated to the requested time postion -relative to the beginning of the stream, at which playback -and recording must start. -If the requested position is beyond the end of file, -the stream is temporarly disabled until a valid postion is requested. -.El -.Pp -For instance, the following command will play a file on the -.Va aucat:0.mmc -audio device, and let full control to MIDI software or hardware -connected to the -.Va midithru:0 -MIDI device: -.Bd -literal -offset indent -$ aucat -f aucat:0.mmc -t slave -q midithru:0 -i file.wav -.Ed -.Pp -At this stage, -.Nm -will start, stop and relocate automatically following all user -actions in the MIDI sequencer. -Note that the sequencer must use -.Va aucat:0 -as MTC source, i.e., the audio server, not the audio player. .Sh LEGACY MODE If neither .Fl i diff --git a/usr.bin/aucat/aucat.c b/usr.bin/aucat/aucat.c index e2bebf47668..81093f42a4c 100644 --- a/usr.bin/aucat/aucat.c +++ b/usr.bin/aucat/aucat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aucat.c,v 1.81 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: aucat.c,v 1.82 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -43,6 +43,9 @@ #include "dbg.h" #endif +#define MODE_PLAY 1 +#define MODE_REC 2 + #define PROG_AUCAT "aucat" #define PROG_MIDICAT "midicat" @@ -156,33 +159,16 @@ opt_xrun(void) errx(1, "%s: bad underrun/overrun policy", optarg); } -unsigned +int opt_mode(void) { - unsigned mode = 0; - char *p = optarg; - size_t len; - - for (p = optarg; *p != NULL; p++) { - len = strcspn(p, ","); - if (strncmp("play", p, len) == 0) { - mode |= MODE_PLAY; - } else if (strncmp("rec", p, len) == 0) { - mode |= MODE_REC; - } else if (strncmp("mon", p, len) == 0) { - mode |= MODE_MON; - } else if (strncmp("duplex", p, len) == 0) { - /* XXX: backward compat, remove this */ - mode |= MODE_REC | MODE_PLAY; - } else - errx(1, "%s: bad mode", optarg); - p += len; - if (*p == '\0') - break; - } - if (mode == 0) - errx(1, "empty mode"); - return mode; + if (strcmp("play", optarg) == 0) + return MODE_PLAY; + if (strcmp("rec", optarg) == 0) + return MODE_REC; + if (strcmp("duplex", optarg) == 0) + return MODE_PLAY | MODE_REC; + errx(1, "%s: bad mode", optarg); } /* @@ -197,7 +183,6 @@ struct farg { int hdr; /* header format */ int xrun; /* overrun/underrun policy */ int mmc; /* MMC mode */ - unsigned mode; }; SLIST_HEAD(farglist, farg); @@ -209,7 +194,7 @@ SLIST_HEAD(farglist, farg); void farg_add(struct farglist *list, struct aparams *ipar, struct aparams *opar, unsigned vol, - int hdr, int xrun, int mmc, unsigned mode, char *name) + int hdr, int xrun, int mmc, char *name) { struct farg *fa; size_t namelen; @@ -227,15 +212,12 @@ farg_add(struct farglist *list, } } else fa->hdr = hdr; - if (mmc && xrun == XRUN_IGNORE) - xrun = XRUN_SYNC; fa->xrun = xrun; fa->ipar = *ipar; fa->opar = *opar; fa->vol = vol; fa->name = name; fa->mmc = mmc; - fa->mode = mode; SLIST_INSERT_HEAD(list, fa, entry); } @@ -305,61 +287,28 @@ getbasepath(char *base, size_t size) } void -stopall(char *base) -{ - struct file *f; - - restart: - LIST_FOREACH(f, &file_list, entry) { - /* - * skip connected streams (handled by dev_done()) - */ - if (APROC_OK(dev_mix) && f->rproc && - aproc_depend(dev_mix, f->rproc)) - continue; - if (APROC_OK(dev_sub) && f->wproc && - aproc_depend(f->wproc, dev_sub)) - continue; - if (APROC_OK(dev_midi)) { - if (f->rproc && aproc_depend(dev_midi, f->rproc)) - continue; - if (f->wproc && aproc_depend(f->wproc, dev_midi)) - continue; - } - /* - * kill anything else - */ - file_close(f); - goto restart; - } -} - -void aucat_usage(void) { (void)fputs("usage: " PROG_AUCAT " [-dlnu] [-b nframes] " - "[-C min:max] [-c min:max] [-e enc]\n\t" - "[-f device] [-h fmt] [-i file] [-m mode]" - "[-o file] [-q device]\n\t" - "[-r rate] [-s name] [-t mode] [-U unit] " - "[-v volume] [-x policy]\n\t" - "[-z nframes]\n", + "[-C min:max] [-c min:max] [-e enc] [-f device]\n" + "\t[-h fmt] [-i file] [-m mode] [-o file] [-r rate] [-s name]\n" + "\t[-t mode] [-U unit] [-v volume] [-x policy] [-z nframes]\n", stderr); } int aucat_main(int argc, char **argv) { - int c, u_flag, d_flag, l_flag, n_flag, hdr, xrun, unit; + int c, u_flag, d_flag, l_flag, n_flag, hdr, xrun, suspend = 0, unit; struct farg *fa; - struct farglist ifiles, ofiles, sfiles, qfiles; + struct farglist ifiles, ofiles, sfiles; struct aparams ipar, opar, dipar, dopar; char base[PATH_MAX], path[PATH_MAX], *file; unsigned bufsz, round, mode; char *devpath; const char *str; unsigned volctl; - int mmc, autostart; + int mmc; aparams_init(&ipar, 0, 1, 44100); aparams_init(&opar, 0, 1, 44100); @@ -373,16 +322,14 @@ aucat_main(int argc, char **argv) SLIST_INIT(&ifiles); SLIST_INIT(&ofiles); SLIST_INIT(&sfiles); - SLIST_INIT(&qfiles); hdr = HDR_AUTO; xrun = XRUN_IGNORE; volctl = MIDI_MAXCTL; - mode = MODE_PLAY | MODE_REC; + mode = 0; bufsz = 0; round = 0; - autostart = 1; - while ((c = getopt(argc, argv, "dnb:c:C:e:r:h:x:v:i:o:f:m:luq:s:U:t:z:")) != -1) { + while ((c = getopt(argc, argv, "dnb:c:C:e:r:h:x:v:i:o:f:m:lus:U:t:z:")) != -1) { switch (c) { case 'd': #ifdef DEBUG @@ -405,8 +352,6 @@ aucat_main(int argc, char **argv) break; case 't': mmc = opt_mmc(); - if (mmc) - autostart = 0; break; case 'c': opt_ch(&ipar); @@ -434,22 +379,18 @@ aucat_main(int argc, char **argv) if (strcmp(file, "-") == 0) file = NULL; farg_add(&ifiles, &ipar, &opar, volctl, - hdr, xrun, mmc, mode & MODE_PLAY, file); + hdr, xrun, 0, file); break; case 'o': file = optarg; if (strcmp(file, "-") == 0) file = NULL; farg_add(&ofiles, &ipar, &opar, volctl, - hdr, xrun, mmc, mode & MODE_RECMASK, file); + hdr, xrun, 0, file); break; case 's': farg_add(&sfiles, &ipar, &opar, volctl, - hdr, xrun, mmc, mode, optarg); - break; - case 'q': - farg_add(&qfiles, &aparams_none, &aparams_none, - 0, HDR_RAW, 0, 0, 0, optarg); + hdr, xrun, mmc, optarg); break; case 'f': if (devpath) @@ -460,7 +401,6 @@ aucat_main(int argc, char **argv) break; case 'l': l_flag = 1; - autostart = 0; break; case 'u': u_flag = 1; @@ -511,12 +451,22 @@ aucat_main(int argc, char **argv) if (!l_flag && (!SLIST_EMPTY(&sfiles) || unit >= 0)) errx(1, "can't use -s or -U without -l"); - if (l_flag && (!SLIST_EMPTY(&ofiles) || !SLIST_EMPTY(&ifiles))) - errx(1, "can't use -l, and -s with -o or -i"); + if ((l_flag || mode != 0) && + (!SLIST_EMPTY(&ofiles) || !SLIST_EMPTY(&ifiles))) + errx(1, "can't use -l, -m and -s with -o or -i"); + if (!mode) { + if (l_flag || !SLIST_EMPTY(&ifiles)) + mode |= MODE_PLAY; + if (l_flag || !SLIST_EMPTY(&ofiles)) + mode |= MODE_REC; + if (!mode) { + aucat_usage(); + exit(1); + } + } if (n_flag) { - if (devpath != NULL || !SLIST_EMPTY(&qfiles) || - l_flag || !autostart) - errx(1, "can't use -n with -f, -q, -t or -l"); + if (devpath != NULL || l_flag) + errx(1, "can't use -n with -f or -l"); if (SLIST_EMPTY(&ifiles) || SLIST_EMPTY(&ofiles)) errx(1, "both -i and -o are required with -n"); } @@ -526,43 +476,28 @@ aucat_main(int argc, char **argv) */ if (l_flag && SLIST_EMPTY(&sfiles)) { farg_add(&sfiles, &dopar, &dipar, - volctl, HDR_RAW, XRUN_IGNORE, mmc, mode, DEFAULT_OPT); + volctl, HDR_RAW, XRUN_IGNORE, mmc, DEFAULT_OPT); } - /* - * Check modes and calculate "best" device parameters. Iterate over all - * inputs and outputs and find the maximum sample rate and channel - * number. - */ - mode = 0; - aparams_init(&dipar, dipar.cmin, dipar.cmax, dipar.rate); - aparams_init(&dopar, dopar.cmin, dopar.cmax, dopar.rate); - SLIST_FOREACH(fa, &ifiles, entry) { - if (fa->mode == 0) - errx(1, "%s: not in play mode", fa->name); - mode |= fa->mode; - if (!u_flag) + if (!u_flag) { + /* + * Calculate "best" device parameters. Iterate over all + * inputs and outputs and find the maximum sample rate + * and channel number. + */ + aparams_init(&dipar, dipar.cmin, dipar.cmax, dipar.rate); + aparams_init(&dopar, dopar.cmin, dopar.cmax, dopar.rate); + SLIST_FOREACH(fa, &ifiles, entry) { aparams_grow(&dopar, &fa->ipar); - } - SLIST_FOREACH(fa, &ofiles, entry) { - if (fa->mode == 0) - errx(1, "%s: not in rec/mon mode", fa->name); - if ((fa->mode & MODE_REC) && (fa->mode & MODE_MON)) - errx(1, "%s: can't record and monitor", fa->name); - mode |= fa->mode; - if (!u_flag) + } + SLIST_FOREACH(fa, &ofiles, entry) { aparams_grow(&dipar, &fa->opar); - } - SLIST_FOREACH(fa, &sfiles, entry) { - if ((fa->mode & MODE_REC) && (fa->mode & MODE_MON)) - errx(1, "%s: can't record and monitor", fa->name); - mode |= fa->mode; - if (!u_flag) { + } + SLIST_FOREACH(fa, &sfiles, entry) { aparams_grow(&dopar, &fa->ipar); aparams_grow(&dipar, &fa->opar); } } - if (!round) round = ((mode & MODE_REC) ? dipar.rate : dopar.rate) / 15; if (!bufsz) @@ -581,13 +516,12 @@ aucat_main(int argc, char **argv) * the other half is for the socket/files. */ if (n_flag) { - if (mode & MODE_MON) - errx(1, "monitoring not allowed in loopback mode"); dev_loopinit(&dipar, &dopar, bufsz); } else { - if ((mode & MODE_MON) && !(mode & MODE_PLAY)) - errx(1, "no playback stream to monitor"); - if (!dev_init(devpath, mode, &dipar, &dopar, bufsz, round)) { + if (!dev_init(devpath, + (mode & MODE_REC) ? &dipar : NULL, + (mode & MODE_PLAY) ? &dopar : NULL, + bufsz, round)) { errx(1, "%s: can't open device", devpath ? devpath : "<default>"); } @@ -596,33 +530,26 @@ aucat_main(int argc, char **argv) /* * Create buffers for all input and output pipes. */ - while (!SLIST_EMPTY(&qfiles)) { - fa = SLIST_FIRST(&qfiles); - SLIST_REMOVE_HEAD(&qfiles, entry); - if (!dev_thruadd(fa->name, 1, 1)) - errx(1, "%s: can't open device", fa->name); - free(fa); - } while (!SLIST_EMPTY(&ifiles)) { fa = SLIST_FIRST(&ifiles); SLIST_REMOVE_HEAD(&ifiles, entry); - if (!wav_new_in(&wav_ops, fa->mode, fa->name, - fa->hdr, &fa->ipar, fa->xrun, fa->vol, fa->mmc)) + if (!wav_new_in(&wav_ops, fa->name, + fa->hdr, &fa->ipar, fa->xrun, fa->vol)) exit(1); free(fa); } while (!SLIST_EMPTY(&ofiles)) { fa = SLIST_FIRST(&ofiles); SLIST_REMOVE_HEAD(&ofiles, entry); - if (!wav_new_out(&wav_ops, fa->mode, fa->name, - fa->hdr, &fa->opar, fa->xrun, fa->mmc)) + if (!wav_new_out(&wav_ops, fa->name, + fa->hdr, &fa->opar, fa->xrun)) free(fa); } while (!SLIST_EMPTY(&sfiles)) { fa = SLIST_FIRST(&sfiles); SLIST_REMOVE_HEAD(&sfiles, entry); opt_new(fa->name, &fa->opar, &fa->ipar, - MIDI_TO_ADATA(fa->vol), fa->mmc, fa->mode); + MIDI_TO_ADATA(fa->vol), fa->mmc); free(fa); } if (l_flag) { @@ -632,14 +559,6 @@ aucat_main(int argc, char **argv) if (!d_flag && daemon(0, 0) < 0) err(1, "daemon"); } - if (autostart) { - /* - * inject artificial mmc start - */ - ctl_start(dev_midi); - } - if (l_flag) - dev_prime(); /* * Loop, start audio. @@ -648,48 +567,57 @@ aucat_main(int argc, char **argv) if (quit_flag) { break; } - if ((APROC_OK(dev_mix) && LIST_EMPTY(&dev_mix->obuflist)) || - (APROC_OK(dev_sub) && LIST_EMPTY(&dev_sub->ibuflist))) { + if ((dev_mix && LIST_EMPTY(&dev_mix->obuflist)) || + (dev_sub && LIST_EMPTY(&dev_sub->ibuflist))) { fprintf(stderr, "device disappeared, terminating\n"); break; } - if (!l_flag && ctl_idle(dev_midi)) - break; if (!file_poll()) break; - if ((!APROC_OK(dev_mix) || dev_mix->u.mix.idle > 2 * dev_bufsz) && - (!APROC_OK(dev_sub) || dev_sub->u.sub.idle > 2 * dev_bufsz) && - (!APROC_OK(dev_submon) || dev_submon->u.sub.idle > 2 * dev_bufsz) && - (!APROC_OK(dev_midi) || dev_midi->u.ctl.tstate != CTL_RUN)) { - if (dev_pstate == DEV_RUN) { - dev_pstate = DEV_INIT; + if ((!dev_mix || dev_mix->u.mix.idle > 2 * dev_bufsz) && + (!dev_sub || dev_sub->u.sub.idle > 2 * dev_bufsz) && + ((dev_mix || dev_sub) && dev_midi->u.ctl.tstate != CTL_RUN)) { + if (!l_flag) + break; + if (!suspend) { +#ifdef DEBUG + if (debug_level >= 2) + dbg_puts("suspending\n"); +#endif + suspend = 1; dev_stop(); dev_clear(); - /* - * priming buffer in non-server mode is not - * ok, because it will insert silence and - * break synchronization - */ - if (l_flag) - dev_prime(); + dev_prime(); } } - /* - * move device state machine - * XXX: move this to dev.c - */ - if (dev_pstate == DEV_START) { - dev_pstate = DEV_RUN; - dev_start(); + if ((dev_mix && dev_mix->u.mix.idle == 0) || + (dev_sub && dev_sub->u.sub.idle == 0) || + ((dev_mix || dev_sub) && dev_midi->u.ctl.tstate == CTL_RUN)) { + if (suspend) { +#ifdef DEBUG + if (debug_level >= 2) + dbg_puts("resuming\n"); +#endif + suspend = 0; + dev_start(); + } } } - stopall(base); - dev_done(); - filelist_done(); if (l_flag) { - if (rmdir(base) < 0 && errno != ENOTEMPTY) + filelist_unlisten(); + if (rmdir(base) < 0) warn("rmdir(\"%s\")", base); } + if (suspend) { +#ifdef DEBUG + if (debug_level >= 2) + dbg_puts("resuming to drain\n"); +#endif + suspend = 0; + dev_start(); + } + dev_done(); + filelist_done(); unsetsig(); return 0; } @@ -697,8 +625,8 @@ aucat_main(int argc, char **argv) void midicat_usage(void) { - (void)fputs("usage: " PROG_MIDICAT " [-dl] " - "[-i file] [-o file] [-q device] [-U unit]\n", + (void)fputs("usage: " PROG_MIDICAT " [-dl] [-f device] " + "[-i file] [-o file] [-U unit]\n", stderr); } int @@ -720,7 +648,7 @@ midicat_main(int argc, char **argv) SLIST_INIT(&ifiles); SLIST_INIT(&ofiles); - while ((c = getopt(argc, argv, "di:o:lf:q:U:")) != -1) { + while ((c = getopt(argc, argv, "di:o:lf:U:")) != -1) { switch (c) { case 'd': #ifdef DEBUG @@ -731,17 +659,15 @@ midicat_main(int argc, char **argv) break; case 'i': farg_add(&ifiles, &aparams_none, &aparams_none, - 0, HDR_RAW, 0, 0, 0, optarg); + 0, HDR_RAW, 0, 0, optarg); break; case 'o': farg_add(&ofiles, &aparams_none, &aparams_none, - 0, HDR_RAW, 0, 0, 0, optarg); + 0, HDR_RAW, 0, 0, optarg); break; - /* XXX: backward compat, remove this */ - case 'f': - case 'q': + case 'f': farg_add(&dfiles, &aparams_none, &aparams_none, - 0, HDR_RAW, 0, 0, 0, optarg); + 0, HDR_RAW, 0, 0, optarg); break; case 'l': l_flag = 1; @@ -777,12 +703,12 @@ midicat_main(int argc, char **argv) filelist_init(); dev_thruinit(); - if (!l_flag && APROC_OK(dev_midi)) + if (!l_flag) dev_midi->flags |= APROC_QUIT; if ((!SLIST_EMPTY(&ifiles) || !SLIST_EMPTY(&ofiles)) && SLIST_EMPTY(&dfiles)) { farg_add(&dfiles, &aparams_none, &aparams_none, - 0, HDR_RAW, 0, 0, 0, NULL); + 0, HDR_RAW, 0, 0, NULL); } while (!SLIST_EMPTY(&dfiles)) { fa = SLIST_FIRST(&dfiles); @@ -841,6 +767,7 @@ midicat_main(int argc, char **argv) dev_midiattach(NULL, buf); free(fa); } + /* * loop, start processing */ @@ -851,13 +778,13 @@ midicat_main(int argc, char **argv) if (!file_poll()) break; } - stopall(base); - dev_done(); - filelist_done(); if (l_flag) { - if (rmdir(base) < 0 && errno != ENOTEMPTY) + filelist_unlisten(); + if (rmdir(base) < 0) warn("rmdir(\"%s\")", base); } + dev_done(); + filelist_done(); unsetsig(); return 0; } diff --git a/usr.bin/aucat/conf.h b/usr.bin/aucat/conf.h index 66b7b9ee2b4..47bc9ae7e11 100644 --- a/usr.bin/aucat/conf.h +++ b/usr.bin/aucat/conf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.h,v 1.13 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: conf.h,v 1.14 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -31,6 +31,19 @@ extern int debug_level; #endif /* + * Number of blocks in the device play/record buffers. Because Sun API + * cannot notify apps of the current positions, we have to use all N + * buffers devices blocks plus one extra block, to make write() block, + * so that poll() can return the exact postition. + */ +#define DEV_NBLK 2 + +/* + * Number of blocks in the wav-file i/o buffers. + */ +#define WAV_NBLK 6 + +/* * socket and option names */ #define DEFAULT_MIDITHRU "midithru" diff --git a/usr.bin/aucat/dev.c b/usr.bin/aucat/dev.c index 683ba1b6c5a..09e97da8ea0 100644 --- a/usr.bin/aucat/dev.c +++ b/usr.bin/aucat/dev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dev.c,v 1.44 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: dev.c,v 1.45 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -27,15 +27,13 @@ #include "miofile.h" #include "siofile.h" #include "midi.h" -#include "opt.h" #ifdef DEBUG #include "dbg.h" #endif -unsigned dev_pstate; unsigned dev_bufsz, dev_round, dev_rate; struct aparams dev_ipar, dev_opar; -struct aproc *dev_mix, *dev_sub, *dev_rec, *dev_play, *dev_submon, *dev_mon; +struct aproc *dev_mix, *dev_sub, *dev_rec, *dev_play; struct aproc *dev_midi; /* @@ -103,14 +101,6 @@ dev_loopinit(struct aparams *dipar, struct aparams *dopar, unsigned bufsz) struct aparams par; unsigned cmin, cmax, rate; - /* - * in principle we don't need control, but the start-stop mechanism - * depend on it and it's simpler to reuse this mechanism rather than - * dealing with lots of special cases - */ - dev_midi = ctl_new("ctl"); - dev_midi->refs++; - cmin = (dipar->cmin < dopar->cmin) ? dipar->cmin : dopar->cmin; cmax = (dipar->cmax > dopar->cmax) ? dipar->cmax : dopar->cmax; rate = (dipar->rate > dopar->rate) ? dipar->rate : dopar->rate; @@ -122,14 +112,11 @@ dev_loopinit(struct aparams *dipar, struct aparams *dopar, unsigned bufsz) dev_rate = rate; dev_rec = NULL; dev_play = NULL; - dev_mon = NULL; - dev_submon = NULL; - dev_pstate = DEV_INIT; buf = abuf_new(dev_bufsz, &par); - dev_mix = mix_new("mix", dev_bufsz, 1, NULL); + dev_mix = mix_new("mix", dev_bufsz, NULL); dev_mix->refs++; - dev_sub = sub_new("sub", dev_bufsz, 1, NULL); + dev_sub = sub_new("sub", dev_bufsz, NULL); dev_sub->refs++; aproc_setout(dev_mix, buf); aproc_setin(dev_sub, buf); @@ -153,13 +140,14 @@ dev_roundof(unsigned newrate) * setup. */ int -dev_init(char *devpath, unsigned mode, +dev_init(char *devpath, struct aparams *dipar, struct aparams *dopar, unsigned bufsz, unsigned round) { struct file *f; struct aparams ipar, opar; struct aproc *conv; struct abuf *buf; + unsigned nfr, ibufsz, obufsz; dev_midi = ctl_new("ctl"); dev_midi->refs++; @@ -169,13 +157,13 @@ dev_init(char *devpath, unsigned mode, * limit the block size to 1/4 of the requested buffer. */ dev_round = round; - dev_bufsz = bufsz; + dev_bufsz = (bufsz + 3) / 4 + (dev_round - 1); + dev_bufsz -= dev_bufsz % dev_round; f = (struct file *)siofile_new(&siofile_ops, devpath, - mode & (MODE_PLAY | MODE_REC), dipar, dopar, - &dev_bufsz, &dev_round); + dipar, dopar, &dev_bufsz, &dev_round); if (f == NULL) return 0; - if (mode & MODE_REC) { + if (dipar) { #ifdef DEBUG if (debug_level >= 2) { dbg_puts("hw recording "); @@ -185,7 +173,7 @@ dev_init(char *devpath, unsigned mode, #endif dev_rate = dipar->rate; } - if (mode & MODE_PLAY) { + if (dopar) { #ifdef DEBUG if (debug_level >= 2) { dbg_puts("hw playing "); @@ -195,19 +183,33 @@ dev_init(char *devpath, unsigned mode, #endif dev_rate = dopar->rate; } + ibufsz = obufsz = dev_bufsz; + bufsz = (bufsz > dev_bufsz) ? bufsz - dev_bufsz : 0; + + /* + * Use 1/8 of the buffer for the mixer/converters. Since we + * already consumed 1/4 for the device, bufsz represents the + * remaining 3/4. So 1/8 is 1/6 of 3/4. + */ + nfr = (bufsz + 5) / 6; + nfr += dev_round - 1; + nfr -= nfr % dev_round; + if (nfr == 0) + nfr = dev_round; /* * Create record chain. */ - if (mode & MODE_REC) { + if (dipar) { aparams_init(&ipar, dipar->cmin, dipar->cmax, dipar->rate); /* * Create the read end. */ - dev_rec = rsio_new(f); + dev_rec = rfile_new(f); dev_rec->refs++; - buf = abuf_new(dev_bufsz, dipar); + buf = abuf_new(nfr, dipar); aproc_setout(dev_rec, buf); + ibufsz += nfr; /* * Append a converter, if needed. @@ -215,8 +217,9 @@ dev_init(char *devpath, unsigned mode, if (!aparams_eqenc(dipar, &ipar)) { conv = dec_new("rec", dipar); aproc_setin(conv, buf); - buf = abuf_new(dev_round, &ipar); + buf = abuf_new(nfr, &ipar); aproc_setout(conv, buf); + ibufsz += nfr; } dev_ipar = ipar; @@ -224,8 +227,7 @@ dev_init(char *devpath, unsigned mode, * Append a "sub" to which clients will connect. * Link it to the controller only in record-only mode */ - dev_sub = sub_new("rec", dev_bufsz, dev_round, - dopar ? NULL : dev_midi); + dev_sub = sub_new("rec", ibufsz, dopar ? NULL : dev_midi); dev_sub->refs++; aproc_setin(dev_sub, buf); } else { @@ -236,15 +238,16 @@ dev_init(char *devpath, unsigned mode, /* * Create play chain. */ - if (mode & MODE_PLAY) { + if (dopar) { aparams_init(&opar, dopar->cmin, dopar->cmax, dopar->rate); /* * Create the write end. */ - dev_play = wsio_new(f); + dev_play = wfile_new(f); dev_play->refs++; - buf = abuf_new(dev_bufsz, dopar); + buf = abuf_new(nfr, dopar); aproc_setin(dev_play, buf); + obufsz += nfr; /* * Append a converter, if needed. @@ -252,50 +255,23 @@ dev_init(char *devpath, unsigned mode, if (!aparams_eqenc(&opar, dopar)) { conv = enc_new("play", dopar); aproc_setout(conv, buf); - buf = abuf_new(dev_round, &opar); + buf = abuf_new(nfr, &opar); aproc_setin(conv, buf); + obufsz += nfr; } dev_opar = opar; /* * Append a "mix" to which clients will connect. */ - dev_mix = mix_new("play", dev_bufsz, dev_round, dev_midi); + dev_mix = mix_new("play", obufsz, dev_midi); dev_mix->refs++; aproc_setout(dev_mix, buf); } else { dev_play = NULL; dev_mix = NULL; } - - /* - * Create monitoring chain - */ - if (mode & MODE_MON) { - dev_mon = mon_new("mon", dev_bufsz); - dev_mon->refs++; - buf = abuf_new(dev_bufsz, &dev_opar); - aproc_setout(dev_mon, buf); - - /* - * Append a "sub" to which clients will connect. - * Link it to the controller only in record-only mode - */ - dev_submon = sub_new("mon", dev_bufsz, dev_round, NULL); - dev_submon->refs++; - aproc_setin(dev_submon, buf); - - /* - * Attack to the mixer - */ - dev_mix->u.mix.mon = dev_mon; - dev_mon->refs++; - } else { - dev_submon = NULL; - if (APROC_OK(dev_mix)) - dev_mix->u.mix.mon = NULL; - } - + dev_bufsz = (dopar) ? obufsz : ibufsz; #ifdef DEBUG if (debug_level >= 2) { dbg_puts("device block size is "); @@ -305,7 +281,7 @@ dev_init(char *devpath, unsigned mode, dbg_puts(" blocks\n"); } #endif - dev_pstate = DEV_INIT; + dev_start(); return 1; } @@ -334,11 +310,6 @@ dev_done(void) * after each call to file_eof(). */ dev_mix->flags |= APROC_QUIT; - if (APROC_OK(dev_mix->u.mix.mon)) { - dev_mix->u.mix.mon->refs--; - aproc_del(dev_mix->u.mix.mon); - dev_mix->u.mix.mon = NULL; - } restart_mix: LIST_FOREACH(f, &file_list, entry) { if (f->rproc != NULL && @@ -347,7 +318,7 @@ dev_done(void) goto restart_mix; } } - } else if (dev_sub || dev_submon) { + } else if (dev_sub) { /* * Same as above, but since there's no mixer, * we generate EOF on the record-end of the @@ -356,8 +327,7 @@ dev_done(void) restart_sub: LIST_FOREACH(f, &file_list, entry) { if (f->rproc != NULL && - (aproc_depend(dev_sub, f->rproc) || - aproc_depend(dev_submon, f->rproc))) { + aproc_depend(dev_sub, f->rproc)) { file_eof(f); goto restart_sub; } @@ -377,37 +347,32 @@ dev_done(void) } } if (dev_mix) { - if (--dev_mix->refs == 0 && (dev_mix->flags & APROC_ZOMB)) + dev_mix->refs--; + if (dev_mix->flags & APROC_ZOMB) aproc_del(dev_mix); dev_mix = NULL; } if (dev_play) { - if (--dev_play->refs == 0 && (dev_play->flags & APROC_ZOMB)) + dev_play->refs--; + if (dev_play->flags & APROC_ZOMB) aproc_del(dev_play); dev_play = NULL; } if (dev_sub) { - if (--dev_sub->refs == 0 && (dev_sub->flags & APROC_ZOMB)) + dev_sub->refs--; + if (dev_sub->flags & APROC_ZOMB) aproc_del(dev_sub); dev_sub = NULL; } if (dev_rec) { - if (--dev_rec->refs == 0 && (dev_rec->flags & APROC_ZOMB)) + dev_rec->refs--; + if (dev_rec->flags & APROC_ZOMB) aproc_del(dev_rec); dev_rec = NULL; } - if (dev_submon) { - if (--dev_submon->refs == 0 && (dev_submon->flags & APROC_ZOMB)) - aproc_del(dev_submon); - dev_submon = NULL; - } - if (dev_mon) { - if (--dev_mon->refs == 0 && (dev_mon->flags & APROC_ZOMB)) - aproc_del(dev_mon); - dev_mon = NULL; - } if (dev_midi) { - if (--dev_midi->refs == 0 && (dev_midi->flags & APROC_ZOMB)) + dev_midi->refs--; + if (dev_midi->flags & APROC_ZOMB) aproc_del(dev_midi); dev_midi = NULL; } @@ -425,64 +390,49 @@ dev_start(void) { struct file *f; -#ifdef DEBUG - if (debug_level >= 2) - dbg_puts("starting audio device\n"); -#endif - if (APROC_OK(dev_mix)) + if (dev_mix) dev_mix->flags |= APROC_DROP; - if (APROC_OK(dev_sub)) + if (dev_sub) dev_sub->flags |= APROC_DROP; - if (APROC_OK(dev_submon)) - dev_submon->flags |= APROC_DROP; - if (APROC_OK(dev_play) && dev_play->u.io.file) { + if (dev_play && dev_play->u.io.file) { f = dev_play->u.io.file; f->ops->start(f); - } else if (APROC_OK(dev_rec) && dev_rec->u.io.file) { + } else if (dev_rec && dev_rec->u.io.file) { f = dev_rec->u.io.file; f->ops->start(f); } } /* - * Pause the device. This may trigger context switches, - * so it shouldn't be called from aproc methods + * Pause the device. */ void dev_stop(void) { struct file *f; - if (APROC_OK(dev_play) && dev_play->u.io.file) { + if (dev_play && dev_play->u.io.file) { f = dev_play->u.io.file; f->ops->stop(f); - } else if (APROC_OK(dev_rec) && dev_rec->u.io.file) { + } else if (dev_rec && dev_rec->u.io.file) { f = dev_rec->u.io.file; f->ops->stop(f); } - if (APROC_OK(dev_mix)) + if (dev_mix) dev_mix->flags &= ~APROC_DROP; - if (APROC_OK(dev_sub)) + if (dev_sub) dev_sub->flags &= ~APROC_DROP; - if (APROC_OK(dev_submon)) - dev_submon->flags &= ~APROC_DROP; -#ifdef DEBUG - if (debug_level >= 2) - dbg_puts("audio device stopped\n"); -#endif } /* * Find the end points connected to the mix/sub. */ int -dev_getep(unsigned mode, struct abuf **sibuf, struct abuf **sobuf) +dev_getep(struct abuf **sibuf, struct abuf **sobuf) { struct abuf *ibuf, *obuf; - if (mode & MODE_PLAY) { - if (!APROC_OK(dev_mix)) - return 0; + if (sibuf && *sibuf) { ibuf = *sibuf; for (;;) { if (!ibuf || !ibuf->rproc) { @@ -500,9 +450,7 @@ dev_getep(unsigned mode, struct abuf **sibuf, struct abuf **sobuf) } *sibuf = ibuf; } - if (mode & MODE_REC) { - if (!APROC_OK(dev_sub)) - return 0; + if (sobuf && *sobuf) { obuf = *sobuf; for (;;) { if (!obuf || !obuf->wproc) { @@ -520,26 +468,6 @@ dev_getep(unsigned mode, struct abuf **sibuf, struct abuf **sobuf) } *sobuf = obuf; } - if (mode & MODE_MON) { - if (!APROC_OK(dev_submon)) - return 0; - obuf = *sobuf; - for (;;) { - if (!obuf || !obuf->wproc) { -#ifdef DEBUG - if (debug_level >= 3) { - abuf_dbg(*sobuf); - dbg_puts(": not connected to device\n"); - } -#endif - return 0; - } - if (obuf->wproc == dev_submon) - break; - obuf = LIST_FIRST(&obuf->wproc->ibuflist); - } - *sobuf = obuf; - } return 1; } @@ -548,38 +476,45 @@ dev_getep(unsigned mode, struct abuf **sibuf, struct abuf **sobuf) * them underruns/overruns). */ void -dev_sync(unsigned mode, struct abuf *ibuf, struct abuf *obuf) +dev_sync(struct abuf *ibuf, struct abuf *obuf) { + struct abuf *pbuf, *rbuf; int delta; - if (!dev_getep(mode, &ibuf, &obuf)) + if (!dev_mix || !dev_sub) return; + pbuf = LIST_FIRST(&dev_mix->obuflist); + if (!pbuf) + return; + rbuf = LIST_FIRST(&dev_sub->ibuflist); + if (!rbuf) + return; + if (!dev_getep(&ibuf, &obuf)) + return; + /* * Calculate delta, the number of frames the play chain is ahead * of the record chain. It's necessary to schedule silences (or * drops) in order to start playback and record in sync. */ - if (APROC_OK(dev_mix) && APROC_OK(dev_sub)) { - delta = dev_mix->u.mix.abspos - dev_sub->u.sub.abspos; - } else if (APROC_OK(dev_mix)) { - delta = dev_mix->u.mix.lat; - } else - delta = 0; + delta = + rbuf->bpf * (pbuf->abspos + pbuf->used) - + pbuf->bpf * rbuf->abspos; + delta /= pbuf->bpf * rbuf->bpf; #ifdef DEBUG if (debug_level >= 3) { dbg_puts("syncing device, delta = "); dbg_putu(delta); - dbg_puts(" "); - if (APROC_OK(dev_mix)) { - aproc_dbg(dev_mix); - dbg_puts(": abspos = "); - dbg_putu(dev_mix->u.mix.abspos); - } - if (APROC_OK(dev_sub)) { - aproc_dbg(dev_sub); - dbg_puts(": abspos = "); - dbg_putu(dev_sub->u.sub.abspos); - } + dbg_puts(": "); + abuf_dbg(pbuf); + dbg_puts(" abspos = "); + dbg_putu(pbuf->abspos); + dbg_puts(" used = "); + dbg_putu(pbuf->used); + dbg_puts(" <---> "); + abuf_dbg(rbuf); + dbg_puts(" abspos = "); + dbg_putu(rbuf->abspos); dbg_puts("\n"); } #endif @@ -588,15 +523,19 @@ dev_sync(unsigned mode, struct abuf *ibuf, struct abuf *obuf) * The play chain is ahead (most cases) drop some of * the recorded input, to get both in sync. */ - if (mode & MODE_RECMASK) - sub_silence(obuf, -delta); + if (obuf) { + obuf->drop += delta * obuf->bpf; + abuf_ipos(obuf, -delta); + } } else if (delta < 0) { /* * The record chain is ahead (should never happen, * right?) then insert silence to play. */ - if (mode & MODE_PLAY) - mix_drop(ibuf, delta); + if (ibuf) { + ibuf->silence += -delta * ibuf->bpf; + abuf_opos(ibuf, delta); + } } } @@ -611,20 +550,23 @@ dev_getpos(void) int plat = 0, rlat = 0; int delta; - if (APROC_OK(dev_mix)) { + if (dev_mix) { pbuf = LIST_FIRST(&dev_mix->obuflist); if (!pbuf) return 0; plat = -dev_mix->u.mix.lat; } - if (APROC_OK(dev_sub)) { + if (dev_sub) { rbuf = LIST_FIRST(&dev_sub->ibuflist); if (!rbuf) return 0; rlat = -dev_sub->u.sub.lat; } - if (APROC_OK(dev_mix) && APROC_OK(dev_sub)) { - delta = dev_mix->u.mix.abspos - dev_sub->u.sub.abspos; + if (dev_mix && dev_sub) { + delta = + rbuf->bpf * (pbuf->abspos + pbuf->used) - + pbuf->bpf * rbuf->abspos; + delta /= pbuf->bpf * rbuf->bpf; if (delta > 0) rlat -= delta; else if (delta < 0) @@ -639,7 +581,7 @@ dev_getpos(void) } #endif } - return APROC_OK(dev_mix) ? plat : rlat; + return dev_mix ? plat : rlat; } /* @@ -649,25 +591,16 @@ dev_getpos(void) * and rec. */ void -dev_attach(char *name, unsigned mode, - struct abuf *ibuf, struct aparams *sipar, - struct abuf *obuf, struct aparams *sopar, - unsigned xrun, int vol) +dev_attach(char *name, + struct abuf *ibuf, struct aparams *sipar, unsigned underrun, + struct abuf *obuf, struct aparams *sopar, unsigned overrun, int vol) { struct abuf *pbuf = NULL, *rbuf = NULL; struct aparams ipar, opar; struct aproc *conv; unsigned round, nblk; -#ifdef DEBUG - if ((!APROC_OK(dev_mix) && (mode & MODE_PLAY)) || - (!APROC_OK(dev_sub) && (mode & MODE_REC)) || - (!APROC_OK(dev_submon) && (mode & MODE_MON))) { - dbg_puts("mode beyond device mode, not attaching\n"); - return; - } -#endif - if (mode & MODE_PLAY) { + if (ibuf) { ipar = *sipar; pbuf = LIST_FIRST(&dev_mix->obuflist); nblk = (dev_bufsz / dev_round + 3) / 4; @@ -700,11 +633,13 @@ dev_attach(char *name, unsigned mode, aproc_setout(conv, ibuf); } aproc_setin(dev_mix, ibuf); - ibuf->r.mix.xrun = xrun; + if (dev_mix->u.mix.lat > 0) + abuf_opos(ibuf, -dev_mix->u.mix.lat); + ibuf->r.mix.xrun = underrun; ibuf->r.mix.maxweight = vol; mix_setmaster(dev_mix); } - if (mode & MODE_REC) { + if (obuf) { opar = *sopar; rbuf = LIST_FIRST(&dev_sub->ibuflist); round = dev_roundof(opar.rate); @@ -737,58 +672,19 @@ dev_attach(char *name, unsigned mode, aproc_setin(conv, obuf); } aproc_setout(dev_sub, obuf); - obuf->w.sub.xrun = xrun; - } - if (mode & MODE_MON) { - opar = *sopar; - rbuf = LIST_FIRST(&dev_submon->ibuflist); - round = dev_roundof(opar.rate); - nblk = (dev_bufsz / dev_round + 3) / 4; - if (!aparams_eqenc(&opar, &dev_opar)) { - conv = enc_new(name, &opar); - opar.bps = dev_opar.bps; - opar.bits = dev_opar.bits; - opar.sig = dev_opar.sig; - opar.le = dev_opar.le; - opar.msb = dev_opar.msb; - aproc_setout(conv, obuf); - obuf = abuf_new(nblk * round, &opar); - aproc_setin(conv, obuf); - } - if (!aparams_subset(&opar, &dev_opar)) { - conv = cmap_new(name, &dev_opar, &opar); - opar.cmin = dev_opar.cmin; - opar.cmax = dev_opar.cmax; - aproc_setout(conv, obuf); - obuf = abuf_new(nblk * round, &opar); - aproc_setin(conv, obuf); - } - if (!aparams_eqrate(&opar, &dev_opar)) { - conv = resamp_new(name, dev_round, round); - opar.rate = dev_opar.rate; - round = dev_round; - aproc_setout(conv, obuf); - obuf = abuf_new(nblk * round, &opar); - aproc_setin(conv, obuf); - } - aproc_setout(dev_submon, obuf); - obuf->w.sub.xrun = xrun; + if (dev_sub->u.sub.lat > 0) + abuf_ipos(obuf, -dev_sub->u.sub.lat); + obuf->w.sub.xrun = overrun; } /* * Sync play to record. */ - if ((mode & MODE_PLAY) && (mode & MODE_RECMASK)) { + if (ibuf && obuf) { ibuf->duplex = obuf; obuf->duplex = ibuf; } - dev_sync(mode, ibuf, obuf); - - /* - * Start device if not already started - */ - if (dev_pstate == DEV_INIT) - dev_pstate = DEV_START; + dev_sync(ibuf, obuf); } /* @@ -805,7 +701,7 @@ dev_setvol(struct abuf *ibuf, int vol) dbg_puts("\n"); } #endif - if (!dev_getep(MODE_PLAY, &ibuf, NULL)) { + if (!dev_getep(&ibuf, NULL)) { return; } ibuf->r.mix.vol = vol; @@ -820,7 +716,7 @@ dev_clear(void) { struct abuf *buf; - if (APROC_OK(dev_mix)) { + if (dev_mix) { #ifdef DEBUG if (!LIST_EMPTY(&dev_mix->ibuflist)) { dbg_puts("play end not idle, can't clear device\n"); @@ -834,7 +730,7 @@ dev_clear(void) } mix_clear(dev_mix); } - if (APROC_OK(dev_sub)) { + if (dev_sub) { #ifdef DEBUG if (!LIST_EMPTY(&dev_sub->obuflist)) { dbg_puts("record end not idle, can't clear device\n"); @@ -848,22 +744,6 @@ dev_clear(void) } sub_clear(dev_sub); } - if (APROC_OK(dev_submon)) { -#ifdef DEBUG - dbg_puts("clearing monitor\n"); - if (!LIST_EMPTY(&dev_submon->obuflist)) { - dbg_puts("monitoring end not idle, can't clear device\n"); - dbg_panic(); - } -#endif - buf = LIST_FIRST(&dev_submon->ibuflist); - while (buf) { - abuf_clear(buf); - buf = LIST_FIRST(&buf->wproc->ibuflist); - } - sub_clear(dev_submon); - mon_clear(dev_mon); - } } /* @@ -873,7 +753,7 @@ dev_clear(void) void dev_prime(void) { - if (APROC_OK(dev_mix)) { + if (dev_mix) { #ifdef DEBUG if (!LIST_EMPTY(&dev_mix->ibuflist)) { dbg_puts("play end not idle, can't prime device\n"); diff --git a/usr.bin/aucat/dev.h b/usr.bin/aucat/dev.h index f9a97d31921..2f3195d701c 100644 --- a/usr.bin/aucat/dev.h +++ b/usr.bin/aucat/dev.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dev.h,v 1.18 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: dev.h,v 1.19 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -21,33 +21,25 @@ struct aproc; struct aparams; struct abuf; -#define DEV_INIT 0 -#define DEV_START 1 -#define DEV_RUN 2 -#define DEV_STOP 3 - -extern unsigned dev_pstate; extern unsigned dev_bufsz, dev_round, dev_rate; extern struct aparams dev_ipar, dev_opar; -extern struct aproc *dev_mix, *dev_sub, *dev_midi, *dev_submon, *dev_mon; +extern struct aproc *dev_mix, *dev_sub, *dev_midi; void dev_thruinit(void); int dev_thruadd(char *, int, int); void dev_midiattach(struct abuf *, struct abuf *); unsigned dev_roundof(unsigned); void dev_loopinit(struct aparams *, struct aparams *, unsigned); -int dev_init(char *, unsigned, - struct aparams *, struct aparams *, unsigned, unsigned); +int dev_init(char *, struct aparams *, struct aparams *, unsigned, unsigned); void dev_start(void); void dev_stop(void); void dev_run(int); void dev_done(void); -int dev_getep(unsigned, struct abuf **, struct abuf **); -void dev_sync(unsigned, struct abuf *, struct abuf *); -unsigned dev_getmode(void); +int dev_getep(struct abuf **, struct abuf **); +void dev_sync(struct abuf *, struct abuf *); int dev_getpos(void); -void dev_attach(char *, unsigned, - struct abuf *, struct aparams *, +void dev_attach(char *, + struct abuf *, struct aparams *, unsigned, struct abuf *, struct aparams *, unsigned, int); void dev_setvol(struct abuf *, int); void dev_clear(void); diff --git a/usr.bin/aucat/file.c b/usr.bin/aucat/file.c index af37e199fa0..4172325ec10 100644 --- a/usr.bin/aucat/file.c +++ b/usr.bin/aucat/file.c @@ -1,4 +1,4 @@ -/* $OpenBSD: file.c,v 1.16 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: file.c,v 1.17 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -63,6 +63,8 @@ #define MAXFDS 100 +extern struct fileops listen_ops, pipe_ops; + struct timeval file_tv; struct filelist file_list; struct timo *timo_queue; @@ -518,6 +520,23 @@ filelist_done(void) timo_done(); } +/* + * Close all listening sockets. + * + * XXX: remove this + */ +void +filelist_unlisten(void) +{ + struct file *f, *fnext; + + for (f = LIST_FIRST(&file_list); f != NULL; f = fnext) { + fnext = LIST_NEXT(f, entry); + if (f->ops == &listen_ops) + file_del(f); + } +} + unsigned file_read(struct file *f, unsigned char *data, unsigned count) { @@ -657,8 +676,6 @@ file_close(struct file *f) dbg_puts(": closing\n"); } #endif - if (f->wproc == NULL && f->rproc == NULL) - f->state |= FILE_ZOMB; if (!(f->state & (FILE_RINUSE | FILE_WINUSE))) { p = f->rproc; if (p) { diff --git a/usr.bin/aucat/headers.c b/usr.bin/aucat/headers.c index 7859e29a436..33978d50b90 100644 --- a/usr.bin/aucat/headers.c +++ b/usr.bin/aucat/headers.c @@ -1,4 +1,4 @@ -/* $OpenBSD: headers.c,v 1.11 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: headers.c,v 1.12 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -129,7 +129,7 @@ wav_readfmt(int fd, unsigned csize, struct aparams *par, short **map) } int -wav_readhdr(int fd, struct aparams *par, off_t *startpos, off_t *datasz, short **map) +wav_readhdr(int fd, struct aparams *par, off_t *datasz, short **map) { struct wavriff riff; struct wavchunk chunk; @@ -161,7 +161,6 @@ wav_readhdr(int fd, struct aparams *par, off_t *startpos, off_t *datasz, short * return 0; fmt_done = 1; } else if (memcmp(chunk.id, wav_id_data, 4) == 0) { - *startpos = pos; *datasz = csize; break; } else { @@ -187,12 +186,10 @@ wav_readhdr(int fd, struct aparams *par, off_t *startpos, off_t *datasz, short * return 1; } -/* - * Write header and seek to start position - */ int -wav_writehdr(int fd, struct aparams *par, off_t *startpos, off_t datasz) +wav_writehdr(int fd, struct aparams *par) { + off_t datasz; unsigned nch = par->cmax - par->cmin + 1; struct { struct wavriff riff; @@ -201,6 +198,16 @@ wav_writehdr(int fd, struct aparams *par, off_t *startpos, off_t datasz) struct wavchunk data_hdr; } hdr; + datasz = lseek(fd, 0, SEEK_CUR); + if (datasz < 0) { + warn("wav_writehdr: lseek(end)"); + return 0; + } + if (datasz >= sizeof(hdr)) + datasz -= sizeof(hdr); + else + datasz = 0; + /* * Check that encoding is supported by .wav file format. */ @@ -246,6 +253,5 @@ wav_writehdr(int fd, struct aparams *par, off_t *startpos, off_t datasz) warn("wav_writehdr: write"); return 0; } - *startpos = sizeof(hdr); return 1; } diff --git a/usr.bin/aucat/legacy.c b/usr.bin/aucat/legacy.c index 5f7a3655137..18e93c1e095 100644 --- a/usr.bin/aucat/legacy.c +++ b/usr.bin/aucat/legacy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: legacy.c,v 1.9 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: legacy.c,v 1.10 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 1997 Kenneth Stailey. All rights reserved. * @@ -64,7 +64,7 @@ legacy_play(char *dev, char *aufile) struct sio_par spar, par; struct aparams apar; ssize_t rd; - off_t datasz, dummy; + off_t datasz; char buf[5120]; size_t readsz; int fd, fmt = FMT_RAW; @@ -96,7 +96,7 @@ legacy_play(char *dev, char *aufile) if (read(fd, &chan, sizeof(chan)) == sizeof(chan)) chan = ntohl(chan); } else if (!strncmp(magic, "RIFF", 4) && - wav_readhdr(fd, &apar, &dummy, &datasz, &map)) { + wav_readhdr(fd, &apar, &datasz, &map)) { fmt = FMT_WAV; } diff --git a/usr.bin/aucat/midi.c b/usr.bin/aucat/midi.c index 8244a4cba3f..70d9aec2f3a 100644 --- a/usr.bin/aucat/midi.c +++ b/usr.bin/aucat/midi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: midi.c,v 1.17 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: midi.c,v 1.18 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -132,7 +132,7 @@ thru_rt(struct aproc *p, struct abuf *ibuf, struct abuf *obuf, unsigned c) if (debug_level >= 4) { aproc_dbg(p); dbg_puts(": "); - dbg_putx(c); + dbg_putu(c); dbg_puts(": flushing realtime message\n"); } #endif @@ -350,15 +350,16 @@ ctl_slotdbg(struct aproc *p, int slot) { struct ctl_slot *s; + aproc_dbg(p); if (slot < 0) { - dbg_puts("none"); + dbg_puts("/none"); } else { s = p->u.ctl.slot + slot; dbg_puts(s->name); dbg_putu(s->unit); - dbg_puts("("); + dbg_puts("="); dbg_putu(s->vol); - dbg_puts(")/"); + dbg_puts("/"); switch (s->tstate) { case CTL_OFF: dbg_puts("off"); @@ -393,7 +394,7 @@ ctl_sendmsg(struct aproc *p, struct abuf *ibuf, unsigned char *msg, unsigned len for (i = LIST_FIRST(&p->obuflist); i != NULL; i = inext) { inext = LIST_NEXT(i, oent); - if (i->duplex && i->duplex == ibuf) + if (i->duplex == ibuf) continue; itodo = len; idata = msg; @@ -638,10 +639,8 @@ ctl_trystart(struct aproc *p, int caller) if (p->u.ctl.tstate != CTL_START) { #ifdef DEBUG - if (debug_level >= 3) { - ctl_slotdbg(p, caller); - dbg_puts(": server not started, delayd\n"); - } + aproc_dbg(p); + dbg_puts(": not in starting state\n"); #endif return 0; } @@ -650,10 +649,8 @@ ctl_trystart(struct aproc *p, int caller) continue; if (s->tstate != CTL_OFF && s->tstate != CTL_START) { #ifdef DEBUG - if (debug_level >= 3) { - ctl_slotdbg(p, i); - dbg_puts(": not ready, server delayed\n"); - } + ctl_slotdbg(p, i); + dbg_puts(": not ready to start, start delayed\n"); #endif return 0; } @@ -663,10 +660,8 @@ ctl_trystart(struct aproc *p, int caller) continue; if (s->tstate == CTL_START) { #ifdef DEBUG - if (debug_level >= 3) { - ctl_slotdbg(p, i); - dbg_puts(": started\n"); - } + ctl_slotdbg(p, i); + dbg_puts(": started\n"); #endif s->tstate = CTL_RUN; s->ops->start(s->arg); @@ -676,10 +671,10 @@ ctl_trystart(struct aproc *p, int caller) p->u.ctl.slot[caller].tstate = CTL_RUN; p->u.ctl.tstate = CTL_RUN; p->u.ctl.delta = MTC_SEC * dev_getpos(); - if (dev_rate % (30 * 4 * dev_round) == 0) { + if (dev_rate % (30 * 4 * dev_round)) { p->u.ctl.fps_id = MTC_FPS_30; p->u.ctl.fps = 30; - } else if (dev_rate % (25 * 4 * dev_round) == 0) { + } else if (dev_rate % (25 * 4 * dev_round)) { p->u.ctl.fps_id = MTC_FPS_25; p->u.ctl.fps = 25; } else { @@ -687,17 +682,13 @@ ctl_trystart(struct aproc *p, int caller) p->u.ctl.fps = 24; } #ifdef DEBUG - if (debug_level >= 3) { - ctl_slotdbg(p, caller); - dbg_puts(": started server at "); - dbg_puti(p->u.ctl.delta); - dbg_puts(", "); - dbg_puti(p->u.ctl.fps); - dbg_puts(" mtc fps\n"); - } + ctl_slotdbg(p, caller); + dbg_puts(": started server at "); + dbg_puti(p->u.ctl.delta); + dbg_puts(", "); + dbg_puti(p->u.ctl.fps); + dbg_puts(" mtc fps\n"); #endif - if (dev_pstate == DEV_INIT) - dev_pstate = DEV_START; ctl_full(p); return 1; } @@ -711,15 +702,8 @@ ctl_slotnew(struct aproc *p, char *who, struct ctl_ops *ops, void *arg, int tr) int idx; struct ctl_slot *s; - if (!APROC_OK(p)) { -#ifdef DEBUG - if (debug_level >= 1) { - dbg_puts(who); - dbg_puts(": MIDI control not available\n"); - } -#endif + if (p == NULL) return -1; - } idx = ctl_getidx(p, who); if (idx < 0) return -1; @@ -742,7 +726,7 @@ ctl_slotdel(struct aproc *p, int index) unsigned i; struct ctl_slot *s; - if (!APROC_OK(p)) + if (p == NULL) return; p->u.ctl.slot[index].ops = NULL; if (!(p->flags & APROC_QUIT)) @@ -795,7 +779,7 @@ ctl_slotvol(struct aproc *p, int slot, unsigned vol) { unsigned char msg[3]; - if (!APROC_OK(p)) + if (p == NULL) return; #ifdef DEBUG if (debug_level >= 3) { @@ -823,7 +807,7 @@ ctl_slotstart(struct aproc *p, int slot) { struct ctl_slot *s = p->u.ctl.slot + slot; - if (!APROC_OK(p)) + if (p == NULL) return 1; if (s->tstate == CTL_OFF || p->u.ctl.tstate == CTL_OFF) return 1; @@ -847,7 +831,7 @@ ctl_slotstop(struct aproc *p, int slot) { struct ctl_slot *s = p->u.ctl.slot + slot; - if (!APROC_OK(p)) + if (p == NULL) return; /* * tag the stream as not trying to start, @@ -858,118 +842,6 @@ ctl_slotstop(struct aproc *p, int slot) } /* - * start all slots simultaneously - */ -void -ctl_start(struct aproc *p) -{ - if (!APROC_OK(p)) - return; - if (p->u.ctl.tstate == CTL_STOP) { - p->u.ctl.tstate = CTL_START; - (void)ctl_trystart(p, -1); -#ifdef DEBUG - } else { - if (debug_level >= 3) { - aproc_dbg(p); - dbg_puts(": ignoring mmc start\n"); - } -#endif - } -} - -/* - * stop all slots simultaneously - */ -void -ctl_stop(struct aproc *p) -{ - unsigned i; - struct ctl_slot *s; - - if (!APROC_OK(p)) - return; - switch (p->u.ctl.tstate) { - case CTL_START: - p->u.ctl.tstate = CTL_STOP; - return; - case CTL_RUN: - p->u.ctl.tstate = CTL_STOP; - break; - default: -#ifdef DEBUG - if (debug_level >= 3) { - aproc_dbg(p); - dbg_puts(": ignored mmc stop\n"); - } -#endif - return; - } - for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) { - if (!s->ops) - continue; - if (s->tstate == CTL_RUN) { -#ifdef DEBUG - if (debug_level >= 3) { - ctl_slotdbg(p, i); - dbg_puts(": requested to stop\n"); - } -#endif - s->ops->stop(s->arg); - } - } -} - -/* - * relocate all slots simultaneously - */ -void -ctl_loc(struct aproc *p, unsigned origin) -{ - unsigned i, tstate; - struct ctl_slot *s; - - if (!APROC_OK(p)) - return; -#ifdef DEBUG - if (debug_level >= 2) { - dbg_puts("server relocated to "); - dbg_putu(origin); - dbg_puts("\n"); - } -#endif - tstate = p->u.ctl.tstate; - if (tstate == CTL_RUN) - ctl_stop(p); - p->u.ctl.origin = origin; - for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) { - if (!s->ops) - continue; - s->ops->loc(s->arg, p->u.ctl.origin); - } - if (tstate == CTL_RUN) - ctl_start(p); -} - -/* - * check if there are controlled streams - */ -int -ctl_idle(struct aproc *p) -{ - unsigned i; - struct ctl_slot *s; - - if (!APROC_OK(p)) - return 1; - for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) { - if (s->ops) - return 0; - } - return 1; -} - -/* * handle a MIDI event received from ibuf */ void @@ -1011,21 +883,41 @@ ctl_ev(struct aproc *p, struct abuf *ibuf) switch (ibuf->r.midi.msg[4]) { case 0x01: /* mmc stop */ #ifdef DEBUG - if (debug_level >= 3) { + if (debug_level >= 1) { abuf_dbg(ibuf); dbg_puts(": mmc stop\n"); } #endif - ctl_stop(p); + if (p->u.ctl.tstate == CTL_RUN || + p->u.ctl.tstate == CTL_START) + p->u.ctl.tstate = CTL_STOP; +#ifdef DEBUG + else { + if (debug_level >= 1) { + aproc_dbg(p); + dbg_puts(": ignored mmc stop\n"); + } + } +#endif break; case 0x02: /* mmc start */ #ifdef DEBUG - if (debug_level >= 3) { + if (debug_level >= 1) { abuf_dbg(ibuf); dbg_puts(": mmc start\n"); } #endif - ctl_start(p); + if (p->u.ctl.tstate == CTL_STOP) { + p->u.ctl.tstate = CTL_START; + (void)ctl_trystart(p, -1); +#ifdef DEBUG + } else { + if (debug_level >= 1) { + abuf_dbg(ibuf); + dbg_puts(": ignoring mmc start\n"); + } +#endif + } break; } } @@ -1051,12 +943,20 @@ ctl_ev(struct aproc *p, struct abuf *ibuf) p->u.ctl.origin = 0; return; } - ctl_loc(p, + p->u.ctl.origin = (ibuf->r.midi.msg[7] & 0x1f) * 3600 * MTC_SEC + ibuf->r.midi.msg[8] * 60 * MTC_SEC + ibuf->r.midi.msg[9] * MTC_SEC + ibuf->r.midi.msg[10] * (MTC_SEC / fps) + - ibuf->r.midi.msg[11] * (MTC_SEC / 100 / fps)); + ibuf->r.midi.msg[11] * (MTC_SEC / 100 / fps); +#ifdef DEBUG + if (debug_level >= 1) { + aproc_dbg(p); + dbg_puts(": relocated to "); + dbg_putu(p->u.ctl.origin); + dbg_puts("\n"); + } +#endif } } diff --git a/usr.bin/aucat/midi.h b/usr.bin/aucat/midi.h index 4b5cdf183df..809dc2ae90f 100644 --- a/usr.bin/aucat/midi.h +++ b/usr.bin/aucat/midi.h @@ -1,4 +1,4 @@ -/* $OpenBSD: midi.h,v 1.6 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: midi.h,v 1.7 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -27,8 +27,4 @@ int ctl_slotstart(struct aproc *, int); void ctl_slotstop(struct aproc *, int); void ctl_ontick(struct aproc *, int); -void ctl_stop(struct aproc *); -void ctl_start(struct aproc *); -int ctl_idle(struct aproc *); - #endif /* !defined(MIDI_H) */ diff --git a/usr.bin/aucat/midicat.1 b/usr.bin/aucat/midicat.1 index 3befc6a3bbf..11c828798e1 100644 --- a/usr.bin/aucat/midicat.1 +++ b/usr.bin/aucat/midicat.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: midicat.1,v 1.7 2010/04/03 17:40:33 ratchov Exp $ +.\" $OpenBSD: midicat.1,v 1.8 2010/04/03 17:59:17 ratchov Exp $ .\" .\" Copyright (c) 2006 Alexandre Ratchov <alex@caoua.org> .\" @@ -23,9 +23,9 @@ .Sh SYNOPSIS .Nm midicat .Op Fl dl +.Op Fl f Ar device .Op Fl i Ar file .Op Fl o Ar file -.Op Fl q Ar device .Op Fl U Ar unit .Sh DESCRIPTION The @@ -45,6 +45,13 @@ If this option is specified, .Nm will run in the foreground and log to .Em stderr . +.It Fl f Ar device +The +.Xr midi 4 +device or +.Nm +socket to use for MIDI input/output. +In server mode, devices are subscribed to the MIDI thru box. .It Fl i Ar file Send contents of this file to the device. If the option argument is @@ -64,11 +71,6 @@ Store received data from the device into this file. If the option argument is .Sq - then standard output will be used. -.It Fl q Ar device -The -.Xr sndio 7 -MIDI device to use for MIDI input/output. -In server mode, devices are subscribed to the MIDI thru box. .It Fl U Ar unit Use the given unit number when creating a software MIDI thru box. Only one diff --git a/usr.bin/aucat/opt.c b/usr.bin/aucat/opt.c index c4fd6e6c3c1..2bcaee5a3fc 100644 --- a/usr.bin/aucat/opt.c +++ b/usr.bin/aucat/opt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: opt.c,v 1.5 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: opt.c,v 1.6 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -27,8 +27,8 @@ struct optlist opt_list = SLIST_HEAD_INITIALIZER(&opt_list); void -opt_new(char *name, struct aparams *wpar, struct aparams *rpar, - int maxweight, int mmc, unsigned mode) +opt_new(char *name, + struct aparams *wpar, struct aparams *rpar, int maxweight, int mmc) { struct opt *o; unsigned len; @@ -54,39 +54,21 @@ opt_new(char *name, struct aparams *wpar, struct aparams *rpar, exit(1); } memcpy(o->name, name, len + 1); - if (mode & MODE_RECMASK) - o->wpar = (mode & MODE_MON) ? *rpar : *wpar; - if (mode & MODE_PLAY) - o->rpar = *rpar; + o->wpar = *wpar; + o->rpar = *rpar; o->maxweight = maxweight; o->mmc = mmc; - o->mode = mode; #ifdef DEBUG if (debug_level >= 2) { dbg_puts(o->name); - dbg_puts(":"); - if (mode & MODE_REC) { - dbg_puts(" rec="); - dbg_putu(o->wpar.cmin); - dbg_puts(":"); - dbg_putu(o->wpar.cmax); - } - if (mode & MODE_PLAY) { - dbg_puts(" play="); - dbg_putu(o->rpar.cmin); - dbg_puts(":"); - dbg_putu(o->rpar.cmax); - dbg_puts(" vol="); - dbg_putu(o->maxweight); - } - if (mode & MODE_MON) { - dbg_puts(" mon="); - dbg_putu(o->wpar.cmin); - dbg_puts(":"); - dbg_putu(o->wpar.cmax); - } + dbg_puts(": rec "); + aparams_dbg(&o->wpar); + dbg_puts(", play "); + aparams_dbg(&o->rpar); + dbg_puts(", vol "); + dbg_putu(o->maxweight); if (o->mmc) - dbg_puts(" mmc"); + dbg_puts(", mmc"); dbg_puts("\n"); } #endif diff --git a/usr.bin/aucat/opt.h b/usr.bin/aucat/opt.h index 3572d560397..875f0537601 100644 --- a/usr.bin/aucat/opt.h +++ b/usr.bin/aucat/opt.h @@ -1,4 +1,4 @@ -/* $OpenBSD: opt.h,v 1.3 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: opt.h,v 1.4 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -28,18 +28,11 @@ struct opt { struct aparams wpar; /* template for clients write params */ struct aparams rpar; /* template for clients read params */ int mmc; /* true if MMC control 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_RECMASK (MODE_REC | MODE_MON) - unsigned mode; /* bitmap of above */ }; SLIST_HEAD(optlist,opt); -void opt_new(char *, struct aparams *, struct aparams *, int, int, unsigned); +void opt_new(char *, struct aparams *, struct aparams *, int, int); struct opt *opt_byname(char *); #endif /* !defined(OPT_H) */ diff --git a/usr.bin/aucat/pipe.c b/usr.bin/aucat/pipe.c index 065f6f0ad7a..76f98baa832 100644 --- a/usr.bin/aucat/pipe.c +++ b/usr.bin/aucat/pipe.c @@ -139,54 +139,3 @@ pipe_close(struct file *file) close(f->fd); } - -off_t -pipe_endpos(struct file *file) -{ - struct pipe *f = (struct pipe *)file; - off_t pos; - - pos = lseek(f->fd, 0, SEEK_END); - if (pos < 0) { -#ifdef DEBUG - file_dbg(&f->file); - dbg_puts(": couldn't get file size\n"); -#endif - return 0; - } - return pos; -} - -int -pipe_seek(struct file *file, off_t pos) -{ - struct pipe *f = (struct pipe *)file; - off_t newpos; - - newpos = lseek(f->fd, pos, SEEK_SET); - if (newpos < 0) { -#ifdef DEBUG - file_dbg(&f->file); - dbg_puts(": couldn't seek\n"); -#endif - /* XXX: call eof() */ - return 0; - } - return 1; -} - -int -pipe_trunc(struct file *file, off_t pos) -{ - struct pipe *f = (struct pipe *)file; - - if (ftruncate(f->fd, pos) < 0) { -#ifdef DEBUG - file_dbg(&f->file); - dbg_puts(": couldn't truncate file\n"); -#endif - /* XXX: call hup() */ - return 0; - } - return 1; -} diff --git a/usr.bin/aucat/pipe.h b/usr.bin/aucat/pipe.h index b2f986f92bd..adcc0e89f5f 100644 --- a/usr.bin/aucat/pipe.h +++ b/usr.bin/aucat/pipe.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pipe.h,v 1.3 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: pipe.h,v 1.4 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -33,8 +33,5 @@ unsigned pipe_write(struct file *, unsigned char *, unsigned); int pipe_nfds(struct file *); int pipe_pollfd(struct file *, struct pollfd *, int); int pipe_revents(struct file *, struct pollfd *); -int pipe_seek(struct file *, off_t); -int pipe_trunc(struct file *, off_t); -off_t pipe_endpos(struct file *); #endif /* !defined(PIPE_H) */ diff --git a/usr.bin/aucat/siofile.c b/usr.bin/aucat/siofile.c index ae225460bb1..f52a0c2d647 100644 --- a/usr.bin/aucat/siofile.c +++ b/usr.bin/aucat/siofile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: siofile.c,v 1.2 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: siofile.c,v 1.3 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -26,7 +26,6 @@ #include "aparams.h" #include "aproc.h" -#include "abuf.h" #include "conf.h" #include "dev.h" #include "file.h" @@ -38,9 +37,6 @@ struct siofile { struct file file; struct sio_hdl *hdl; - unsigned wtickets, wbpf; - unsigned rtickets, rbpf; - unsigned bufsz; int started; }; @@ -66,95 +62,6 @@ struct fileops siofile_ops = { siofile_revents }; -int wsio_out(struct aproc *, struct abuf *); -int rsio_in(struct aproc *, struct abuf *); - -struct aproc_ops rsio_ops = { - "rsio", - rsio_in, - rfile_out, - rfile_eof, - rfile_hup, - NULL, /* newin */ - NULL, /* newout */ - aproc_ipos, - aproc_opos, - rfile_done -}; - -struct aproc_ops wsio_ops = { - "wsio", - wfile_in, - wsio_out, - wfile_eof, - wfile_hup, - NULL, /* newin */ - NULL, /* newout */ - aproc_ipos, - aproc_opos, - wfile_done -}; - -struct aproc * -rsio_new(struct file *f) -{ - struct aproc *p; - - p = aproc_new(&rsio_ops, f->name); - p->u.io.file = f; - p->u.io.partial = 0; - f->rproc = p; - return p; -} - -struct aproc * -wsio_new(struct file *f) -{ - struct aproc *p; - - p = aproc_new(&wsio_ops, f->name); - p->u.io.file = f; - p->u.io.partial = 0; - f->wproc = p; - return p; -} - -int -wsio_out(struct aproc *p, struct abuf *obuf) -{ - struct siofile *f = (struct siofile *)p->u.io.file; - - if (f->wtickets == 0) { -#ifdef DEBUG - if (debug_level >= 4) { - file_dbg(&f->file); - dbg_puts(": no more write tickets\n"); - } -#endif - f->file.state &= ~FILE_WOK; - return 0; - } - return wfile_out(p, obuf); -} - -int -rsio_in(struct aproc *p, struct abuf *ibuf) -{ - struct siofile *f = (struct siofile *)p->u.io.file; - - if (f->rtickets == 0) { -#ifdef DEBUG - if (debug_level >= 4) { - file_dbg(&f->file); - dbg_puts(": no more read tickets\n"); - } -#endif - f->file.state &= ~FILE_ROK; - return 0; - } - return rfile_in(p, ibuf); -} - void siofile_cb(void *addr, int delta) { @@ -163,18 +70,12 @@ siofile_cb(void *addr, int delta) #ifdef DEBUG if (delta < 0 || delta > (60 * RATE_MAX)) { - file_dbg(&f->file); + dbg_puts(f->file.name); dbg_puts(": "); dbg_puti(delta); dbg_puts(": bogus sndio delta"); dbg_panic(); } - if (debug_level >= 4) { - file_dbg(&f->file); - dbg_puts(": tick, delta = "); - dbg_puti(delta); - dbg_puts("\n"); - } #endif if (delta != 0) { p = f->file.wproc; @@ -186,27 +87,31 @@ siofile_cb(void *addr, int delta) if (p && p->ops->ipos) p->ops->ipos(p, NULL, delta); } - f->wtickets += delta * f->wbpf; - f->rtickets += delta * f->rbpf; } /* * Open the device. */ struct siofile * -siofile_new(struct fileops *ops, char *path, unsigned mode, +siofile_new(struct fileops *ops, char *path, struct aparams *ipar, struct aparams *opar, unsigned *bufsz, unsigned *round) { struct sio_par par; struct sio_hdl *hdl; struct siofile *f; + int mode; + mode = 0; + if (ipar) + mode |= SIO_REC; + if (opar) + mode |= SIO_PLAY; hdl = sio_open(path, mode, 1); if (hdl == NULL) return NULL; sio_initpar(&par); - if (mode & SIO_REC) { + if (ipar) { par.bits = ipar->bits; par.bps = ipar->bps; par.sig = ipar->sig; @@ -222,7 +127,7 @@ siofile_new(struct fileops *ops, char *path, unsigned mode, par.msb = opar->msb; par.rate = opar->rate; } - if (mode & SIO_PLAY) + if (opar) par.pchan = opar->cmax - opar->cmin + 1; par.appbufsz = *bufsz; par.round = *round; @@ -230,7 +135,7 @@ siofile_new(struct fileops *ops, char *path, unsigned mode, goto bad_close; if (!sio_getpar(hdl, &par)) goto bad_close; - if (mode & SIO_REC) { + if (ipar) { ipar->bits = par.bits; ipar->bps = par.bps; ipar->sig = par.sig; @@ -239,7 +144,7 @@ siofile_new(struct fileops *ops, char *path, unsigned mode, ipar->rate = par.rate; ipar->cmax = ipar->cmin + par.rchan - 1; } - if (mode & SIO_PLAY) { + if (opar) { opar->bits = par.bits; opar->bps = par.bps; opar->sig = par.sig; @@ -257,11 +162,6 @@ siofile_new(struct fileops *ops, char *path, unsigned mode, goto bad_close; f->hdl = hdl; f->started = 0; - f->wtickets = 0; - f->rtickets = 0; - f->wbpf = par.pchan * par.bps; - f->rbpf = par.rchan * par.bps; - f->bufsz = par.bufsz; sio_onmove(f->hdl, siofile_cb, f); return f; bad_close: @@ -283,8 +183,6 @@ siofile_start(struct file *file) return; } f->started = 1; - f->wtickets = f->bufsz * f->wbpf; - f->rtickets = 0; #ifdef DEBUG if (debug_level >= 3) { file_dbg(&f->file); @@ -321,14 +219,6 @@ siofile_read(struct file *file, unsigned char *data, unsigned count) struct siofile *f = (struct siofile *)file; unsigned n; -#ifdef DEBUG - if (f->rtickets == 0) { - file_dbg(&f->file); - dbg_puts(": called with no read tickets\n"); - } -#endif - if (count > f->rtickets) - count = f->rtickets; n = f->started ? sio_read(f->hdl, data, count) : 0; if (n == 0) { f->file.state &= ~FILE_ROK; @@ -347,17 +237,6 @@ siofile_read(struct file *file, unsigned char *data, unsigned count) #endif } return 0; - } else { - f->rtickets -= n; - if (f->rtickets == 0) { - f->file.state &= ~FILE_ROK; -#ifdef DEBUG - if (debug_level >= 4) { - file_dbg(&f->file); - dbg_puts(": read tickets exhausted\n"); - } -#endif - } } return n; @@ -369,14 +248,6 @@ siofile_write(struct file *file, unsigned char *data, unsigned count) struct siofile *f = (struct siofile *)file; unsigned n; -#ifdef DEBUG - if (f->wtickets == 0) { - file_dbg(&f->file); - dbg_puts(": called with no write tickets\n"); - } -#endif - if (count > f->wtickets) - count = f->wtickets; n = f->started ? sio_write(f->hdl, data, count) : 0; if (n == 0) { f->file.state &= ~FILE_WOK; @@ -395,17 +266,6 @@ siofile_write(struct file *file, unsigned char *data, unsigned count) #endif } return 0; - } else { - f->wtickets -= n; - if (f->wtickets == 0) { - f->file.state &= ~FILE_WOK; -#ifdef DEBUG - if (debug_level >= 4) { - file_dbg(&f->file); - dbg_puts(": write tickets exhausted\n"); - } -#endif - } } return n; } diff --git a/usr.bin/aucat/siofile.h b/usr.bin/aucat/siofile.h index bb8cb5dd801..b218bf1080d 100644 --- a/usr.bin/aucat/siofile.h +++ b/usr.bin/aucat/siofile.h @@ -1,4 +1,4 @@ -/* $OpenBSD: siofile.h,v 1.2 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: siofile.h,v 1.3 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -20,12 +20,9 @@ struct fileops; struct siofile; struct aparams; -struct aproc; -struct siofile *siofile_new(struct fileops *, char *, unsigned, +struct siofile *siofile_new(struct fileops *, char *, struct aparams *, struct aparams *, unsigned *, unsigned *); -struct aproc *rsio_new(struct file *f); -struct aproc *wsio_new(struct file *f); extern struct fileops siofile_ops; diff --git a/usr.bin/aucat/sock.c b/usr.bin/aucat/sock.c index 4086e1ba478..bb12d836d70 100644 --- a/usr.bin/aucat/sock.c +++ b/usr.bin/aucat/sock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sock.c,v 1.40 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: sock.c,v 1.41 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -14,6 +14,12 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/* + * TODO: + * + * change f->bufsz to contain only socket-side buffer, + * because it's less error prone + */ #include <stdio.h> #include <stdlib.h> @@ -30,7 +36,7 @@ #include "dbg.h" #endif -void sock_attach(struct sock *, int); +int sock_attach(struct sock *, int); int sock_read(struct sock *); int sock_write(struct sock *); int sock_execmsg(struct sock *); @@ -53,11 +59,11 @@ 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", "run", "mid" }; static char *rstates[] = { "rdat", "rmsg", "rret" }; static char *wstates[] = { "widl", "wmsg", "wdat" }; - if (f->slot >= 0 && APROC_OK(dev_midi)) { + if (f->slot >= 0 && dev_midi) { dbg_puts(dev_midi->u.ctl.slot[f->slot].name); dbg_putu(dev_midi->u.ctl.slot[f->slot].unit); } else @@ -73,14 +79,10 @@ sock_dbg(struct sock *f) void sock_setvol(void *, unsigned); void sock_startreq(void *); -void sock_stopreq(void *); -void sock_locreq(void *, unsigned); struct ctl_ops ctl_sockops = { sock_setvol, - sock_startreq, - sock_stopreq, - sock_locreq + sock_startreq }; void @@ -156,7 +158,7 @@ rsock_opos(struct aproc *p, struct abuf *obuf, int delta) { struct sock *f = (struct sock *)p->u.io.file; - if (f->mode & AMSG_RECMASK) + if (f->mode & AMSG_REC) return; f->delta += delta; @@ -255,7 +257,7 @@ wsock_ipos(struct aproc *p, struct abuf *obuf, int delta) { struct sock *f = (struct sock *)p->u.io.file; - if (!(f->mode & AMSG_RECMASK)) + if (!(f->mode & AMSG_REC)) return; f->delta += delta; @@ -304,9 +306,9 @@ sock_new(struct fileops *ops, int fd) f->mode = 0; f->opt = opt_byname("default"); if (f->opt) { - if (f->opt->mode & MODE_RECMASK) + if (dev_sub) f->wpar = f->opt->wpar; - if (f->opt->mode & MODE_PLAY) + if (dev_mix) f->rpar = f->opt->rpar; } f->xrun = AMSG_IGNORE; @@ -314,20 +316,17 @@ sock_new(struct fileops *ops, int fd) f->round = dev_round; f->delta = 0; f->tickpending = 0; - f->startpending = 0; f->vol = f->lastvol = MIDI_MAXCTL; f->slot = -1; wproc = aproc_new(&wsock_ops, f->pipe.file.name); wproc->u.io.file = &f->pipe.file; - wproc->u.io.partial = 0; f->pipe.file.wproc = wproc; f->wstate = SOCK_WIDLE; f->wtodo = 0xdeadbeef; rproc = aproc_new(&rsock_ops, f->pipe.file.name); rproc->u.io.file = &f->pipe.file; - rproc->u.io.partial = 0; f->pipe.file.rproc = rproc; f->rstate = SOCK_RMSG; f->rtodo = sizeof(struct amsg); @@ -358,7 +357,6 @@ sock_freebuf(struct sock *f) if (wbuf) abuf_hup(wbuf); f->tickpending = 0; - f->startpending = 0; } /* @@ -369,40 +367,28 @@ sock_allocbuf(struct sock *f) { struct abuf *rbuf = NULL, *wbuf = NULL; - f->pstate = SOCK_START; if (f->mode & AMSG_PLAY) { rbuf = abuf_new(f->bufsz, &f->rpar); aproc_setout(f->pipe.file.rproc, rbuf); - if (!ABUF_WOK(rbuf) || (f->pipe.file.state & FILE_EOF)) - f->pstate = SOCK_READY; } - if (f->mode & AMSG_RECMASK) { + if (f->mode & AMSG_REC) { wbuf = abuf_new(f->bufsz, &f->wpar); aproc_setin(f->pipe.file.wproc, wbuf); - f->walign = f->round; + f->walign = dev_round * wbuf->bpf; } f->delta = 0; - f->wmax = 0; - f->rmax = f->bufsz; f->tickpending = 0; - f->startpending = 0; #ifdef DEBUG if (debug_level >= 3) { sock_dbg(f); dbg_puts(": allocating "); dbg_putu(f->bufsz); - dbg_puts(" fr buffers, rmax = "); - dbg_putu(f->rmax); - dbg_puts("\n"); + dbg_puts(" fr buffers\n"); } #endif - if (f->mode & AMSG_PLAY) { - f->pstate = SOCK_START; - } else { - f->pstate = SOCK_READY; - if (ctl_slotstart(dev_midi, f->slot)) - (void)sock_attach(f, 0); - } + f->pstate = SOCK_START; + if (!(f->mode & AMSG_PLAY) && ctl_slotstart(dev_midi, f->slot)) + (void)sock_attach(f, 0); } /* @@ -437,9 +423,9 @@ sock_startreq(void *arg) struct sock *f = (struct sock *)arg; #ifdef DEBUG - if (f->pstate != SOCK_READY) { + if (f->pstate != SOCK_START) { sock_dbg(f); - dbg_puts(": not in READY state\n"); + dbg_puts(": not in START state\n"); dbg_panic(); } #endif @@ -447,41 +433,9 @@ sock_startreq(void *arg) } /* - * Callback invoked by MMC stop - */ -void -sock_stopreq(void *arg) -{ -#ifdef DEBUG - struct sock *f = (struct sock *)arg; - - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": ignored STOP signal\n"); - } -#endif -} - -/* - * Callback invoked by MMC relocate, ignored - */ -void -sock_locreq(void *arg, unsigned mmcpos) -{ -#ifdef DEBUG - struct sock *f = (struct sock *)arg; - - if (debug_level >= 3) { - sock_dbg(f); - dbg_puts(": ignored RELOCATE signal\n"); - } -#endif -} - -/* * Attach play and/or record buffers to dev_mix and/or dev_sub. */ -void +int sock_attach(struct sock *f, int force) { struct abuf *rbuf, *wbuf; @@ -494,30 +448,23 @@ sock_attach(struct sock *f, int force) * the buffer isn't completely filled. */ if (!force && rbuf && ABUF_WOK(rbuf)) - return; + return 0; - /* - * get the current position, the origin is when - * the first sample is played/recorded - */ - f->delta = dev_getpos() * (int)f->round / (int)dev_round; - f->startpending = 1; - f->pstate = SOCK_RUN; #ifdef DEBUG if (debug_level >= 3) { sock_dbg(f); - dbg_puts(": attaching at "); - dbg_puti(f->delta); - dbg_puts("\n"); + dbg_puts(": attaching to device\n"); } #endif + f->pstate = SOCK_RUN; + /* - * We dont check whether the device is dying, - * because dev_xxx() functions are supposed to - * work (i.e., not to crash) + * Attach them to the device. */ - dev_attach(f->pipe.file.name, f->mode, - rbuf, &f->rpar, wbuf, &f->wpar, f->xrun, f->opt->maxweight); + dev_attach(f->pipe.file.name, + (f->mode & AMSG_PLAY) ? rbuf : NULL, &f->rpar, f->xrun, + (f->mode & AMSG_REC) ? wbuf : NULL, &f->wpar, f->xrun, + f->opt->maxweight); if (f->mode & AMSG_PLAY) dev_setvol(rbuf, MIDI_TO_ADATA(f->vol)); @@ -528,6 +475,7 @@ sock_attach(struct sock *f, int force) if (!sock_write(f)) break; } + return 1; } void @@ -535,7 +483,6 @@ sock_reset(struct sock *f) { switch (f->pstate) { case SOCK_START: - case SOCK_READY: if (ctl_slotstart(dev_midi, f->slot)) { (void)sock_attach(f, 1); f->pstate = SOCK_RUN; @@ -637,7 +584,8 @@ sock_rdata(struct sock *f) { struct aproc *p; struct abuf *obuf; - unsigned n; + unsigned char *data; + unsigned count, n; #ifdef DEBUG if (f->pstate != SOCK_MIDI && f->rtodo == 0) { @@ -650,20 +598,17 @@ sock_rdata(struct sock *f) obuf = LIST_FIRST(&p->obuflist); if (obuf == NULL) return 0; - if (!ABUF_WOK(obuf) || !(f->pipe.file.state & FILE_ROK)) + if (ABUF_FULL(obuf) || !(f->pipe.file.state & FILE_ROK)) return 0; - if (f->pstate == SOCK_MIDI) { - if (!rfile_do(p, obuf->len, NULL)) - return 0; - } else { - if (!rfile_do(p, f->rtodo, &n)) - return 0; + data = abuf_wgetblk(obuf, &count, 0); + if (f->pstate != SOCK_MIDI && count > f->rtodo) + count = f->rtodo; + n = file_read(&f->pipe.file, data, count); + if (n == 0) + return 0; + abuf_wcommit(obuf, n); + if (f->pstate != SOCK_MIDI) f->rtodo -= n; - if (f->pstate == SOCK_START) { - if (!ABUF_WOK(obuf) || (f->pipe.file.state & FILE_EOF)) - f->pstate = SOCK_READY; - } - } return 1; } @@ -676,7 +621,10 @@ sock_wdata(struct sock *f) { struct aproc *p; struct abuf *ibuf; - unsigned n; + unsigned char *data; + unsigned count, n; +#define ZERO_MAX 0x1000 + static unsigned char zero[ZERO_MAX]; #ifdef DEBUG if (f->pstate != SOCK_MIDI && f->wtodo == 0) { @@ -689,22 +637,32 @@ sock_wdata(struct sock *f) return 0; p = f->pipe.file.wproc; ibuf = LIST_FIRST(&p->ibuflist); -#ifdef DEBUG - if (f->pstate != SOCK_MIDI && ibuf == NULL) { - sock_dbg(f); - dbg_puts(": attempted to write on detached buffer\n"); - dbg_panic(); - } -#endif - if (ibuf == NULL) - return 0; - if (!ABUF_ROK(ibuf)) - return 0; - if (f->pstate == SOCK_MIDI) { - if (!wfile_do(p, ibuf->len, NULL)) + if (ibuf) { + if (ABUF_EMPTY(ibuf)) return 0; + data = abuf_rgetblk(ibuf, &count, 0); + if (f->pstate != SOCK_MIDI && count > f->wtodo) + count = f->wtodo; + n = file_write(&f->pipe.file, data, count); + if (n == 0) + return 0; + abuf_rdiscard(ibuf, n); + if (f->pstate != SOCK_MIDI) + f->wtodo -= n; } else { - if (!wfile_do(p, f->wtodo, &n)) + if (f->pstate == SOCK_MIDI) + return 0; + /* + * There's no dev_detach() routine yet, + * so now we abruptly destroy the buffer. + * Until we implement dev_detach, complete + * the packet with zeros... + */ + count = ZERO_MAX; + if (count > f->wtodo) + count = f->wtodo; + n = file_write(&f->pipe.file, zero, count); + if (n == 0) return 0; f->wtodo -= n; } @@ -762,7 +720,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 & AMSG_REC)) { if (p->rchan < 1) p->rchan = 1; if (p->rchan > NCHAN_MAX) @@ -877,8 +835,8 @@ sock_setpar(struct sock *f) } if (AMSG_ISSET(p->appbufsz)) { rate = (f->mode & AMSG_PLAY) ? f->rpar.rate : f->wpar.rate; - min = 1; - max = 1 + rate / dev_round; + min = 2; + max = 2 + rate / dev_round; min *= f->round; max *= f->round; p->appbufsz += f->round - 1; @@ -899,7 +857,7 @@ sock_setpar(struct sock *f) } #ifdef DEBUG if (debug_level >= 2) { - if (f->slot >= 0 && dev_midi) { + if (f->slot >= -1 && dev_midi) { dbg_puts(dev_midi->u.ctl.slot[f->slot].name); dbg_putu(dev_midi->u.ctl.slot[f->slot].unit); } else @@ -910,7 +868,7 @@ sock_setpar(struct sock *f) dbg_puts(", play = "); aparams_dbg(&f->rpar); } - if (f->mode & AMSG_RECMASK) { + if (f->mode & AMSG_REC) { dbg_puts(", rec:"); aparams_dbg(&f->wpar); } @@ -970,7 +928,7 @@ sock_hello(struct sock *f) /* * XXX : dev_midi can no longer be NULL, right ? */ - if (APROC_OK(dev_midi) && (p->proto & (AMSG_MIDIIN | AMSG_MIDIOUT))) { + if (dev_midi && (p->proto & (AMSG_MIDIIN | AMSG_MIDIOUT))) { if (p->proto & ~(AMSG_MIDIIN | AMSG_MIDIOUT)) { #ifdef DEBUG if (debug_level >= 1) { @@ -990,9 +948,9 @@ sock_hello(struct sock *f) f->opt = opt_byname(p->opt); if (f->opt == NULL) return 0; - if (f->opt->mode & MODE_RECMASK) + if (dev_sub) f->wpar = f->opt->wpar; - if (f->opt->mode & MODE_PLAY) + if (dev_mix) f->rpar = f->opt->rpar; if (f->opt->mmc) f->xrun = AMSG_SYNC; @@ -1010,7 +968,7 @@ sock_hello(struct sock *f) } f->mode = 0; if (p->proto & AMSG_PLAY) { - if (!APROC_OK(dev_mix) || !(f->opt->mode & MODE_PLAY)) { + if (!dev_mix) { #ifdef DEBUG if (debug_level >= 1) { sock_dbg(f); @@ -1022,8 +980,7 @@ sock_hello(struct sock *f) f->mode |= AMSG_PLAY; } if (p->proto & AMSG_REC) { - if (!(APROC_OK(dev_sub) && (f->opt->mode & MODE_REC)) && - !(APROC_OK(dev_submon) && (f->opt->mode & MODE_MON))) { + if (!dev_sub) { #ifdef DEBUG if (debug_level >= 1) { sock_dbg(f); @@ -1032,9 +989,9 @@ sock_hello(struct sock *f) #endif return 0; } - f->mode |= (f->opt->mode & MODE_MON) ? AMSG_MON : AMSG_REC; + f->mode |= AMSG_REC; } - if (APROC_OK(dev_midi)) { + if (dev_midi) { f->slot = ctl_slotnew(dev_midi, p->who, &ctl_sockops, f, f->opt->mmc); @@ -1060,7 +1017,6 @@ int sock_execmsg(struct sock *f) { struct amsg *m = &f->rmsg; - struct abuf *obuf; switch (m->cmd) { case AMSG_DATA: @@ -1070,8 +1026,7 @@ sock_execmsg(struct sock *f) dbg_puts(": DATA message\n"); } #endif - if (f->pstate != SOCK_RUN && f->pstate != SOCK_START && - f->pstate != SOCK_READY) { + if (f->pstate != SOCK_RUN && f->pstate != SOCK_START) { #ifdef DEBUG if (debug_level >= 1) { sock_dbg(f); @@ -1091,8 +1046,8 @@ sock_execmsg(struct sock *f) aproc_del(f->pipe.file.rproc); return 0; } - obuf = LIST_FIRST(&f->pipe.file.rproc->obuflist); - if (f->pstate == SOCK_START && !ABUF_WOK(obuf)) { + if (f->pstate == SOCK_START && + ABUF_FULL(LIST_FIRST(&f->pipe.file.rproc->obuflist))) { #ifdef DEBUG if (debug_level >= 1) { sock_dbg(f); @@ -1102,31 +1057,8 @@ sock_execmsg(struct sock *f) aproc_del(f->pipe.file.rproc); return 0; } - if (m->u.data.size % obuf->bpf != 0) { -#ifdef DEBUG - if (debug_level >= 1) { - sock_dbg(f); - dbg_puts(": unaligned data chunk\n"); - } -#endif - aproc_del(f->pipe.file.rproc); - return 0; - } f->rstate = SOCK_RDATA; - f->rtodo = m->u.data.size / obuf->bpf; -#ifdef DEBUG - if (f->rtodo > f->rmax && debug_level >= 2) { - sock_dbg(f); - dbg_puts(": received past current position, rtodo = "); - dbg_putu(f->rtodo); - dbg_puts(", rmax = "); - dbg_putu(f->rmax); - dbg_puts("\n"); - aproc_del(f->pipe.file.rproc); - return 0; - } -#endif - f->rmax -= f->rtodo; + f->rtodo = m->u.data.size; if (f->rtodo == 0) { #ifdef DEBUG if (debug_level >= 1) { @@ -1166,8 +1098,7 @@ sock_execmsg(struct sock *f) dbg_puts(": STOP message\n"); } #endif - if (f->pstate != SOCK_RUN && - f->pstate != SOCK_START && f->pstate != SOCK_READY) { + if (f->pstate != SOCK_RUN && f->pstate != SOCK_START) { #ifdef DEBUG if (debug_level >= 1) { sock_dbg(f); @@ -1176,18 +1107,11 @@ sock_execmsg(struct sock *f) #endif aproc_del(f->pipe.file.rproc); return 0; - /* - * XXX: device could have desappeared at this point, - * see how this is fixed in wav.c - */ } - if ((f->pstate == SOCK_START || f->pstate == SOCK_READY) && + if (f->pstate == SOCK_START && ctl_slotstart(dev_midi, f->slot)) (void)sock_attach(f, 1); - if (f->wstate != SOCK_WDATA || f->wtodo == 0) - sock_freebuf(f); - else - f->pstate = SOCK_STOP; + sock_freebuf(f); AMSG_INIT(m); m->cmd = AMSG_ACK; f->rstate = SOCK_RRET; @@ -1237,24 +1161,14 @@ sock_execmsg(struct sock *f) AMSG_INIT(m); m->cmd = AMSG_GETPAR; m->u.par.legacy_mode = f->mode; - if (f->mode & AMSG_PLAY) { - m->u.par.bits = f->rpar.bits; - m->u.par.bps = f->rpar.bps; - m->u.par.sig = f->rpar.sig; - m->u.par.le = f->rpar.le; - m->u.par.msb = f->rpar.msb; - m->u.par.rate = f->rpar.rate; - m->u.par.pchan = f->rpar.cmax - f->rpar.cmin + 1; - } - if (f->mode & AMSG_RECMASK) { - m->u.par.bits = f->wpar.bits; - m->u.par.bps = f->wpar.bps; - m->u.par.sig = f->wpar.sig; - m->u.par.le = f->wpar.le; - m->u.par.msb = f->wpar.msb; - m->u.par.rate = f->wpar.rate; - m->u.par.rchan = f->wpar.cmax - f->wpar.cmin + 1; - } + m->u.par.bits = f->rpar.bits; + m->u.par.bps = f->rpar.bps; + m->u.par.sig = f->rpar.sig; + m->u.par.le = f->rpar.le; + m->u.par.msb = f->rpar.msb; + m->u.par.rate = f->rpar.rate; + m->u.par.rchan = f->wpar.cmax - f->wpar.cmin + 1; + m->u.par.pchan = f->rpar.cmax - f->rpar.cmin + 1; m->u.par.appbufsz = f->bufsz; m->u.par.bufsz = f->bufsz + (dev_bufsz / dev_round) * f->round; @@ -1282,9 +1196,9 @@ sock_execmsg(struct sock *f) AMSG_INIT(m); m->cmd = AMSG_GETCAP; m->u.cap.rate = dev_rate; - m->u.cap.pchan = (f->opt->mode & MODE_PLAY) ? + m->u.cap.pchan = dev_mix ? (f->opt->rpar.cmax - f->opt->rpar.cmin + 1) : 0; - m->u.cap.rchan = (f->opt->mode & (MODE_PLAY | MODE_REC)) ? + m->u.cap.rchan = dev_sub ? (f->opt->wpar.cmax - f->opt->wpar.cmin + 1) : 0; m->u.cap.bits = sizeof(short) * 8; m->u.cap.bps = sizeof(short); @@ -1298,8 +1212,8 @@ sock_execmsg(struct sock *f) dbg_puts(": SETVOL message\n"); } #endif - if (f->pstate != SOCK_RUN && f->pstate != SOCK_START && - f->pstate != SOCK_INIT && f->pstate != SOCK_READY) { + if (f->pstate != SOCK_RUN && + f->pstate != SOCK_START && f->pstate != SOCK_INIT) { #ifdef DEBUG if (debug_level >= 1) { sock_dbg(f); @@ -1407,7 +1321,7 @@ sock_buildmsg(struct sock *f) { struct aproc *p; struct abuf *ibuf; - unsigned size, max; + unsigned size; if (f->pstate == SOCK_MIDI) { #ifdef DEBUG @@ -1424,7 +1338,7 @@ sock_buildmsg(struct sock *f) /* * If pos changed, build a MOVE message. */ - if ((f->tickpending && f->delta > 0) || f->startpending) { + if (f->tickpending) { #ifdef DEBUG if (debug_level >= 4) { sock_dbg(f); @@ -1433,9 +1347,6 @@ sock_buildmsg(struct sock *f) dbg_puts("\n"); } #endif - f->wmax += f->delta; - if (f->delta > 0) - f->rmax += f->delta; AMSG_INIT(&f->wmsg); f->wmsg.cmd = AMSG_MOVE; f->wmsg.u.ts.delta = f->delta; @@ -1443,7 +1354,6 @@ sock_buildmsg(struct sock *f) f->wstate = SOCK_WMSG; f->delta = 0; f->tickpending = 0; - f->startpending = 0; return 1; } @@ -1474,29 +1384,17 @@ sock_buildmsg(struct sock *f) p = f->pipe.file.wproc; ibuf = LIST_FIRST(&p->ibuflist); if (ibuf && ABUF_ROK(ibuf)) { -#ifdef DEBUG - if (ibuf->used > f->wmax && debug_level >= 3) { - sock_dbg(f); - dbg_puts(": attempt to send past current position\n"); - } -#endif - max = AMSG_DATAMAX / ibuf->bpf; - size = ibuf->used; + size = ibuf->used - (ibuf->used % ibuf->bpf); + if (size > AMSG_DATAMAX) + size = AMSG_DATAMAX - (AMSG_DATAMAX % ibuf->bpf); if (size > f->walign) size = f->walign; - if (size > f->wmax) - size = f->wmax; - if (size > max) - size = max; - if (size == 0) - return 0; f->walign -= size; - f->wmax -= size; if (f->walign == 0) - f->walign = f->round; + f->walign = dev_round * ibuf->bpf; AMSG_INIT(&f->wmsg); f->wmsg.cmd = AMSG_DATA; - f->wmsg.u.data.size = size * ibuf->bpf; + f->wmsg.u.data.size = size; f->wtodo = sizeof(struct amsg); f->wstate = SOCK_WMSG; return 1; @@ -1542,11 +1440,9 @@ sock_read(struct sock *f) f->rtodo = sizeof(struct amsg); } /* - * XXX: sock_attach() may not start if there's not enough - * samples queues, if so ctl_slotstart() will trigger - * other streams, but this one won't start. + * XXX: have to way that the buffer is full before starting */ - if (f->pstate == SOCK_READY && ctl_slotstart(dev_midi, f->slot)) + if (f->pstate == SOCK_START && ctl_slotstart(dev_midi, f->slot)) (void)sock_attach(f, 0); break; case SOCK_RRET: @@ -1629,12 +1525,8 @@ sock_write(struct sock *f) f->wtodo = 0xdeadbeef; break; } - /* - * XXX: why not set f->wtodo in sock_wmsg() ? - */ f->wstate = SOCK_WDATA; - f->wtodo = f->wmsg.u.data.size / - LIST_FIRST(&f->pipe.file.wproc->ibuflist)->bpf; + f->wtodo = f->wmsg.u.data.size; /* PASSTHROUGH */ case SOCK_WDATA: if (!sock_wdata(f)) @@ -1643,8 +1535,6 @@ sock_write(struct sock *f) break; f->wstate = SOCK_WIDLE; f->wtodo = 0xdeadbeef; - if (f->pstate == SOCK_STOP) - sock_freebuf(f); /* PASSTHROUGH */ case SOCK_WIDLE: if (!sock_return(f)) diff --git a/usr.bin/aucat/sock.h b/usr.bin/aucat/sock.h index bc5bfa2607d..bc6e62a1da4 100644 --- a/usr.bin/aucat/sock.h +++ b/usr.bin/aucat/sock.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sock.h,v 1.13 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: sock.h,v 1.14 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -30,8 +30,6 @@ struct sock { * to decode/encode messages in the stream. */ struct amsg rmsg, wmsg; /* messages being sent/received */ - unsigned wmax; /* max frames we're allowed to write */ - unsigned rmax; /* max frames we're allowed to read */ unsigned rtodo; /* input bytes not read yet */ unsigned wtodo; /* output bytes not written yet */ #define SOCK_RDATA 0 /* data chunk being read */ @@ -45,17 +43,14 @@ struct sock { #define SOCK_HELLO 0 /* waiting for HELLO message */ #define SOCK_INIT 1 /* parameter negotiation */ #define SOCK_START 2 /* filling play buffers */ -#define SOCK_READY 3 /* play buffers full */ -#define SOCK_RUN 4 /* attached to the mix / sub */ -#define SOCK_STOP 5 /* draining rec buffers */ -#define SOCK_MIDI 6 /* raw byte stream (midi) */ +#define SOCK_RUN 3 /* attached to the mix / sub */ +#define SOCK_MIDI 4 /* raw byte stream (midi) */ unsigned pstate; /* one of the above */ unsigned mode; /* a set of AMSG_PLAY, AMSG_REC */ struct aparams rpar; /* read (ie play) parameters */ struct aparams wpar; /* write (ie rec) parameters */ int delta; /* pos. change to send */ int tickpending; /* delta waiting to be transmitted */ - int startpending; /* initial delta waiting to be transmitted */ unsigned walign; /* align data packets to this */ unsigned bufsz; /* total buffer size */ unsigned round; /* block size */ diff --git a/usr.bin/aucat/wav.c b/usr.bin/aucat/wav.c index af7a3de9982..e811c61aa6b 100644 --- a/usr.bin/aucat/wav.c +++ b/usr.bin/aucat/wav.c @@ -23,9 +23,7 @@ #include "aproc.h" #include "conf.h" #include "dev.h" -#include "midi.h" #include "wav.h" -#include "opt.h" #ifdef DEBUG #include "dbg.h" #endif @@ -125,33 +123,19 @@ int rwav_out(struct aproc *, struct abuf *); void rwav_eof(struct aproc *, struct abuf *); void rwav_hup(struct aproc *, struct abuf *); void rwav_done(struct aproc *); -struct aproc *rwav_new(struct file *); int wwav_in(struct aproc *, struct abuf *); int wwav_out(struct aproc *, struct abuf *); void wwav_eof(struct aproc *, struct abuf *); void wwav_hup(struct aproc *, struct abuf *); void wwav_done(struct aproc *); -struct aproc *wwav_new(struct file *); - -void wav_setvol(void *, unsigned); -void wav_startreq(void *); -void wav_stopreq(void *); -void wav_locreq(void *, unsigned); - -struct ctl_ops ctl_wavops = { - wav_setvol, - wav_startreq, - wav_stopreq, - wav_locreq -}; struct aproc_ops rwav_ops = { "rwav", rwav_in, rwav_out, - rfile_eof, - rfile_hup, + rwav_eof, + rwav_hup, NULL, /* newin */ NULL, /* newout */ NULL, /* ipos */ @@ -163,8 +147,8 @@ struct aproc_ops wwav_ops = { "wwav", wwav_in, wwav_out, - wfile_eof, - wfile_hup, + wwav_eof, + wwav_hup, NULL, /* newin */ NULL, /* newout */ NULL, /* ipos */ @@ -172,466 +156,189 @@ struct aproc_ops wwav_ops = { wwav_done }; -#ifdef DEBUG -/* - * print the given wav structure - */ -void -wav_dbg(struct wav *f) -{ - static char *pstates[] = { "ini", "sta", "rdy", "run", "fai" }; - - dbg_puts("wav("); - if (f->slot >= 0 && APROC_OK(dev_midi)) { - dbg_puts(dev_midi->u.ctl.slot[f->slot].name); - dbg_putu(dev_midi->u.ctl.slot[f->slot].unit); - } else - dbg_puts(f->pipe.file.name); - dbg_puts(")/"); - dbg_puts(pstates[f->pstate]); -} -#endif - -/* - * convert ``count'' samples using the given char->short map - */ -void -wav_conv(unsigned char *data, unsigned count, short *map) +struct aproc * +rwav_new(struct file *f) { - unsigned i; - unsigned char *iptr; - short *optr; + struct aproc *p; - iptr = data + count; - optr = (short *)data + count; - for (i = count; i > 0; i--) { - --optr; - --iptr; - *optr = map[*iptr]; - } + p = aproc_new(&rwav_ops, f->name); + p->u.io.file = f; + f->rproc = p; + return p; } -/* - * read method of the file structure - */ -unsigned -wav_read(struct file *file, unsigned char *data, unsigned count) +int +rwav_in(struct aproc *p, struct abuf *ibuf_dummy) { - struct wav *f = (struct wav *)file; - unsigned n; + struct abuf *obuf = LIST_FIRST(&p->obuflist); + struct file *f = p->u.io.file; + unsigned char *data; + unsigned count; - if (f->map) - count /= sizeof(short); - if (f->rbytes >= 0 && count > f->rbytes) { - count = f->rbytes; /* file->rbytes fits in count */ - if (count == 0) { -#ifdef DEBUG - if (debug_level >= 3) { - wav_dbg(f); - dbg_puts(": read complete\n"); - } -#endif - if (!f->tr) - file_eof(&f->pipe.file); - return 0; - } - } - n = pipe_read(file, data, count); - if (n == 0) + if (ABUF_FULL(obuf) || !(f->state & FILE_ROK)) return 0; - if (f->rbytes >= 0) - f->rbytes -= n; - if (f->map) { - wav_conv(data, n, f->map); - n *= sizeof(short); - } - return n; -} - -/* - * write method of the file structure - */ -unsigned -wav_write(struct file *file, unsigned char *data, unsigned count) -{ - struct wav *f = (struct wav *)file; - unsigned n; - - if (f->wbytes >= 0 && count > f->wbytes) { - count = f->wbytes; /* wbytes fits in count */ - if (count == 0) { -#ifdef DEBUG - if (debug_level >= 3) { - wav_dbg(f); - dbg_puts(": write complete\n"); - } -#endif - file_hup(&f->pipe.file); - return 0; - } - } - n = pipe_write(file, data, count); - if (f->wbytes >= 0) - f->wbytes -= n; - f->endpos += n; - return n; -} - -/* - * close method of the file structure - */ -void -wav_close(struct file *file) -{ - struct wav *f = (struct wav *)file; - - if (f->mode & MODE_RECMASK) { - pipe_trunc(&f->pipe.file, f->endpos); - if (f->hdr == HDR_WAV) { - wav_writehdr(f->pipe.fd, - &f->hpar, - &f->startpos, - f->endpos - f->startpos); - } - } - pipe_close(file); + data = abuf_wgetblk(obuf, &count, 0); + count = file_read(f, data, count); + if (count == 0) + return 0; + abuf_wcommit(obuf, count); + if (!abuf_flush(obuf)) + return 0; + return 1; } -/* - * attach play (rec) abuf structure to the device and - * switch to the ``RUN'' state; the play abug must not be empty - */ int -wav_attach(struct wav *f, int force) +rwav_out(struct aproc *p, struct abuf *obuf) { - struct abuf *rbuf = NULL, *wbuf = NULL; + struct file *f = p->u.io.file; + unsigned char *data; + unsigned count; - if (f->mode & MODE_PLAY) - rbuf = LIST_FIRST(&f->pipe.file.rproc->obuflist); - if (f->mode & MODE_RECMASK) - wbuf = LIST_FIRST(&f->pipe.file.wproc->ibuflist); - f->pstate = WAV_RUN; -#ifdef DEBUG - if (debug_level >= 3) { - wav_dbg(f); - dbg_puts(": attaching\n"); - } -#endif - dev_attach(f->pipe.file.name, f->mode, - rbuf, &f->hpar, wbuf, &f->hpar, f->xrun, f->maxweight); - if (f->mode & MODE_PLAY) - dev_setvol(rbuf, MIDI_TO_ADATA(f->vol)); + if (f->state & FILE_RINUSE) + return 0; + if (ABUF_FULL(obuf) || !(f->state & FILE_ROK)) + return 0; + data = abuf_wgetblk(obuf, &count, 0); + count = file_read(f, data, count); + if (count == 0) + return 0; + abuf_wcommit(obuf, count); return 1; } -/* - * allocate the play (rec) abuf structure; if this is a - * file to record, then attach it to the device - * - * XXX: buffer size should be larger than dev_bufsz, because - * in non-server mode we don't prime play buffers with - * silence - */ void -wav_allocbuf(struct wav *f) +rwav_done(struct aproc *p) { - struct abuf *buf; - unsigned nfr; + struct file *f = p->u.io.file; + struct abuf *obuf; - f->pstate = WAV_START; - if (f->mode & MODE_PLAY) { - nfr = 2 * dev_bufsz * f->hpar.rate / dev_rate; - buf = abuf_new(nfr, &f->hpar); - aproc_setout(f->pipe.file.rproc, buf); - abuf_fill(buf); - if (!ABUF_WOK(buf) || (f->pipe.file.state & FILE_EOF)) - f->pstate = WAV_READY; - } - if (f->mode & MODE_RECMASK) { - nfr = 2 * dev_bufsz * f->hpar.rate / dev_rate; - buf = abuf_new(nfr, &f->hpar); - aproc_setin(f->pipe.file.wproc, buf); - f->pstate = WAV_READY; - } -#ifdef DEBUG - if (debug_level >= 3) { - wav_dbg(f); - dbg_puts(": allocating buffers\n"); - } -#endif - if (f->pstate == WAV_READY && ctl_slotstart(dev_midi, f->slot)) - (void)wav_attach(f, 0); + if (f == NULL) + return; + /* + * all buffers must be detached before deleting f->wproc, + * because otherwise it could trigger this code again + */ + obuf = LIST_FIRST(&p->obuflist); + if (obuf) + abuf_eof(obuf); + if (f->wproc) { + f->rproc = NULL; + aproc_del(f->wproc); + } else + file_del(f); + p->u.io.file = NULL; } -/* - * free abuf structure and switch to the ``INIT'' state - */ void -wav_freebuf(struct wav *f) +rwav_eof(struct aproc *p, struct abuf *ibuf_dummy) { - struct abuf *rbuf = NULL, *wbuf = NULL; - - if (f->mode & MODE_PLAY) - rbuf = LIST_FIRST(&f->pipe.file.rproc->obuflist); - if (f->mode & MODE_RECMASK) - wbuf = LIST_FIRST(&f->pipe.file.wproc->ibuflist); - f->pstate = WAV_INIT; -#ifdef DEBUG - if (debug_level >= 3) { - wav_dbg(f); - dbg_puts(": freeing buffers\n"); - } -#endif - if (rbuf || wbuf) - ctl_slotstop(dev_midi, f->slot); - if (rbuf) - abuf_eof(rbuf); - if (wbuf) - abuf_hup(wbuf); + aproc_del(p); } -/* - * switch to the ``INIT'' state performing - * necessary actions to reach it - */ void -wav_reset(struct wav *f) +rwav_hup(struct aproc *p, struct abuf *obuf) { - switch (f->pstate) { - case WAV_START: - case WAV_READY: - if (ctl_slotstart(dev_midi, f->slot)) - (void)wav_attach(f, 1); - /* PASSTHROUGH */ - case WAV_RUN: - wav_freebuf(f); - f->pstate = WAV_INIT; - /* PASSTHROUGH */ - case WAV_INIT: - case WAV_FAILED: - /* nothing yet */ - break; - } + aproc_del(p); } -/* - * terminate the wav reader/writer - */ -void -wav_exit(struct wav *f) +struct aproc * +wwav_new(struct file *f) { - if (f->mode & MODE_PLAY) { - aproc_del(f->pipe.file.rproc); - } else if (f->mode & MODE_RECMASK) { - aproc_del(f->pipe.file.wproc); - } + struct aproc *p; + + p = aproc_new(&wwav_ops, f->name); + p->u.io.file = f; + f->wproc = p; + return p; } -/* - * seek to f->mmcpos and prepare to start, close - * the file on error. - */ -int -wav_seekmmc(struct wav *f) +void +wwav_done(struct aproc *p) { + struct file *f = p->u.io.file; + struct abuf *ibuf; + + if (f == NULL) + return; /* - * don't go beyond the end-of-file, if so - * put it in INIT state so it dosn't start + * all buffers must be detached before deleting f->rproc, + * because otherwise it could trigger this code again */ - if (f->mmcpos > f->endpos) { - wav_reset(f); - f->pstate = WAV_FAILED; - /* - * don't make other stream wait for us - */ - if (f->slot >= 0) - ctl_slotstart(dev_midi, f->slot); - return 0; - } - if (!pipe_seek(&f->pipe.file, f->mmcpos)) { - wav_exit(f); - return 0; - } - if (f->hdr == HDR_WAV) - f->wbytes = WAV_DATAMAX - f->mmcpos; - f->rbytes = f->endpos - f->mmcpos; - wav_reset(f); - wav_allocbuf(f); - return 1; + ibuf = LIST_FIRST(&p->ibuflist); + if (ibuf) + abuf_hup(ibuf); + if (f->rproc) { + f->wproc = NULL; + aproc_del(f->rproc); + } else + file_del(f); + p->u.io.file = NULL; } -/* - * read samples from the file and possibly start it - */ int -wav_rdata(struct wav *f) +wwav_in(struct aproc *p, struct abuf *ibuf) { - struct aproc *p; - struct abuf *obuf; + struct file *f = p->u.io.file; + unsigned char *data; + unsigned count; - p = f->pipe.file.rproc; - obuf = LIST_FIRST(&p->obuflist); - if (obuf == NULL) + if (f->state & FILE_WINUSE) return 0; - if (!ABUF_WOK(obuf) || !(f->pipe.file.state & FILE_ROK)) + if (ABUF_EMPTY(ibuf) || !(f->state & FILE_WOK)) return 0; - if (!rfile_do(p, obuf->len, NULL)) + data = abuf_rgetblk(ibuf, &count, 0); + count = file_write(f, data, count); + if (count == 0) return 0; - switch (f->pstate) { - case WAV_START: - if (!ABUF_WOK(obuf) || (f->pipe.file.state & FILE_EOF)) - f->pstate = WAV_READY; - /* PASSTHROUGH */ - case WAV_READY: - if (ctl_slotstart(dev_midi, f->slot)) - (void)wav_attach(f, 0); - break; -#ifdef DEBUG - case WAV_RUN: - break; - default: - wav_dbg(f); - dbg_puts(": bad state\n"); - dbg_panic(); -#endif - } - if (f->rbytes == 0 && f->tr) { -#ifdef DEBUG - if (debug_level >= 3) { - wav_dbg(f); - dbg_puts(": trying to restart\n"); - } -#endif - if (!wav_seekmmc(f)) - return 0; - } + abuf_rdiscard(ibuf, count); return 1; } int -wav_wdata(struct wav *f) +wwav_out(struct aproc *p, struct abuf *obuf_dummy) { - struct aproc *p; - struct abuf *ibuf; + struct abuf *ibuf = LIST_FIRST(&p->ibuflist); + struct file *f = p->u.io.file; + unsigned char *data; + unsigned count; - if (!(f->pipe.file.state & FILE_WOK)) + if (!abuf_fill(ibuf)) return 0; - p = f->pipe.file.wproc; - ibuf = LIST_FIRST(&p->ibuflist); - if (ibuf == NULL) + if (ABUF_EMPTY(ibuf) || !(f->state & FILE_WOK)) return 0; - if (!ABUF_ROK(ibuf)) + data = abuf_rgetblk(ibuf, &count, 0); + if (count == 0) { + /* XXX: this can't happen, right ? */ return 0; - if (!wfile_do(p, ibuf->len, NULL)) + } + count = file_write(f, data, count); + if (count == 0) return 0; + abuf_rdiscard(ibuf, count); return 1; } -/* - * callback to set the volume, invoked by the MIDI control code - */ -void -wav_setvol(void *arg, unsigned vol) -{ - struct wav *f = (struct wav *)arg; - struct abuf *rbuf; - - f->vol = vol; - if ((f->mode & MODE_PLAY) && f->pstate == WAV_RUN) { - rbuf = LIST_FIRST(&f->pipe.file.rproc->obuflist); - dev_setvol(rbuf, MIDI_TO_ADATA(vol)); - } -} - -/* - * callback to start the stream, invoked by the MIDI control code - */ -void -wav_startreq(void *arg) -{ - struct wav *f = (struct wav *)arg; - - switch (f->pstate) { - case WAV_FAILED: -#ifdef DEBUG - if (debug_level >= 2) { - wav_dbg(f); - dbg_puts(": skipped (failed to seek)\n"); - } -#endif - return; - case WAV_READY: - if (f->mode & MODE_RECMASK) - f->endpos = f->startpos; - (void)wav_attach(f, 0); - break; -#ifdef DEBUG - default: - wav_dbg(f); - dbg_puts(": not in READY state\n"); - dbg_panic(); - break; -#endif - } -} - -/* - * callback to stop the stream, invoked by the MIDI control code - */ void -wav_stopreq(void *arg) +wwav_eof(struct aproc *p, struct abuf *ibuf) { - struct wav *f = (struct wav *)arg; - -#ifdef DEBUG - if (debug_level >= 2) { - wav_dbg(f); - dbg_puts(": stopping"); - if (f->pstate != WAV_FAILED && (f->mode & MODE_RECMASK)) { - dbg_puts(", "); - dbg_putu(f->endpos); - dbg_puts(" bytes recorded"); - } - dbg_puts("\n"); - } -#endif - if (!f->tr) { - wav_exit(f); - return; - } - (void)wav_seekmmc(f); + aproc_del(p); } -/* - * callback to relocate the stream, invoked by the MIDI control code - * on a stopped stream - */ void -wav_locreq(void *arg, unsigned mmc) +wwav_hup(struct aproc *p, struct abuf *obuf_dummy) { - struct wav *f = (struct wav *)arg; - -#ifdef DEBUG - if (f->pstate == WAV_RUN) { - wav_dbg(f); - dbg_puts(": in RUN state\n"); - dbg_panic(); - } -#endif - f->mmcpos = f->startpos + - ((off_t)mmc * f->hpar.rate / MTC_SEC) * aparams_bpf(&f->hpar); - (void)wav_seekmmc(f); + aproc_del(p); } -/* - * create a file reader in the ``INIT'' state - */ struct wav * -wav_new_in(struct fileops *ops, unsigned mode, char *name, unsigned hdr, - struct aparams *par, unsigned xrun, unsigned volctl, int tr) +wav_new_in(struct fileops *ops, char *name, unsigned hdr, + struct aparams *par, unsigned xrun, unsigned volctl) { int fd; struct wav *f; + struct aproc *p; + struct abuf *buf; + unsigned nfr; if (name != NULL) { fd = open(name, O_RDONLY | O_NONBLOCK, 0666); @@ -649,59 +356,43 @@ wav_new_in(struct fileops *ops, unsigned mode, char *name, unsigned hdr, if (f == NULL) return NULL; if (hdr == HDR_WAV) { - if (!wav_readhdr(f->pipe.fd, par, &f->startpos, &f->rbytes, &f->map)) { + if (!wav_readhdr(f->pipe.fd, par, &f->rbytes, &f->map)) { file_del((struct file *)f); return NULL; } - f->endpos = f->startpos + f->rbytes; + f->hpar = *par; } else { - f->startpos = 0; - f->endpos = pipe_endpos(&f->pipe.file); - if (f->endpos > 0) { - if (!pipe_seek(&f->pipe.file, 0)) { - file_del((struct file *)f); - return NULL; - } - f->rbytes = f->endpos; - } else - f->rbytes = -1; + f->rbytes = -1; f->map = NULL; } - f->tr = tr; - f->mode = mode; - f->hpar = *par; f->hdr = 0; - f->xrun = xrun; - f->maxweight = MIDI_TO_ADATA(volctl); - f->slot = ctl_slotnew(dev_midi, "play", &ctl_wavops, f, 1); - rwav_new((struct file *)f); - wav_allocbuf(f); + nfr = dev_bufsz * par->rate / dev_rate; + buf = abuf_new(nfr, par); + p = rwav_new((struct file *)f); + aproc_setout(p, buf); + abuf_fill(buf); /* XXX: move this in dev_attach() ? */ + dev_attach(name, buf, par, xrun, NULL, NULL, 0, ADATA_UNIT); + dev_setvol(buf, MIDI_TO_ADATA(volctl)); #ifdef DEBUG if (debug_level >= 2) { dbg_puts(name); dbg_puts(": playing "); - dbg_putu(f->startpos); - dbg_puts(".."); - dbg_putu(f->endpos); - dbg_puts(": playing "); aparams_dbg(par); - if (f->tr) - dbg_puts(", mmc"); dbg_puts("\n"); } #endif return f; } -/* - * create a file writer in the ``INIT'' state - */ struct wav * -wav_new_out(struct fileops *ops, unsigned mode, char *name, unsigned hdr, - struct aparams *par, unsigned xrun, int tr) +wav_new_out(struct fileops *ops, char *name, unsigned hdr, + struct aparams *par, unsigned xrun) { int fd; struct wav *f; + struct aproc *p; + struct abuf *buf; + unsigned nfr; if (name == NULL) { name = "stdout"; @@ -723,24 +414,20 @@ wav_new_out(struct fileops *ops, unsigned mode, char *name, unsigned hdr, par->le = 1; par->sig = (par->bits <= 8) ? 0 : 1; par->bps = (par->bits + 7) / 8; - if (!wav_writehdr(f->pipe.fd, par, &f->startpos, 0)) { + if (!wav_writehdr(f->pipe.fd, par)) { file_del((struct file *)f); return NULL; } + f->hpar = *par; f->wbytes = WAV_DATAMAX; - f->endpos = f->startpos; - } else { + } else f->wbytes = -1; - f->startpos = f->endpos = 0; - } - f->tr = tr; - f->mode = mode; - f->hpar = *par; f->hdr = hdr; - f->xrun = xrun; - f->slot = ctl_slotnew(dev_midi, "rec", &ctl_wavops, f, 1); - wwav_new((struct file *)f); - wav_allocbuf(f); + nfr = dev_bufsz * par->rate / dev_rate; + p = wwav_new((struct file *)f); + buf = abuf_new(nfr, par); + aproc_setin(p, buf); + dev_attach(name, NULL, NULL, 0, buf, par, xrun, 0); #ifdef DEBUG if (debug_level >= 2) { dbg_puts(name); @@ -753,107 +440,86 @@ wav_new_out(struct fileops *ops, unsigned mode, char *name, unsigned hdr, } void -rwav_done(struct aproc *p) -{ - struct wav *f = (struct wav *)p->u.io.file; - - if (f->slot >= 0) - ctl_slotdel(dev_midi, f->slot); - f->slot = -1; - rfile_done(p); -} - -int -rwav_in(struct aproc *p, struct abuf *ibuf_dummy) +wav_conv(unsigned char *data, unsigned count, short *map) { - struct wav *f = (struct wav *)p->u.io.file; - struct abuf *obuf; + unsigned i; + unsigned char *iptr; + short *optr; - if (!wav_rdata(f)) - return 0; - obuf = LIST_FIRST(&p->obuflist); - if (obuf && f->pstate >= WAV_RUN) { - if (!abuf_flush(obuf)) - return 0; + iptr = data + count; + optr = (short *)data + count; + for (i = count; i > 0; i--) { + --optr; + --iptr; + *optr = map[*iptr]; } - return 1; } -int -rwav_out(struct aproc *p, struct abuf *obuf) +unsigned +wav_read(struct file *file, unsigned char *data, unsigned count) { - struct wav *f = (struct wav *)p->u.io.file; + struct wav *f = (struct wav *)file; + unsigned n; - if (f->pipe.file.state & FILE_RINUSE) - return 0; - for (;;) { - if (!wav_rdata(f)) + if (f->map) + count /= sizeof(short); + if (f->rbytes >= 0 && count > f->rbytes) { + count = f->rbytes; /* file->rbytes fits in count */ + if (count == 0) { +#ifdef DEBUG + if (debug_level >= 3) { + file_dbg(&f->pipe.file); + dbg_puts(": read complete\n"); + } +#endif + file_eof(&f->pipe.file); return 0; + } } - return 1; -} - -struct aproc * -rwav_new(struct file *f) -{ - struct aproc *p; - - p = aproc_new(&rwav_ops, f->name); - p->u.io.file = f; - p->u.io.partial = 0;; - f->rproc = p; - return p; -} - -void -wwav_done(struct aproc *p) -{ - struct wav *f = (struct wav *)p->u.io.file; - - if (f->slot >= 0) - ctl_slotdel(dev_midi, f->slot); - f->slot = -1; - wfile_done(p); -} - -int -wwav_in(struct aproc *p, struct abuf *ibuf) -{ - struct wav *f = (struct wav *)p->u.io.file; - - if (f->pipe.file.state & FILE_WINUSE) + n = pipe_read(file, data, count); + if (n == 0) return 0; - for (;;) { - if (!wav_wdata(f)) - return 0; + if (f->rbytes >= 0) + f->rbytes -= n; + if (f->map) { + wav_conv(data, n, f->map); + n *= sizeof(short); } - return 1; + return n; } -int -wwav_out(struct aproc *p, struct abuf *obuf_dummy) +unsigned +wav_write(struct file *file, unsigned char *data, unsigned count) { - struct abuf *ibuf = LIST_FIRST(&p->ibuflist); - struct wav *f = (struct wav *)p->u.io.file; + struct wav *f = (struct wav *)file; + unsigned n; - if (ibuf && f->pstate == WAV_RUN) { - if (!abuf_fill(ibuf)) + if (f->wbytes >= 0 && count > f->wbytes) { + count = f->wbytes; /* wbytes fits in count */ + if (count == 0) { +#ifdef DEBUG + if (debug_level >= 3) { + file_dbg(&f->pipe.file); + dbg_puts(": write complete\n"); + } +#endif + file_hup(&f->pipe.file); return 0; + } } - if (!wav_wdata(f)) - return 0; - return 1; + n = pipe_write(file, data, count); + if (f->wbytes >= 0) + f->wbytes -= n; + return n; } -struct aproc * -wwav_new(struct file *f) +void +wav_close(struct file *file) { - struct aproc *p; + struct wav *f = (struct wav *)file; - p = aproc_new(&wwav_ops, f->name); - p->u.io.file = f; - p->u.io.partial = 0;; - f->wproc = p; - return p; + if (f->hdr == HDR_WAV) + wav_writehdr(f->pipe.fd, &f->hpar); + pipe_close(file); } diff --git a/usr.bin/aucat/wav.h b/usr.bin/aucat/wav.h index 4543d1a89da..8e8288cdecd 100644 --- a/usr.bin/aucat/wav.h +++ b/usr.bin/aucat/wav.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wav.h,v 1.6 2010/04/03 17:40:33 ratchov Exp $ */ +/* $OpenBSD: wav.h,v 1.7 2010/04/03 17:59:17 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -28,38 +28,23 @@ struct wav { #define HDR_RAW 1 /* no headers, ie openbsd native ;-) */ #define HDR_WAV 2 /* microsoft riff wave */ unsigned hdr; /* HDR_RAW or HDR_WAV */ - unsigned xrun; /* xrun policy */ struct aparams hpar; /* parameters to write on the header */ off_t rbytes; /* bytes to read, -1 if no limit */ off_t wbytes; /* bytes to write, -1 if no limit */ - off_t startpos; /* beginning of the data chunk */ - off_t endpos; /* end of the data chunk */ - off_t mmcpos; /* play/rec start point set by MMC */ short *map; /* mulaw/alaw -> s16 conversion table */ - int slot; /* mixer ctl slot number */ - int tr; /* use MMC control */ - unsigned vol; /* current volume */ - unsigned maxweight; /* dynamic range when vol == 127 */ -#define WAV_INIT 0 /* not trying to do anything */ -#define WAV_START 1 /* buffer allocated */ -#define WAV_READY 2 /* buffer filled enough */ -#define WAV_RUN 3 /* buffer attached to device */ -#define WAV_FAILED 4 /* failed to seek */ - unsigned pstate; /* one of above */ - unsigned mode; /* bitmap of MODE_* */ }; extern struct fileops wav_ops; -struct wav *wav_new_in(struct fileops *, unsigned, char *, unsigned, - struct aparams *, unsigned, unsigned, int); -struct wav *wav_new_out(struct fileops *, unsigned, char *, unsigned, - struct aparams *, unsigned, int); +struct wav *wav_new_in(struct fileops *, char *, unsigned, + struct aparams *, unsigned, unsigned); +struct wav *wav_new_out(struct fileops *, char *, unsigned, + struct aparams *, unsigned); unsigned wav_read(struct file *, unsigned char *, unsigned); unsigned wav_write(struct file *, unsigned char *, unsigned); void wav_close(struct file *); -int wav_readhdr(int, struct aparams *, off_t *, off_t *, short **); -int wav_writehdr(int, struct aparams *, off_t *, off_t); +int wav_readhdr(int, struct aparams *, off_t *, short **); +int wav_writehdr(int, struct aparams *); void wav_conv(unsigned char *, unsigned, short *); /* legacy */ |